commit 058977dd74fb1ca710c8d146d9ed7f76d5218fac Author: jiahao <283739569@qq.com> Date: Mon Mar 16 14:24:08 2020 +0800 1 diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies new file mode 100644 index 0000000..3616769 --- /dev/null +++ b/.flutter-plugins-dependencies @@ -0,0 +1 @@ +{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"agora_rtc_engine","dependencies":[]},{"name":"amap_location","dependencies":[]},{"name":"android_intent","dependencies":[]},{"name":"app_installer","dependencies":[]},{"name":"apple_sign_in","dependencies":[]},{"name":"audioplayer","dependencies":[]},{"name":"auto_orientation","dependencies":[]},{"name":"city_pickers","dependencies":[]},{"name":"connectivity","dependencies":[]},{"name":"easy_contact_picker","dependencies":[]},{"name":"file_picker","dependencies":[]},{"name":"flutter_app_badger","dependencies":[]},{"name":"flutter_audio_recorder","dependencies":[]},{"name":"flutter_bugly","dependencies":[]},{"name":"flutter_facebook_login","dependencies":[]},{"name":"flutter_ijkplayer","dependencies":[]},{"name":"flutter_image_compress","dependencies":[]},{"name":"flutter_inapp_purchase","dependencies":[]},{"name":"flutter_local_notifications","dependencies":[]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"flutter_qr_reader","dependencies":["image_picker"]},{"name":"flutter_webview_plugin","dependencies":[]},{"name":"fluwx_no_pay","dependencies":[]},{"name":"geolocator","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","dependencies":[]},{"name":"google_maps_flutter","dependencies":[]},{"name":"image_cropper","dependencies":[]},{"name":"image_gallery_saver","dependencies":[]},{"name":"image_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"jpush_flutter","dependencies":[]},{"name":"keyboard_utils","dependencies":[]},{"name":"location","dependencies":[]},{"name":"location_permissions","dependencies":[]},{"name":"open_file","dependencies":[]},{"name":"package_info","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"photo_manager","dependencies":[]},{"name":"receive_sharing_intent","dependencies":[]},{"name":"share","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]},{"name":"url_launcher","dependencies":[]},{"name":"video_player","dependencies":[]},{"name":"video_thumbnail","dependencies":[]},{"name":"wifi_info_plugin","dependencies":[]}]} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa35107 --- /dev/null +++ b/.gitignore @@ -0,0 +1,72 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +/build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..4d08967 --- /dev/null +++ b/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: b712a172f9694745f50505c93340883493b505e5 + channel: stable + +project_type: app diff --git a/README.md b/README.md new file mode 100644 index 0000000..cd71c14 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# chat + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/android/.project b/android/.project new file mode 100644 index 0000000..549de72 --- /dev/null +++ b/android/.project @@ -0,0 +1,17 @@ + + + android + Project android created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/android/app/.classpath b/android/app/.classpath new file mode 100644 index 0000000..4f3f504 --- /dev/null +++ b/android/app/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/android/app/.project b/android/app/.project new file mode 100644 index 0000000..d1eb8cb --- /dev/null +++ b/android/app/.project @@ -0,0 +1,23 @@ + + + app + Project app created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/android/app/.settings/org.eclipse.buildship.core.prefs b/android/app/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..a7b84d9 --- /dev/null +++ b/android/app/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1 diff --git a/android/app/agconnect-services.json b/android/app/agconnect-services.json new file mode 100644 index 0000000..abbd909 --- /dev/null +++ b/android/app/agconnect-services.json @@ -0,0 +1,26 @@ +{ + "agcgw":{ + "backurl":"connect-dra.dbankcloud.cn", + "url":"connect-dra.hispace.hicloud.com" + }, + "client":{ + "cp_id":"890086000300385560", + "product_id":"9105385871708389411", + "client_id":"270664671340528640", + "client_secret":"00CC308FC014C334D58CF79471B490FD6274BC39FEAAD89B63E762871DB4EBCC", + "app_id":"101598177", + "package_name":"com.cyhd.henhoandroid" + }, + "service":{ + "analytics":{ + "collector_url":"datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn", + "resource_id":"p1", + "channel_id":"" + }, + "ml":{ + "mlservice_url":"ml-api-dra.ai.hicloud.com,ml-api-dra.ai.dbankcloud.cn" + } + }, + "region":"SG", + "configuration_version":"1.0" +} \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..73e1601 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,156 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" +apply plugin: 'com.google.gms.google-services' +apply plugin: 'com.huawei.agconnect' +android { + compileSdkVersion 28 + + lintOptions { + disable 'InvalidPackage' + } + + signingConfigs { + + release { + keyAlias 'cyhd' + keyPassword '@)!&8888cyhd' + storeFile file('../cyhdSign') + storePassword '@)!&8888cyhd' + } + } + + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.cyhd.henhoandroid" + minSdkVersion 21 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + // manifestPlaceholders = [ + // AMAP_KEY : "1fd4e93e3b4b13747da41f484c955fe2", /// 高德地图key + // ] + ndk { + abiFilters 'armeabi-v7a' + } + multiDexEnabled true + manifestPlaceholders = [ + JPUSH_PKGNAME : 'com.cyhd.henhoandroid', + JPUSH_APPKEY : "13dd603952a6632d1dd3ac54", // NOTE: JPush 上注册的包名对应的 Appkey. + JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可. + + AMAP_KEY : "1fd4e93e3b4b13747da41f484c955fe2", /// 高德地图key + + XIAOMI_APPKEY:"MI-5221829498125",//小米平台注册的appkey + XIAOMI_APPID:"MI-2882303761518294125",//小米平台注册的appid +// + HUAWEI_APPID:"101598177",//华为平台注册的appid + + + OPPO_APPKEY : "OP-cd9ece5049514019842f54d537068018", // OPPO平台注册的appkey + OPPO_APPID : "OP-30233397", // OPPO平台注册的appid + OPPO_APPSECRET: "OP-您的应用对应OPPO的APPSECRET",//OPPO平台注册的appsecret + +// +// MEIZU_APPKEY:"MZ-您的应用对应的魅族appkey",//魅族平台注册的appkey +// MEIZU_APPID:"MZ-您的应用对应魅族的appid",//魅族平台注册的appid + + ] + } + + buildTypes { + release { +// minifyEnabled true //混淆 +// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' +// shrinkResources false + signingConfig signingConfigs.release + minifyEnabled false + shrinkResources false + } + debug { + signingConfig signingConfigs.release + minifyEnabled false + shrinkResources false + } + } + + +} + +flutter { + source '../..' +} + +subprojects { + project.configurations.all { + resolutionStrategy.eachDependency { details -> + if (details.requested.group == 'com.android.support' + && !details.requested.name.contains('multidex') ) { + details.useVersion "27.1.1" + } + + if (details.requested.group == 'androidx.core' + && !details.requested.name.contains('androidx') ) { + + } + } + } +} + + +dependencies { + + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + //implementation 'com.amap.api:location:latest.integration' + implementation 'com.android.support:multidex:1.0.3' + + + //接入厂商推送-跟jpush插件版本要配套 + implementation 'cn.jiguang.sdk.plugin:xiaomi:3.3.4' +// implementation 'cn.jiguang.sdk.plugin:huawei:3.3.4' + + + implementation 'com.huawei.hms:push:3.0.3.301' + implementation files('src/main/libs/jpush-android-plugin-huawei-v3.5.4.jar') + +// implementation'cn.jiguang.sdk.plugin:meizu:3.4.1'//JPushSDK3.4.1 + implementation 'com.google.firebase:firebase-messaging:17.3.4' + + implementation files('src/main/libs/jpush-android-plugin-fcm-v3.5.4.jar') + + implementation 'cn.jiguang.sdk.plugin:oppo:3.3.4' + compile "androidx.core:core-ktx:+" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + +} +repositories { + mavenCentral() +} diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..a471004 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,40 @@ +{ + "project_info": { + "project_number": "151024159565", + "firebase_url": "https://hi-cyhd.firebaseio.com", + "project_id": "hi-cyhd", + "storage_bucket": "hi-cyhd.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:151024159565:android:cfc78480e0b6c10e730504", + "android_client_info": { + "package_name": "com.cyhd.henhoandroid" + } + }, + "oauth_client": [ + { + "client_id": "151024159565-62j3d7gvusqusksu8dehjd7v6eq0g6he.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyB676Y2P0xOg7qFlhOOI_wuMhrqI32AN1I" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "151024159565-62j3d7gvusqusksu8dehjd7v6eq0g6he.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..e5f10cd --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f7305f0 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/java/com/cyhd/henhoandroid/MainActivity.java b/android/app/src/main/java/com/cyhd/henhoandroid/MainActivity.java new file mode 100644 index 0000000..12b9509 --- /dev/null +++ b/android/app/src/main/java/com/cyhd/henhoandroid/MainActivity.java @@ -0,0 +1,31 @@ +package com.cyhd.henhoandroid; +import android.os.Bundle; +import android.util.Log; + +import com.cyhd.henhoandroid.plugin.FlutterWindowManagerPlugin; + +import io.flutter.app.FlutterActivity; +import io.flutter.plugins.GeneratedPluginRegistrant; +import com.cyhd.henhoandroid.plugin.ScreenShot; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GoogleApiAvailability; +import com.xiaomi.mipush.sdk.MiPushClient; + +public class MainActivity extends FlutterActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + GeneratedPluginRegistrant.registerWith(this); + FlutterWindowManagerPlugin.registerWith(registrarFor("io.adaptant.labs.flutter_windowmanager.FlutterWindowManagerPlugin")); + ScreenShot.registerWith(this, registrarFor("make.photo.screen.hibok")); + + + + + } + + + + + +} diff --git a/android/app/src/main/java/com/cyhd/henhoandroid/plugin/FlutterWindowManagerPlugin.java b/android/app/src/main/java/com/cyhd/henhoandroid/plugin/FlutterWindowManagerPlugin.java new file mode 100644 index 0000000..e70a76f --- /dev/null +++ b/android/app/src/main/java/com/cyhd/henhoandroid/plugin/FlutterWindowManagerPlugin.java @@ -0,0 +1,123 @@ +package com.cyhd.henhoandroid.plugin; + +import android.app.Activity; +import android.os.Build; +import android.util.Log; +import android.view.WindowManager; + +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugin.common.PluginRegistry.Registrar; + +/** FlutterWindowManagerPlugin */ +public class FlutterWindowManagerPlugin implements MethodCallHandler { + private final Activity activity; + + private FlutterWindowManagerPlugin(Registrar registrar) { + this.activity = registrar.activity(); + } + + /** Plugin registration. */ + public static void registerWith(Registrar registrar) { + final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_windowmanager"); + FlutterWindowManagerPlugin instance = new FlutterWindowManagerPlugin(registrar); + channel.setMethodCallHandler(instance); + } + + /** + * Validate flag specification against WindowManager.LayoutParams and API levels, as per: + * https://developer.android.com/reference/android/view/WindowManager.LayoutParams + */ + @SuppressWarnings("deprecation") + private boolean validLayoutParam(int flag) { + switch (flag) { + case WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON: + case WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM: + case WindowManager.LayoutParams.FLAG_DIM_BEHIND: + case WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN: + case WindowManager.LayoutParams.FLAG_FULLSCREEN: + case WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED: + case WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES: + case WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON: + case WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR: + case WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN: + case WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS: + case WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE: + case WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE: + case WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL: + case WindowManager.LayoutParams.FLAG_SCALED: + case WindowManager.LayoutParams.FLAG_SECURE: + case WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER: + case WindowManager.LayoutParams.FLAG_SPLIT_TOUCH: + case WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH: + return true; + case WindowManager.LayoutParams.FLAG_BLUR_BEHIND: + return !(Build.VERSION.SDK_INT >= 15); + case WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD: + return (Build.VERSION.SDK_INT >= 5 && Build.VERSION.SDK_INT < 26); + case WindowManager.LayoutParams.FLAG_DITHER: + return !(Build.VERSION.SDK_INT >= 17); + case WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS: + return (Build.VERSION.SDK_INT >= 21); + case WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR: + return (Build.VERSION.SDK_INT >= 22); + case WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN: + return (Build.VERSION.SDK_INT >= 18); + case WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE: + return (Build.VERSION.SDK_INT >= 19); + case WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED: + return !(Build.VERSION.SDK_INT >= 27); + case WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING: + return !(Build.VERSION.SDK_INT >= 20); + case WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION: + case WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS: + return (Build.VERSION.SDK_INT >= 19); + case WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON: + return !(Build.VERSION.SDK_INT >= 27); + default: + return false; + } + } + + private boolean validLayoutParams(Result result, int flags) { + for (int i = 0; i < Integer.SIZE; i++) { + int flag = (1 << i); + if ((flags & flag) == 1) { + if (!validLayoutParam(flag)) { + result.error("FlutterWindowManagerPlugin","FlutterWindowManagerPlugin: invalid flag specification: " + Integer.toHexString(flag), null); + return false; + } + } + } + + return true; + } + + @Override + public void onMethodCall(MethodCall call, Result result) { + final int flags = call.argument("flags"); + + if (activity == null) { + result.error("FlutterWindowManagerPlugin", "FlutterWindowManagerPlugin: ignored flag state change, current activity is null", null); + } + + if (!validLayoutParams(result, flags)) { + return; + } + + switch (call.method) { + case "addFlags": + activity.getWindow().addFlags(flags); + result.success(true); + break; + case "clearFlags": + activity.getWindow().clearFlags(flags); + result.success(true); + break; + default: + result.notImplemented(); + } + } +} diff --git a/android/app/src/main/java/com/cyhd/henhoandroid/plugin/ScreenShot.java b/android/app/src/main/java/com/cyhd/henhoandroid/plugin/ScreenShot.java new file mode 100644 index 0000000..a410410 --- /dev/null +++ b/android/app/src/main/java/com/cyhd/henhoandroid/plugin/ScreenShot.java @@ -0,0 +1,216 @@ +package com.cyhd.henhoandroid.plugin; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.net.Uri; +import android.util.Log; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GoogleApiAvailability; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.List; + +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugin.common.PluginRegistry.Registrar; +import io.flutter.view.FlutterView; + +/** + * ScreenshotShareImagePlugin + */ + + +public class ScreenShot implements MethodCallHandler { + + private Registrar registrar; + private FlutterView flutterView; + private MethodChannel channel; + private Context context; + + public static double pi = 3.1415926535897932384626; + public static double x_pi = 3.14159265358979324 * 3000.0 / 180.0; + + + public ScreenShot(Context context, Registrar registrar, FlutterView flutterView, MethodChannel channel) { + this.context = context; + this.registrar = registrar; + this.flutterView = flutterView; + this.channel = channel; + this.channel.setMethodCallHandler(this); + } + + + /** + * Plugin registration. + */ + public static void registerWith(Context context, Registrar registrar) { + + final MethodChannel channel = new MethodChannel(registrar.messenger(), "make.photo.screen.hibok"); + channel.setMethodCallHandler(new ScreenShot(context, registrar, registrar.view(), channel)); + } + + @Override + public void onMethodCall(MethodCall call, Result result) { + if (call.method.equals("makePhotoScreen")) { + takeScreenshot(result); + } else if (call.method.equals("getListForMap")) { + getOtherMapApp(result); + } else if (call.method.equals("openMapForOth")) { + + String mapType = call.argument("mapType"); + ArrayList lanLng = call.argument("latLng"); + String address = call.argument("address"); + + Log.d("1", "地址参数 " + address); + openMapForOth(mapType, lanLng, address); + } else if(call.method.equals("isSupportGoogle")){ + result.success(onCheckGooglePlayServices()); + } + else { + result.notImplemented(); + } + } + + private void getOtherMapApp(Result result) { + + + //获取packagemanager + final PackageManager packageManager = context.getPackageManager(); + //获取所有已安装程序的包信息 + List packageInfos = packageManager.getInstalledPackages(0); + //用于存储所有已安装程序的包名 + List packageNames = new ArrayList(); + //从pinfo中将包名字逐一取出,压入pName list中 + if (packageInfos != null) { + for (int i = 0; i < packageInfos.size(); i++) { + String packName = packageInfos.get(i).packageName; + packageNames.add(packName); + } + } + + ArrayList mapList = new ArrayList(); + if (packageNames.contains("com.baidu.BaiduMap")) { + mapList.add("baidu"); + } + + if (packageNames.contains("com.autonavi.minimap")) { + mapList.add("minimap"); + } + + if (packageNames.contains("com.google.android.apps.maps")) { + mapList.add("google"); + } + + result.success(mapList); + } + + private void openMapForOth(String mapType, ArrayList latLng, String address) { + + Log.d("1", mapType); + if (mapType.equals("minimap")) { + + Log.d("1", "打开高德地图 " + address); + String uri = String.format("androidamap://viewReGeo?sourceApplication=amap&lat=%f&lon=%f&dev=1", latLng.get(0), latLng.get(1)); + + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.setPackage("com.autonavi.minimap"); + intent.setData(Uri.parse(uri)); + + context.startActivity(intent); + } else if (mapType.equals("baidu")) { + Log.d("1", "打开百度地图"); + double[] location = gcj02_To_Bd09((double) latLng.get(0), (double) latLng.get(1)); + String uri = String.format("baidumap://map/geocoder?location=%f,%f&src=com.cyhd.henhoandroid", + location[0], location[1]); + Intent intent = new Intent(); + intent.setData(Uri.parse(uri)); + context.startActivity(intent); + } else if (mapType.equals("google")) { + Log.d("1", "打开谷歌地图" + address); + String gmmIntentUri = String.format("https://ditu.google.com/maps/dir/?q=%f,%f&destination=%s", + latLng.get(0), latLng.get(1), address); + + Intent mapIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(gmmIntentUri)); + mapIntent.setPackage("com.google.android.apps.maps"); + context.startActivity(mapIntent); + } + + } + + /** + * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标 + * + * @param lat + * @param lon + */ + private double[] gcj02_To_Bd09(double lat, double lon) { + double x = lon, y = lat; + double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi); + double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi); + double tempLon = z * Math.cos(theta) + 0.0065; + double tempLat = z * Math.sin(theta) + 0.006; + double[] gps = {tempLat, tempLon}; + return gps; + } + + private void takeScreenshot(Result result) { + try { + Bitmap bitmap = flutterView.getBitmap(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + boolean isSuccess = bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos); + result.success(isSuccess ? baos.toByteArray() : ""); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + + /** + * 检查 Google Play 服务 + */ + private boolean onCheckGooglePlayServices() { + // 验证是否已在此设备上安装并启用Google Play服务,以及此设备上安装的旧版本是否为此客户端所需的版本 + int code = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context); + if (code == ConnectionResult.SUCCESS) { + // 支持Google服务 + return true; + } else { + return false; +// /** +// * 依靠 Play 服务 SDK 运行的应用在访问 Google Play 服务功能之前,应始终检查设备是否拥有兼容的 Google Play 服务 APK。 +// * 我们建议您在以下两个位置进行检查:主 Activity 的 onCreate() 方法中,及其 onResume() 方法中。 +// * onCreate() 中的检查可确保该应用在检查成功之前无法使用。 +// * onResume() 中的检查可确保当用户通过一些其他方式返回正在运行的应用(比如通过返回按钮)时,检查仍将继续进行。 +// * 如果设备没有兼容的 Google Play 服务版本,您的应用可以调用以下方法,以便让用户从 Play 商店下载 Google Play 服务。 +// * 它将尝试在此设备上提供Google Play服务。如果Play服务已经可用,则Task可以立即完成返回。 +// */ +// GoogleApiAvailability.getInstance().makeGooglePlayServicesAvailable(this); +// +// // 或者使用以下代码 +// +// /** +// * 通过isUserResolvableError来确定是否可以通过用户操作解决错误 +// */ +// if (GoogleApiAvailability.getInstance().isUserResolvableError(code)) { +// /** +// * 返回一个对话框,用于解决提供的errorCode。 +// * @param activity 用于创建对话框的父活动 +// * @param code 通过调用返回的错误代码 +// * @param activity 调用startActivityForResult时给出的requestCode +// */ +// GoogleApiAvailability.getInstance().getErrorDialog(this, code, 200).show(); +// } + + } + } + +} \ No newline at end of file diff --git a/android/app/src/main/libs/jpush-android-plugin-fcm-v3.5.4.jar b/android/app/src/main/libs/jpush-android-plugin-fcm-v3.5.4.jar new file mode 100644 index 0000000..684d55d Binary files /dev/null and b/android/app/src/main/libs/jpush-android-plugin-fcm-v3.5.4.jar differ diff --git a/android/app/src/main/libs/jpush-android-plugin-huawei-v3.5.4.jar b/android/app/src/main/libs/jpush-android-plugin-huawei-v3.5.4.jar new file mode 100644 index 0000000..3de52bd Binary files /dev/null and b/android/app/src/main/libs/jpush-android-plugin-huawei-v3.5.4.jar differ diff --git a/android/app/src/main/res/drawable/ic_launcher_1.png b/android/app/src/main/res/drawable/ic_launcher_1.png new file mode 100644 index 0000000..fb234ee Binary files /dev/null and b/android/app/src/main/res/drawable/ic_launcher_1.png differ diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..8403758 --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_1.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_1.png new file mode 100644 index 0000000..bc7a622 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_1.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_1.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_1.png new file mode 100644 index 0000000..d712178 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_1.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_1.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_1.png new file mode 100644 index 0000000..4234a90 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_1.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_1.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_1.png new file mode 100644 index 0000000..524510e Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_1.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_1.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_1.png new file mode 100644 index 0000000..954d29a Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_1.png differ diff --git a/android/app/src/main/res/values/string.xml b/android/app/src/main/res/values/string.xml new file mode 100644 index 0000000..e539bfc --- /dev/null +++ b/android/app/src/main/res/values/string.xml @@ -0,0 +1,13 @@ + + + HiBok + + + 473720630090702 + + + fb473720630090702 + \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..4c57322 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android/app/src/main/res/xml/file_paths.xml b/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..c93af76 --- /dev/null +++ b/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..651c1ec --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..eb74505 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,88 @@ +buildscript { + ext.kotlin_version = '1.3.61' + repositories { + google() + jcenter() +// maven { url 'https://maven.aliyun.com/repository/google' } +// maven{ url 'https://maven.aliyun.com/repository/jcenter'} + maven { + url 'http://download.flutter.io' + } + maven { url 'http://developer.huawei.com/repo/'} + + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.huawei.agconnect:agcp:1.0.0.300' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() +// maven { url 'https://maven.aliyun.com/repository/google' } +// maven{ url 'https://maven.aliyun.com/repository/jcenter'} + maven { + url 'http://download.flutter.io' + } + maven { url'http://developer.huawei.com/repo/'} + + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" + configurations.all { + resolutionStrategy { + resolutionStrategy.eachDependency { details -> + if (details.requested.group == 'androidx.core') { + details.useVersion "1.0.1" + } + if (details.requested.group == 'androidx.lifecycle') { + details.useVersion "2.0.0-rc01" + } + if (details.requested.group == 'androidx.legacy') { + details.useVersion "1.0.0-rc01" + } + if (details.requested.group == 'androidx.versionedparcelable') { + details.useVersion "1.0.0" + } + + if (details.requested.group == 'com.google.android.gms') { + details.useVersion "17.0.0" + } + + + if (details.requested.group == 'androidx.fragment') { + details.useVersion "1.0.0" + } + if (details.requested.group == 'androidx.appcompat') { + details.useVersion "1.0.1" + } + + if (details.requested.group == 'androidx.annotation') { + details.useVersion "1.1.0" + } + + + } + } + } +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} + + +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} \ No newline at end of file diff --git a/android/cyhdSign b/android/cyhdSign new file mode 100644 index 0000000..a92141f Binary files /dev/null and b/android/cyhdSign differ diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..7dee586 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,5 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true + +android.enableR8=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..0ff455f --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Nov 18 15:39:25 CST 2019 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..4f14f8e --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/android/settings_aar.gradle b/android/settings_aar.gradle new file mode 100644 index 0000000..3d1d8e6 --- /dev/null +++ b/android/settings_aar.gradle @@ -0,0 +1,2 @@ +include ':app' + diff --git a/assets/fonts/iconfont.ttf b/assets/fonts/iconfont.ttf new file mode 100644 index 0000000..24f3210 Binary files /dev/null and b/assets/fonts/iconfont.ttf differ diff --git a/assets/fonts/uiIconfont.ttf b/assets/fonts/uiIconfont.ttf new file mode 100644 index 0000000..2d6294c Binary files /dev/null and b/assets/fonts/uiIconfont.ttf differ diff --git a/assets/images/2.0x/chat_icon_1.png b/assets/images/2.0x/chat_icon_1.png new file mode 100644 index 0000000..a64b9d0 Binary files /dev/null and b/assets/images/2.0x/chat_icon_1.png differ diff --git a/assets/images/2.0x/chat_icon_2.png b/assets/images/2.0x/chat_icon_2.png new file mode 100644 index 0000000..55b7721 Binary files /dev/null and b/assets/images/2.0x/chat_icon_2.png differ diff --git a/assets/images/2.0x/chat_icon_3.png b/assets/images/2.0x/chat_icon_3.png new file mode 100644 index 0000000..5ed91be Binary files /dev/null and b/assets/images/2.0x/chat_icon_3.png differ diff --git a/assets/images/2.0x/chat_icon_4.png b/assets/images/2.0x/chat_icon_4.png new file mode 100644 index 0000000..4a9c42c Binary files /dev/null and b/assets/images/2.0x/chat_icon_4.png differ diff --git a/assets/images/2.0x/chat_icon_5.png b/assets/images/2.0x/chat_icon_5.png new file mode 100644 index 0000000..f007525 Binary files /dev/null and b/assets/images/2.0x/chat_icon_5.png differ diff --git a/assets/images/2.0x/coin.png b/assets/images/2.0x/coin.png new file mode 100644 index 0000000..d5dc305 Binary files /dev/null and b/assets/images/2.0x/coin.png differ diff --git a/assets/images/2.0x/service_icon.png b/assets/images/2.0x/service_icon.png new file mode 100644 index 0000000..5daf7da Binary files /dev/null and b/assets/images/2.0x/service_icon.png differ diff --git a/assets/images/3.0x/chat_icon_1.png b/assets/images/3.0x/chat_icon_1.png new file mode 100644 index 0000000..b6b4573 Binary files /dev/null and b/assets/images/3.0x/chat_icon_1.png differ diff --git a/assets/images/3.0x/chat_icon_2.png b/assets/images/3.0x/chat_icon_2.png new file mode 100644 index 0000000..7ac65c6 Binary files /dev/null and b/assets/images/3.0x/chat_icon_2.png differ diff --git a/assets/images/3.0x/chat_icon_3.png b/assets/images/3.0x/chat_icon_3.png new file mode 100644 index 0000000..afe1d6b Binary files /dev/null and b/assets/images/3.0x/chat_icon_3.png differ diff --git a/assets/images/3.0x/chat_icon_4.png b/assets/images/3.0x/chat_icon_4.png new file mode 100644 index 0000000..8ec7dc9 Binary files /dev/null and b/assets/images/3.0x/chat_icon_4.png differ diff --git a/assets/images/3.0x/chat_icon_5.png b/assets/images/3.0x/chat_icon_5.png new file mode 100644 index 0000000..8eea895 Binary files /dev/null and b/assets/images/3.0x/chat_icon_5.png differ diff --git a/assets/images/VIP.png b/assets/images/VIP.png new file mode 100644 index 0000000..1b7a4f2 Binary files /dev/null and b/assets/images/VIP.png differ diff --git a/assets/images/back.png b/assets/images/back.png new file mode 100644 index 0000000..cfb7393 Binary files /dev/null and b/assets/images/back.png differ diff --git a/assets/images/bg.png b/assets/images/bg.png new file mode 100644 index 0000000..6474e84 Binary files /dev/null and b/assets/images/bg.png differ diff --git a/assets/images/bofang.png b/assets/images/bofang.png new file mode 100644 index 0000000..42664e2 Binary files /dev/null and b/assets/images/bofang.png differ diff --git a/assets/images/chat/emoji.png b/assets/images/chat/emoji.png new file mode 100644 index 0000000..a5ef162 Binary files /dev/null and b/assets/images/chat/emoji.png differ diff --git a/assets/images/chat/icon1.png b/assets/images/chat/icon1.png new file mode 100644 index 0000000..06e33d4 Binary files /dev/null and b/assets/images/chat/icon1.png differ diff --git a/assets/images/chat/icon2.png b/assets/images/chat/icon2.png new file mode 100644 index 0000000..6e50548 Binary files /dev/null and b/assets/images/chat/icon2.png differ diff --git a/assets/images/chat/icon3.png b/assets/images/chat/icon3.png new file mode 100644 index 0000000..8976496 Binary files /dev/null and b/assets/images/chat/icon3.png differ diff --git a/assets/images/chat/icon4.png b/assets/images/chat/icon4.png new file mode 100644 index 0000000..4cfbe7c Binary files /dev/null and b/assets/images/chat/icon4.png differ diff --git a/assets/images/chat/icon5.png b/assets/images/chat/icon5.png new file mode 100644 index 0000000..d8c479e Binary files /dev/null and b/assets/images/chat/icon5.png differ diff --git a/assets/images/chat/icon6.png b/assets/images/chat/icon6.png new file mode 100644 index 0000000..460bb36 Binary files /dev/null and b/assets/images/chat/icon6.png differ diff --git a/assets/images/chat/onion.png b/assets/images/chat/onion.png new file mode 100644 index 0000000..beddf33 Binary files /dev/null and b/assets/images/chat/onion.png differ diff --git a/assets/images/chat_item_1.png b/assets/images/chat_item_1.png new file mode 100644 index 0000000..a101aec Binary files /dev/null and b/assets/images/chat_item_1.png differ diff --git a/assets/images/chat_item_2.png b/assets/images/chat_item_2.png new file mode 100644 index 0000000..da2a759 Binary files /dev/null and b/assets/images/chat_item_2.png differ diff --git a/assets/images/chat_item_3.png b/assets/images/chat_item_3.png new file mode 100644 index 0000000..e89ecba Binary files /dev/null and b/assets/images/chat_item_3.png differ diff --git a/assets/images/chat_item_4.png b/assets/images/chat_item_4.png new file mode 100644 index 0000000..489021c Binary files /dev/null and b/assets/images/chat_item_4.png differ diff --git a/assets/images/chat_item_5.png b/assets/images/chat_item_5.png new file mode 100644 index 0000000..4e73d27 Binary files /dev/null and b/assets/images/chat_item_5.png differ diff --git a/assets/images/chat_item_6.png b/assets/images/chat_item_6.png new file mode 100644 index 0000000..449b045 Binary files /dev/null and b/assets/images/chat_item_6.png differ diff --git a/assets/images/chat_item_7.png b/assets/images/chat_item_7.png new file mode 100644 index 0000000..030213f Binary files /dev/null and b/assets/images/chat_item_7.png differ diff --git a/assets/images/coin.png b/assets/images/coin.png new file mode 100644 index 0000000..1e0bbe5 Binary files /dev/null and b/assets/images/coin.png differ diff --git a/assets/images/daily_bg_1.png b/assets/images/daily_bg_1.png new file mode 100644 index 0000000..5063a92 Binary files /dev/null and b/assets/images/daily_bg_1.png differ diff --git a/assets/images/daily_bg_2.png b/assets/images/daily_bg_2.png new file mode 100644 index 0000000..0003342 Binary files /dev/null and b/assets/images/daily_bg_2.png differ diff --git a/assets/images/daily_btn_1.png b/assets/images/daily_btn_1.png new file mode 100644 index 0000000..7a1a9fb Binary files /dev/null and b/assets/images/daily_btn_1.png differ diff --git a/assets/images/daily_btn_2.png b/assets/images/daily_btn_2.png new file mode 100644 index 0000000..7c3d607 Binary files /dev/null and b/assets/images/daily_btn_2.png differ diff --git a/assets/images/daily_coin.png b/assets/images/daily_coin.png new file mode 100644 index 0000000..5b2c04d Binary files /dev/null and b/assets/images/daily_coin.png differ diff --git a/assets/images/daily_icon.png b/assets/images/daily_icon.png new file mode 100644 index 0000000..a4c08f9 Binary files /dev/null and b/assets/images/daily_icon.png differ diff --git a/assets/images/default_nor_avatar.png b/assets/images/default_nor_avatar.png new file mode 100644 index 0000000..4351ba5 Binary files /dev/null and b/assets/images/default_nor_avatar.png differ diff --git a/assets/images/emojiface/1.png b/assets/images/emojiface/1.png new file mode 100644 index 0000000..aab1f8b Binary files /dev/null and b/assets/images/emojiface/1.png differ diff --git a/assets/images/emojiface/10.png b/assets/images/emojiface/10.png new file mode 100644 index 0000000..5b3b641 Binary files /dev/null and b/assets/images/emojiface/10.png differ diff --git a/assets/images/emojiface/11.png b/assets/images/emojiface/11.png new file mode 100644 index 0000000..21f6d38 Binary files /dev/null and b/assets/images/emojiface/11.png differ diff --git a/assets/images/emojiface/12.png b/assets/images/emojiface/12.png new file mode 100644 index 0000000..2007bf7 Binary files /dev/null and b/assets/images/emojiface/12.png differ diff --git a/assets/images/emojiface/13.png b/assets/images/emojiface/13.png new file mode 100644 index 0000000..7866e5c Binary files /dev/null and b/assets/images/emojiface/13.png differ diff --git a/assets/images/emojiface/14.png b/assets/images/emojiface/14.png new file mode 100644 index 0000000..451d2a8 Binary files /dev/null and b/assets/images/emojiface/14.png differ diff --git a/assets/images/emojiface/15.png b/assets/images/emojiface/15.png new file mode 100644 index 0000000..2f5cdb8 Binary files /dev/null and b/assets/images/emojiface/15.png differ diff --git a/assets/images/emojiface/16.png b/assets/images/emojiface/16.png new file mode 100644 index 0000000..52a5ff0 Binary files /dev/null and b/assets/images/emojiface/16.png differ diff --git a/assets/images/emojiface/17.png b/assets/images/emojiface/17.png new file mode 100644 index 0000000..38a51ca Binary files /dev/null and b/assets/images/emojiface/17.png differ diff --git a/assets/images/emojiface/18.png b/assets/images/emojiface/18.png new file mode 100644 index 0000000..dea5802 Binary files /dev/null and b/assets/images/emojiface/18.png differ diff --git a/assets/images/emojiface/19.png b/assets/images/emojiface/19.png new file mode 100644 index 0000000..2ff354c Binary files /dev/null and b/assets/images/emojiface/19.png differ diff --git a/assets/images/emojiface/2.png b/assets/images/emojiface/2.png new file mode 100644 index 0000000..a2ad3c4 Binary files /dev/null and b/assets/images/emojiface/2.png differ diff --git a/assets/images/emojiface/20.png b/assets/images/emojiface/20.png new file mode 100644 index 0000000..a90ab15 Binary files /dev/null and b/assets/images/emojiface/20.png differ diff --git a/assets/images/emojiface/21.png b/assets/images/emojiface/21.png new file mode 100644 index 0000000..e1e81c7 Binary files /dev/null and b/assets/images/emojiface/21.png differ diff --git a/assets/images/emojiface/22.png b/assets/images/emojiface/22.png new file mode 100644 index 0000000..9639302 Binary files /dev/null and b/assets/images/emojiface/22.png differ diff --git a/assets/images/emojiface/23.png b/assets/images/emojiface/23.png new file mode 100644 index 0000000..976edc1 Binary files /dev/null and b/assets/images/emojiface/23.png differ diff --git a/assets/images/emojiface/24.png b/assets/images/emojiface/24.png new file mode 100644 index 0000000..68f107c Binary files /dev/null and b/assets/images/emojiface/24.png differ diff --git a/assets/images/emojiface/25.png b/assets/images/emojiface/25.png new file mode 100644 index 0000000..c21c56d Binary files /dev/null and b/assets/images/emojiface/25.png differ diff --git a/assets/images/emojiface/26.png b/assets/images/emojiface/26.png new file mode 100644 index 0000000..31e5217 Binary files /dev/null and b/assets/images/emojiface/26.png differ diff --git a/assets/images/emojiface/27.png b/assets/images/emojiface/27.png new file mode 100644 index 0000000..8ac3263 Binary files /dev/null and b/assets/images/emojiface/27.png differ diff --git a/assets/images/emojiface/28.png b/assets/images/emojiface/28.png new file mode 100644 index 0000000..9fcc8c4 Binary files /dev/null and b/assets/images/emojiface/28.png differ diff --git a/assets/images/emojiface/29.png b/assets/images/emojiface/29.png new file mode 100644 index 0000000..f94800e Binary files /dev/null and b/assets/images/emojiface/29.png differ diff --git a/assets/images/emojiface/3.png b/assets/images/emojiface/3.png new file mode 100644 index 0000000..c1920d7 Binary files /dev/null and b/assets/images/emojiface/3.png differ diff --git a/assets/images/emojiface/30.png b/assets/images/emojiface/30.png new file mode 100644 index 0000000..863561d Binary files /dev/null and b/assets/images/emojiface/30.png differ diff --git a/assets/images/emojiface/31.png b/assets/images/emojiface/31.png new file mode 100644 index 0000000..7b2300b Binary files /dev/null and b/assets/images/emojiface/31.png differ diff --git a/assets/images/emojiface/32.png b/assets/images/emojiface/32.png new file mode 100644 index 0000000..c5bc183 Binary files /dev/null and b/assets/images/emojiface/32.png differ diff --git a/assets/images/emojiface/33.png b/assets/images/emojiface/33.png new file mode 100644 index 0000000..7df05d6 Binary files /dev/null and b/assets/images/emojiface/33.png differ diff --git a/assets/images/emojiface/34.png b/assets/images/emojiface/34.png new file mode 100644 index 0000000..fdc7af8 Binary files /dev/null and b/assets/images/emojiface/34.png differ diff --git a/assets/images/emojiface/35.png b/assets/images/emojiface/35.png new file mode 100644 index 0000000..6620e93 Binary files /dev/null and b/assets/images/emojiface/35.png differ diff --git a/assets/images/emojiface/36.png b/assets/images/emojiface/36.png new file mode 100644 index 0000000..694248d Binary files /dev/null and b/assets/images/emojiface/36.png differ diff --git a/assets/images/emojiface/37.png b/assets/images/emojiface/37.png new file mode 100644 index 0000000..7e68fc7 Binary files /dev/null and b/assets/images/emojiface/37.png differ diff --git a/assets/images/emojiface/38.png b/assets/images/emojiface/38.png new file mode 100644 index 0000000..06c1510 Binary files /dev/null and b/assets/images/emojiface/38.png differ diff --git a/assets/images/emojiface/39.png b/assets/images/emojiface/39.png new file mode 100644 index 0000000..593da05 Binary files /dev/null and b/assets/images/emojiface/39.png differ diff --git a/assets/images/emojiface/4.png b/assets/images/emojiface/4.png new file mode 100644 index 0000000..428d2e4 Binary files /dev/null and b/assets/images/emojiface/4.png differ diff --git a/assets/images/emojiface/40.png b/assets/images/emojiface/40.png new file mode 100644 index 0000000..dcd2b59 Binary files /dev/null and b/assets/images/emojiface/40.png differ diff --git a/assets/images/emojiface/41.png b/assets/images/emojiface/41.png new file mode 100644 index 0000000..eb2d907 Binary files /dev/null and b/assets/images/emojiface/41.png differ diff --git a/assets/images/emojiface/42.png b/assets/images/emojiface/42.png new file mode 100644 index 0000000..2edd744 Binary files /dev/null and b/assets/images/emojiface/42.png differ diff --git a/assets/images/emojiface/43.png b/assets/images/emojiface/43.png new file mode 100644 index 0000000..ef3cf0e Binary files /dev/null and b/assets/images/emojiface/43.png differ diff --git a/assets/images/emojiface/44.png b/assets/images/emojiface/44.png new file mode 100644 index 0000000..f2c2903 Binary files /dev/null and b/assets/images/emojiface/44.png differ diff --git a/assets/images/emojiface/45.png b/assets/images/emojiface/45.png new file mode 100644 index 0000000..2094034 Binary files /dev/null and b/assets/images/emojiface/45.png differ diff --git a/assets/images/emojiface/46.png b/assets/images/emojiface/46.png new file mode 100644 index 0000000..b0522c7 Binary files /dev/null and b/assets/images/emojiface/46.png differ diff --git a/assets/images/emojiface/47.png b/assets/images/emojiface/47.png new file mode 100644 index 0000000..86a1f91 Binary files /dev/null and b/assets/images/emojiface/47.png differ diff --git a/assets/images/emojiface/48.png b/assets/images/emojiface/48.png new file mode 100644 index 0000000..094aa75 Binary files /dev/null and b/assets/images/emojiface/48.png differ diff --git a/assets/images/emojiface/49.png b/assets/images/emojiface/49.png new file mode 100644 index 0000000..0b3441d Binary files /dev/null and b/assets/images/emojiface/49.png differ diff --git a/assets/images/emojiface/5.png b/assets/images/emojiface/5.png new file mode 100644 index 0000000..28c0f28 Binary files /dev/null and b/assets/images/emojiface/5.png differ diff --git a/assets/images/emojiface/50.png b/assets/images/emojiface/50.png new file mode 100644 index 0000000..429c076 Binary files /dev/null and b/assets/images/emojiface/50.png differ diff --git a/assets/images/emojiface/51.png b/assets/images/emojiface/51.png new file mode 100644 index 0000000..61c1459 Binary files /dev/null and b/assets/images/emojiface/51.png differ diff --git a/assets/images/emojiface/52.png b/assets/images/emojiface/52.png new file mode 100644 index 0000000..6796ea8 Binary files /dev/null and b/assets/images/emojiface/52.png differ diff --git a/assets/images/emojiface/53.png b/assets/images/emojiface/53.png new file mode 100644 index 0000000..119dd2c Binary files /dev/null and b/assets/images/emojiface/53.png differ diff --git a/assets/images/emojiface/54.png b/assets/images/emojiface/54.png new file mode 100644 index 0000000..31837d5 Binary files /dev/null and b/assets/images/emojiface/54.png differ diff --git a/assets/images/emojiface/55.png b/assets/images/emojiface/55.png new file mode 100644 index 0000000..dc70d3f Binary files /dev/null and b/assets/images/emojiface/55.png differ diff --git a/assets/images/emojiface/56.png b/assets/images/emojiface/56.png new file mode 100644 index 0000000..edc5516 Binary files /dev/null and b/assets/images/emojiface/56.png differ diff --git a/assets/images/emojiface/57.png b/assets/images/emojiface/57.png new file mode 100644 index 0000000..8c6dcfb Binary files /dev/null and b/assets/images/emojiface/57.png differ diff --git a/assets/images/emojiface/58.png b/assets/images/emojiface/58.png new file mode 100644 index 0000000..2915d13 Binary files /dev/null and b/assets/images/emojiface/58.png differ diff --git a/assets/images/emojiface/59.png b/assets/images/emojiface/59.png new file mode 100644 index 0000000..af542e0 Binary files /dev/null and b/assets/images/emojiface/59.png differ diff --git a/assets/images/emojiface/6.png b/assets/images/emojiface/6.png new file mode 100644 index 0000000..deb60c2 Binary files /dev/null and b/assets/images/emojiface/6.png differ diff --git a/assets/images/emojiface/60.png b/assets/images/emojiface/60.png new file mode 100644 index 0000000..7859b57 Binary files /dev/null and b/assets/images/emojiface/60.png differ diff --git a/assets/images/emojiface/61.png b/assets/images/emojiface/61.png new file mode 100644 index 0000000..ee3038b Binary files /dev/null and b/assets/images/emojiface/61.png differ diff --git a/assets/images/emojiface/62.png b/assets/images/emojiface/62.png new file mode 100644 index 0000000..8ce677c Binary files /dev/null and b/assets/images/emojiface/62.png differ diff --git a/assets/images/emojiface/63.png b/assets/images/emojiface/63.png new file mode 100644 index 0000000..e942f5a Binary files /dev/null and b/assets/images/emojiface/63.png differ diff --git a/assets/images/emojiface/64.png b/assets/images/emojiface/64.png new file mode 100644 index 0000000..3541814 Binary files /dev/null and b/assets/images/emojiface/64.png differ diff --git a/assets/images/emojiface/65.png b/assets/images/emojiface/65.png new file mode 100644 index 0000000..43d3697 Binary files /dev/null and b/assets/images/emojiface/65.png differ diff --git a/assets/images/emojiface/66.png b/assets/images/emojiface/66.png new file mode 100644 index 0000000..5202154 Binary files /dev/null and b/assets/images/emojiface/66.png differ diff --git a/assets/images/emojiface/67.png b/assets/images/emojiface/67.png new file mode 100644 index 0000000..4af079f Binary files /dev/null and b/assets/images/emojiface/67.png differ diff --git a/assets/images/emojiface/68.png b/assets/images/emojiface/68.png new file mode 100644 index 0000000..efb4b08 Binary files /dev/null and b/assets/images/emojiface/68.png differ diff --git a/assets/images/emojiface/69.png b/assets/images/emojiface/69.png new file mode 100644 index 0000000..904516f Binary files /dev/null and b/assets/images/emojiface/69.png differ diff --git a/assets/images/emojiface/7.png b/assets/images/emojiface/7.png new file mode 100644 index 0000000..dee9ed4 Binary files /dev/null and b/assets/images/emojiface/7.png differ diff --git a/assets/images/emojiface/70.png b/assets/images/emojiface/70.png new file mode 100644 index 0000000..19c1bd4 Binary files /dev/null and b/assets/images/emojiface/70.png differ diff --git a/assets/images/emojiface/71.png b/assets/images/emojiface/71.png new file mode 100644 index 0000000..d01c654 Binary files /dev/null and b/assets/images/emojiface/71.png differ diff --git a/assets/images/emojiface/72.png b/assets/images/emojiface/72.png new file mode 100644 index 0000000..e734839 Binary files /dev/null and b/assets/images/emojiface/72.png differ diff --git a/assets/images/emojiface/73.png b/assets/images/emojiface/73.png new file mode 100644 index 0000000..0708a32 Binary files /dev/null and b/assets/images/emojiface/73.png differ diff --git a/assets/images/emojiface/74.png b/assets/images/emojiface/74.png new file mode 100644 index 0000000..081534e Binary files /dev/null and b/assets/images/emojiface/74.png differ diff --git a/assets/images/emojiface/75.png b/assets/images/emojiface/75.png new file mode 100644 index 0000000..7cd38e1 Binary files /dev/null and b/assets/images/emojiface/75.png differ diff --git a/assets/images/emojiface/76.png b/assets/images/emojiface/76.png new file mode 100644 index 0000000..dd84965 Binary files /dev/null and b/assets/images/emojiface/76.png differ diff --git a/assets/images/emojiface/77.png b/assets/images/emojiface/77.png new file mode 100644 index 0000000..a87686f Binary files /dev/null and b/assets/images/emojiface/77.png differ diff --git a/assets/images/emojiface/78.png b/assets/images/emojiface/78.png new file mode 100644 index 0000000..6ba8a3e Binary files /dev/null and b/assets/images/emojiface/78.png differ diff --git a/assets/images/emojiface/79.png b/assets/images/emojiface/79.png new file mode 100644 index 0000000..ef1a886 Binary files /dev/null and b/assets/images/emojiface/79.png differ diff --git a/assets/images/emojiface/8.png b/assets/images/emojiface/8.png new file mode 100644 index 0000000..5c18640 Binary files /dev/null and b/assets/images/emojiface/8.png differ diff --git a/assets/images/emojiface/80.png b/assets/images/emojiface/80.png new file mode 100644 index 0000000..6041c84 Binary files /dev/null and b/assets/images/emojiface/80.png differ diff --git a/assets/images/emojiface/81.png b/assets/images/emojiface/81.png new file mode 100644 index 0000000..394ee50 Binary files /dev/null and b/assets/images/emojiface/81.png differ diff --git a/assets/images/emojiface/82.png b/assets/images/emojiface/82.png new file mode 100644 index 0000000..f48744d Binary files /dev/null and b/assets/images/emojiface/82.png differ diff --git a/assets/images/emojiface/83.png b/assets/images/emojiface/83.png new file mode 100644 index 0000000..6397907 Binary files /dev/null and b/assets/images/emojiface/83.png differ diff --git a/assets/images/emojiface/84.png b/assets/images/emojiface/84.png new file mode 100644 index 0000000..9579911 Binary files /dev/null and b/assets/images/emojiface/84.png differ diff --git a/assets/images/emojiface/85.png b/assets/images/emojiface/85.png new file mode 100644 index 0000000..c5988d9 Binary files /dev/null and b/assets/images/emojiface/85.png differ diff --git a/assets/images/emojiface/86.png b/assets/images/emojiface/86.png new file mode 100644 index 0000000..27138c0 Binary files /dev/null and b/assets/images/emojiface/86.png differ diff --git a/assets/images/emojiface/87.png b/assets/images/emojiface/87.png new file mode 100644 index 0000000..db6ba6e Binary files /dev/null and b/assets/images/emojiface/87.png differ diff --git a/assets/images/emojiface/88.png b/assets/images/emojiface/88.png new file mode 100644 index 0000000..576fe5c Binary files /dev/null and b/assets/images/emojiface/88.png differ diff --git a/assets/images/emojiface/89.png b/assets/images/emojiface/89.png new file mode 100644 index 0000000..dcc2f78 Binary files /dev/null and b/assets/images/emojiface/89.png differ diff --git a/assets/images/emojiface/9.png b/assets/images/emojiface/9.png new file mode 100644 index 0000000..0bedc08 Binary files /dev/null and b/assets/images/emojiface/9.png differ diff --git a/assets/images/emojiface/90.png b/assets/images/emojiface/90.png new file mode 100644 index 0000000..ffd4b2a Binary files /dev/null and b/assets/images/emojiface/90.png differ diff --git a/assets/images/ext_apk.png b/assets/images/ext_apk.png new file mode 100644 index 0000000..6db026c Binary files /dev/null and b/assets/images/ext_apk.png differ diff --git a/assets/images/ext_excel.png b/assets/images/ext_excel.png new file mode 100644 index 0000000..0369045 Binary files /dev/null and b/assets/images/ext_excel.png differ diff --git a/assets/images/ext_pdf.png b/assets/images/ext_pdf.png new file mode 100644 index 0000000..af67b13 Binary files /dev/null and b/assets/images/ext_pdf.png differ diff --git a/assets/images/ext_ppt.png b/assets/images/ext_ppt.png new file mode 100644 index 0000000..34d9cb1 Binary files /dev/null and b/assets/images/ext_ppt.png differ diff --git a/assets/images/ext_sound.png b/assets/images/ext_sound.png new file mode 100644 index 0000000..11c54c6 Binary files /dev/null and b/assets/images/ext_sound.png differ diff --git a/assets/images/ext_txt.png b/assets/images/ext_txt.png new file mode 100644 index 0000000..73925d5 Binary files /dev/null and b/assets/images/ext_txt.png differ diff --git a/assets/images/ext_unknown.png b/assets/images/ext_unknown.png new file mode 100644 index 0000000..cb5ab1a Binary files /dev/null and b/assets/images/ext_unknown.png differ diff --git a/assets/images/ext_video.png b/assets/images/ext_video.png new file mode 100644 index 0000000..f1df55f Binary files /dev/null and b/assets/images/ext_video.png differ diff --git a/assets/images/ext_word.png b/assets/images/ext_word.png new file mode 100644 index 0000000..a769b14 Binary files /dev/null and b/assets/images/ext_word.png differ diff --git a/assets/images/ext_zip.png b/assets/images/ext_zip.png new file mode 100644 index 0000000..ce453c0 Binary files /dev/null and b/assets/images/ext_zip.png differ diff --git a/assets/images/gift_1.png b/assets/images/gift_1.png new file mode 100644 index 0000000..2897873 Binary files /dev/null and b/assets/images/gift_1.png differ diff --git a/assets/images/gift_2.png b/assets/images/gift_2.png new file mode 100644 index 0000000..18387cd Binary files /dev/null and b/assets/images/gift_2.png differ diff --git a/assets/images/gift_3.png b/assets/images/gift_3.png new file mode 100644 index 0000000..1fa28ef Binary files /dev/null and b/assets/images/gift_3.png differ diff --git a/assets/images/gift_anim_1.gif b/assets/images/gift_anim_1.gif new file mode 100644 index 0000000..95a75ff Binary files /dev/null and b/assets/images/gift_anim_1.gif differ diff --git a/assets/images/gift_anim_2.gif b/assets/images/gift_anim_2.gif new file mode 100644 index 0000000..a40abb8 Binary files /dev/null and b/assets/images/gift_anim_2.gif differ diff --git a/assets/images/gift_anim_3.gif b/assets/images/gift_anim_3.gif new file mode 100644 index 0000000..d8a72ef Binary files /dev/null and b/assets/images/gift_anim_3.gif differ diff --git a/assets/images/gift_show_2_1.png b/assets/images/gift_show_2_1.png new file mode 100644 index 0000000..70b0f73 Binary files /dev/null and b/assets/images/gift_show_2_1.png differ diff --git a/assets/images/gift_show_2_2.png b/assets/images/gift_show_2_2.png new file mode 100644 index 0000000..123cf28 Binary files /dev/null and b/assets/images/gift_show_2_2.png differ diff --git a/assets/images/gift_show_2_3.png b/assets/images/gift_show_2_3.png new file mode 100644 index 0000000..bf03da9 Binary files /dev/null and b/assets/images/gift_show_2_3.png differ diff --git a/assets/images/gift_show_2_4.png b/assets/images/gift_show_2_4.png new file mode 100644 index 0000000..f07936e Binary files /dev/null and b/assets/images/gift_show_2_4.png differ diff --git a/assets/images/hand.png b/assets/images/hand.png new file mode 100644 index 0000000..8245646 Binary files /dev/null and b/assets/images/hand.png differ diff --git a/assets/images/ic_album.png b/assets/images/ic_album.png new file mode 100644 index 0000000..0f80105 Binary files /dev/null and b/assets/images/ic_album.png differ diff --git a/assets/images/ic_bottle_msg.png b/assets/images/ic_bottle_msg.png new file mode 100644 index 0000000..d8ec09a Binary files /dev/null and b/assets/images/ic_bottle_msg.png differ diff --git a/assets/images/ic_cards_wallet.png b/assets/images/ic_cards_wallet.png new file mode 100644 index 0000000..751b3ab Binary files /dev/null and b/assets/images/ic_cards_wallet.png differ diff --git a/assets/images/ic_collections.png b/assets/images/ic_collections.png new file mode 100644 index 0000000..9227706 Binary files /dev/null and b/assets/images/ic_collections.png differ diff --git a/assets/images/ic_emotions.png b/assets/images/ic_emotions.png new file mode 100644 index 0000000..516f12b Binary files /dev/null and b/assets/images/ic_emotions.png differ diff --git a/assets/images/ic_feeds.png b/assets/images/ic_feeds.png new file mode 100644 index 0000000..feddb20 Binary files /dev/null and b/assets/images/ic_feeds.png differ diff --git a/assets/images/ic_fengchao.png b/assets/images/ic_fengchao.png new file mode 100644 index 0000000..2431a2c Binary files /dev/null and b/assets/images/ic_fengchao.png differ diff --git a/assets/images/ic_file_transfer.png b/assets/images/ic_file_transfer.png new file mode 100644 index 0000000..43175d0 Binary files /dev/null and b/assets/images/ic_file_transfer.png differ diff --git a/assets/images/ic_game_entry.png b/assets/images/ic_game_entry.png new file mode 100644 index 0000000..f44f8a5 Binary files /dev/null and b/assets/images/ic_game_entry.png differ diff --git a/assets/images/ic_group_chat.png b/assets/images/ic_group_chat.png new file mode 100644 index 0000000..14c8df1 Binary files /dev/null and b/assets/images/ic_group_chat.png differ diff --git a/assets/images/ic_mini_program.png b/assets/images/ic_mini_program.png new file mode 100644 index 0000000..fa197b4 Binary files /dev/null and b/assets/images/ic_mini_program.png differ diff --git a/assets/images/ic_new_friend.png b/assets/images/ic_new_friend.png new file mode 100644 index 0000000..1e80d8d Binary files /dev/null and b/assets/images/ic_new_friend.png differ diff --git a/assets/images/ic_people_nearby.png b/assets/images/ic_people_nearby.png new file mode 100644 index 0000000..a15e66e Binary files /dev/null and b/assets/images/ic_people_nearby.png differ diff --git a/assets/images/ic_public_account.png b/assets/images/ic_public_account.png new file mode 100644 index 0000000..c8aec2a Binary files /dev/null and b/assets/images/ic_public_account.png differ diff --git a/assets/images/ic_qrcode_preview_tiny.png b/assets/images/ic_qrcode_preview_tiny.png new file mode 100644 index 0000000..de0667e Binary files /dev/null and b/assets/images/ic_qrcode_preview_tiny.png differ diff --git a/assets/images/ic_quick_scan.png b/assets/images/ic_quick_scan.png new file mode 100644 index 0000000..60be1a9 Binary files /dev/null and b/assets/images/ic_quick_scan.png differ diff --git a/assets/images/ic_quick_search.png b/assets/images/ic_quick_search.png new file mode 100644 index 0000000..76ce3db Binary files /dev/null and b/assets/images/ic_quick_search.png differ diff --git a/assets/images/ic_settings.png b/assets/images/ic_settings.png new file mode 100644 index 0000000..14c7886 Binary files /dev/null and b/assets/images/ic_settings.png differ diff --git a/assets/images/ic_shake_phone.png b/assets/images/ic_shake_phone.png new file mode 100644 index 0000000..039b5dc Binary files /dev/null and b/assets/images/ic_shake_phone.png differ diff --git a/assets/images/ic_shopping.png b/assets/images/ic_shopping.png new file mode 100644 index 0000000..68598c3 Binary files /dev/null and b/assets/images/ic_shopping.png differ diff --git a/assets/images/ic_social_circle.png b/assets/images/ic_social_circle.png new file mode 100644 index 0000000..97cc4d5 Binary files /dev/null and b/assets/images/ic_social_circle.png differ diff --git a/assets/images/ic_tag.png b/assets/images/ic_tag.png new file mode 100644 index 0000000..1feca1c Binary files /dev/null and b/assets/images/ic_tag.png differ diff --git a/assets/images/ic_tx_news.png b/assets/images/ic_tx_news.png new file mode 100644 index 0000000..0a345df Binary files /dev/null and b/assets/images/ic_tx_news.png differ diff --git a/assets/images/ic_wallet.png b/assets/images/ic_wallet.png new file mode 100644 index 0000000..5340357 Binary files /dev/null and b/assets/images/ic_wallet.png differ diff --git a/assets/images/ic_wx_games.png b/assets/images/ic_wx_games.png new file mode 100644 index 0000000..d7075cb Binary files /dev/null and b/assets/images/ic_wx_games.png differ diff --git a/assets/images/img_fyj.png b/assets/images/img_fyj.png new file mode 100644 index 0000000..0a124c7 Binary files /dev/null and b/assets/images/img_fyj.png differ diff --git a/assets/images/img_long_index.png b/assets/images/img_long_index.png new file mode 100644 index 0000000..64a5105 Binary files /dev/null and b/assets/images/img_long_index.png differ diff --git a/assets/images/img_splash_1.png b/assets/images/img_splash_1.png new file mode 100644 index 0000000..ecd49f2 Binary files /dev/null and b/assets/images/img_splash_1.png differ diff --git a/assets/images/img_splash_2.png b/assets/images/img_splash_2.png new file mode 100644 index 0000000..598067a Binary files /dev/null and b/assets/images/img_splash_2.png differ diff --git a/assets/images/img_splash_3.png b/assets/images/img_splash_3.png new file mode 100644 index 0000000..266bf59 Binary files /dev/null and b/assets/images/img_splash_3.png differ diff --git a/assets/images/img_temp_hy.png b/assets/images/img_temp_hy.png new file mode 100644 index 0000000..f01406d Binary files /dev/null and b/assets/images/img_temp_hy.png differ diff --git a/assets/images/img_temp_qb.png b/assets/images/img_temp_qb.png new file mode 100644 index 0000000..091d451 Binary files /dev/null and b/assets/images/img_temp_qb.png differ diff --git a/assets/images/img_temp_qd.png b/assets/images/img_temp_qd.png new file mode 100644 index 0000000..4118026 Binary files /dev/null and b/assets/images/img_temp_qd.png differ diff --git a/assets/images/img_temp_see.png b/assets/images/img_temp_see.png new file mode 100644 index 0000000..1db2fcf Binary files /dev/null and b/assets/images/img_temp_see.png differ diff --git a/assets/images/img_temp_share.png b/assets/images/img_temp_share.png new file mode 100644 index 0000000..cbf6a16 Binary files /dev/null and b/assets/images/img_temp_share.png differ diff --git a/assets/images/img_update_bg.png b/assets/images/img_update_bg.png new file mode 100644 index 0000000..7987d47 Binary files /dev/null and b/assets/images/img_update_bg.png differ diff --git a/assets/images/left_gray.png b/assets/images/left_gray.png new file mode 100644 index 0000000..cc1627e Binary files /dev/null and b/assets/images/left_gray.png differ diff --git a/assets/images/left_white.png b/assets/images/left_white.png new file mode 100644 index 0000000..d35cece Binary files /dev/null and b/assets/images/left_white.png differ diff --git a/assets/images/login/SY_bg.png b/assets/images/login/SY_bg.png new file mode 100644 index 0000000..f1bde79 Binary files /dev/null and b/assets/images/login/SY_bg.png differ diff --git a/assets/images/login/SY_logo.png b/assets/images/login/SY_logo.png new file mode 100644 index 0000000..df5646e Binary files /dev/null and b/assets/images/login/SY_logo.png differ diff --git a/assets/images/login/delete.png b/assets/images/login/delete.png new file mode 100644 index 0000000..40d72f7 Binary files /dev/null and b/assets/images/login/delete.png differ diff --git a/assets/images/login/dly_icon1.png b/assets/images/login/dly_icon1.png new file mode 100644 index 0000000..47becb2 Binary files /dev/null and b/assets/images/login/dly_icon1.png differ diff --git a/assets/images/login/dly_icon2.png b/assets/images/login/dly_icon2.png new file mode 100644 index 0000000..469e3c8 Binary files /dev/null and b/assets/images/login/dly_icon2.png differ diff --git a/assets/images/login/dly_icon3.png b/assets/images/login/dly_icon3.png new file mode 100644 index 0000000..1c258ef Binary files /dev/null and b/assets/images/login/dly_icon3.png differ diff --git a/assets/images/login/dly_icon4.png b/assets/images/login/dly_icon4.png new file mode 100644 index 0000000..10d7ac1 Binary files /dev/null and b/assets/images/login/dly_icon4.png differ diff --git a/assets/images/login/dly_logo.png b/assets/images/login/dly_logo.png new file mode 100644 index 0000000..cd3abf9 Binary files /dev/null and b/assets/images/login/dly_logo.png differ diff --git a/assets/images/login/lock.png b/assets/images/login/lock.png new file mode 100644 index 0000000..80efcf6 Binary files /dev/null and b/assets/images/login/lock.png differ diff --git a/assets/images/login/money.png b/assets/images/login/money.png new file mode 100644 index 0000000..a83c580 Binary files /dev/null and b/assets/images/login/money.png differ diff --git a/assets/images/login/rzzx.png b/assets/images/login/rzzx.png new file mode 100644 index 0000000..083f888 Binary files /dev/null and b/assets/images/login/rzzx.png differ diff --git a/assets/images/login/vip_logio.png b/assets/images/login/vip_logio.png new file mode 100644 index 0000000..9d55de0 Binary files /dev/null and b/assets/images/login/vip_logio.png differ diff --git a/assets/images/login/vip_other.png b/assets/images/login/vip_other.png new file mode 100644 index 0000000..c7e9f93 Binary files /dev/null and b/assets/images/login/vip_other.png differ diff --git a/assets/images/login/vip_rect1.png b/assets/images/login/vip_rect1.png new file mode 100644 index 0000000..d8212f3 Binary files /dev/null and b/assets/images/login/vip_rect1.png differ diff --git a/assets/images/login/vip_rect2.png b/assets/images/login/vip_rect2.png new file mode 100644 index 0000000..3c8d0da Binary files /dev/null and b/assets/images/login/vip_rect2.png differ diff --git a/assets/images/login/vip_rect3.png b/assets/images/login/vip_rect3.png new file mode 100644 index 0000000..38febd3 Binary files /dev/null and b/assets/images/login/vip_rect3.png differ diff --git a/assets/images/login/vip_wx.png b/assets/images/login/vip_wx.png new file mode 100644 index 0000000..e2b0ef4 Binary files /dev/null and b/assets/images/login/vip_wx.png differ diff --git a/assets/images/login/vip_zfb.png b/assets/images/login/vip_zfb.png new file mode 100644 index 0000000..1fa1830 Binary files /dev/null and b/assets/images/login/vip_zfb.png differ diff --git a/assets/images/login/xzxb_female.png b/assets/images/login/xzxb_female.png new file mode 100644 index 0000000..4e55c34 Binary files /dev/null and b/assets/images/login/xzxb_female.png differ diff --git a/assets/images/login/xzxb_male.png b/assets/images/login/xzxb_male.png new file mode 100644 index 0000000..407c145 Binary files /dev/null and b/assets/images/login/xzxb_male.png differ diff --git a/assets/images/net_error.png b/assets/images/net_error.png new file mode 100644 index 0000000..5023596 Binary files /dev/null and b/assets/images/net_error.png differ diff --git a/assets/images/park/qz_icon1.png b/assets/images/park/qz_icon1.png new file mode 100644 index 0000000..d19f3df Binary files /dev/null and b/assets/images/park/qz_icon1.png differ diff --git a/assets/images/park/qz_icon2.png b/assets/images/park/qz_icon2.png new file mode 100644 index 0000000..6b78f0b Binary files /dev/null and b/assets/images/park/qz_icon2.png differ diff --git a/assets/images/park/qz_icon3.png b/assets/images/park/qz_icon3.png new file mode 100644 index 0000000..8802029 Binary files /dev/null and b/assets/images/park/qz_icon3.png differ diff --git a/assets/images/park/qz_icon4.png b/assets/images/park/qz_icon4.png new file mode 100644 index 0000000..b1d59a8 Binary files /dev/null and b/assets/images/park/qz_icon4.png differ diff --git a/assets/images/park/qz_icon5.png b/assets/images/park/qz_icon5.png new file mode 100644 index 0000000..a70f31d Binary files /dev/null and b/assets/images/park/qz_icon5.png differ diff --git a/assets/images/park/qz_icon6.png b/assets/images/park/qz_icon6.png new file mode 100644 index 0000000..38dbc11 Binary files /dev/null and b/assets/images/park/qz_icon6.png differ diff --git a/assets/images/park/qz_icon7.png b/assets/images/park/qz_icon7.png new file mode 100644 index 0000000..407e3a9 Binary files /dev/null and b/assets/images/park/qz_icon7.png differ diff --git a/assets/images/park/qz_icon8.png b/assets/images/park/qz_icon8.png new file mode 100644 index 0000000..869b139 Binary files /dev/null and b/assets/images/park/qz_icon8.png differ diff --git a/assets/images/qianbao_bg.png b/assets/images/qianbao_bg.png new file mode 100644 index 0000000..f297828 Binary files /dev/null and b/assets/images/qianbao_bg.png differ diff --git a/assets/images/red_packet_bg.png b/assets/images/red_packet_bg.png new file mode 100644 index 0000000..34a5695 Binary files /dev/null and b/assets/images/red_packet_bg.png differ diff --git a/assets/images/right_gray.png b/assets/images/right_gray.png new file mode 100644 index 0000000..b8333bc Binary files /dev/null and b/assets/images/right_gray.png differ diff --git a/assets/images/right_white.png b/assets/images/right_white.png new file mode 100644 index 0000000..9836cc9 Binary files /dev/null and b/assets/images/right_white.png differ diff --git a/assets/images/robot.jpg b/assets/images/robot.jpg new file mode 100644 index 0000000..56a3647 Binary files /dev/null and b/assets/images/robot.jpg differ diff --git a/assets/images/server_icon.png b/assets/images/server_icon.png new file mode 100644 index 0000000..0daa649 Binary files /dev/null and b/assets/images/server_icon.png differ diff --git a/assets/images/service_icon.png b/assets/images/service_icon.png new file mode 100644 index 0000000..4b243fd Binary files /dev/null and b/assets/images/service_icon.png differ diff --git a/assets/images/sticker/sticker_1.gif b/assets/images/sticker/sticker_1.gif new file mode 100644 index 0000000..69b5cca Binary files /dev/null and b/assets/images/sticker/sticker_1.gif differ diff --git a/assets/images/sticker/sticker_10.gif b/assets/images/sticker/sticker_10.gif new file mode 100644 index 0000000..d72f6f4 Binary files /dev/null and b/assets/images/sticker/sticker_10.gif differ diff --git a/assets/images/sticker/sticker_11.gif b/assets/images/sticker/sticker_11.gif new file mode 100644 index 0000000..5bec743 Binary files /dev/null and b/assets/images/sticker/sticker_11.gif differ diff --git a/assets/images/sticker/sticker_12.gif b/assets/images/sticker/sticker_12.gif new file mode 100644 index 0000000..ce99228 Binary files /dev/null and b/assets/images/sticker/sticker_12.gif differ diff --git a/assets/images/sticker/sticker_13.gif b/assets/images/sticker/sticker_13.gif new file mode 100644 index 0000000..814bb4a Binary files /dev/null and b/assets/images/sticker/sticker_13.gif differ diff --git a/assets/images/sticker/sticker_14.gif b/assets/images/sticker/sticker_14.gif new file mode 100644 index 0000000..8cddb19 Binary files /dev/null and b/assets/images/sticker/sticker_14.gif differ diff --git a/assets/images/sticker/sticker_15.gif b/assets/images/sticker/sticker_15.gif new file mode 100644 index 0000000..cf9accf Binary files /dev/null and b/assets/images/sticker/sticker_15.gif differ diff --git a/assets/images/sticker/sticker_16.gif b/assets/images/sticker/sticker_16.gif new file mode 100644 index 0000000..1d98dc3 Binary files /dev/null and b/assets/images/sticker/sticker_16.gif differ diff --git a/assets/images/sticker/sticker_17.gif b/assets/images/sticker/sticker_17.gif new file mode 100644 index 0000000..cdf6f9e Binary files /dev/null and b/assets/images/sticker/sticker_17.gif differ diff --git a/assets/images/sticker/sticker_18.gif b/assets/images/sticker/sticker_18.gif new file mode 100644 index 0000000..504f356 Binary files /dev/null and b/assets/images/sticker/sticker_18.gif differ diff --git a/assets/images/sticker/sticker_19.gif b/assets/images/sticker/sticker_19.gif new file mode 100644 index 0000000..fb950a4 Binary files /dev/null and b/assets/images/sticker/sticker_19.gif differ diff --git a/assets/images/sticker/sticker_2.gif b/assets/images/sticker/sticker_2.gif new file mode 100644 index 0000000..8200e4b Binary files /dev/null and b/assets/images/sticker/sticker_2.gif differ diff --git a/assets/images/sticker/sticker_20.gif b/assets/images/sticker/sticker_20.gif new file mode 100644 index 0000000..2d2e175 Binary files /dev/null and b/assets/images/sticker/sticker_20.gif differ diff --git a/assets/images/sticker/sticker_21.gif b/assets/images/sticker/sticker_21.gif new file mode 100644 index 0000000..71ac8d9 Binary files /dev/null and b/assets/images/sticker/sticker_21.gif differ diff --git a/assets/images/sticker/sticker_22.gif b/assets/images/sticker/sticker_22.gif new file mode 100644 index 0000000..2711192 Binary files /dev/null and b/assets/images/sticker/sticker_22.gif differ diff --git a/assets/images/sticker/sticker_23.gif b/assets/images/sticker/sticker_23.gif new file mode 100644 index 0000000..96aceea Binary files /dev/null and b/assets/images/sticker/sticker_23.gif differ diff --git a/assets/images/sticker/sticker_24.gif b/assets/images/sticker/sticker_24.gif new file mode 100644 index 0000000..43174a3 Binary files /dev/null and b/assets/images/sticker/sticker_24.gif differ diff --git a/assets/images/sticker/sticker_25.gif b/assets/images/sticker/sticker_25.gif new file mode 100644 index 0000000..3d1ba72 Binary files /dev/null and b/assets/images/sticker/sticker_25.gif differ diff --git a/assets/images/sticker/sticker_26.gif b/assets/images/sticker/sticker_26.gif new file mode 100644 index 0000000..7eb1837 Binary files /dev/null and b/assets/images/sticker/sticker_26.gif differ diff --git a/assets/images/sticker/sticker_27.gif b/assets/images/sticker/sticker_27.gif new file mode 100644 index 0000000..b08173c Binary files /dev/null and b/assets/images/sticker/sticker_27.gif differ diff --git a/assets/images/sticker/sticker_28.gif b/assets/images/sticker/sticker_28.gif new file mode 100644 index 0000000..51476b8 Binary files /dev/null and b/assets/images/sticker/sticker_28.gif differ diff --git a/assets/images/sticker/sticker_29.gif b/assets/images/sticker/sticker_29.gif new file mode 100644 index 0000000..e5f309e Binary files /dev/null and b/assets/images/sticker/sticker_29.gif differ diff --git a/assets/images/sticker/sticker_3.gif b/assets/images/sticker/sticker_3.gif new file mode 100644 index 0000000..11b9bb2 Binary files /dev/null and b/assets/images/sticker/sticker_3.gif differ diff --git a/assets/images/sticker/sticker_30.gif b/assets/images/sticker/sticker_30.gif new file mode 100644 index 0000000..119a4ef Binary files /dev/null and b/assets/images/sticker/sticker_30.gif differ diff --git a/assets/images/sticker/sticker_4.gif b/assets/images/sticker/sticker_4.gif new file mode 100644 index 0000000..c756cde Binary files /dev/null and b/assets/images/sticker/sticker_4.gif differ diff --git a/assets/images/sticker/sticker_5.gif b/assets/images/sticker/sticker_5.gif new file mode 100644 index 0000000..c9bdcbf Binary files /dev/null and b/assets/images/sticker/sticker_5.gif differ diff --git a/assets/images/sticker/sticker_6.gif b/assets/images/sticker/sticker_6.gif new file mode 100644 index 0000000..3fd56ce Binary files /dev/null and b/assets/images/sticker/sticker_6.gif differ diff --git a/assets/images/sticker/sticker_7.gif b/assets/images/sticker/sticker_7.gif new file mode 100644 index 0000000..2f9ca6d Binary files /dev/null and b/assets/images/sticker/sticker_7.gif differ diff --git a/assets/images/sticker/sticker_8.gif b/assets/images/sticker/sticker_8.gif new file mode 100644 index 0000000..099eca0 Binary files /dev/null and b/assets/images/sticker/sticker_8.gif differ diff --git a/assets/images/sticker/sticker_9.gif b/assets/images/sticker/sticker_9.gif new file mode 100644 index 0000000..60bb089 Binary files /dev/null and b/assets/images/sticker/sticker_9.gif differ diff --git a/assets/images/suo.png b/assets/images/suo.png new file mode 100644 index 0000000..f751b02 Binary files /dev/null and b/assets/images/suo.png differ diff --git a/assets/images/svip.png b/assets/images/svip.png new file mode 100644 index 0000000..f36454e Binary files /dev/null and b/assets/images/svip.png differ diff --git a/assets/images/vip/hy_bg.png b/assets/images/vip/hy_bg.png new file mode 100644 index 0000000..38efa46 Binary files /dev/null and b/assets/images/vip/hy_bg.png differ diff --git a/assets/images/vip/hy_cjhy.png b/assets/images/vip/hy_cjhy.png new file mode 100644 index 0000000..89a91f9 Binary files /dev/null and b/assets/images/vip/hy_cjhy.png differ diff --git a/assets/images/vip/hy_hy.png b/assets/images/vip/hy_hy.png new file mode 100644 index 0000000..c57a25e Binary files /dev/null and b/assets/images/vip/hy_hy.png differ diff --git a/assets/images/vip/hy_tj.png b/assets/images/vip/hy_tj.png new file mode 100644 index 0000000..5676fa5 Binary files /dev/null and b/assets/images/vip/hy_tj.png differ diff --git a/assets/images/vip/hy_tq.png b/assets/images/vip/hy_tq.png new file mode 100644 index 0000000..390ef79 Binary files /dev/null and b/assets/images/vip/hy_tq.png differ diff --git a/assets/images/vip/hy_xz.png b/assets/images/vip/hy_xz.png new file mode 100644 index 0000000..192d497 Binary files /dev/null and b/assets/images/vip/hy_xz.png differ diff --git a/assets/images/voucher.png b/assets/images/voucher.png new file mode 100644 index 0000000..13e8c5d Binary files /dev/null and b/assets/images/voucher.png differ diff --git a/assets/images/yqm_bg.png b/assets/images/yqm_bg.png new file mode 100644 index 0000000..d8a2ff1 Binary files /dev/null and b/assets/images/yqm_bg.png differ diff --git a/assets/images/zhiwen.png b/assets/images/zhiwen.png new file mode 100644 index 0000000..f5c88d0 Binary files /dev/null and b/assets/images/zhiwen.png differ diff --git a/i18n/en-US.json b/i18n/en-US.json new file mode 100644 index 0000000..8916cb1 --- /dev/null +++ b/i18n/en-US.json @@ -0,0 +1,1164 @@ +{ + "appName": "Hibok park", + "login": "Login", + "registration": "Registration", + "other_login": "Other login", + "account": "Account number", + "enter_username": "Please enter Username", + "password": "Password", + "enter_password": "Enter password", + "forget_password": "Forget password", + "reset_password": "Reset Password", + "number_registration": "Mobile number registration", + "enter_number": "Please enter phone number", + "code": "Code", + "enter_code": "Please enter the code", + "send_code": "Send the code", + "send_again": "Send again", + "set_password": "Set password", + "password_limit": "Password least six", + "set_password2": "Set Password", + "next_step": "Next step", + "agreed_agreement": "Click to enter means you have read and agreed <>", + "enter_password2": "Please enter your password", + "reset_now": "Reset now", + "choose_gender": "Choose gender", + "who": "You are...", + "determine": "Determine", + "cannot_modified": "Cannot be modified after selecting gender", + "tip": "Tip", + "choose_quit": "You are about to complete registration, are you quit now?", + "confirm": "Confirm", + "use": "Use", + "cancel": "Cancel", + "close": "Close", + "delete": "Delete", + "forget_it": "Forget it", + "ok": "OK", + "choose_quit2": "After registration, you will not be able to modify your gender. Are you sure?", + "tip_content": "Tip: You can't communicate with users of the same gender", + "welcome": "Welcome", + "enter_incode": "Please enter the invitation code", + "must_incode": "Hibok only serves men with invitation codes", + "your_incode": "Your invitation code", + "how_get": "No invitation code? You can get it in the following ways", + "method1": "Method 1", + "free": "Free application", + "apply_now": "Apply now", + "check_incode": "Check code", + "so_get": "You need to fill in some personal information, and send you an invitation code after the review is passed.", + "apply_incode": "Apply for an invitation code", + "location": "Location", + "cityname": "The name of your city", + "message_channel": "Message channel", + "how_know": "Where do you know the APP?", + "wechat_number": "Wechat", + "your_wechat": "Your we chat", + "facebook": "Facebook", + "your_facebook": "Your Facebook", + "submit_application": "Submit application", + "enter_city": "Please enter your city", + "so_know": "Please tell us about your access to the app.", + "your_social": "Please tell us your social account", + "receive_incode": "We will process your application as soon as possible. If you pass the review, you will receive the invitation code we issued in the message center.", + "wait_incode": "The invitation code has not been issued yet, please be patient after applying!", + "successful_application1": "Application successful!", + "application_failed1": "Application failed!", + "successful_copy": "Successful copy", + "method2": "Method 2", + "joinvip": "Join member", + "join_now": "Join now", + "joined": "Joined", + "join_odds": "Joining members can enjoy various privileges, including registration without an invitation code", + "not_joinvip": "You have not joined the membership yet.", + "join_after": "After joining the membership, you can complete the registration without the invitation code.", + "incode_passed": "Invitation code verification passed", + "welcome_join": "Welcome! Do not reveal your account to others. Once you find that the login is abnormal, the account will be automatically frozen.", + "member_centre": "Member Centre", + "members_privilege": "Member's privilege", + "see_more": "Right 1", + "unlimited_see": "View users unlimited times a day", + "see_cheaper": "Right 2", + "free10": "/s1 free times per day to pay photo or social accounts", + "see_longer": "Right 3", + "towto6": "View time increased from 2s to /s1s.", + "see_better": "Right 4", + "free_release": "Free release of dating broadcasts", + "choose_price": "Choose a package", + "pay_method": "Payment method", + "pay_amount": "Payment amount", + "not_enough": "Insufficient wallet balance", + "confirm_pay": "Confirm payment", + "complete_material": "Complete material", + "basic_information": "Basic information", + "upload_avatar": "Upload avatar", + "choose": "Please choose", + "fill_out": "Please fill out", + "choose_multiple": "Can choose multiple", + "optional": "Optional", + "least": "Fill in at least /s1", + "introduce_yourself": "Introduce yourself", + "most": "Select up to /s1", + "nickname": "nickname", + "only1_8": "Nickname can only be 1-20 characters", + "Resident_city": "Current City", + "Please_select_a_resident_city": "Please select the current city", + "City1": "Can Tho", + "City2": "Da Nang", + "City3": "Hai phong", + "City4": "Hanoi", + "City5": "Ho Chi Minh", + "City6": "An Giang", + "City7": "Bac Giang", + "City8": "Bac Can", + "City9": "Bo Liao", + "City10": "Bac Ninh", + "City11": "Ba Ria-Vung Tau", + "City12": "Ben Tre", + "City13": "Binh Dinh", + "City14": "Binh Duong", + "City15": "Binh Phuoc", + "City16": "Binh Thuan", + "City17": "Ca Mau", + "City18": "Cao Bang", + "City19": "Dele", + "City20": "Dac Nong", + "City21": "Dien Bien", + "City22": "Dong Nai", + "City23": "Dong Thap", + "City24": "Gia Lai", + "City25": "Ha Giang", + "City26": "Hai Duong", + "City27": "Ha Nam", + "City28": "Ha Tinh", + "City29": "Hoa Binh", + "City30": "Hau Giang", + "City31": "Hung Yen", + "City32": "Khanh Hoa", + "City33": "Kien Giang", + "City34": "Kon Tum", + "City35": "Lai Chau", + "City36": "Lam Dong", + "City37": "Lang Son", + "City38": "Lao Cai", + "City39": "Long An", + "City40": "Nghe An", + "City41": "Ninh Binh", + "City42": "Ninh Thuan", + "City43": "Phu Tho", + "City44": "Phu Yen", + "City45": "Quang Binh", + "City46": "Quang Nam", + "City47": "Quang Ngai", + "City48": "Quang Ninh", + "City49": "Quang Tri", + "City50": "Soc Trang", + "City51": "Son La", + "City52": "Tay Ninh", + "City53": "Thai Binh", + "City54": "Thai Nguyen", + "City55": "Thanh Hoa", + "City56": "Thua Thien-Hue", + "City57": "Tien Giang", + "City58": "Tra Vinh", + "City59": "Tuyen Quang", + "City60": "Vinh Long", + "City61": "Vinh Phuc", + "City62": "Yen Bai", + "City63": "Nam Dinh", + "birthday": "Birthday", + "choose_birthday": "Please choose birthday", + "year": "Year", + "month": "Month", + "day": "Day", + "hour": "Hour", + "minute": "Minute", + "second": "Second", + "just": "Just", + "minute_ago": "/s1 minute ago", + "hour_ago": "/s1 hour ago", + "day_ago": "/s1 day ago", + "week_ago": "/s1 week ago", + "month_ago": "/s1 month ago", + "morning": "Morning", + "noon": "Noon", + "afternoon": "Afternoon", + "night": "Night", + "all_day": "All day", + "yesterday": "Yesterday", + "two_yesterday": "The day before yesterday", + "overnight": "Overnight", + "one": "One", + "ten": "Ten", + "hundred": "Hundred", + "thousand": "Thousand", + "ten_thousand": "Ten thousand", + "aries": "Aries", + "taurus": "Taurus", + "gemini": "Gemini", + "cancer": "Cancer", + "leo": "Leo", + "virgo": "Virgo", + "libra": "Libra", + "scorpio": "Scorpio", + "sagittarius": "Sagittarius", + "capricorn": "Capricorn", + "aquarius": "Aquarius", + "pisces": "Pisces", + "monday": "Monday", + "tuesday": "Tuesday", + "wednesday": "Wednesday", + "thursday": "Thursday", + "friday": "Friday", + "saturday": "Saturday", + "sunday": "Sunday", + "job": "Job", + "choose_career": "Please choose a career", + "career1": "Information Technology", + "career2": "Internet", + "career3": "IT", + "career4": "Telecommunications operation", + "career5": "Online game", + "career6": "Financial insurance", + "career7": "Investment", + "career8": "Equity fund", + "career9": "Insurance", + "career10": "Bank", + "career11": "Trust guarantee", + "career12": "Business service", + "career13": "Advisory", + "career14": "Self-employed", + "career15": "Beauty salons", + "career16": "Tourism", + "career17": "Hotel catering", + "career18": "Leisure and entertainment", + "career19": "Trading", + "career20": "Driver", + "career21": "Estate", + "career22": "Property management", + "career23": "Decoration worker", + "career24": "Detective", + "career25": "Engineering manufacturing", + "career26": "Builder", + "career27": "Civil Engineering", + "career28": "Machine made", + "career29": "Electronic", + "career30": "Biomedical Science", + "career31": "Food", + "career32": "Clothing", + "career33": "Energy", + "career34": "Transportation", + "career35": "Aviation", + "career36": "Railway", + "career37": "Shipping ship", + "career38": "Public transit", + "career39": "Logistics transportation", + "career40": "Culture Media", + "career41": "Media publishing", + "career42": "Design", + "career43": "Cultural communication", + "career44": "Advertising creativity", + "career45": "Anime", + "career46": "Public relations exhibition", + "career47": "Photography", + "career48": "Entertainment sports", + "career49": "Movie", + "career50": "Sports sports", + "career51": "Music", + "career52": "Model", + "career53": "Public utilities", + "career54": "Medical", + "career55": "Legal", + "career56": "Education", + "career57": "Government agency", + "career58": "Public welfare", + "career59": "Student", + "career60": "No", + "program": "Program", + "select_program": "Please select a nationality", + "healthy_exercise": "Exercise", + "night_party": "Party", + "gourmet_party": "Food", + "watch_movie": "Movie", + "play_games": "Games", + "travel_together": "Travel", + "voice_chat": "Voice chat", + "other": "Other", + "expect_lover": "Expect lover", + "choose_lover": "Please choose the expect lover", + "beautiful": "Beautiful", + "rich": "Rich", + "care_me": "Care for me", + "look_feeling": "Look feeling", + "doesnt_matter": "Does not matter", + "least_account": "Please fill in at least one social networking account", + "hide_account1": "Hide social account", + "more_information": "More information", + "height": "Height", + "weight": "Weight", + "not_show": "Hidden", + "self_introduction": "Introduction", + "registration_success1": "Registration success", + "exit": "Exit?", + "exit_registration": "Your personal information is not yet perfect, if you quit now, next time you enter, sign directly with a registered account", + "cant_see": "Men can't see other men's details", + "cant_see2": "Ms. cannot see other ladies details", + "see_one": "You can still see /s1 lady today.", + "only_see": "Non-members can only view 15 women per day", + "continue_see": "Continue to see", + "user_frozen": "User has frozen", + "search_user": "Please enter a nickname / occupation to search", + "nearby": "Nearby", + "member": "Member", + "new_registration": "New", + "authenticate": "Certified", + "first_online": "Online", + "not_positioned": "Positioning is off, distance cannot be calculated", + "unknown": "Unknown", + "secrecy": "Secrecy", + "collection": "Collection", + "cancel_collection": "Cancel collection", + "canceled_collection": "Canceled collection", + "like": "Like", + "added_like": "Added like", + "canceled_like": "Canceled like", + "blacklist": "Blacklist", + "blacklist_choose": "You will no longer see each other and each other's dynamic, Are you sure", + "blacklisted": "Blacklisted", + "reject_message": "Add the other party to the blacklist and reject the message", + "remove_blacklist": "Remove blacklist", + "blacklist_removed": "Blacklist removed", + "receive_message": "Move the other party out of the blacklist", + "online": "Online", + "paid_photo": "Paid photo album", + "application_view": "Apply", + "passed": "Passed", + "park": "Park", + "radio": "Radio", + "news": "News", + "me": "Me", + "more_operations": "More operations", + "anonymous_report": "Anonymous report", + "certified_video": "Video", + "passed_video": "She has passed the video certification authenticity", + "not_video": "She has not yet verified identity authenticity", + "her_appointment": "She is starting a date.", + "pay_join": "He joined through paid", + "passed_review": "He passed the identity security review", + "invited_user": "He joined from user /s1's invitation code", + "his_appointment": "He is starting a date.", + "her_dynamics": "Her dynamics", + "his_dynamics": "His dynamics", + "low_key": "She is very low-key", + "low_key2": "He is very low-key", + "her_photo": "Her photo album", + "his_photo": "His photo album", + "set_lock": "He set up the album lock", + "set_lock2": "She set up the album lock", + "free_unlock": "Unlock album (/s1), members free", + "unlock_user": "Unlock /s1 album", + "pay_unlock": "Paid unlock (/s1 H coin)", + "become_member": "Free for members", + "consumption_once": "Whether to use 1 chance to unlock the album of /s1", + "remaining_once": "(You still have /s1 chance today)", + "no_times": "You have run out of free opportunities today, would you like to give /s1 to unlock all the information for /s2?", + "pay": "Pay", + "view_user": "He set a limit, see the information need to request his consent", + "view_user2": "She set a limit, see the information need to request her consent", + "need_photo": "You need to send your photo to the other party. Rest assured, your photo will be destroyed 2 seconds after the other party presses the screen to view it.", + "choose_photo": "Choose a photo", + "send_application": "The application has been sent, and you will receive a message reminder after the other party confirms", + "not_authenticate": "You have not certified yet", + "after_authenticate": "Only after authenticating your authenticity can you interact with others", + "authenticate_now": "Authenticate now", + "destroy_after": "Destroy after viewing", + "destroyed": "Destroyed", + "red_photo1": "Red packet photo", + "ask_me": "Please ask me for a private chat.", + "filled_in": "Filled in, click to view", + "unlock_information": "Unlock all the information", + "unlock_choose": "Use 1 free unlock", + "your_evaluation": "Your true evaluation", + "her_evaluation": "Her true evaluation", + "his_evaluation": "His true evaluation", + "evaluate": "Evaluate", + "friendly": "Friendly", + "interesting": "Interesting", + "readily": "Readily", + "patient": "Patient", + "indifferent": "Indifferent", + "bad_temper": "Bad temper", + "courtesy": "Courtesy", + "generous": "Generous", + "lie": "Lie", + "unfriendly": "Unfriendly", + "anonymous_evaluation": "Anonymous evaluation", + "cant_evaluate": "You haven't dated her yet, can't evaluate", + "cant_evaluate2": "He hasn't dated you yet, can't evaluate", + "bad_evaluate": "Please provide relevant screenshots so that we can follow up to verify", + "submit": "Submit", + "evaluation_success": "Evaluation success", + "private_chat": "Private chat", + "close_reminder": "Close message reminder", + "closed_reminder": "Close message reminder success", + "open_reminder": "Open message reminder", + "opened_reminder": "Open message reminder success", + "her_account": "Her social account", + "his_account": "His social account", + "copy": "Copy", + "send_account": "Send my social account to her", + "enter_account": "Enter your social account", + "for_example": "For example: We chat abc", + "sent_she": "Sent to her", + "chat": "Voice chat", + "cantt_voice": "The other party turned off the voice chat function", + "authentication_voice": "Active voice after authenticating your authenticity", + "requesting_voice": "Requesting voice chat", + "waitting_answer": "Waiting to answer", + "answer": "Answer", + "hang_up": "Hang up", + "chatting": "Chatting", + "handsfree": "Handsfree", + "giving_gift": "Giving a gift", + "give_success": "Give a gift success", + "others_gift": "The other party has given a gift", + "given_gift": "You have given a gift worth /s1 H coin", + "earned_gift": "You have earned /s1 H coin", + "available_balance": "Available balance /s1", + "recharge": "Recharge", + "give": "Give", + "balance_insufficien": "Sorry, your balance is not enough.", + "first_recharge": "Please recharge the gift before giving it", + "give_coin": "This chat gives /s1 H coin", + "get_coin": "This chat gets /s1 H coin", + "give_get": "This chat gives /s1 H coin and gets /s2 H coin", + "chat_over": "Chat is over, duration /s1", + "message_center": "Message center", + "can_chat": "You can start a private chat on the person's user details page.", + "text_chat": "Text chat", + "system_information": "System information", + "system_notification": "System notification", + "report_failure": "The situation of the user /s1 you reported is not true. Please provide more valid evidence. Thank you!", + "report_success": "The fact that you reported the user /s1 is true and the system has processed the user.", + "successful_application": "Invitation code application is successful! Invitation code [/s1] (click to copy)", + "successful_application2": "The invitation code is applied successfully, thank you for introducing friends! Invitation code [/s1] (click to copy)", + "application_failed": "Invitation code application failed! Unfortunately, your application failed to pass the review. Please fill in the real information to effectively improve the approval rate.", + "important_notice": "【Important Notice】:", + "authentication_failed": "Your certification information does not meet the requirements, please modify and resubmit.", + "request1": "1. Please take the certification video according to the certification requirements.", + "request2": "2. Please upload a clear facial photo of the facial features", + "successful_authentication": "Congratulations, your certification application has been approved", + "re_upload": "Your newly uploaded photo has not been approved. Please re-upload as required.", + "upload_success": "Congratulations, your newly uploaded photo has been successfully reviewed.", + "caveat": "Your appointment registration has been deleted due to violations. Multiple violations or serious circumstances will limit or even limit your account. Please follow and remember. Thank you for your cooperation.", + "caveat2": "Your comment has been deleted due to violations. Multiple violations or serious circumstances will restrict or even limit your account. Please follow and remember. Thank you for your cooperation.", + "radio_message": "Radio message", + "no_message": "There is no such message for the time being.", + "dating_news": "/s1 posted a treaty message in /s2, click to view", + "go_see": "Go and see", + "thumbs_up": "/s1 liked your updates", + "thumbs_up2": "/s1 liked your date show", + "comment1": "/s1 commented on your activity", + "comment2": "/s1 commented on your dating show", + "replied_comment": "/s1 replied to your comment", + "signed_up": "/s1 has signed up for your date show", + "favorite_user": "Your favorite user /s1 posted a treaty, click to view", + "favorite_user2": "Your favorite user /s1 posted a dynamic, click to view", + "wallet_reminder": "Wallet reminder", + "paid_you": "/s1 paid (/s2 H coin) to view your red packet photo", + "paid_you2": "/s1 paid (/s2 H coin) to view your album", + "paid_you3": "/s1 paid to unlock all your information", + "view_application": "View application", + "view_application2": "/s1Request to view your details page", + "aging": "Allowed (valid for 15 days)", + "refuse": "Refuse", + "passed_request": "Passed request", + "l15_days": "/s1 has been approved by your review and is valid for 15 days.", + "evaluation_notice": "Evaluation Notifications", + "rate_her": "Please rate her", + "received_evaluation": "A woman who has contacted you has evaluated you: /s1", + "received_evaluation2": "A man who has contacted you has evaluated you: /s1", + "application_appeal": "If the evaluation is not true, you can apply for the above and we will verify it.", + "appeal": "I want to appeal", + "appealed": "Already appealed", + "waiting_results": "We will check the situation as soon as possible and tell you the result by email.", + "successful_appeal": "Your appeal is evaluated: /s1 appeal is successful and we will withdraw this review for you.", + "social_account": "Social account", + "get_account": "/s1 sent you his social account", + "edit_information": "Edit information", + "save": "Save", + "passed_verification1": "You passed the identity security verification", + "by_code": "You join through the invitation code of the veteran user /s1", + "by_paying": "You join by paying", + "passed_verification": "You have authenticated identity authenticity through video", + "not_certified": "You have not verified identity authenticity", + "verificating": "We are certifying your authenticity", + "real_girl": "Certified girls are more popular", + "certificating": "In certification", + "re_upload2": "Please re-upload the video", + "update_certification": "Update certification", + "enjoy_privileges": "Join members to enjoy privileges", + "expires": "/s1 expires", + "wallet": "Wallet", + "setting": "Privacy", + "my_dynamic": "My dynamic", + "my_album": "My album", + "first_photo": "Upload my first photo", + "no_photo": "Have photos to attract more men", + "upload_photos": "Upload photos", + "upload_video": "Upload video", + "upload": "Upload photos", + "set_photo": "Set red packet photo", + "photo_order": "Long press to drag the photo", + "my_evaluation": "My evaluation", + "my_show": "My show", + "i_like": "I like", + "your_favorite": "Your favorite lady will show here", + "your_favorite2": "The guy you like will show here", + "no_data": "No data", + "historical_visitor": "Historical visitor", + "visit_you": "Have /s1 people seen you", + "visit_photo": "/s1 person has destroyed your photo", + "recovery_photo": "One-click recovery", + "setting2": "Setting", + "apply_code": "Help a friend apply for an invitation code", + "issue_choose": "The application invitation code is free, and we will evaluate whether to issue the invitation code based on your historical spending. In order to maintain the atmosphere of the park, please send the invitation code to a reliable friend.", + "successfully_submit": "Successfully submit an application", + "share_app": "Share the app to a friend", + "need_help": "Help", + "need_help2": "Contact Customer Service", + "need_help3": "In order to improve service efficiency, if there is your problem below, please reply directly to the serial number!", + "question1": "[1] What is the reason why the account is frozen?", + "answer1": "In any of the following cases, the account will be frozen: 1 liar 2 intermediary 3 harassment advertisement 4 more people report 5 already have other accounts 6 times issued illegal radio broadcasts ignore warning 7 users themselves request cancellation", + "question2": "[2] When can the cash in the wallet be cashed out?", + "answer2": "All proceeds will go directly to the wallet, withdrawal takes three days (starting with the time of collection), the amount collected after three days will enter the wallet, the amount >=10 yuan can be withdrawn", + "question3": "[3] Why didn't I show the red packet I gave?", + "answer3": "It may be caused by a network cause. Rest assured, in this case the other party can not receive your red packet, the red packet will be automatically refunded after 24 hours.", + "question4": "[4] How long does it take to withdraw cash?", + "answer4": "Expected to arrive within two business days. Tips: Please confirm the account number is correct!", + "question5": "[5] How to report other users/radio broadcasts anonymously?", + "answer5": "Go to the other party's details page or select a radio station broadcast, click on the top right corner and select [Anonymous Report], please fill in the relevant report information to report it.", + "question6": "[6] How to become an authenticated user?", + "answer6": "The certification must meet the following requirements: 1Personal information to fill in a valid social account 2 Album at least upload a clear face photo 3 See the verification code on the certification page, write the nickname + verification code 4 on the paper, hold the paper, Take a video with your face and click Upload Authentication Video", + "question7": "[7] Can the certified video be hidden?", + "answer7": "Can choose whether to display: User Center - click on the authentication video - bottom left 'Show the certified video on my details page'", + "question8": "[8] How to avoid the certification being cancelled?", + "answer8": "The photo album has at least one photo of me.", + "question9": "[9] What is the reason for the dynamic deletion?", + "answer9": "Dynamics cannot publish sensitive maps, sensitive words, including but not limited to implied or explicit words, cannot post personal information (including avatars, nicknames, contact details), violations will be deleted", + "question10": "[10] How to cancel the account?", + "answer10": "If you cancel the account, you will not be able to log in to the app. If you want to use the service later, you will need to re-register. Please consider carefully. If you still decide to cancel your account, please reply to the serial number [12] contact customer service.", + "question11": "[11] What should I do if I forget my password?", + "answer11": "Users who register by mobile phone number or who have a mobile phone number can reset their password by using the \"Forgot Password\" function in the upper right corner of the login page. Unbound users, please bind the phone number first, then set a new login password.", + "question12": "[12] Other questions / transfer customer service", + "answer12": "Hello, what can I do for you? Please describe your problem (Customer service time is 8:00 every day - 02:00 the next day, due to the large number of consultations, you may need to wait for a reply)", + "certification_center": "Certification center", + "for_example2": "Example of certified video capture mode", + "certification_conditions": "Certification conditions", + "conditions1": "1. Good personal image", + "conditions2": "2. Upload at least one photo of yourself in the album", + "verification_method": "Verification method", + "method3": "1. Take a piece of paper and write your nickname and the following verification code:", + "method4": "2. Hold this piece of paper and take a video with your face (3~15 seconds)", + "upload_video2": "Upload certification video", + "after_authentication": "After the authentication is successful, your avatar will have a real logo.", + "show_video": "Display the certified video on my details page", + "uploaded_video": "Uploaded certified video", + "under_review": "During the review (within 24 hours)", + "certification_status": "Certification status", + "certified": "You have been certified", + "wait_resubmitted": "Authentication waiting to be resubmitted", + "reason_failure": "Your certified video does not meet the requirements due to:", + "claim": "Please take the certification video according to the certification requirements.", + "claim2": "Please upload a photo of the face of the facial features in the album.", + "re_upload_video": "Re-upload the certification video", + "update_video": "Update upload certification video", + "mask_coin": "H coin", + "get_way": "You can get H coins by recharging, etc.", + "coin_use": "It can be used to chat and give gifts when chatting.", + "coin_total": "H coin total", + "can_redeemed": "Can be redeemed", + "who_account": "/s1 account", + "bind_account": "Bind /s1 account", + "your_account": "Your /s1 account", + "get_coin2": "You got the /s1 H coin by recharging", + "viewed_your": "/s1viewed your social account", + "give_gift": "/s1 presented a gift: 1 /s2", + "add_coin": "+/s1 H coin", + "give_one": "You give 1 /s1 to /s2", + "less_coin": "-/s1 H coin", + "exchange_cash": "Exchange cash", + "withdrawal_application": "Withdrawal application", + "redeem_choose": "You have /s1 H coins to convert to /s2, and /s3 H coins remaining after redemption. Are you sure to redeem?", + "application_submitted": "Application submitted", + "working_days": "We will handle it within 2 working days. If you have any questions, please contact customer service.", + "cash": "Cash", + "handling_fee": "Whenever you receive a red packet on the chat page, the red packet amount will be here. No one reported that you can redeem cash within 3 days, the system charges 5% fee", + "total_account": "Total account", + "cannot_redeemed": "Insufficient amount, cannot be redeemed", + "successful_redemption": "Successful redemption", + "redeem_choose2": "Your account total is /s1, this time you can redeem /s2, will you redeem it?", + "personal_details": "Personal details", + "public": "Public (recommended)", + "paid_album": "Paid View album", + "must_pay": "Others must pay to view your photo album, the cost is up to you, which may reduce your traffic", + "set_amount1": "Set the view amount", + "first_upload": "Please upload photos before setting up paid albums", + "need_permission": "Can only be viewed by my permission", + "permission_choose": "Must send photos to me, can view my homepage after I allow it", + "hide_me": "Hide me from a list of people nearby", + "hide_distance": "Hide my distance", + "hide_account": "Hide my social account", + "chat_setting": "Chat settings", + "chat_me": "Allow authorized people to initiate a voice chat with me", + "successfully_saved": "Successfully saved", + "on_dynamic": "You have not posted dynamic", + "release_dynamics": "Release dynamics", + "dynamic_details": "Dynamic details", + "release": "Release", + "i_posted": "I posted", + "delete_dynamic": "Delete dynamic", + "delete_choose": "Are you sure you want to delete this dynamic?", + "posted_on": "Posted on /s1", + "thumbs_up3": "Thumbs up", + "already_praised": "Already praised", + "comment": "Comment", + "send": "Send", + "comment_closed": "Comment closed", + "your_comment": "Only publishers can see your comment", + "everyone_comment": "Everyone can see your comment", + "prohibit_comments": "Prohibit comments", + "comments_disabled": "Comments disabled", + "open_comments": "Open Comments", + "already_open": "Already open comment", + "reply": "Reply", + "report": "Report", + "report_choose": "Are you sure you want to report this comment?", + "successful_report": "Successful report, we will deal with it as soon as possible", + "successfully_deleted": "Successfully deleted", + "please_civilization": "People who talk about civilization are more popular. Don't post vulgar, pornographic, or otherwise revealing the privacy of others.", + "same_sex": "Hidden with the same sex user", + "member_free": "Members are free, non-members need /s1 H coin", + "certified_free": "Certified women are free 3 times, then need to pay /s1H coins", + "enter_something": "Please enter text or select image", + "raid_release": "Paid release (/s1 H coin)", + "become_member2": "Free for members", + "now_certification": "Immediate certification, free release", + "successfully_released": "Successfully released", + "no_program": "You haven't posted a program yet.", + "program_details": "Program details", + "program_theme": "Program theme", + "click_select": "Click to select", + "city": "City", + "select_city": "Select City", + "time": "Time", + "select_date": "Select date", + "select_time": "Select time", + "unlimited_time": "Unlimited time", + "supplementary_explanation": "Supplementary explanation", + "image": "Image", + "delete_program": "Delete program", + "delete_choose2": "Are you sure you want to delete this program?", + "please_choose": "Please select a program theme", + "please_choose2": "Please select the desired object", + "please_choose3": "Please select city", + "please_choose4": "Please select a date", + "please_choose5": "Please select time", + "release_program": "Release program", + "sign_up": "Sign up", + "end_registration": "End registration", + "end_choose": "Are you sure you want to end your appointment?", + "contact_her": "Contact her", + "talk_him": "Talk to him privately", + "report_choose2": "Are you sure you want to report this registration information?", + "release_time": "Release time", + "activity_time": "Activity time", + "any_sex": "Any sex", + "look_women": "Look Ms.", + "look_men": "Look Men", + "unlimited_area": "Unlimited area", + "program_deleted": "The program has been deleted", + "cant_comment": "Non-members can't comment", + "sign_up2": "Join", + "need_photo2": "Registration needs to send your photo of the face (only the other party can see)", + "registration_success": "Registration is successful, if the other party feels appropriate, you will be contacted.", + "has_ended": "Has ended", + "men_cant": "Men can't sign up for men's shows", + "ms_cant": "Ms. can't sign up for a lady's show", + "men_cant2": "Men can't comment on men's shows", + "ms_cant2": "Ms. can't comment on the lady's show", + "message_push": "Message push, change password", + "phone_number": "Phone number", + "bind_phone1": "Bind phone number", + "more_safer": "Bind your phone number to make your account safer", + "modify_choose": "Do you want to modify the bound mobile number?", + "change_password": "Change password", + "first_bind": "Users need to bind the mobile phone number before they can set the login password.", + "old_password": "Old password", + "current_password": "Please enter your current login password", + "new_password": "New password", + "set_new": "Please set a new password, at least 6 digits", + "clear_cache": "Clear image cache", + "cleared_successfully": "Cleared successfully", + "user_agreement1": "User agreement", + "sign_out": "Sign out", + "out_choose": "Are you sure you want to log out?", + "push_settings": "Push settings", + "permission_denied": "Permission denied", + "push_setting2": "Message push settings", + "private_chat2": "Private chat message", + "new_date": "Have a new date", + "passed_request2": "A lady passed my request", + "men_view": "Some men apply to view my profile page", + "men_view2": "Some men look at my social account", + "men_view3": "Some men look at my red packet photos", + "men_view4": "Someone who has viewed me sent me a social account", + "applied_successfully": "Invitation code applied successfully", + "after_open": "Will open the corresponding message type when opened", + "if_something": "If you have paid her/he in the last 3 days, we will automatically refund the amount to you after we verify the report.", + "advertise": "Advertise", + "false_photo": "False photo", + "erotic_vulgarity": "Erotic vulgarity", + "harassment": "Harassment", + "she_liar": "She is a liar", + "he_liar": "He is a liar", + "provide_screenshots": "Please provide relevant screenshots so that we can follow up to verify", + "describe_details": "Please describe the details (within 100 words)", + "report_reason": "Please select the reason for reporting", + "report_success2": "Report success", + "successfully_modified": "Successfully modified", + "boy": "Boy", + "girl": "Girl", + "already_applied": "Applied", + "view_registration": "View registration", + "expand": "Expand", + "collapse": "Collapse", + "application_notice": "Application Notifications", + "agrees_application": "Someone agrees with your application", + "red_photo": "Red packet photo", + "dont": "Do not upload illegal nudity photos/videos, or severely", + "current_version": "Current version", + "bank_card": "Binding bank card", + "choose_bank": "Please select an account bank", + "bank_number": "Please enter the bank card number", + "id_number": "Please enter the ID number", + "name": "Name", + "bank_number2": "Bank card number", + "license_number": "License number", + "bind_phone": "Bind phone number", + "his_homepage": "His homepage", + "her_homepage": "Her homepage", + "wechat_pay": "WeChat payment", + "facebook_pay": "Facebook payment", + "google_pay": "Google pay", + "payment_successful": "Payment successful", + "set_amount": "Set withdrawal amount", + "enter_amount": "Please enter the number of H coins", + "can_withdraw": "Can withdraw", + "language_set": "Language settings", + "user_agreement": "User Agreement", + "renewal_fee": "Renewal fee", + "open_immediately": "Open immediately", + "total": "Total", + "half_month": "Half a month", + "month2": "/s1 month", + "cancel_shield": "Cancel shield", + "blacklist2": "Blacklist", + "longTime": "(Members can extend the time by 6 seconds)", + "longClick": "Press and hold the screen to view", + "stop_program": "Please finish the program that is in effect first", + "not_love": "Men can't collect men", + "not_love2": "Women can't collect women", + "women_free": "Women can post for free", + "not_up_man": "He has not uploaded photos yet", + "not_up_women": "She has not uploaded photos yet", + "not_illage": "Do not conduct illegal transactions through the platform. If it is reported, it will be processed as a seal.", + "alreay_join": "Signed", + "sure_delete": "Are you sure you want to delete this photo?", + "white_now": "Fill in now", + "personal": "You haven't filled out a personal introduction yet, and the attractive personal introduction has a great impact on the success of the appointment.", + "success": "Success", + "fail": "Fail", + "moneyPageTip": "Only certified users can set red packet photos", + "alreadyJoin": "You have already signed up and will contact you if they feel it is appropriate.", + "waring": "Violation warning", + "userPravicy": "Respect user privacy, do not take screenshots. If you have another time, you will be prohibited from viewing other user photos.", + "outTime": "Appointment time has expired, please edit", + "reviewing": "under review", + "reviewed": "Successful review", + "reviewedFail": "Audit failure", + "needCard": "Users need to bind the bank card before they can withdraw cash.", + "women_not_d": "Ms. can't comment on the dynamics of women", + "man_not_d": "Men can't comment on men's dynamics", + "have_picture": "Have photos to attract women.", + "up_cancle": "Sliding cancels sending", + "msg_not": "Message cannot be empty", + "need_record": "This feature requires permission to record", + "downloading_video": "Downloading video file", + "reinput": "Please re-enter the question number", + "dy_delete": "Your activity is reported anonymously by the user. After the system verifies that the activity has been deleted, please do not violate the rules.", + "pro_delete": "Your program is reported anonymously by the user. After the system has verified that the program has been deleted, please do not violate the rules.", + "con_delete": "Your comment has been reported anonymously by the user. The system has verified that the comment has been deleted. Please do not violate the rules.", + "coin_returen": "Reported by anonymous users, the system verifies that you have recently violated the rules and has received your recent return of H currency. If there is a next time, the account will be frozen.", + "voicing": "Illegal acts such as pornography and obscenity are prohibited during the call.", + "help": "Customer service", + "translate_on": "Manual translation on", + "translate_off": "Manual translation off", + "becomeSvip": "Consuming /s1 H coins will be renewed for SVIP", + "need_svip": "Svip permission can be turned on", + "cannot_vip": "SVIP cannot be renewed as VIP", + "offline": "You are offline and cannot send and receive messages", + "otherLogin": "The account is logged in on another device, you are offline", + "no_new": "No new news for the time being", + "over": "Translated", + "bad_ev": "Are you sure you want to make a bad review of this translation?", + "right5": "Right 5", + "right6": "Right 6", + "man_vi": "Gentleman", + "women_vi": "Lady", + "kf_tips": "In order to improve service efficiency, if there is your problem below, please reply directly to the serial number!", + "rejected": "Rejected", + "buy_vip": "You have purchased /s1H coins to buy members.", + "buy_program": "You consumed /s1H coins to post a dynamic program.", + "del_add_money": "Your H currency withdrawal request has been processed, transferred /s1 to your account, please check", + "adding_money": "The /s1H currency you applied for withdrawal is under review.", + "free_translate": "Free translation commissioner real-time translation", + "personalTraff": "Exclusive customer service for you", + "ManTranslate": "In human translation...", + "robotTranslate": "In machine translation...", + "translated": "Manual translation completed", + "delete_progarm": "Healthy communication, please do not broadcast vulgar content, once it is found, it will be deleted.", + "open_location": "Targeting permission is not turned on", + "get_location": "Please enable targeting in your phone settings to get additional user distance", + "confirm_exit": "Press again to exit", + "free_program": "Free broadcasts per day /s1 chance", + "picture": "Image", + "camera": "Camera", + "video": "Video", + "red_money": "Red packet", + "stick": "Paste", + "press_say": "Hold and talk", + "get_money": "/s1 received your red packet", + "you_get_money": "You received the red packet of /s1", + "ones_money": "/s1 red packet", + "money_over": "Red packet has expired", + "downloading_fail": "Download file failed", + "downloading": "Downloading video file", + "back_money": "Unclaimed red packet will be refunded after 24 hours", + "no_money": "Red packet does not exist", + "already_money": "Red packet has been received", + "back_user": "Expired, has been refunded to the account", + "waiting_user": "Waiting for the other party", + "other_get": "The other party has received", + "little": "Take the money and spend it.", + "put_money": "Cash into the red packet", + "mount": "Amount", + "over_time": "Expired", + "has_get": "Received", + "no_gift": "No gifts for the time being", + "sent_gift": "Gift", + "fill_tips": "If you fill in successfully, you can get /s1H coins, which cannot be modified after binding.", + "bind_code": "Bind invitation code", + "invide_code": "Invitation code", + "confirm_delete": "Confirm deletion", + "has_eva": "You have already evaluated", + "open": "open", + "voice": "Voice", + "release_send": "Release send", + "time_little": "Recording time is too short", + "not_online": "The other party is not online, can't connect to Mai", + "give_red_money": "You sent a red packet of /s2 H coin to /s1", + "get_red_money": "You received /s1’s red packet of /s2 H coins.", + "give_other_money": "You have won the /s1 /s2H coin", + "get_other_money": "You got a reward for /s2 H coins of /s1.", + "svip": "Super member", + "recommend": "Recommend", + "paid_you4": "You paid (/s2H coins) to view the red packet photo of /s1", + "paid_you5": "You paid for /s2H coins to view /s1's album", + "paid_you6": "You paid to unlock all the information of /s1", + "UG_LINE0": "Hibok license and service agreement", + "UG_LINE1": "[First and Introduction]", + "UG_LINE2": "Qianhai Youlong Technology Co., Ltd. (hereinafter referred to as “Qianhai Youlong Technology Co., Ltd.”) hereby reminds users to carefully read and fully understand this Service Agreement (hereinafter referred to as “Agreement”). Users should carefully read and fully understand this Agreement. The terms, including the exemption or limitation of Qianhai Youlong Technology Co., Ltd.'s liability and the restrictions on the rights of users. Please read carefully and choose to accept or not accept this Agreement (minors should be accompanied by a legal guardian). You are not authorized to register, log in or use the services covered by this Agreement unless you accept all of the terms of this Agreement. Your registration, login, use, etc. will be deemed acceptance of this Agreement and you agree to be bound by the terms of this Agreement.", + "UG_LINE3": "This Agreement is an agreement between you (hereinafter referred to as \"User\" and Qianhai Youlong Technology Co., Ltd. regarding the registration, registration and use of the \"Hibok service\". This Agreement describes the relationship between Qianhai Youlong Technology Co., Ltd. and the User regarding \"Hibok services\". Rights and obligations. “User” means the individual or organization that registers, logs in, uses, and browses the Service. Your acceptance of this Agreement is subject to all terms and conditions, including any modifications made by Qianhai Youlong Technology Co., Ltd. to any Terms of Service at any time. The Agreement may be updated by Qianhai Youlong Technology Co., Ltd. at any time. The updated terms of the agreement will be replaced by the original terms of the agreement without prior notice. Users can check the terms of the latest agreement in this app. After Qianhai Youlong Technology Co., Ltd. amends the terms of the agreement, If the user does not accept the revised terms, please stop using the services provided by Qianhai Youlong Technology Co., Ltd. immediately, and the user's continued use of the services provided by Qianhai Youlong Technology Co., Ltd. will be deemed to have accepted the revised agreement.", + "UG_LINE4": "First, the use of rules", + "UG_LINE5": "1. The user fully understands and agrees that only the platform for information sharing, transmission and acquisition is provided to the user. The user must be responsible for all actions under the registered account, including but not limited to any content you transmit and any resulting results. .", + "UG_LINE6": "2. Qianhai Youlong Technology Co., Ltd. assumes no responsibility for any content transmitted by or through the Services that does not reflect Qianhai Youlong Technology Co., Ltd.'s views or policies.", + "UG_LINE7": "3. The user fully understands and agrees that it is a social information browsing product based on the user relationship network. The user must bear full responsibility for the authenticity, legality and validity of the registered information, and the user must not impersonate others; Any information shall be transmitted in the name; no malicious use of the registered account may cause misidentification by other users; otherwise, Qianhai Youlong Technology Co., Ltd. shall have the right to immediately stop providing the service, recover the account number and assume all legal liabilities arising therefrom.", + "UG_LINE8": "4. The user shall be solely responsible for the authenticity, legality, harmlessness and validity of the information transmitted on the website. Any legal liability related to the information transmitted by the user shall be borne by the user and shall not be related to Qianhai Youlong Technology Co., Ltd.", + "UG_LINE9": "5. Qianhai Youlong Technology Co., Ltd. reserves the right to change, suspend, limit, terminate or revoke the services of any or all of the services of the Service at any time without any notice due to business development needs, and the user shall bear this risk.", + "UG_LINE10": "6. The services provided may include advertisements, and the user agrees to display advertisements provided by third-party suppliers and partners during use.", + "UG_LINE11": "7. Users may not use or service to make, upload, copy or send the following content:", + "UG_LINE12": "(1) against the basic principles established by the Constitution;", + "UG_LINE13": "(2) endangering national security, divulging state secrets, subverting state power, and undermining national unity;", + "UG_LINE14": "(3) damaging national honors and interests;", + "UG_LINE15": "(4) Inciting ethnic hatred, ethnic discrimination, and undermining national unity;", + "UG_LINE16": "(5) Destroying the state's religious policies and promoting cults and feudal superstitions;", + "UG_LINE17": "(6) Spreading rumors, disrupting social order and undermining social stability;", + "UG_LINE18": "(7) spreading obscenity, pornography, gambling, violence, murder, terror or abetment;", + "UG_LINE19": "(8) insulting or slandering others and infringing upon the lawful rights and interests of others;", + "UG_LINE20": "(9) Information containing other content prohibited by laws and administrative regulations.", + "UG_LINE21": "8. Qianhai Youlong Technology Co., Ltd. may, in its reasonable judgment, cease to transmit any of the foregoing in accordance with law, in violation of relevant laws and regulations or the provisions of this Agreement; or infringement, obstruction, threats to the rights or safety of any person, or the act of impersonating another person. And shall have the right, at its sole discretion, to take appropriate legal action against any person who violates these Terms, including but not limited to removing illegal, infringing, improper, etc. from the Service, terminating the violators' membership and preventing them from Use all or part of the service, and keep relevant information and report to relevant departments according to laws and regulations.", + "UG_LINE22": "9. User rights and obligations:", + "UG_LINE23": "(1) The ownership of the Qianhai Youlong Technology Co., Ltd. account is owned by Qianhai Youlong Technology Co., Ltd. After the user completes the application for registration, he or she will obtain the right to use the account. The right to use belongs to the initial applicant and is prohibited from being donated, borrowed, rented, transferred or sold. Qianhai Youlong Technology Co., Ltd. has the right to recycle the user's account due to business needs, and has the right to use the user's photos, videos, voices, etc. for product promotion activities.", + "UG_LINE24": "(2) The user has the right to change or delete the personal data, registration information and transmission content on Qianhai Youlong Technology Co., Ltd. However, please note that deleting the information will also delete any text and images you have stored in the system. The user is responsible for this risk.", + "UG_LINE25": "(3) The user is responsible for the safekeeping of the registered account information and the account password. The user is responsible for the registered account and the behavior under the password. The User agrees not to use the account number or password of another member under any circumstances. You agree to notify Qianhai Youlong Technology Co., Ltd. immediately if you suspect that someone else is using your account or password.", + "UG_LINE26": "(4) The User shall abide by the terms of this Agreement and use the Service correctly and appropriately. If the User violates any of the terms of this Agreement, Qianhai Youlong Technology Co., Ltd. shall have the right to terminate the service of the default user Qianhai Youlong Technology Co., Ltd. account in accordance with the Agreement. At the same time, Qianhai Youlong Technology Co., Ltd. reserves the right to withdraw Qianhai Youlong Technology Co., Ltd. account number and username at any time.", + "UG_LINE27": "(5) If the user has his or her common English account, the user has the right to register the English account as an account first, but if the user does not register the account after the service is online, or the user has registered the WeChat account, but If the English account is not used as the WeChat account, the user is deemed to have waived the right to register the English account as a WeChat account. Qianhai Youlong Technology Co., Ltd. has the right to recycle and distribute the English account to other users, so as to avoid wasting resources. The problem is the user's responsibility.", + "UG_LINE28": "(6) If the user does not log in to the account after registering the account for a long time, Qianhai Youlong Technology Co., Ltd. has the right to recycle the account, so as to avoid wasting resources, and the problems are caused by the user.", + "UG_LINE29": "(7) The user may use the report function to maintain the user platform's rights and interests. If the user receives the report feedback, the reported user is obliged to inform or cooperate with the customer service personnel to verify the situation. The report content is verified. The mask park has the right to warn and restrict the user. The account usage function and other methods restrict the user's violations. The serious violation of the Hibok has the right to directly freeze the account, and the balance in the account is not returned. If the account is frozen and needs to be appealed, the user can contact customer service.", + "UG_LINE30": "Second, privacy protection", + "UG_LINE31": "The user agrees that the personal privacy information refers to those information that can personally identify the user or involve personal communication, including the following information: the user's real name, mobile phone number, WeChat account, facebook account, and IP address. The non-personal private information refers to the general information that the user clearly and objectively reflects the basic record information of the Qianhai Youlong Technology Co., Ltd. server and all other personal privacy information, and the above-mentioned private information that the user agrees to disclose. . Respecting the privacy of the user's personal privacy information is a consistent system of Qianhai Youlong Technology Co., Ltd. Qianhai Youlong Technology Co., Ltd. will take reasonable steps to protect the user's personal privacy information. Qianhai Youlong Technology Co., Ltd., in addition to legal or legal requirements or government consent. The user's personal privacy information will not be disclosed or disclosed to third parties other than the partner unit without the user's consent. However, the user chooses to agree at the time of registration, or the user and Qianhai Youlong Technology Co., Ltd. and the cooperation unit have otherwise agreed on the disclosure or use of the user's personal information, and the user shall bear any risk that may arise, Qianhai Youlong Technology Co., Ltd. does not Responsible. At the same time, in order to operate and improve Qianhai Youlong Technology Co., Ltd.'s technology and services, Qianhai Youlong Technology Co., Ltd. may collect or provide non-personal private information to users of third parties, which will help Qianhai Youlong Technology Co., Ltd. to provide users with a better user experience and improve Quality of service of Qianhai Youlong Technology Co., Ltd. Qianhai Youlong Technology Co., Ltd. collects data based on user interactions with Qianhai Youlong Technology Co., Ltd. and user choices, including user privacy settings and products and features used by users. Data collected by Qianhai Youlong Technology Co., Ltd. may include SDK/API/JS code version, IP address, platform, timestamp, application identifier, application version, application distribution channel, standalone device identifier, iOS advertising identifier (IDFA), Android ad Primary identifier, network card (MAC) address, International Mobile Equipment Identity (IMEI), device model, terminal manufacturer, terminal device operating system version, session start/stop time, language location, time zone, and network status (WiFi, etc.) Hard disk, CPU and battery usage, etc. This will enable Qianhai Youlong Technology Co., Ltd. to conduct internal data analysis and research, third-party SDK statistical services, and improve Qianhai Youlong Technology Co., Ltd.'s products or services. In order to ensure the authenticity of the user's identity, the user is provided with better security protection, and the biometric information (such as personal sensitive information) such as identity information or facial features that the user needs to submit is required to complete the real person authentication required or necessary for the specific product service. The above information will only be used to verify the authenticity of the user's identity. The above information provided by the user will continue to be authorized by Qianhai Youlong Technology Co., Ltd. during the user's use of the Service. Qianhai Youlong Technology Co., Ltd. will stop using it when the user logs out of the account. The above information will be stored in the People's Republic of China. For cross-border transmission, Qianhai Youlong Technology Co., Ltd. will separately obtain the user's authorization. App user authenticity authentication requires the user to provide some information that can verify the authenticity of the user's identity. Relevant information is only used for platform review and will not be disclosed to any other users or for commercial purposes, except for legal or related departments requesting intervention.", + "UG_LINE32": "Third, Qianhai Youlong Technology Co., Ltd. Trademark Information ", + "UG_LINE33": "The logos, characters or their components, and other Qianhai Youlong Technology Co., Ltd. logos and products and service names involved in Qianhai Youlong Technology Co., Ltd.'s services are trademarks of Qianhai Youlong Technology Co., Ltd. (hereinafter referred to as “Qianhai Youlong Technology Co., Ltd. Logo”). The Qianhai Youlong Technology Co., Ltd. logo may not be displayed or used or otherwise disposed of in any way without the prior written consent of Qianhai Youlong Technology Co., Ltd., and may not indicate to others that you have the right to display, use, or otherwise be authorized to deal with the Qianhai Youlong Technology Co., Ltd. logo.", + "UG_LINE34": "Fourth, legal responsibility and exemption", + "UG_LINE35": "1. The user violates the provisions of this Agreement or the relevant terms of service, resulting in or arising from any claims, claims or losses claimed by any third party, including reasonable attorneys' fees, and the user agrees to compensate Qianhai Youlong Technology Co., Ltd. and the partner company, affiliates, And protect it from damage.", + "UG_LINE36": "2. Qianhai Youlong Technology Co., Ltd. and its partners are not responsible for any losses suffered by users due to communication line failures, technical problems, network, computer failures, system instability and other various force majeure causes of third parties such as the telecommunications department.", + "UG_LINE37": "3. Due to technical failures and other irresistible incidents affecting the normal operation of the service, Qianhai Youlong Technology Co., Ltd. and the cooperation unit promised to cooperate with the relevant units in the first time to deal with the repairs in time, but all losses suffered by the users, Qianhai Youlong Technology Co., Ltd. and The partner unit is not responsible.", + "UG_LINE38": "4. This service, like most Internet services, may be affected by various security issues, including but not limited to user reasons, network service quality, social environment and other factors. For example, other users use the user's data to cause real life. Harassment; other software downloaded or installed by users or other websites that are visited contain \"Trojan Horse\" and other viruses, which threaten the security of the user's computer information and data, which in turn affects the normal use of the service. Users should strengthen the information security and user information protection awareness, and pay attention to strengthen password protection to avoid loss and harassment.", + "UG_LINE39": "5. Users must understand that the use of this service may be affected by unstable factors in various links due to Internet services. Therefore, the service has the risk of service interruption or failure to meet user requirements due to force majeure, computer virus or hacker attack, system instability, user location, user shutdown, and any other technology, internet, communication line reasons. The user is responsible for the above risks and Qianhai Youlong Technology Co., Ltd. does not guarantee. Qianhai Youlong Technology Co., Ltd. assumes no responsibility for the fact that the user cannot send and receive reading information or receive incorrect information.", + "UG_LINE40": "6. The user must understand that there are threats, defamatory, offensive or illegal content or acts or violations of the rights of others (including intellectual property rights) from any other person in the course of using the service. The risk of anonymous or impersonal information is subject to the above risks. Qianhai Youlong Technology Co., Ltd. and the partner company do not make any type of guarantee for the service, whether explicit or implied, including all relevant information authenticity, merchantability, suitable for a certain A specific use, title and non-infringement of implied warranties and conditions shall not be liable for any direct, indirect, incidental, special or consequential damages resulting from any improper or unlawful use of the Services by the User.", + "UG_LINE41": "7. The information content defined by Qianhai Youlong Technology Co., Ltd. includes: text, software, sound, photos, videos, graphics; all content in the advertisement; commercial information provided by Qianhai Youlong Technology Co., Ltd. for users, all of which are subject to copyright, trademark, and other intellectual property rights. And the protection of ownership laws. Therefore, users can only use these contents under the authorization of Qianhai Youlong Technology Co., Ltd. and advertisers, and cannot copy, modify, compile, or create derivative products related to the content.", + "UG_LINE42": "8. Under no circumstances shall Qianhai Youlong Technology Co., Ltd. be liable for any indirect, consequential, punitive, incidental, special or penal damages, including loss of profits suffered as a result of the user's use of the Services, even if notified of the The possibility of loss is also the same). Notwithstanding the fact that this Agreement may contain conflicting rules, Qianhai Youlong Technology Co., Ltd.'s entire liability to you, for whatever reason or behavior, shall not exceed the fees paid to Qianhai Youlong Technology Co., Ltd. during your membership due to the use of the Services.", + "UG_LINE43": "Five, membership terms", + "UG_LINE44": "1. Hibok members have equal rights to members and shall abide by Qianhai Youlong Technology Co., Ltd.'s specifications and rules, including but not limited to these Terms of Service and the User Agreement.", + "UG_LINE45": "2. The loss related to the suspension of membership services due to violation of the Qianhai Youlong Technology Co., Ltd. User Agreement shall be borne by the user.", + "UG_LINE46": "3. Members can enjoy the value-added services of Hibok members during the membership period.", + "UG_LINE47": "4. If the member actively terminates or cancels the membership during the validity period of the membership, Qianhai Youlong Technology Co., Ltd. is not responsible for refunding the service fee corresponding to the validity period of the remaining membership of the member.", + "UG_LINE48": "5. Members shall bear the legal responsibility for transmitting, publishing information and using Hibok free services or fee-based services in Hibok. Members' use of Hibok services, including free services and fee-based services, shall abide by various laws, regulations, rules and regulations. file.", + "UG_LINE49": "6. After the membership service is opened, it cannot be transferred or unsubscribed.", + "UG_LINE50": "7. In the course of the use of Qianhai Youlong Technology Co., Ltd.'s free service or fee-based service, there is a violation of laws and regulations. Qianhai Youlong Technology Co., Ltd. reserves the right to cancel the membership of the member without any compensation, and the member shall bear full responsibility.", + "UG_LINE51": "Six other terms", + "UG_LINE52": "1. Qianhai Youlong Technology Co., Ltd. solemnly reminds users to pay attention to the terms of the Agreement that exempt Qianhai Youlong Technology Co., Ltd. from liability and aggravate user obligations. Please read carefully and consider risks. Minors should read this Agreement accompanied by a legal guardian. The final interpretation and modification of the above terms and conditions is owned by Qianhai Youlong Technology Co., Ltd.", + "UG_LINE53": "2. The invalidity of some or all of the terms set forth in this Agreement shall not affect the validity of other terms.", + "UG_LINE54": "3. The interpretation, validity and settlement of disputes in this Agreement shall apply to the laws of the People's Republic of China. If there is any dispute or dispute between the user and Qianhai Youlong Technology Co., Ltd., it should be settled through friendly negotiation. If the negotiation fails, the user hereby completely agrees to submit the dispute or dispute to the people's court of Qianhai Youlong Technology Co., Ltd.'s domicile.", + "UG_LINE55": "4. The copyright of this Agreement is owned by Qianhai Youlong Technology Co., Ltd., and Qianhai Youlong Technology Co., Ltd. reserves all rights to interpret and modify.", + "UG_LINE56": "Qianhai Youlong Technology Co., Ltd.", + "net_error": "Network anomaly", + "enter_name": "Please type in your name", + "translate": "Aa", + "locate": "Location", + "voice_tips": "Press and hold the recording, release the send", + "unlock": "Unlock", + "input_content": "Enter chat content", + "connecting": "Connecting...", + "logining": "Landing...", + "reject_reply": "/s1 rejected your request to view", + "warning_text": "You can redeem H coin within 3 days after no one reports it (1: 1000Vietnamese Dong)", + "more_big": "The number of inputs is not greater than /s1", + "little_min": "The number of inputs is not less than /s1", + "voice_msg": "/s1 invites you to a call", + "send_gift": "You rewarded each other /s1 /s2", + "receive_gift": "Your opponent rewarded you /s1 /s2", + "cannot_join": "Non-members cannot register", + "alreay_back": "Returned", + "video_more_big": "File is too large", + "select_all": "Select all", + "re_connect": "Reconnect", + "voice_tips2": "Release to send, swipe to cancel", + "country": "country", + "have_picture_view": "Under review", + "speaker_play": "Speaker play", + "handset_playback": "Handset playback", + "play_model": "Turn Off Speaker", + "password_less": "Password is too short", + "years_old": "Years old", + "coin_returen1": "After an anonymous user reports, the system verifies that you have recently violated the rules. Do not perform any illegal actions. If the next time, the account will be frozen", + "already_new": "Already the latest version", + "test_it": "Experience now", + "found_new": "Discover new version", + "ad": "ad", + "attention": "Focus", + "fans": "Fans", + "apply_see": "/s1 applies to view my profile", + "agree_apply": "/s1 passed my review request", + "see_redBag": "/s1 viewed my red envelope photo", + "notice": "remind", + "notice_open": "Turn on notification permissions for notifications", + "open_notice": "Notification permission is not turned on", + "not_open": "Notifications are not turned on and cannot be received", + "withdraw_fail": "The /s1 H coin you applied for withdrawal has been returned, please confirm that the bound account is correct", + "dynamics": "Moments", + "Remark": "Remark", + "setRemark": "Setting Notes", + "content_num": "/s1 comment", + "Redeem": "/s1H Coins for Points Exchange", + "location_permission": "No access to phone storage", + "camera_permission": "No access to the camera", + "photo_permission": "No access to albums", + "video_permission": "No access to microphone", + "your_redMoney_over": "The red envelope you sent has expired", + "other_redMoney_over": "The red envelope sent by the other party has expired", + "server_error_tips": "Looks like something went wrong ...", + "emoji": "emoji", + "today_score": "Sign up today to receive /s1 points", + "sign_tips": "1. Daily sign-in can receive points. The more accumulated days, the higher the points. \n2. The points can be exchanged for H coins. The exchange will consume the corresponding points. Please redeem carefully. \n3. The sign-in will be reset on the last day of each month. Redeem in time.", + "sign_in": "Sign in", + "my_score": "My scores", + "signin_now": "Sign in now", + "sign_in_day": "Accumulated sign in for /s1 day", + "have_get": "Redeemed", + "scan": "Scan", + "my_qr": "My QR code", + "scan_and_add": "Scan and add friends", + "amap": "Amap", + "baidumap": "Baidu Map", + "googlemap": "Google Map", + "applemap": "Apple Map", + "go_open": "Go open", + "Preview": "Preview", + "Photo_album": "Photo album", + "all_photo": "All pictures", + "have_select": "You have selected /s1 pictures", + "loading": "Loading...", + "new_chat_msg": "You have new chat messages", + "new_video_msg": "You have new Lianmai news", + "apply_friends": "/s1 apply to be your friend", + "applyed_friends": "/s1 passed your friend request", + "contact_permission": "No access to contacts", + "contact": "Contacts", + "search": "search", + "contact_add": "Add friends from contacts", + "find": "Find", + "translate_robot": "Translation robot", + "robot_hello": "Hello i'm a translation robot...", + "Simplified_Chinese": "Simplified Chinese", + "traditional_Chinese": "Traditional Chinese", + "english": "English", + "Vietnamese": "Vietnamese", + "Korean": "Korean", + "Japanese": "Japanese", + "add_friends": "add friend", + "stranger": "stranger", + "receive_stranger": "Receive messages from strangers", + "signin": "SignIn", + "stranger_close": "They refuse to receive messages from strangers, continue to unlock all information?", + "add": "add", + "added": "added", + "stranger_close_tips": "They refuse to receive messages from strangers.", + "translate_fail": "Translation failed", + "no_photos": "Please upload photos first, and then set up red envelope photos. ", + "successful_appeal1": "Your appeal evaluation: /s1 the appeal failed. ", + "add_success": "Add succeeded and wait for their consent", + "other_pay": "Payment by others", + "friend_verification": "Friend verification ", + "add_friends_tips": "You have sent a verification application and wait for them to pass", + "i_am": "I am /s1", + "agree": "Agree", + "privacyAgreement": "\"Hi\"You need to approve the Privacy Agreement before use ", + "privacy": "Privacy Agreement", + "notification_addfriend": "Hi!someone has applied to add you as a friend and to see who it is ", + "distance_long": "You can only add friends face to face ", + "chat_tips": "For accuracy of translation, please do not abbreviate ", + "fans_list": "Fans list ", + "system_not_open": "During beta test", + "service_withdraw_tips": "Withdrawal is not supported for IOS client at present. You can withdraw by Android client, or click the button below", + "withdraw_tips": "Click to withdraw ", + "add_member": "Add member ", + "delete_member": "Delete member", + "change_group_name": "Change group name", + "my_group_nickname": "My group nickname", + "group_chat": "Group chat", + "create_group_chat": "Create group chat", + "added_friends_tips": "You need to send a verification application and wait for them to pass ", + "group_chat_name": "Group chat name", + "my_group_nickname_tips": "You can set your group nickname here, which will only be displayed in this group ", + "man_gold": "Male god message", + "woman_gold": "Goddess message", + "choose_group_owner": "Choose a new group owner", + "group_announcement": "Group announcement", + "chat_news": "Chat news", + "group_qr": "Group QR code", + "group_setting": "Group management", + "close_news_notice": "Close news notice", + "set_chat_top": "Sticky on top", + "show_group_member_name": "Show group member nicknames", + "quit_group_tips": "No other members in the group chat will be notified and this group chat message will not be received anymore ", + "quit_and_delete": "Quit and delete", + "show_more_member": "Show more members", + "group_invite": "Invitation confirmation", + "change_group_owner": "Transfer of group ownership", + "group_setting_tips": "After enabling, group members need confirmation from the group owner to invite friends to the group. Scanning QR code to enter the group will also be disabled", + "invite_detail": "Invitation details", + "undefine_name": "Unnamed", + "group_qr_code": "Group QR code business card", + "group_qr_code_tips": "The QR code is valid within 7 days (before /s1 month /s2 days), re-entry will be updated", + "Goddess_heat": "Goddess heat", + "Goddess_heat_tips": "Gifts accumulated", + "new_friends": "New friends", + "before_three_day": "Three days ago", + "after_three_day": "Last three days", + "group_clean_chat_record": "Clear chat history", + "check": "Check", + "apply_fro_friends": "Request to add you as a friend", + "no_vip_cannot_withdraw": "Non-members cannot withdraw", + "not_true_woman": "This user is not authenticated, be careful not to be cheated", + "join_group": "Join group chat", + "sign_in_apple": "Login through Apple", + "only_host": "Only group owner can edit group announcements", + "send_gift1": "You sent /s1 gifts to others ", + "receive_gift1": "They sent /s1 gifts to you ", + "not_in_group": "You are no longer in this group ", + "creating_group": "Creating, please wait ", + "article": "Article", + "group_open_verification": "Verification has been opened, and you can only enter the group by invitation", + "group_memeber": "Group members", + "invite_members": "Invite friends to join in the group chat", + "total_members": "/s1 persons in total", + "qr_outtime": "QR code expired ", + "no_goupr_info": "No group information", + "you_invite": "You invited /s1 to join the group chat ", + "invite_you": "You are invited into group chat by /s1 ", + "invite_someone": "/s1 invites /s2 to join the group chat ", + "you": "You", + "delete_group": "/s1 moves /s2 out of group chat ", + "you_group_owner": "You have become a new group owner", + "someone_group_owner": "/s1 has become a new group owner ", + "change_group_owner1": "The group name has been changed to /s1 ", + "update_group_announce": " Group announcement has been updated ", + "you_qr": "You join group chat by scanning QR code", + "others_qr": "/s1 join group chat by scanning QR code ", + "invite_confirm": " \"/s1 \" want to invite /S2 friends to join the group chat \\$ to confirm \\$", + "want_invite_confirm": " \" /s1 \"want to invite \" /s2 \" to join the group chat ", + "join_group_confirm": " \"/s1 \"joins group chat, confirmed", + "you_invite_gourp": "You are invited into group chat by /s1 ", + "someone_join_group": " \"/s1\" joins group chat ", + "group_setting_tips1": " Group owner has opened the \" group chat invitation confirmation \", group members can invite friends into the group only after group owner's confirmation ", + "group_setting_tips2": "The group owner has restored the default group entering method ", + "members_max": " Group members have reached the upper limit ", + "group_max": " The number of groups has reached the upper limit ", + "my_money_info": "my bills", + "my_left_money": "my balance", + "money_tips": "H coins can be obtained by recharging or exchange, and cannot be withdrawn", + "get_money_detail": "income details", + "hibok_money": "Hibox revenue", + "charge_h": "exchange h coins ", + "charge_tips": "withdrawal rules", + "splash_tips1": "variable positioning", + "splash_tips2": "Translation robot", + "splash_tips3": "friends-making APP", + "splash_tips_content1": "gorgeous goddess, choose what you love ", + "splash_tips_content2": "chat together by voice interaction", + "splash_tips_content3": "solving language problems", + "splash_go": "experience immediately", + "change_h_coin": "you exchanged /s1H coins through your income", + "Representation_succes": " your application is successful, and the system has refunded", + "system_give": " presented by system ", + "exchange_fail": "your withdrawal application failed and has been returned", + "hibok_exchange": "exchange /s1H coins through Hibox income ", + "bind_code_success": "binding invitation code succeeded", + "translate_money": " you have spent /s1H coins on manual translation", + "system_back": " system return cancelled", + "you_give": "you gave rewards to others ", + "you_get": " you got rewards from others", + "enter_num_qian": " number of exchanges (unit K) ", + "enter_num_qian1": " number of withdrawals (unit K) ", + "daily_translate_voucher": "翻译券", + "msg_notice":"通知消息", + "select_notice_people":"选择提醒的人", + "search_phone":"查找手机号", + "not_have_user":"用户不存在", + "not_add_Myself":"你不能添加自己", + "you_are_blaklisted":"对方已拉黑了你", + "confrim_recovery":"确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)", + "send_to": "發送到" +} \ No newline at end of file diff --git a/i18n/ja-JP.json b/i18n/ja-JP.json new file mode 100644 index 0000000..4365a7e --- /dev/null +++ b/i18n/ja-JP.json @@ -0,0 +1,1164 @@ +{ + "appName": " Hi公園", + "login": "登録", + "registration": "新規取得", + "other_login": "他の登録", + "account": "アカウント", + "enter_username": "アカウントを入力してください", + "password": "パスワード", + "enter_password": "パスワードを入力してください", + "forget_password": "パスワードを忘れた", + "reset_password": "パスワードをリセットする", + "number_registration": "携帯番号で新規取得", + "enter_number": "携帯番号を入力してください", + "code": "検証コード", + "enter_code": "受け取った検証コードを入力してください", + "send_code": "検証コードを送信する", + "send_again": "再送する", + "set_password": "パスワードを設定する", + "password_limit": "パスワードは少なくても6桁に設定する", + "set_password2": "登録パスワードを設定してください", + "next_step": "次へ", + "agreed_agreement": "クリックすると、《ユーザー協議》を読んで同意したことになります", + "enter_password2": "パスワードを入力してください", + "reset_now": "すぐリセット", + "choose_gender": "性別を選択", + "who": "あなたは...", + "determine": "確定", + "cannot_modified": "性別を選択後変更できません", + "tip": "ヒント", + "choose_quit": "あなたは間もなく新規取得完成しますが、今ログアウトしますか?", + "confirm": "確認", + "use": "使用", + "cancel": "キャンセル", + "close": "閉じる", + "delete": "削除", + "forget_it": "やめる", + "ok": " OK ", + "choose_quit2": "登録後に性別を変更することはできません、確定ですか?", + "tip_content": "ヒント:同性別のユーザとのコミュニケーションすることができません", + "welcome": "ようこそ", + "enter_incode": "招待コードを入力してください", + "must_incode": " Hiは招待コードを持つ男性のみにサービスを提供しています", + "your_incode": "あなたの招待コード", + "how_get": "招待コードがないですか?以下の方法で入手できます", + "method1": "方法1", + "free": "無料申請", + "apply_now": "すぐ申請", + "check_incode": "招待コードを査収してください", + "so_get": "個人情報を記入して、審査した後招待コードを送ります", + "apply_incode": "招待コードを申請する", + "location": "所在地", + "cityname": "あなたいる都市の名前", + "message_channel": "情報ルート", + "how_know": "どこからこのAPPを知っていますか", + "wechat_number": "ウィーチャットID ", + "your_wechat": "あなたのウィーチャットID ", + "facebook": "フェイスブック", + "your_facebook": "あなたのフェイスブック", + "submit_application": "申請を提出します", + "enter_city": "あなたにいる都市を入力してください", + "so_know": " APPを獲得ルートを教えてください", + "your_social": "あなたのSNSアカウントを教えてください", + "receive_incode": "あなたの申請を出来るだけ早く処理します、もし審査に合格したらメッセージセンターで私たちが送った招待コードを受け取ります", + "wait_incode": "招待コードはまだ発行されていませんので、暫くお待ちください!", + "successful_application1": "申し込み成功", + "application_failed1": "レビューに失敗しました", + "successful_copy": "コピー成功", + "method2": "方法2", + "joinvip": " VIPになり", + "join_now": "すぐ加入する", + "joined": "加入しました", + "join_odds": " VIPになるとさまざまな特権があります、招待コードなしでの登録を含めます", + "not_joinvip": "あなたはまだVIPになっていません", + "join_after": " VIPになったら、招待コードなしで登録できます", + "incode_passed": "招待コードの認証をパスしました", + "welcome_join": "いらっしゃいませ、あなたのアカウントを他人に漏らさないでください。登録異常が発見されたら、アカウントは自動的に凍結されます", + "member_centre": " VIPセンター", + "members_privilege": " VIP特権", + "see_more": "もっと見える", + "unlimited_see": "毎日無制限でユーザを見えます", + "see_cheaper": "もっと節約で見る", + "free10": "毎日/s1回のチャンスで有料アルバム或いはSNSアカウントを閲覧できます", + "see_longer": "もっと長く見えます", + "towto6": "写真閲覧後焼却の時間が2秒から/s1に上げます", + "see_better": "もっと気持ち良く見える", + "free_release": "デート放送無料発表", + "choose_price": "コースを選択してください", + "pay_method": "支払い方法", + "pay_amount": "支払い金額", + "not_enough": "残高が足りない", + "confirm_pay": "支払い確認", + "complete_material": "資料を完備する", + "basic_information": "基本資料", + "upload_avatar": "アバターをアップロッド", + "choose": "選択してください", + "fill_out": "入力してください", + "choose_multiple": "複数の選択肢", + "optional": "オプショナル", + "least": "少なくても/sl個を入力してください", + "introduce_yourself": "自己紹介してください", + "most": "多くても/sl個を選んでください", + "nickname": "ニックネーム", + "only1_8": "ニックネームは1~20文字のみです", + "Resident_city": "現在の都市", + "Please_select_a_resident_city": "現在の都市を選択してください", + "City1": "芹苴", + "City2": "岘港", + "City3": "海防", + "City4": "河内", + "City5": "胡志明", + "City6": "安江", + "City7": "北江", + "City8": "北件", + "City9": "薄辽", + "City10": "北宁", + "City11": "巴地头顿", + "City12": "槟椥", + "City13": "平定", + "City14": "平陽", + "City15": "平福", + "City16": "平順", + "City17": "金瓯", + "City18": "高平", + "City19": "得楽", + "City20": "得农", + "City21": "奠边", + "City22": "同奈", + "City23": "同塔", + "City24": "嘉莱", + "City25": "河江", + "City26": "海陽", + "City27": "河南", + "City28": "河静", + "City29": "和平", + "City30": "後江", + "City31": "興安", + "City32": "庆和", + "City33": "坚江", + "City34": "昆嵩", + "City35": "莱州", + "City36": "林同", + "City37": "谅山", + "City38": "老街", + "City39": "隆安", + "City40": "乂安", + "City41": "寧平", + "City42": "寧顺", + "City43": "富寿", + "City44": "富安", + "City45": "広平", + "City46": "広南", + "City47": "広義", + "City48": "広寧", + "City49": "広治", + "City50": "朔庄", + "City51": "山羅", + "City52": "西寧", + "City53": "太平", + "City54": "太原", + "City55": "清化", + "City56": "承天順化", + "City57": "前江", + "City58": "茶荣", + "City59": "宣光", + "City60": "永隆", + "City61": "永富", + "City62": "安沛", + "City63": "南定", + "birthday": "誕生日", + "choose_birthday": "誕生日を選んでください", + "year": "年", + "month": "月", + "day": "日", + "hour": "時", + "minute": "分", + "second": "秒", + "just": "たった今", + "minute_ago": "/s1分前", + "hour_ago": "/s1時間前", + "day_ago": "/s1日前", + "week_ago": "/s1週間前", + "month_ago": "/s1ヶ月前", + "morning": "午前", + "noon": "昼ごろ", + "afternoon": "午後", + "night": "夜", + "all_day": "一日中", + "yesterday": "昨日", + "two_yesterday": "一昨日", + "overnight": "徹夜", + "one": "一桁", + "ten": "十", + "hundred": "百", + "thousand": "千", + "ten_thousand": "万", + "aries": "おひつじ座", + "taurus": "おうし座", + "gemini": "ふたご座", + "cancer": "かに座", + "leo": "しし座", + "virgo": "おとめ座", + "libra": "てんびん座", + "scorpio": "さそり座", + "sagittarius": "いて座", + "capricorn": "やぎ座", + "aquarius": "みずがめ座", + "pisces": "うお座", + "monday": "月曜日", + "tuesday": "火曜日", + "wednesday": "水曜日", + "thursday": "木曜日", + "friday": "金曜日", + "saturday": "土曜日", + "sunday": "日曜日", + "job": "職業", + "choose_career": "職業を選択ください", + "career1": "インフォメーション", + "career2": "インターネット", + "career3": " IT ", + "career4": "電信運行", + "career5": "ネットゲーム", + "career6": "金融保険", + "career7": "投資", + "career8": "株式ファンド", + "career9": "保険", + "career10": "銀行", + "career11": "信託保証", + "career12": "ビジネスサービス", + "career13": "相談", + "career14": "自営業", + "career15": "美容、美髪", + "career16": "旅行", + "career17": "ホテル飲食", + "career18": "レクリエーション", + "career19": "貿易", + "career20": "汽車", + "career21": "不動産", + "career22": "不動産管理", + "career23": "内装、表装", + "career24": "探偵", + "career25": "工程製造", + "career26": "建築", + "career27": "土木建築工事", + "career28": "機械製造", + "career29": "電子", + "career30": "生物医学", + "career31": "食品", + "career32": "服装", + "career33": "エネルギー", + "career34": "交通運輸", + "career35": "航空", + "career36": "鉄道", + "career37": "航运船舶", + "career38": "パブリック交通", + "career39": "物流運輸", + "career40": "文化メディア", + "career41": "メディア出版", + "career42": "デザイン", + "career43": "文化伝播", + "career44": "コマーシャルアイデア", + "career45": "アニメ", + "career46": "広報会議", + "career47": "撮影", + "career48": "娯楽スポーツ", + "career49": "映画とテレビ", + "career50": "スポーツ", + "career51": "音楽", + "career52": "モデル", + "career53": "パブリック事業", + "career54": "医療", + "career55": "法律", + "career56": "教育", + "career57": "政府機関", + "career58": "公益", + "career59": "学生", + "career60": "無", + "program": "番組", + "select_program": "国籍を選択してください", + "healthy_exercise": "健康スポーツ", + "night_party": "パーティー", + "gourmet_party": "食べ物", + "watch_movie": "映画を見る", + "play_games": "ゲームを遊ぶ", + "travel_together": "旅行", + "voice_chat": "音声チャット", + "other": "他", + "expect_lover": "希望相手", + "choose_lover": "希望相手を選んでください", + "beautiful": "顔を見る", + "rich": "お金持ち", + "care_me": "愛護をください", + "look_feeling": "気持ちによる", + "doesnt_matter": "どうでもいい", + "least_account": "少なくとも一つのSNSアカウントを記入してください", + "hide_account1": "ソーシャルアカウントを非表示", + "more_information": "詳細情報", + "height": "身長", + "weight": "体重", + "not_show": "表示しません", + "self_introduction": "個人紹介", + "registration_success1": "新規取得成功", + "exit": "ログアウトしますか", + "exit_registration": "あなたの個人情報はまだ完備していません、今ログアウトしたら次入る時は登録済みのアカウントで直接ログインしてください", + "cant_see": "男性は男性の詳細情報を確認出来ません", + "cant_see2": "女性は女性の詳細情報を確認出来ません", + "see_one": "今日はまだ/s1人の女性情報が確認できます", + "only_see": "非VIPユーザーは毎日15人の女性情報しか見られません", + "continue_see": "続き見る", + "user_frozen": "ユーザーが凍結しました", + "search_user": "ニックネームを入力ください/職業で検索します", + "nearby": "近辺", + "member": " VIP ", + "new_registration": "新規取得", + "authenticate": "認証", + "first_online": "オンライン", + "not_positioned": "位置付けが開けてないから他ユーザとの距離が計算できません", + "unknown": "未知", + "secrecy": "秘密を守る", + "collection": "コレクション", + "cancel_collection": "コレクションをキャンセル", + "canceled_collection": "コレクションをキャンセルしました", + "like": "お気に入り", + "added_like": "お気になりに追加しました", + "canceled_like": "お気になりをキャンセルしました", + "blacklist": "ブロックする", + "blacklist_choose": "ブロックすると、このユーザーからのメッセージを受け取れなくなり、お互いにモーメンツの更新が表示されなくなります、このユーザーをブロックしますか", + "blacklisted": "ブロックしました", + "reject_message": "相手をブロックしました、相手のメッセージを拒否します", + "remove_blacklist": "ブロックリストから削除", + "blacklist_removed": "ブロックリストから削除しました", + "receive_message": "相手をブロックリストから削除しました、メッセージ拒否を解除しました", + "online": "オンライン", + "paid_photo": "有料アルバム", + "application_view": "ブラウズを申請する", + "passed": "パスしました", + "park": "公園", + "radio": "放送局", + "news": "情報", + "me": "私", + "more_operations": "詳細操作", + "anonymous_report": "匿名告発", + "certified_video": "認証ビデオ", + "passed_video": "彼女はビデオを通じて真実性を認証しました", + "not_video": "彼女はまだ身分の真実性を認証していません", + "her_appointment": "彼女からデートを誘っていますよ", + "pay_join": "彼は有料で入る", + "passed_review": "彼は身分安全審査に合格しました", + "invited_user": "ベテランユーザー/s1贈った招待コードを通して入りました", + "his_appointment": "彼からデートを誘っていますよ", + "her_dynamics": "彼女のダイナミック", + "his_dynamics": "彼のダイナミック", + "low_key": "彼女は非常に控えめ", + "low_key2": "彼は非常に控えめ", + "her_photo": "彼女のアルバム", + "his_photo": "彼のアルバム", + "set_lock": "彼はアルバムのロックを設置しました", + "set_lock2": "彼女はアルバムのロックを設置しました", + "free_unlock": "アルバムのロックを解除(/s1)、VIPは無料", + "unlock_user": "/s1のアルバムロックを解除", + "pay_unlock": "有料でロックを解除(/s1H幤)", + "become_member": " VIPになり、無料でロックを解除します", + "consumption_once": " 1回のチャンスで/s1のアルバムロックを解除しますか?", + "remaining_once": "(今日はまだ/s1回チャンスがあります)", + "no_times": "今日の無料機会はもうなくなりました、/s1を贈って/s2の全部資料をロック解除するか", + "pay": "支払い", + "view_user": "彼は制限を設定、資料を見るには彼の同意が必要です", + "view_user2": "彼女は制限を設定、資料を見るには彼女の同意が必要です", + "need_photo": "レビューの申請はなたの写真を相手に送り必要があります、ご安心して、あなたの写真は相手が長いスクリーンを押して2秒後に焼却します", + "choose_photo": "写真を選択", + "send_application": "申請が発送済み、相手が確認したらメッセージが届きます", + "not_authenticate": "あなたはまだ認証していません", + "after_authenticate": "あなたの真実性を認証してから、他人との対話することができます", + "authenticate_now": "すぐ認証する", + "destroy_after": "読んだらすぐ焼却", + "destroyed": "焼却しました", + "red_photo1": "読んだらすぐ焼却のご礼儀写真", + "ask_me": "二人きりチャットで私に請求してください", + "filled_in": "記入済み、クリックして確認してください", + "unlock_information": "全資料をロック解除する", + "unlock_choose": "1回無料でロックを解除する", + "your_evaluation": "あなたの本当の評価", + "her_evaluation": "彼女の本当の評価", + "his_evaluation": "彼の本当の評価", + "evaluate": "評価", + "friendly": "友好", + "interesting": "面白い", + "readily": "爽やか", + "patient": "辛抱強い", + "indifferent": "冷たい", + "bad_temper": "気性が荒い", + "courtesy": "礼儀正しい", + "generous": "気前がいい", + "lie": "口が軽い", + "unfriendly": "不友好", + "anonymous_evaluation": "匿名評価", + "cant_evaluate": "あなたはまだ彼女を誘ったことがないからコメントできません", + "cant_evaluate2": "彼はまだあなたを誘ったことがないからコメントできません", + "bad_evaluate": "関連のスクリーンショットを提供してください、こちらはフォローして確認します", + "submit": "提出", + "evaluation_success": "コメント成功", + "private_chat": "チャット", + "close_reminder": "メッセージのアラームをオフにする", + "closed_reminder": "メッセージのアラームをオフにしました", + "open_reminder": "メッセージのアラームをオープンにする", + "opened_reminder": "メッセージのアラームをオープンにしました", + "her_account": "彼女のSNSアカウント", + "his_account": "彼のSNSアカウント", + "copy": "コピー", + "send_account": "彼女に私のSNSアカウントを送ります", + "enter_account": "あなたのSNSアカウントを入力してください", + "for_example": "例:ウィーキャットID abc ", + "sent_she": "彼女に送信します", + "chat": "音声通話", + "cantt_voice": "相手はマイクの功能をオフしました", + "authentication_voice": "あなたの真実性を認証後音声ができます", + "requesting_voice": "音声を請求しています", + "waitting_answer": "反応を待っています", + "answer": "受け入れ", + "hang_up": "ハングアップ", + "chatting": "音声繋がる中", + "handsfree": "ハンズフリー", + "giving_gift": "プレゼントを贈る", + "give_success": "プレゼントを贈りました", + "others_gift": "相手からプレゼントをくれました", + "given_gift": "あなたは/s1H幤のプレゼントを贈りました", + "earned_gift": "あなたは/s1H幤プレゼントを貰いました", + "available_balance": "利用可能残高/s1", + "recharge": "チャージ", + "give": "贈る", + "balance_insufficien": "すみません、あなたの残高が足りません", + "first_recharge": "プレゼントを贈る前チャージしてくださいね", + "give_coin": "今回は/s1H幤を贈りました", + "get_coin": "今回の音声は/s1H幤を貰いました。", + "give_get": "今回の音声は/s1H幤を贈りました、/s2H幤を貰いました。", + "chat_over": "音声会話は完了しました、長さ/s1", + "message_center": "インフォメーションセンター", + "can_chat": "相手のユーザー詳細ページで二人きりチャット申請できます", + "text_chat": "チャット", + "system_information": "システムメッセージ", + "system_notification": "システム通知", + "report_failure": "あなたが告発した/s1の状況は事実ではありません、もっと有効な証拠を提出して再告発してください", + "report_success": "あなたが告発した/s1の状況は事実ですので、このユーザを処理しました", + "successful_application": "招待コードの申請が成功!招待コード【/s1】(クリックしてコピーできます)", + "successful_application2": "招待コードの申請が成功、友達のご紹介、ありがとうございます。招待コード【/s1】(クリックしてコピーできます)", + "application_failed": "招待コードの申請が失敗した!残念ながら、あなたの申請は審査に合格できませんでした、真実な情報を記入して審査パス率が上げる", + "important_notice": "【重要なお知らせ】:", + "authentication_failed": "あなたの認証資料は要求に合わないから修正して再提出してください", + "request1": "1. 認証要求に基づいて認証ビデオを撮ってください", + "request2": "2. 写真集に目鼻立ちのはっきりした顔写真をアップロードしてください", + "successful_authentication": "あなたの認証申請は審査に合格しました,おめでとうございます", + "re_upload": "あなたがアップロードした写真は審査に合格しませんでした、必要に応じて再アップロードしてください", + "upload_success": "新しくアップロードされた写真はもう審査に合格しました、おめでとうございます", + "caveat": "あなたのデートの申し込みは規則違反で削除されました、何回かの違反や事態重大な場合はシステムからあなたのアカウントを制限し凍結しますので、ご了承ください", + "caveat2": "あなたのコメントは規則違反で削除されました。何回かの違反や事態重大な場合はシステムからあなたのアカウントを制限し凍結しますので、ご了承ください", + "radio_message": "ラジオニュース", + "no_message": "このような情報はしばらくありません", + "dating_news": "/s1は//s2にデート情報を発表しました。クリックして確認してください", + "go_see": "確認", + "thumbs_up": "/s1はあなたのダイナミックをいいねにした", + "thumbs_up2": " /s1はあなたのデート番組をいいねした", + "comment1": "/s1はあなたのダイナミックにコメントしました", + "comment2": "/s1はあなたのデート番組にコメントしました", + "replied_comment": "/s1はあなたのコメントを返信しました", + "signed_up": "/s1はあなたのデート番組を申し込みました", + "favorite_user": "あなた気に入りユーザー/s 1がデートを発表しました。クリックして確認してください", + "favorite_user2": "お気に入りユーザ/s 1がダイナミックをリリースしました。クリックして確認してください", + "wallet_reminder": "ウォレットのリマインダ", + "paid_you": "/s1(/s2H 幤)を払ってあなたのご祝儀写真を見ました", + "paid_you2": "/s1は(/s2H幤)を払ってあなたのアルバムを見ました", + "paid_you3": "/s1は有料で、あなたの資料を全部ロックしました", + "view_application": "申請を確認します", + "view_application2": "/s1はあなたの詳細ページ閲覧をリクエスする", + "aging": "許可(有効期間15日間))", + "refuse": "拒否", + "passed_request": "リクエストをパスしました", + "l15_days": "/s1はもうあなたの閲覧申請をパスしました、有効期間は15日間です", + "evaluation_notice": "コメントのお知らせ", + "rate_her": "もう/s1を誘いましたか?早く彼女を評価してください", + "received_evaluation": "あなたに連絡した女性ユーザー(匿名)があなたにコメントした:/s1", + "received_evaluation2": "あなたに連絡した男性ユーザー(匿名)があなたにコメントした:/s1", + "application_appeal": "コメントは事実と合わない場合、申告してください、こちらは事実を確実します", + "appeal": "申告します", + "appealed": "申告しました", + "waiting_results": "私たちはできるだけ早く状況を確認して、内部メールで処理結果を連絡します", + "successful_appeal": "あなたの申告評価:/s 申告成功、コメントを取り消します", + "social_account": " SNSアカウント", + "get_account": "/s1はあなたにSNSアカウントを送信します", + "edit_information": "資料編集", + "save": "保存", + "passed_verification1": "あなたの身分安全認証をパスしました", + "by_code": "あなたはベテランユーザー/s 1の招待コードで入りました", + "by_paying": "あなたは有料で入りました", + "passed_verification": "あなたはビデオを通じて身分の真実性を認証しました", + "not_certified": "あなたはまだ認証されていません", + "verificating": "あなたの真実性を認証しています", + "real_girl": "認証を受けた女性の方がもっと人気がありますよ", + "certificating": "認証中", + "re_upload2": "ビデオを再アップロードをお待ちしております", + "update_certification": "認証更新", + "enjoy_privileges": " VIPをアップして特権を尊ぶ", + "expires": "/s1満期", + "wallet": "財布", + "setting": "プライバシー", + "my_dynamic": "私のダイナミック", + "my_album": "私のアルバム", + "first_photo": "第一枚写真をアップロードします", + "no_photo": "写真があったら男性を引き付けることができますよ", + "upload_photos": "写真をアップロード", + "upload_video": "ビデオをアップロード", + "upload": "写真をアップロードする", + "set_photo": "ご祝儀の写真を設定する", + "photo_order": "長いドラッグで写真の並べ替えができます", + "my_evaluation": "私の評価", + "my_show": "私の番組", + "i_like": "私の気に入り", + "your_favorite": "ご好きな女性がここを表示します", + "your_favorite2": "ご好きな男性がここを表示します", + "no_data": "データがありません", + "historical_visitor": "過去の訪問者", + "visit_you": "/s1人が訪問したことがある", + "visit_photo": "/s1人があなたの写真を焼却しました", + "recovery_photo": "ワンタッチで回復", + "setting2": "設定", + "apply_code": "友達に招待コードを申請してあげます", + "issue_choose": "招待コードの申し込みは無料です、あなたの過去消費履歴によって招待コードを発行するかどうかを評価します。公園の雰囲気を維持するために、ぜひ信頼できる友達に招待コードを贈ってしてください", + "successfully_submit": "申請書提出成功", + "share_app": "友達にAPPを共有する", + "need_help": "助けてください", + "need_help2": "顧客サービスに連絡する", + "need_help3": "サービスの効率を高めるために、以下の問題があれば、直接番号を回答ください", + "question1": "【1】アカウントが凍結された理由は何ですか??", + "answer1": "下記のいずれかの状況が発生したら、アカウントは凍結されます:①詐欺師②仲介③嫌がらせ広告④複数人が告発され。⑤他のアカウントがすでにありました。⑥何度も違法放送を発表して、警告を無視しました。⑦ユーザーが自分でログアウトを要求する", + "question2": "【2】財布の現金はいつ換金できますか?", + "answer2": "すべての収益は直接財布に入ります。換金には三日間かかります(請求時間による計算開始)。三日後に受け取った金額は財布に入ります。金額>=10元の場合換金できます", + "question3": "【3】私が出したご祝儀はなぜ表示されていませんか?", + "answer3": "ネットの原因かもしれません。ご安心してください、この場合、相手はあなたのご祝儀を受け取ることができません。ご祝儀は24時間後に自動的にあなたの支払ルートに返却されます", + "question4": "【4】換金はどれぐらいかかりますか?", + "answer4": "換金申請を提出してから二つの出勤日以内に入金します。ご注意:アカウントは間違いないようご注意ください!", + "question5": "【5】どうやって匿名で他のユーザー/ラジオ放送の内容を告発しますか?", + "answer5": "相手の詳細ページに入るか、ラジオ放送を選択し、右上をクリックして「匿名通報」を選択し、関連の告発情報を記入してください", + "question6": "【6】どのように認証ユーザになりますか?", + "answer6": "認証をパスするには以下の要求を満たす必要があります。①個人資料には有効なsnsアカウントを記入する②アルバムは少なくとも本人のはっきりした顔写真をアップロードする③認証ページで検証コードを確認し、紙にニックネーム+認証コードを記入する④この紙を持って、あなたの顔と一緒にビデオを撮ってアップロードする", + "question7": "【7】認証されたビデオは公開しなくてもいいですか?", + "answer7": "設定欄で公開するかどうかを選択できます。ユーザーセンター→認証ビデオをクリックして、左下に“認証ビデオを私の詳細ページに表示します", + "question8": "【8】どうやって認証がキャンセルされるのを避けるべきですか?", + "answer8": "アルバムには少なくとも一枚本人の写真があります", + "question9": "【9】ラジオ放送が削除された理由は何ですか?", + "answer9": "ラジオ放送は敏感図を発表できません。敏感語は含みますが、これに限らず、個人情報(顔写真、ニックネーム、連絡先を含む)を発表できません、違法放送は削除されます", + "question10": "【10】どうやってアカウントをキャンセルしますか?", + "answer10": "アカウントの抹消はAPPにログインできなくなりますので、後でサービスを使用の場合は改めて新規取得必要です、それでもアカウントをキャンセルする場合は、シリアル番号[12]に顧客サービスに連絡してください ", + "question11": "【11】パスワードを忘れたらどうすればいいですか?", + "answer11": "携帯番号で登録したユーザー或いは携帯番号を関連したたユーザーはページ右上の「パスワード忘れ」機能でパスワードをリセットできます。携帯番号を関連していないユーザはまず携帯番号を関連して、そして新しいログインパスワードを設定してください", + "question12": "【12】その他の問題/人工サービスに連絡", + "answer12": "こんにちは、なにかお手伝いところがありますか?ご質問を説明してください。(顧客サービスの出勤時間は毎日8時から翌日02時までです。問い合わせ人数が多いので、お待ちしてください)", + "certification_center": "認証センター", + "for_example2": "認証ビデオの撮影例", + "certification_conditions": "認証条件", + "conditions1": "1. 個人のイメージが良い", + "conditions2": "2. アルバムに少なくとも一枚本人の写真をアップロードしてください", + "verification_method": "認証方法", + "method3": "1. 紙にニックネームと検証コードを書いてください", + "method4": "2. この紙を持って、あなたの顔と一緒にビデオを撮ってください(3~15秒)(3~15秒)", + "upload_video2": "認証ビデオをアップロードする", + "after_authentication": "認証成功後にあなたのアバター写真にrealのマックが付いてる", + "show_video": "認証ビデオを私の詳細ページに表示する", + "uploaded_video": "認証ビデオがアップロードしました", + "under_review": "審査中(24時間以内))", + "certification_status": "認証状態", + "certified": "認証パスしました", + "wait_resubmitted": "認証は再提出する必要があります", + "reason_failure": "あなたの認証ビデオは要求に合わないです。原因は:", + "claim": "認証要求に基づいて認証ビデオを撮ってください", + "claim2": "アルバムにはっきりした顔の写真をアップロードしてください", + "re_upload_video": "認証ビデオを再アップロードしてください", + "update_video": "アップロードした認証ビデオを更新する", + "mask_coin": "H幣", + "get_way": "チャージやマイク付けなど方法でH幣が貰える。", + "coin_use": " H幣は、音声通話と報酬に使用できます。", + "coin_total": "H幣総額", + "can_redeemed": "両替可", + "who_account": "/s1アカウント", + "bind_account": "/s1アカウントを関連する", + "your_account": "あなたの/s1アカウント", + "get_coin2": "チャージで/s1H幣を貰いました", + "viewed_your": "/s1はあなたのsnsアカウントを確認しました", + "give_gift": "/s1からプレゼントをくれました:1个/s2", + "add_coin": "+/s1H幣", + "give_one": " /s2に1個/s1を贈りました", + "less_coin": "-/s1H幣", + "exchange_cash": "換金", + "withdrawal_application": "換金申請申请", + "redeem_choose": "/s1枚のH貨は/s2に両替できます、両替後/s3枚H幣を残っています、両替確定ですか?", + "application_submitted": "換金申請が提出しました", + "working_days": "二日間(出勤日)内で処理します、ご疑問がありれば顧客サービスに問い合わせしてください", + "cash": "現金", + "handling_fee": "チャットベージで貰ったご祝儀はここに入ります、入金されてから3日間以内に通報がない場合は換金可能です、換金の場合は5%の手数料が掛かります", + "total_account": "アカウント総額", + "cannot_redeemed": "金額が不足で両替できません", + "successful_redemption": "両替成功", + "redeem_choose2": "あなたのアカウント総額は/s1元、今回/s2元換金可能です、換金申請は確定ですか?", + "personal_details": "個人情報", + "public": "公開(推薦)", + "paid_album": "アルバムは有料で閲覧", + "must_pay": "あなたのアルバムは有料でしか見られない、費用はあなたが決めます、これはあなたの訪問量を減らすかもしれません", + "set_amount1": "表示金額を設定する", + "first_upload": "有料アルバムを設定する前に写真をアップロードしてください", + "need_permission": "閲覧前に私の確認が必要です", + "permission_choose": "あなたのホームページを閲覧する前に、他人は必ず写真をあなたに送って身分を確認必要です、確定ですか?", + "hide_me": "近くの人のリストから私を隠す", + "hide_distance": "他人に私の位置を隠す", + "hide_account": "他人にわたしのSNSアカウントを隠す", + "chat_setting": "音声コントロール", + "chat_me": "密談の権限を持つユーザーに私と音声を許可する", + "successfully_saved": "正常に保存されました", + "on_dynamic": "あなたはまだダイナミックをリリースしたことはありません", + "release_dynamics": "ダイナミックをリリース", + "dynamic_details": "ダイナミック詳細", + "release": "投稿", + "i_posted": "私が発表した", + "delete_dynamic": "ダイナミックを削除", + "delete_choose": "このダイナミックを削除するのは確定ですが?", + "posted_on": "/s1にリリースしました", + "thumbs_up3": "いいね", + "already_praised": "いいねにした", + "comment": "コメント", + "send": "送信", + "comment_closed": "コメントを閉じました", + "your_comment": "投稿者だけがあなたのコメントを見られます", + "everyone_comment": "みんなさんがあなたのコメントを見えます", + "prohibit_comments": "コメント禁止", + "comments_disabled": "コメント禁止しました", + "open_comments": "コメントオープン", + "already_open": "コメントオープンしました", + "reply": "返信", + "report": "告発", + "report_choose": "このコメントを告発しますか?", + "successful_report": "告発できました、私たちは出来るだけ早く処理します", + "successfully_deleted": "削除しました", + "please_civilization": "文明交流できる人はもっと人気があります、下品、ポルノ、または他人のプライバシーを暴露するコンテンツを投稿しないでください", + "same_sex": "同性ユーザーには隠す", + "member_free": " VIPは無料、非VIPは/slH幤が必要", + "certified_free": "認証された女性は3回無料です、その後、支払い/s1H幤が必要です", + "enter_something": "テキストを入力or写真を選んでください", + "raid_release": "有料リリース(/s1H币)", + "become_member2": " VIPになり、無料投稿", + "now_certification": "今すぐ認証、無料投稿", + "successfully_released": "投稿成功", + "no_program": "あなたは番組を投稿したことがない", + "program_details": "番組詳細", + "program_theme": "番組テーマ", + "click_select": "クリックして選択", + "city": "都市", + "select_city": "都市選択", + "time": "時間", + "select_date": "日付を選択", + "select_time": "時間を選択", + "unlimited_time": "時間限定なし", + "supplementary_explanation": "補充説明", + "image": "画像", + "delete_program": "番組を削除", + "delete_choose2": "この番組を削除しますか?", + "please_choose": "番組のテーマを選んでください", + "please_choose2": "希望する相手を選んでください", + "please_choose3": "都市を選んでください", + "please_choose4": "日付を選んでください", + "please_choose5": "時間を選んでください", + "release_program": "番組を投稿", + "sign_up": "申し込み", + "end_registration": "登録を閉じる", + "end_choose": "デートを終了しますか?", + "contact_her": "彼女に連絡する", + "talk_him": "彼と二人チャット", + "report_choose2": "この申し込みメッセージを告発しますか?", + "release_time": "投稿時間", + "activity_time": "イベント時間", + "any_sex": "性別を問わず", + "look_women": "女性だけを見る", + "look_men": "男性だけを見る", + "unlimited_area": "地域問わず", + "program_deleted": "この番組は削除しました", + "cant_comment": "非VIPはコメントできません", + "sign_up2": "申し込み", + "need_photo2": "申し込みはあなたの正面写真が必要です(相手しか見られない)", + "registration_success": "申し込み成功、相手は気に入ったらあなたと連絡する", + "has_ended": "もう終了しました", + "men_cant": "男性は男性の番組に応募できまえん", + "ms_cant": "女性は女性の番組に応募できません", + "men_cant2": "男性は男性の番組をコメントできなせん", + "ms_cant2": "女性は女性の番組をコメントできません", + "message_push": "メッセージ送信、パスワード修正", + "phone_number": "携帯番号", + "bind_phone1": "携帯番号を関連する", + "more_safer": "携帯番号を関連して、あなたのアカウントの安全性を高めます", + "modify_choose": "関連した携帯番号を修正したいですか?", + "change_password": "パスワードを修正する", + "first_bind": "ユーザー登録パスワードを設定する前に携帯番号を関連する必要です", + "old_password": "元パスワード", + "current_password": "現行の登録パスワードを入力してください", + "new_password": "新しいパスワード", + "set_new": "6桁までの新しいパスワードを設定してください", + "clear_cache": "画像キャッシュをクリア", + "cleared_successfully": "削除しました", + "user_agreement1": "ユーザー使用協議", + "sign_out": "ログアウト", + "out_choose": "ログアウトしますか?", + "push_settings": "送信設定", + "permission_denied": "権限が拒否されました", + "push_setting2": "メッセージ送信設定", + "private_chat2": "二人チャット内容", + "new_date": "新しいデート", + "passed_request2": "私の視点からのアプリケーション", + "men_view": "男性が私のプロフィールを見たい", + "men_view2": "ある男性は私のSNSアカウントを見ました", + "men_view3": "ある男性は私のお祝儀写真を見ました", + "men_view4": "私の資料を確認した男性からSNSアカウントを送ってくれました", + "applied_successfully": "招待コード申請成功", + "after_open": "開いたら、該当するメッセージタイプを送信する", + "if_something": "もしあなたが最近3日間で彼女/彼に費用を支払ったとしたら、告発を確実した後、システムは自動的あなたに消費金額を返します", + "advertise": "広告を発表", + "false_photo": "偽り写真", + "erotic_vulgarity": "エロ低俗", + "harassment": "騒擾悪口", + "she_liar": "彼女は詐欺師です", + "he_liar": "彼は詐欺師です", + "provide_screenshots": "確認をフォローするために、関連のスクリーンショットを提供してください", + "describe_details": "詳細を説明してください(200字以内))", + "report_reason": "告発の原因を選んでください", + "report_success2": "告発成功", + "successfully_modified": "修正成功", + "boy": "男性", + "girl": "女性", + "already_applied": "申請しました", + "view_registration": "サインアップ", + "expand": "展開", + "collapse": "取入れる", + "application_notice": "申請のお知らせ", + "agrees_application": "あなたの申請をパスするユーザーがいる", + "red_photo": "ご祝儀写真", + "dont": "不法露出の低俗な写真/ビデオを掲載しないでください、深刻の場合はアカウントが永遠凍結処理する", + "current_version": "現行バージヨン", + "bank_card": "銀行コード関連する", + "choose_bank": "口座開設銀行を選んでください", + "bank_number": "銀行カード番号を入力してください", + "id_number": "証明番号を記入してください", + "name": "名前", + "bank_number2": "銀行カード番号", + "license_number": "証明番号", + "bind_phone": "携帯番号を関連する", + "his_homepage": "彼のホームページ", + "her_homepage": "彼女のホームページ", + "wechat_pay": "ウィーチャット支払い", + "facebook_pay": "フェイスブック支払い", + "google_pay": " google支払い", + "payment_successful": "支払い成功", + "set_amount": "換金金額を設定", + "enter_amount": "Hコインの数を入力してください", + "can_withdraw": "換金可能", + "language_set": "言語設定", + "user_agreement": "ユーザー協議", + "renewal_fee": "続料", + "open_immediately": "すぐ開通", + "total": "トータル", + "half_month": "半月", + "month2": "/s1ヶ月", + "cancel_shield": "シールドを解除", + "blacklist2": "ブロック", + "longTime": "( VIPは6秒延長できます)", + "longClick": "画面を押してチェックする", + "stop_program": "先に有効なプログラムを終了してください", + "not_love": "男性は男性をコレクションできない", + "not_love2": "女性は女性をコレクションできない", + "women_free": "女神は無料リリースできます", + "not_up_man": "彼はまだ写真をアップロードしてない", + "not_up_women": "彼女はまだ写真をアップロードしてない", + "not_illage": "プラットフォームを通じて不法取引をしないでください、告発された事実を確認出来たら、アカウントは永遠凍結で処理する", + "alreay_join": "申し込み済み", + "sure_delete": "この写真は削除しますか", + "white_now": "すぐ入力", + "personal": "あなたは自己紹介はまだ入力してない、魅力的な個人紹介はデートの成功に大きく影響を与えますよ", + "success": "成功", + "fail": "失敗", + "moneyPageTip": "認証されたユーザーのみご祝儀写真を設定できる", + "alreadyJoin": "あなたは申しみました、相手は気に入ったらあなたと連絡します", + "waring": "ルール違反警告", + "userPravicy": "ユーザーのプライバシーを尊重し、スクリーンショットを撮らないでください。次回があれば、他のユーザーの写真を見ることを禁止する", + "outTime": "デート時間が切りました、変更してください", + "reviewing": "審査中", + "reviewed": "審査成功", + "reviewedFail": "審査失敗", + "needCard": "ユーザーは先に銀行カードを関連してから換金することができる", + "women_not_d": "女性は女性のダイナミックをコメントできません", + "man_not_d": "男性性は男性のダイナミックをコメントできません", + "have_picture": "写真があれば女性を引き付けることができるよ", + "up_cancle": "上にスライドして送信をキャンセルする", + "msg_not": "メッセージはブランクにできません", + "need_record": "この機能は録音権限を与える必要があります", + "downloading_video": "ビデオファイルをダウンロードしている", + "reinput": "問題のシリアル番号を再入力してください", + "dy_delete": "あなたのダイナミックはユーザーに匿名で告発されました。システムで確認した結果よりこの動態は削除されました。二度と不正操作の場合、アカウントは永遠凍結されます。", + "pro_delete": "あなたの番組はユーザーから匿名で告発されました。システムで確認した結果より番組を削除しました。二度と不正操作の場合、アカウントは永遠凍結されます。", + "con_delete": "あなたのコメントはユーザーから匿名で告発されました。システムで確認した結果よりコメントを削除しました。二度と不正操作の場合、アカウントは永遠凍結されます。", + "coin_returen": "匿名ユーザーの告発より、システムはあなた最近ルール違反したことを確認出来た、ご受け取ったH幤を返済しました、二度と不正操作の場合、アカウントは永遠凍結されます", + "voicing": "通話中はエロやわいせつなどの違法行為が禁止されています、一旦発見したらアカウントは永遠凍結を処理する", + "help": "顧客サービス", + "translate_on": "人工翻訳をオンにする", + "translate_off": "人工翻訳をオフにする", + "becomeSvip": "/s1 H幤を使ってSVIPになります", + "need_svip": " svip権限をオンにできます", + "cannot_vip": " SVIPはVIPのチャージができません", + "offline": "あなたはもうオフラインです。メッセージの送信と受信ができません", + "otherLogin": "アカウントは他のデバイスに登録されました、もうオフラインです", + "no_new": "暫く新しいニュースがありません", + "over": "翻訳完了", + "bad_ev": "この翻訳内容に悪評価しますか?", + "right5": "もっと気持ちよくチャットする", + "right6": "もっと気持ちよくに使える", + "man_vi": "お兄ちゃん", + "women_vi": "お姉ちゃん", + "kf_tips": "サービスの効率を高めるために、以下に問題があれば、直接シリアル番号を回答してくださいね!", + "rejected": "拒否されました", + "buy_vip": "あなたは/s1H幤を支払って、VIPを購入しました", + "buy_program": "あなたは/s1H幤を支払って、ダイナミック番組を発表しました", + "del_add_money": "あなたは/s1H幤換金申請は処理出来ました、あなたの銀行カードに/s1を振込ました、ご査収ください", + "adding_money": "あなたが換金/s1H幤の申請は審査中です", + "free_translate": "無料で通訳専任者がリアルタイムで通訳してくれます", + "personalTraff": "あなたに専用顧客サービスを提供する", + "ManTranslate": "人工翻訳中...", + "robotTranslate": "マシン翻訳中...", + "translated": "人工翻訳完了", + "delete_progarm": "健康交流、低俗な内容を放送しないでください、発見したら削除します", + "open_location": "位置決め権限未許可", + "get_location": "他のユーザーの距離を得るために、位置決め権限を設定してください", + "confirm_exit": "もう一度押してログアウトします", + "free_program": "毎日/s1回のチャンスに無料放送を発表します", + "picture": "写真", + "camera": "カメラ", + "video": "ビデオ", + "red_money": "ご祝儀", + "stick": "スティック", + "press_say": "押したまま話す", + "get_money": "/s1はあなたのご祝儀を受け取りました", + "you_get_money": "あなたは/s1のご祝儀を受領しました", + "ones_money": "/s1のご祝儀", + "money_over": "ご祝儀は期限切り", + "downloading_fail": "ファイルのダウンロードに失敗しました", + "downloading": "ビデオファイルをダウンロードしています", + "back_money": "未受け取ったご祝儀は、24時間後に払い戻しいたします", + "no_money": "ご祝儀は存在しません", + "already_money": "ご祝儀は受領しました", + "back_user": "期限切り、アカウントへ返却しました", + "waiting_user": "受取を待つ", + "other_get": "相手が受け取りました", + "little": "ささやかな気持ちですが、どうぞお受け取りください", + "put_money": "お金を入れます", + "mount": "金額", + "over_time": "期限切り", + "has_get": "受け取りました", + "no_gift": "暫くプレゼントがない", + "sent_gift": "プレゼントを贈る", + "fill_tips": "入力してから/s1H幤が得る、関連する後修正できません", + "bind_code": "招待コード関連する", + "invide_code": "招待コード", + "confirm_delete": "削除確認", + "has_eva": "あなたは既にコメントしました", + "open": "オープン", + "voice": "音声", + "release_send": "離して送信", + "time_little": "録音時間が短すぎます", + "not_online": "相手はオンラインではなく、連絡ことができません", + "give_red_money": "あなたは/s1へ/s2H幤のご祝儀を送りました", + "get_red_money": "あなたは/s1から/s2H幤のご祝儀を受領しました", + "give_other_money": "あなたは/s1へ/s2H幤を贈りました", + "get_other_money": "あなたは/s1から/s2H幤を貰いました", + "svip": "スーパーメンバー", + "recommend": "お薦め", + "paid_you4": "あなたは(/s2H幤)を支払って、/s1のご礼儀写真を見ました", + "paid_you5": "あなたは(/s2H幤)を支払って、/s1の写真を見ました", + "paid_you6": "あなたが有料で/s1の全部資料をロック解除しました", + "UG_LINE0": " hiAPP許可及びサービス協議", + "UG_LINE1": "[序言]", + "UG_LINE2": "Qianhai Youlong Technology Co., Ltd.(以下は“Qianhai Youlong Technology Co., Ltd.”と略称) ユーザーは、このサービス契約(以下「契約」と略称)を真面目読み、完全に理解必要です。Qianhai Youlong Technology Co., Ltd.の責任の免除またはユーザー権利の制限を含む本契約の条款を完全に理解すること。深く読みこの契約に同意するかどうかを選択してください(未成年者は法的保護者と一緒に読んでください)。 本契約のすべての条件に同意しない限り、本契約の対象となる関連サービスを登録、ログイン、または使用する権利はありません。 あなたの登録、ログイン、使用などは、本契約に同意したものとみなされ、また本契約の条件に拘束されることも同意すること。", + "UG_LINE3": "本「契約」は、あなた「以下は“ユーザー”と略称」を「hiサービス」のユーザー登録、ログイン、および使用に関するQianhai Youlong Technology Co., Ltd.との間の契約です。本契約は、「hiサービス」に関連するQianhai Youlong Technology Co., Ltd.とユーザー間の権利と義務について説明しています。「ユーザー」とは、登録、ログイン、使用、閲覧する個人または団体を意味します。本契約を同意することは、本契約の条款を受けることとQianhai Youlong Technology Co., Ltd.がいつでも契約条款変更することも受け入れること。本「契約」は、Qianhai Youlong Technology Co., Ltd.がいつでも更新できます。更新された契約条款が発表されると、元の契約条款を置き換えます、改めて通知しませんので、ユーザーはこのAPPで契約条款の最新バージョンが確認できます。Qianhai Youlong Technology Co., Ltd.が契約条件を改訂した後、ユーザーが改訂された条款に同意しない場合、Qianhai Youlong Technology Co., Ltd.が提供するサービスの使用を直ちに停止してください。CyhdLimitedが提供するサービスを継続使用ユーザーは、改訂された契約に同意したものとみなされます。", + "UG_LINE4": "一、使用規則", + "UG_LINE5": "1、ユーザーが十分了解且つ同意して、ただユーザーに情況シェア、伝送、取得用のプラットフォームに限られる。ユーザーは必ずアカウントを登録した後の全ての行為に責任を取ってください。ユーザーが伝送したあらゆる内容及びそれによって発生した全ての結果も含めている。", + "UG_LINE6": "2、ユーザーがサービス中或いはサービスを通して伝送した全ての内容はQianhai Youlong Technology Co., Ltd.の観点と政策を反映していないことである。Qianhai Youlong Technology Co., Ltd.はそのに対して一切責任を負わないことである。", + "UG_LINE7": "3、ユーザーが十分了解且つ同意して、ユーザーネットワークに基づく社交情況ブラウザ製品、ユーザーが必ずその上に登録した情況の真実性、合法性、有効性を全て責任を取ること。ユーザーは他人に見せ掛けていけない、他人の名義で一切の情報を広まっていけない。登録したアカウントを悪用して他のユーザーに誤認されてはいけない。でないとQianhai Youlong Technology Co., Ltd.は直ちにサーブすを停止し、ユーザーアカウントを回収して、ユーザーにそのにより単独で一切の責任を負うことになる。", + "UG_LINE8": "4、ユーザーが必ずその上に登録した情況の真実性、合法性、無害性、有効性を全部責任と取る。ユーザーが広まった情報に関わる一切の法律責任はユーザー本人が担当する、Qianhai Youlong Technology Co., Ltd.に関係ないことである。", + "UG_LINE9": "5、Qianhai Youlong Technology Co., Ltd.が業務発展の必要を保留し、一方的に当サービスの全部或いは一部分のサービス内容をどんな時になんにも通知しない場合に変更、止まる、限定、終止或いはサービスを廃止する権利があり、ユーザーはそのリスクを負うことである。", + "UG_LINE10": "6、提供しているサーブす中には広告がある可能性があり、ユーザーは使用過程中に第三方サプライヤー、経営パートナーと提供している広告を現れることを同意する。", + "UG_LINE11": "7、ユーザーは下記内容を利用又はサービス制作、アップロード、コーピー、送信をできないこと:", + "UG_LINE12": "(1 ) 憲法に定められる基本原則を反対する;", + "UG_LINE13": "(2) 国家安全に危害すること、国家秘密を漏れること、国家政策を顛倒すること、国家統一を破壊すること;", + "UG_LINE14": "(3) 国家の栄誉と利益を損害すること;", + "UG_LINE15": "(4) 民族の恨みを煽動すること、民族差別、民族団結を破壊すること;", + "UG_LINE16": "(5) 国家の宗教政策を破壊すること、邪教と封建迷信を宣伝すること;", + "UG_LINE17": "(6) 謡言を散布すること、社会秩序をすること、社会安定を破壊すること;", + "UG_LINE18": "(7) 猥褻、プルノ、ギャンブル、暴力、殺人、恐怖あるいは犯罪を扇動すること;", + "UG_LINE19": "(8) 他者を侮辱または中傷し、その法的権利および利益を侵害すること;", + "UG_LINE20": "(9) 法律および行政規制により禁止されている内容及び情報。", + "UG_LINE21": "8、Qianhai Youlong Technology Co., Ltd.は、その合理的な判断より、法令または本契約に違反、または他人の権利やセキュリティを侵害、妨害、脅迫する、または他人になります行為、Qianhai Youlong Technology Co., Ltd.は法律に従って前述のコンテンツの送信を停止する権利があるし、独自の裁量でこの条項に違反した人に対して適切な法的措置を取る権利もあり。これには、サービスからの違法、侵害、不適切なコンテンツの削除が含まれますが、これらに限定されません 、違反者のメンバーシップを終了し、サービスのすべてまたは一部を使用することを禁止し、法令に従って関連する情報を保存し関係部門へ報告すること。", + "UG_LINE22": "9、ユーザーの権利と義務:", + "UG_LINE23": "(1 ) Qianhai Youlong Technology Co., Ltd.アカウントはQianhai Youlong Technology Co., Ltd.が所有しています、ユーザーは新規取得登録手順を完了すると、アカウントを使用する権利を取得しますが、この権利は元の申請者のものであり、アカウントの付与、借用、賃貸、譲渡、販売は禁止されること。Qianhai Youlong Technology Co., Ltd.はビジネス上のニーズにより、アカウントを回収する権利があり、また、ユーザーの写真、ビデオ、音声を使って製品プロモーション活動を実施することの権利もあること。", + "UG_LINE24": "(2) ユーザーはQianhai Youlong Technology Co., Ltd.での個人情報、登録情報、および送信コンテンツを変更または削除する権利を持っていますが、関連情報を削除すると、システムに保存されているテキストや写真も削除されます。 ユーザーはこのリスクを負うこと。", + "UG_LINE25": "(3) ユーザはアカウント情報とアカウントパスワードを安全に保つこと責任があり、ユーザーは、登録されたアカウントとパスワードが以下のアクションに対して法律責任を負う。ユーザーは、いかなる状況でも他のメンバーのアカウントまたはパスワードを使用しないことに同意する。 あなたは、誰かがあなたのアカウントまたはパスワードを使用していることを疑い場合、Qianhai Youlong Technology Co., Ltd.に直ちに連絡することを同意する。", + "UG_LINE26": "(4) ユーザは本契約の各条款を遵守し、正しく適度に使用するものとします、ユーザーが本契約の条款に違反した場合、Qianhai Youlong Technology Co., Ltd.は契約に従ってサービスを終了する権利を持、 同時に、Qianhai Youlong Technology Co., Ltd.はアカウントとユーザー名をいつでも回収する権利を保留しています。", + "UG_LINE27": "(5) ユーザーが自分の英語アカウントを持っている場合、優先的に該当アカウントをアカウントとして登録する権利を持ちます、ただし、サービスがオンラインになってから一定期間内ユーザーがアカウントを登録していない場合、あるいは、ユーザーはウィーキャットアカウント登録しますが、該当英語アカウントをウィーキャットアカウントとして使用しない場合、ユーザーは該当英語アカウントをウィーキャットアカウント登録する権利を諦めることに見られる、資源を無駄しないために、Qianhai Youlong Technology Co., Ltd.は該当英語アカウントを回収及び他ユーザーに配分使用権利があります、それらに引きこされる問題はユーザー自身責任を負うこと。", + "UG_LINE28": "(6)資源を無駄しないために、ユーザーはアカウントを登録した後、長期間該当アカウントをログインしない場合、Qianhai Youlong Technology Co., Ltd.は該当アカウントを回収する権利があり、それらに引きこされる問題はユーザー自身責任を負うこと。", + "UG_LINE29": "(7) ユーザは紛争を起きた場合、告発機能を使ってプラットフォーム利益を維持できるユーザーから告発フィードバックを受け取った場合、状況を確認するために、告発されたユーザーは顧客サービス担当者に積極的に回答または協力する義務があります、告発された内容を確認できたら、ユーザに警告し、アカウント使用機能を制限してルール違反ことを制約する権利があります、厳重者に対してhiはアカウントを直接凍結する権利がありますし、アカウントの残高も返金されません。もし、アカウントは凍結された場合、ユーザーはサービス担当者に連絡可能です 。", + "UG_LINE30": "二、プライバシー保護", + "UG_LINE31": "ユーザーは、個人のプライバシー情報とは、ユーザーに対して個人識別、個人的なコミュニケーション情報を指すことに同意する、下記の情報を含め:ユーザーの本名、携帯電話番号、ウィーキャット、faceboodアカウント、IPアドレス。非個人のプライバシー情報とは、ユーザーの操作状態及びサービスの使用習慣、客観的にQianhai Youlong Technology Co., Ltd.サーバーへ反映されている基本情報、および個人のプライバシー情報の範囲外の他のすべての一般情報、ユーザーが開示することを同意する上記のプライバシー情報を指す。ユーザーの個人プライバシーを尊敬することはQianhai Youlong Technology Co., Ltd. 一貫の制度です、法律あるいは法律許可した政府部門からの要求あるいはユーザーの許可を得た原因以外、Qianhai Youlong Technology Co., Ltd.は合理的の方法でユーザーの個人プライバシーを保護する、ユーザーの許可がない限り、Qianhai Youlong Technology Co., Ltd.は協力パートナー以外の第三者にユーザーの個人プライバシー情報を開示する。ただし、ユーザーは登録の時、許可を選択して、またはQianhai Youlong Technology Co., Ltd.と協力パートナーとユーザーの個人プライバシー情報の開示は別の約束は以外、同時に発生する可能のリスクはユーザー自分負担する必要です、Qianhai Youlong Technology Co., Ltd.はこれについて責任を負いません。また、Qianhai Youlong Technology Co., Ltd.の技術とサービスを運用および改善するため、Qianhai Youlong Technology Co., Ltd.は自ら収集、使用あるいは第三者にユーザーの非個人プライバシー情報を提供する、これにより、Qianhai Youlong Technology Co., Ltd.はユーザーにより良いユーザーエクスペリエンスを提供し、Qianhai Youlong Technology Co., Ltd.のサービスの品質を向上させることができる。Qianhai Youlong Technology Co., Ltd. はユーザーとのインタラクティブ、またはユーザーの選択より収集出来たデータ、ユーザーのプライバシー設定及びユーザー使用製品と機能。Qianhai Youlong Technology Co., Ltd.が収集するデータには、SDK / API / JSコードバージョン、IPアドレス、プラットフォーム、タイムスタンプ、アプリケーション識別子、アプリケーションバージョン、アプリケーション配布チャネル、独立したデバイス識別子、iOS Advertising Identifier(IDFA)、Android Advertising識別子、ネットワークカード(MAC)アドレス、International Mobile Equipment Identity(IMEI)、デバイスモデル、端末メーカー、端末デバイスのオペレーティングシステムのバージョン、セッションの開始/停止時間、言語の場所、タイムゾーン、ネットワークステータス(WiFiなど) ハードドライブ、CPU、バッテリーの使用量などを含まれる場合がある。これにより、Qianhai Youlong Technology Co., Ltd.は、内部データ分析と調査、第三者SDK統計サービスを実施し、Qianhai Youlong Technology Co., Ltd.の製品またはサービスを改善することができます。ユーザーID情報の信頼性を確保し、ユーザーにより良いセキュリティを提供するために、ユーザーはID情報または顔の特徴などの生物識別情報(どちらも個人敏感情報)を提供して、特定の製品サービスまたは本人の認証を完成する。上記の情報は、ユーザーの身元の信頼性を確認するためにのみ使用されます。ユーザーが提供する上記の情報は、ユーザーがサービスを使用している間、Qianhai Youlong Technology Co., Ltd.による使用を引き続き許可します。Qianhai Youlong Technology Co., Ltd.はユーザーがログアウトすると使用を停止します。上記の情報は、中華人民共和国に保存されます。 国境を越えて送信が必要な場合、Qianhai Youlong Technology Co., Ltd.はユーザーの承認を取得します。 APPユーザーの認証はユーザーがユーザーのIDの信頼性を検証できる情報を提供する必要があります。関連情報はプラットフォーム監査にのみ使用され、介入を必要とする法務部門または関連部門を除き、他のユーザーに開示されたり、商業目的に使用されたりすることはありません。", + "UG_LINE32": "三、Qianhai Youlong Technology Co., Ltd.商標情報", + "UG_LINE33": " Qianhai Youlong Technology Co., Ltd.サービスに関するlogoなどの図形、文字またはその構成、及び他Qianhai Youlong Technology Co., Ltd.マークと製品、サービス名称などは全部Qianhai Youlong Technology Co., Ltd.の商標です(以下略称“Qianhai Youlong Technology Co., Ltd.標示”)事前に Qianhai Youlong Technology Co., Ltd.の書式許可がないとユーザーはQianhai Youlong Technology Co., Ltd.標示 をいかなる方法で表示または他の処理が禁止、あなたがQianhai Youlong Technology Co., Ltd.標示の展示、使用、またはその他の権利を持っていることを他人に表明してはいけません。", + "UG_LINE34": "四、法律責任及び免責", + "UG_LINE35": "1、ユーザーは本「協議」または関連サービス条項の規定に違反し、任意の第三者の主張によるいかなる賠償、要求または損失を引き起こし、合理的な弁護士費を含み、ユーザーはQianhai Youlong Technology Co., Ltd.と協力会社、関連会社を賠償することに同意し、損害を免除させること。", + "UG_LINE36": "2、ユーザは、電信部門の通信回線の故障、技術問題、ネットワーク、コンピュータの故障、システムの不安定性及びその他の様々な不可抗力の原因によって被ったすべての損失については、Qianhai Youlong Technology Co., Ltd.及び協力機関は責任を負いません。", + "UG_LINE37": "3、技術障害などの不可抗事件によってサービスの正常運行に影響を与えた場合、Qianhai Youlong Technology Co., Ltd.と協力会社は第一時間内に関連会社と協力し、直ちに処理して修復することを承諾しましたが、ユーザーが被ったすべての損失に対して、Qianhai Youlong Technology Co., Ltd.と協力会社は責任を負いません。", + "UG_LINE38": "4、本サービスは大多数のインターネットサービスと同じで、ユーザーの原因、ネットサービスの質、社会環境などの要素の違いによって影響されるかもしれません。様々な安全問題に侵される可能性があります、他人がユーザーの資料を利用して、現実的な生活における嫌がらせを引き起こすかもしれません。ユーザーがインストールした他のソフトウェアや訪問した他のウェブサイトには「トロイの木馬」などのウィルスが含まれています。ユーザーのコンピュータ情報やデータの安全を脅かし、本サービスの正常な利用に影響を及ぼすなど。ユーザーは情報の安全と利用者資料の保護意識を強化し、損失や迷惑にならないように、パスワードの保護を強化してください。", + "UG_LINE39": "5、ユーザーは、本サービスの利用はインターネットサービスに関わるため、各環節の不安定要素の影響を受ける可能性があることを理解してください。したがって、本サービスは、不可抗力、コンピュータウイルスまたはハッカー攻撃、システムの不安定性、ユーザーの位置、ユーザのシャットダウン、その他のいかなる技術、インターネット、通信回線の原因などによるサービスの中断またはユーザーの要求を満たすことができないリスクがあります。ユーザーは以上のリスクを負担し、Qianhai Youlong Technology Co., Ltd.は担保しない。その結果、ユーザが閲覧情報を送信したり、受信したりすることができなくなり、Qianhai Youlong Technology Co., Ltd.は一切の責任を負いません。", + "UG_LINE40": "6、ユーザーは、サービスの使用中に、脅迫的、中傷的、好ましくない、または違法なコンテンツ、行動、または他者の権利(知的財産を含む)の侵害を含む、他者からの匿名性または匿名性があることを理解する必要があります 詐欺的な情報のリスク、ユーザーは上記のリスクを負わなければなりません、。Qianhai Youlong Technology Co., Ltd.と協力会社は本サービスに対していかなる種類の保証をしないで、明確であるかまたは暗黙的であるかに関わらず、すべての関連情報の真実性、適商性、ある特定の用途、所有権と非侵害性に適した黙示担保と条件を含み、それによっていかなる使用者の不正または不法使用サービスによって発生した直接、間接、偶然、特殊及び後続の損害に至るかについていかなる責任も負いません。", + "UG_LINE41": "7、Qianhai Youlong Technology Co., Ltd.で定義されている情報の内容は、文字、ソフトウェア、音声、写真、ビデオ、図表;広告中のすべての内容を含み;Qianhai Youlong Technology Co., Ltd.はユーザーに提供された商業情報で、これらのすべて著作権、商標権、その他の知的財産権と所有権は法律の保護を受けます。したがって、ユーザーはQianhai Youlong Technology Co., Ltd.と広告主の授権がある状況でしかこれらのコンテンツを使用できません。これらの内容を無断でコピー、修正、編集すること、またはコンテンツに関する派生商品を創造することは一切禁止です。", + "UG_LINE42": "8、いずれの場合も、Qianhai Youlong Technology Co., Ltd.は任意の間接性、結果性、懲罰性、偶然性、特殊性または刑罰性の損害、ユーザーのサービスご利用による利益損失も含め、以上について責任を負いません(たとえすでにそのような損失の可能性が告知されたとしても。)。本契約にはパラドックスな規定が含まれているかもしれませんが、Qianhai Youlong Technology Co., Ltd.があなたに対して負担しているすべての責任は、どのような行為があっても、いつまでもメンバー期間内にサービスを利用してQianhai Youlong Technology Co., Ltd.に支払う費用を超えません。", + "UG_LINE43": "五、VIP条項", + "UG_LINE44": "1、Hibok VIPは平等に会員の権利を享有し、同時にQianhai Youlong Technology Co., Ltd.の規則、本サービス条項と「ユーザー協議」を含むがこれに限らないの各条項を遵守しなければならない。", + "UG_LINE45": "2、Qianhai Youlong Technology Co., Ltd.の「ユーザー協議」に違反したた原因でVIPサービスの利用を一時停止させたことに関する損失はユーザー自身で負担すること。", + "UG_LINE46": "3、VIPはVIP資格の有効期限内にhiviipの各種付加価値サービスも享有できること。", + "UG_LINE47": "4、VIPがVIP資格の有効期限内に自発的にVIP資格を終了したり、キャンセルしたりする場合、Qianhai Youlong Technology Co., Ltd.は当該VIPの残りのVIP資格の有効期限に対応するサービス費用を返還しないこと。", + "UG_LINE48": "5、VIPは自分でhiの中で情報を伝達して、発表しておよびhi無料サービスあるいは有料サービスを使う法律責任を負って、VIPはhiサービスを使って、無料サービスと有料サービスの行為を含んで、すべて各法律法規、規則、規範性文書を守るべきであること。", + "UG_LINE49": "6、VIPサービスを開通後は他人に譲り渡す、キャンセルなどはできません。", + "UG_LINE50": "7、VIPはQianhai Youlong Technology Co., Ltd.無料サービスまたは有料サービスを利用する過程で、法律法規に違反する行為がある場合、Qianhai Youlong Technology Co., Ltd.は会員資格を取り消す権利があり、一切の補償もありません、会員は自ら責任を負うべきです。", + "UG_LINE51": "六、他条款", + "UG_LINE52": "1、Qianhai Youlong Technology Co., Ltd.は慎重にユーザーに本「協議」中のQianhai Youlong Technology Co., Ltd.の責任を免除し、ユーザーの義務を強める条項に注意してください。未成年者は法定保護者の同伴で本「協議」を読むべきです。以上の各条項の内容の最終説明権と修正権はQianhai Youlong Technology Co., Ltd.の所有になります。", + "UG_LINE53": "2、本「協議」に定められた如何なる条項の一部または全部無効者は、他の条項の効力に影響しません。", + "UG_LINE54": "3、本「協議」の解釈、効力及び紛争の解決は中華人民共和国の法律に適用される。ユーザーとQianhai Youlong Technology Co., Ltd.の間に如何なる紛争や紛争が発生した場合、まず友好的に協議して解決しなければならず、協議が成立しない場合、ユーザーはここで紛争や争議をQianhai Youlong Technology Co., Ltd.住所地の人民法院の管轄に提出することに完全に同意すること。", + "UG_LINE55": "4、本『契約』の著作権はQianhai Youlong Technology Co., Ltd.が所有し、Qianhai Youlong Technology Co., Ltd.は一切の解釈と修正の権利を保留します。", + "UG_LINE56": "Qianhai Youlong Technology Co., Ltd.", + "net_error": "ネットワーク異常", + "enter_name": "お名前を入力してください", + "translate": "訳", + "locate": "位置", + "voice_tips": "押しまま録音,離して送信", + "unlock": "アンロック", + "input_content": "チャット内容を入力してください", + "connecting": "接続中...", + "logining": "登録中...", + "reject_reply": "/s1はあなたのレビューリクエストを拒否されたました", + "warning_text": " H幣は入金三日間以内告発されない場合、両替可能です(1:1000ベトナムドン)", + "more_big": "入力数量は大きくても/s1", + "little_min": "入力数量は少なくても/s1", + "voice_msg": "/s1音声呼び出しに招待する", + "send_gift": "あなたは相手に/s1个/s2を贈りました", + "receive_gift": "先方は/s1个/s2アイテムを贈りました", + "cannot_join": "非VIPは申し込みできない", + "alreay_back": "バックしました", + "video_more_big": "ファイルが大き過ぎ", + "select_all": "全てを選択", + "re_connect": "再接続", + "voice_tips2": "離して送信、スライドしてキャンセル", + "country": "国", + "have_picture_view": "写真検定中", + "speaker_play": "スピーカー再生", + "handset_playback": "受話器再生", + "play_model": "受話器モード", + "password_less": "パスワードが短すぎる", + "years_old": "歳", + "coin_returen1": "匿名のユーザーからの告発を受けて、最近の不正行為を確認しました。二度と不正行為をしないでください。次回があれば、アカウントを凍結します", + "already_new": "すでに最新バージョンです", + "test_it": "すぐ試します", + "found_new": "新しいバージョンが発見", + "ad": "広告", + "attention": "注目", + "fans": "ファン", + "apply_see": "/s1 は私の資料ベージを見るリクエストがあります", + "agree_apply": "/s1 は私のリクエストをパスしました", + "see_redBag": "/s1 はご祝儀写真を見ました", + "notice": "注意", + "notice_open": "携帯電話の設定で通知権限をオンにして、メッセージの通知が受け取ります。", + "open_notice": "通知権限がオンになっていません", + "not_open": "通知権限がオンになっていませんので、通知を受信できません", + "withdraw_fail": "換金を申請した/s1H幤が返却されました、関連されたアカウントが正しいかを確認してください", + "dynamics": "タイムカプセル", + "Remark": "注釈とタグ", + "setRemark": "設定ノート", + "content_num": "/s1通のコメント", + "Redeem": "ポイント交換で/s1H幤を得る", + "location_permission": "携帯メモリーにアクセスする権限がありません", + "camera_permission": "カメラにアクセスする権限がありません", + "photo_permission": "アルバムにアクセスする権限がありません", + "video_permission": "マイクにアクセス権限がありません", + "your_redMoney_over": "ご祝儀が期限切り", + "other_redMoney_over": "相手からのご祝儀が期限切り", + "server_error_tips": "ちょっと不具合があるようです...", + "emoji": "ステッカー", + "today_score": "本日サインして/s1ポイントが受け入れる", + "sign_tips": "1.毎日サインしてポイントが受け入れます、累積日数が多ければ多いほどポイントが高くなります.\n2.ポイントはH幤に交換できます、交換はポイントを消費しますので慎重に交換してください.\n3.サインは毎月の最終日にリセットされ、ポイントもクリアされます。時間内に交換することを忘れないでください.", + "sign_in": "サイン", + "my_score": "私のポイント", + "signin_now": "すぐサインする", + "sign_in_day": "累計サイン/s1日", + "have_get": "交換しました", + "scan": "スキャン ", + "my_qr": "自分のQRコード", + "scan_and_add": "スキャンして友人を追加する", + "amap": "高徳マップ", + "baidumap": "百度マップ", + "googlemap": "Google マップ", + "applemap": "Apple マップ", + "go_open": "オンにする", + "Preview": "プレビュー", + "Photo_album": "アルバム", + "all_photo": "全ての画像", + "have_select": "/s1枚の画像を選択しました", + "loading": "読み込み中…", + "new_chat_msg": "新しいメッセージがあります", + "new_video_msg": "新しい音声メッセージがあります", + "apply_friends": "/s1から友人になる申請が入りました", + "applyed_friends": "/s1は友人の追加をパスしました", + "contact_permission": "連絡先にアクセスする権限がありません", + "contact": "連絡先", + "search": "検索", + "contact_add": "携帯のアドレス帳から追加", + "find": "発見", + "translate_robot": "翻訳ロボット", + "robot_hello": "こんにちは、私は翻訳ロボットです…", + "Simplified_Chinese": "中国語(簡体字)", + "traditional_Chinese": "中国語(繁体字)", + "english": "英語", + "Vietnamese": "ベトナム語", + "Korean": "韓国語", + "Japanese": "日本語", + "add_friends": "友人の追加", + "stranger": "見知らぬ人", + "receive_stranger": "見知らぬ人からのメッセージを受信する", + "signin": "SignIn", + "stranger_close": "メッセージの受信を拒否された、すべての情報のロックを解除し続けますか。", + "add": "追加", + "added": "追加済み", + "stranger_close_tips": "相手は見知らぬ人からのメッセージの受信を拒否した。", + "translate_fail": "翻訳失敗", + "no_photos": "ご祝儀写真を設定する前に写真をアップロードしてください。", + "successful_appeal1": "あなたのアピールコメント:/s1アピール失敗", + "add_success": "追加しました,相手の同意を待つ", + "other_pay": "他人が立て替える", + "friend_verification": "友人認証", + "add_friends_tips": "認証申請は発送しました、相手の承認待ち", + "i_am": "私は/s1", + "agree": "許可", + "privacyAgreement": "\"Hi\"《プライバシー協議》に同意していただくと使えます", + "privacy": "プライバシー協議", + "notification_addfriend": "Hi!友人要請が入りました、誰か確認しましょう", + "distance_long": "顔を付き合わせて友人追加しかできませんよ", + "chat_tips": "翻訳内容の正確さのために、略語は遠慮してください", + "fans_list": "ファンリスト", + "system_not_open": "機能内テスト中", + "service_withdraw_tips": "iOSクライアントはまだサポートされていません。Androidクライアントを使って引き出したり、下のボタンを押して引き出したりできます", + "withdraw_tips": "クリックして引き出し", + "add_member": "メンバー追加", + "delete_member": "メンバー削除", + "change_group_name": "グループ名を修正", + "my_group_nickname": "マイエイリアスグループ", + "group_chat": "グループチャット", + "create_group_chat": "グループチャットを作る", + "added_friends_tips": "認証申請を送信必要、相手がパスまで待ちます", + "group_chat_name": "グループ名", + "my_group_nickname_tips": "ここであなたのグループニックネームを設定できます、このニックネームはこのグループにしか表示されません", + "man_gold": "男神タイムカプセル", + "woman_gold": "女神タイムカプセル", + "choose_group_owner": "新しいグループオーナーを選択", + "group_announcement": "グループ通知", + "chat_news": "チャットメッセージ", + "group_qr": "グループQRコード", + "group_setting": "グループを管理", + "close_news_notice": "ミュート通知", + "set_chat_top": "一番上に表示する", + "show_group_member_name": "グループメンバーのニックネームを表示", + "quit_group_tips": "退出後グループチャットの他のメンバーには通知せず,これからこのグループからメッセージを受け取りません", + "quit_and_delete": "削除して退出", + "show_more_member": "さらにメンバーを見る", + "group_invite": "グループチャットの招待確認", + "change_group_owner": "グループオーナー管理権譲渡", + "group_setting_tips": "有効にすると、グループメンバーは、グループに友人を招待するためにグループオーナーからの確認を必要とします。ORコードスキャンしてグループに入ることは同時に停止されました。", + "invite_detail": "招待内容", + "undefine_name": "未命名", + "group_qr_code": "グループQRコードカード", + "group_qr_code_tips": "該当QRコード七日内(/s1月/s2日前)有効,再度ログインすると更新されます", + "Goddess_heat": "女神人気", + "Goddess_heat_tips": "累計収穫のプレゼント", + "new_friends": "新しい友人", + "before_three_day": "三日前", + "after_three_day": "この三日間", + "group_clean_chat_record": "チャット履歴の削去", + "check": "確認", + "apply_fro_friends": "友人要請", + "no_vip_cannot_withdraw": "非VIPは引き出しできません", + "not_true_woman": "このユーザは認証されていません、騙されないように注意してください", + "join_group": "グループチャットに参加する", + "sign_in_apple": "Appleで登録", + "only_host": "グループオーナーだけがグループ通知を編集することができる", + "send_gift1": "あなたは相手に/s1個プレゼントを贈りました", + "receive_gift1": "相手は/s1個プレゼントをあなたに贈りました", + "not_in_group": "あなたはもうこのグループにいません", + "creating_group": "作成中です,少々お待ちください", + "article": "条", + "group_open_verification": "このグループはすでにグループ認証をオンにしました。招待によってのみグループに入ることができます", + "group_memeber": "グループメンバー", + "invite_members": "/s1名友人をこのグループに招待する", + "total_members": "トータル/s1人", + "qr_outtime": "QRコードが失効しました", + "no_goupr_info": "このグループ通知がありません", + "you_invite": "あなたは/s1をグループに招待する", + "invite_you": "あなたは/s1にグループへ招待されました", + "invite_someone": " /s1 は /s2 を招待しました", + "you": "あなた", + "delete_group": " /s1は /s2 をグループに削除しました", + "you_group_owner": "あなたは新しいグループオーナーになりました", + "someone_group_owner": "/s1は新しいグループオーナーになりました", + "change_group_owner1": "グループ名は/s1に変更しました", + "update_group_announce": "グループ通知は更新しました", + "you_qr": "あなたはQRコードスキャンしてグループに入る", + "others_qr": "/s1はQRコードスキャンしてグループに入る", + "invite_confirm": "\"/s1\"は/s2名友人をグループに招待したい \\$確認\\$ ", + "want_invite_confirm": " \"/s1\" は\"/s2\" をグループに招待したいです ", + "join_group_confirm": "\"/s1\" はグループに入りました、確認済み", + "you_invite_gourp": "あなたは /s1にグループへ招待されました ", + "someone_join_group": " \"/s1\" はグループに入りました ", + "group_setting_tips1": "グループオーナーはすでに「グループチャット招待確認」をオンにしています。グループメンバーはグループオーナーを確認してから友達をグループに招待することができます", + "group_setting_tips2": "グループオーナーがデフォルトのグループ参加方法を戻す", + "members_max": "グループメンバーが上限になりました", + "group_max": "グループの数量は上限になりました", + "my_money_info": "私の請求書", + "my_left_money": "残高", + "money_tips": "H幣はチャージや両替で得られます、引き出しができません", + "get_money_detail": "所得明細", + "hibok_money": "Hibox收入", + "charge_h": "H幤に両替", + "charge_tips": "引き出し規則", + "splash_tips1": "百変の位置", + "splash_tips2": "翻訳ロボット", + "splash_tips3": "交友APP", + "splash_tips_content1": "百変の女神,好きのを選ぶ", + "splash_tips_content2": "音声チャット", + "splash_tips_content3": "言語問題解決", + "splash_go": "すぐ体験", + "change_h_coin": "収入から/s1H幤を両替します", + "Representation_succes": "申し立ては成功し、システムは返金しました", + "system_give": "システム支払い", + "exchange_fail": "引き出し申請は失敗しました,返送されました", + "hibok_exchange": "Hibox収入で/s 1 H幤に両替します", + "bind_code_success": "招待コード関連成功", + "translate_money": "人工翻訳のために/s1H幤を消費しました", + "system_back": "システムキャンセルリターン", + "you_give": "相手にプレゼントを贈る", + "you_get": "相手からプレゼントを貰った", + "enter_num_qian": "交換数量(单位K)", + "enter_num_qian1": "引き出し数量(单位K)", + "daily_translate_voucher": "翻译券", + "msg_notice":"通知消息", + "select_notice_people":"选择提醒的人", + "search_phone":"查找手机号", + "not_have_user":"用户不存在", + "not_add_Myself":"你不能添加自己", + "you_are_blaklisted":"对方已拉黑了你", + "confrim_recovery":"确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)", + "send_to": "發送到" +} \ No newline at end of file diff --git a/i18n/ko-KR.json b/i18n/ko-KR.json new file mode 100644 index 0000000..e52acc3 --- /dev/null +++ b/i18n/ko-KR.json @@ -0,0 +1,1163 @@ +{ + "appName": " 흔호 공원", + "login": "로그인", + "registration": "회원가입", + "other_login": "기타 로그인", + "account": "아이디 ", + "enter_username": "아이디 입력하세요", + "password": "암호 ", + "enter_password": "암호 입력하세요", + "forget_password": "암호 찾기", + "reset_password": "암호 재설정하기 ", + "number_registration": "휴대폰 번호 등록", + "enter_number": "휴대폰 번호 입력하세요", + "code": "검증 코드", + "enter_code": "받은 인증 코드 입력하세요", + "send_code": "인증 코드 보내기", + "send_again": "다시 보내기 ", + "set_password": "암호 설정", + "password_limit": "암호 6짜리이상 설정하세요", + "set_password2": "로그인 암호 설정하세요", + "next_step": "다음 단계", + "agreed_agreement": "가입 버튼을 누르면《사용자 협의》을 읽고 동의함", + "enter_password2": "로그인 암호 입력하세요", + "reset_now": "바로 재설정하기", + "choose_gender": "성별 선택", + "who": "누구...", + "determine": "확정", + "cannot_modified": "성별을 선택한후에 수정할 수 없음", + "tip": "힌트", + "choose_quit": "바로 회원가입이나 탈퇴 여부?", + "confirm": "확인", + "use": "사용", + "cancel": "취소", + "close": "닫다", + "delete": "삭제", + "forget_it": "안합니다", + "ok": "좋습니다", + "choose_quit2": "등록한후에 성별 변경 할수 없습니다 .확인하시겠요?", + "tip_content": "힌트: 당신은 동성별 사용자와 얘기할 수 없음", + "welcome": "환영합니다", + "enter_incode": "초대 번호를 입력하세요", + "must_incode": "흔호 초대번호 갖은 남자만 서비스 제공함", + "your_incode": "당신의 초대번호 ", + "how_get": "초대 코드 없습니까? 다음 방식으로 받을 수 있습니다", + "method1": "방식 1 ", + "free": "공짜 신청", + "apply_now": "바로 신청", + "check_incode": "초대번호 받음", + "so_get": "개인 정보를 작성해서 심사 통과 후 다시 요청 코드를 보내 드립니다", + "apply_incode": "초대번호 신청하다", + "location": "소재지", + "cityname": "도시 ", + "message_channel": "정보 경로", + "how_know": "앱을 어디서 알게 되셨어요?", + "wechat_number": "Wechat 아이디 ", + "your_wechat": "당신의 Wechat 아이다 ", + "facebook": "페이스북", + "your_facebook": "당신의 페이스북 ", + "submit_application": "신청을 제출하다", + "enter_city": "도시명 입력하세요", + "so_know": "앱을 받을수 있는 경로를 알려 주세요", + "your_social": "사교 아이디 알려주세요", + "receive_incode": "당신의 신청를 최대한 빨리 처리해 드리겠습니다. 심사 통과후 고객센터에서 코드 번호를 받을수 있습니다", + "wait_incode": "초대 번호는 아직 발급되지 않았으니 조금만 기다려 주십시오", + "successful_application1": "신청 성공", + "application_failed1": "검토 실패", + "successful_copy": "복사 성공", + "method2": "방식 2", + "joinvip": "회원 가입", + "join_now": "바로 가입", + "joined": "가입 되었다", + "join_odds": "회원 가입 은 각종 특권 을 갖을 수 있다,요청번호 필요 없는 등록 포함", + "not_joinvip": "당신 아직 회원 아니였습니다", + "join_after": "회원 가입 후 코드 번호 없어도 등록 됩니다", + "incode_passed": "초대번호 인증 통과", + "welcome_join": "가입을 환영하다!당신의 계좌번호를 다른 사람에게 알려주지 마시오,로그인 이상을 발견하면 아이디가 자동으로 동결된다", + "member_centre": "고객센터", + "members_privilege": "회원특권", + "see_more": "더 많은 보기 ", + "unlimited_see": "사용자를 하루에 무제한으로 조회", + "see_cheaper": "더 싸게 볼 수 있습니다", + "free10": "매일/s1차 무료 기회 유료앨범이랑 사교 아이디 볼수 있다", + "see_longer": "더 오래 볼 수 있음", + "towto6": " 보고 바로 간 사진의 시간을 2초에서 /s1초로 올리기", + "see_better": "더 즐겁게 보다", + "free_release": "무료 데이트 방송 ", + "choose_price": "세트 선택", + "pay_method": "지불 방식", + "pay_amount": "지불 금액", + "not_enough": "지갑 잔액이 부족하다", + "confirm_pay": "지불 확인", + "complete_material": "정보 작성", + "basic_information": "기본 정보", + "upload_avatar": "이미지 작성", + "choose": "선택하세요", + "fill_out": "써 주세요", + "choose_multiple": "많이 선택할 수 있다", + "optional": "고르다", + "least": "최소 작성 s1", + "introduce_yourself": "자기 소개 좀 해 주세요", + "most": "최다/s1 선택", + "nickname": "닉네임", + "only1_8": "닉네임은 1-20 글짜만 가능합니다", + "Resident_city": "현재 도시", + "Please_select_a_resident_city": "현재 도시를 선택하십시오", + "City1": "칸토", + "City2": "다낭", + "City3": "하이퐁", + "City4": "하내 ", + "City5": "호치민", + "City6": "안강", + "City7": "북강", + "City8": "북건", + "City9": "볼리 아오", + "City10": "북닝", + "City11": "바디 붕타우", + "City12": "빈랑", + "City13": "평정", + "City14": "평약", + "City15": "평복", + "City16": "평순 ", + "City17": "김오", + "City18": "고평", + "City19": "더락", + "City20": "더농", + "City21": "모비안", + "City22": "동내 ", + "City23": "동타", + "City24": "가래", + "City25": "하강", + "City26": "해양", + "City27": "하남", + "City28": "하정", + "City29": "하평", + "City30": "후강", + "City31": "흥안", + "City32": "경하", + "City33": "견강", + "City34": "쿤호", + "City35": "라이저우", + "City36": "린동", + "City37": "령산", + "City38": "노가", + "City39": "롱안 ", + "City40": "루안", + "City41": "닝평", + "City42": "닝순", + "City43": "부수", + "City44": "부안", + "City45": "광평 ", + "City46": "광남", + "City47": "광의", + "City48": "광닝", + "City49": "광지", + "City50": "수장", + "City51": "산라", + "City52": "서닝", + "City53": "태평", + "City54": "태원", + "City55": "청화", + "City56": "승천순화", + "City57": "전강", + "City58": "차영", + "City59": "선광", + "City60": "영롱", + "City61": "영부", + "City62": "안폐", + "City63": "남정", + "birthday": "새일", + "choose_birthday": "생일날짜 선택", + "year": "년", + "month": "월", + "day": "일", + "hour": "시 ", + "minute": "분", + "second": "초", + "just": "방금", + "minute_ago": "/s1 분 전", + "hour_ago": "/s1 시간 전", + "day_ago": "/s1일 전", + "week_ago": "/s1 주전", + "month_ago": "s1 달 전", + "morning": "오전 ", + "noon": "점심", + "afternoon": "오후", + "night": "저녁", + "all_day": "하루종일", + "yesterday": "어제 ", + "two_yesterday": "그저께", + "overnight": "밤새", + "one": "개 ", + "ten": "십", + "hundred": "백", + "thousand": "천", + "ten_thousand": "만", + "aries": "양자리", + "taurus": "황소자리", + "gemini": "쌍둥이자리", + "cancer": "게자리", + "leo": "사자자리", + "virgo": "처녀자리", + "libra": "천칭자리", + "scorpio": "전갈자리", + "sagittarius": "사수자리", + "capricorn": "염소자리", + "aquarius": "물병자리", + "pisces": "물고기자리", + "monday": "월요일", + "tuesday": "화요일", + "wednesday": "수요일", + "thursday": "목요일", + "friday": "금요일", + "saturday": "토요일", + "sunday": "일요일", + "job": "직업", + "choose_career": "직업 선택", + "career1": "정보 기술", + "career2": "인터넷", + "career3": "IT", + "career4": "통신 운영", + "career5": "네트워크 게임", + "career6": "금용 보험", + "career7": "투자 ", + "career8": "주식 기금", + "career9": "보험", + "career10": "은행", + "career11": "신탁 담보", + "career12": "상업 서비스", + "career13": "컨설팅", + "career14": "자영업자", + "career15": "미용 미발", + "career16": "여행", + "career17": "호텔,식당", + "career18": "레저 오락", + "career19": "무역", + "career20": "자동차 ", + "career21": "부동산", + "career22": "부동산 관리", + "career23": "인테리어", + "career24": "탐정", + "career25": "공사 제조", + "career26": "건설", + "career27": "토목공사 ", + "career28": "기계제조", + "career29": "전자", + "career30": "생물의학", + "career31": "식품", + "career32": "복장", + "career33": "에너지", + "career34": "교통운송", + "career35": "항공", + "career36": "철도", + "career37": "운수선박", + "career38": "대중교통", + "career39": "물류 수송", + "career40": "문화 미디어", + "career41": "미디어 출판", + "career42": "디자인", + "career43": "문화 전파", + "career44": "광고창의", + "career45": "만화", + "career46": "홍보 전시회", + "career47": "촬영", + "career48": "오락 체육", + "career49": "영화", + "career50": "스포츠", + "career51": "음악", + "career52": "모델", + "career53": "공공사업", + "career54": "의료", + "career55": "법률", + "career56": "교육", + "career57": "정부 기관", + "career58": "공공 복지", + "career59": "학생", + "career60": "무", + "program": "프로그램", + "select_program": "국적을 선택하십시오", + "healthy_exercise": "건강 스포츠", + "night_party": "나이트 파티", + "gourmet_party": "음식", + "watch_movie": "영화감상", + "play_games": "게임을 하다", + "travel_together": "동반 여행", + "voice_chat": "음성 채팅", + "other": "기타", + "expect_lover": "이상형", + "choose_lover": "이상형 선택", + "beautiful": "외모", + "rich": "부자", + "care_me": "자상함", + "look_feeling": "첫인상", + "doesnt_matter": "상관 없습니다", + "least_account": "사교 아이디를 최소 한개 적어 주세요", + "hide_account1": "소셜 계정 숨기기", + "more_information": "더 많은 정보", + "height": "키", + "weight": "체중", + "not_show": "표시하지 않음", + "self_introduction": "개인소개", + "registration_success1": "등록 성공", + "exit": "탈퇴 확정하세요?", + "exit_registration": "개인 정보를 완전하게 작성하지 못했습니다. 지금은 종료하십시오. 다음에 등록 된 아이다로 직접 로그인하십시오", + "cant_see": "남자는 다른 남자 사용자 정보 볼 수 없다", + "cant_see2": "여자는 다른 여자 사용자 정보 볼 수 없다", + "see_one": "당신은 오늘에 /S1명 여자 볼 수 있다", + "only_see": "비회원은 하루에 15명 여자 사용자만 볼 수 있다", + "continue_see": "계속 보기", + "user_frozen": "아이디 동결되였다", + "search_user": "닉네임/직업으로 검색", + "nearby": "근처", + "member": "회원", + "new_registration": "새 등록", + "authenticate": "인증", + "first_online": "온라인", + "not_positioned": "포지셔닝이 켜져 있지 않아서 다른 사용자와 거리를 계산할 수 없음", + "unknown": "미지", + "secrecy": "비밀", + "collection": "수장 ", + "cancel_collection": "수장 취소", + "canceled_collection": "수장 취소되였다", + "like": "좋아요", + "added_like": "좋아한 것을 가입했다", + "canceled_like": "좋아한 것을 취소했다", + "blacklist": "블랙리스트", + "blacklist_choose": "더 이상 서로와 동적을 볼 수 없습니다. 확실합니까?", + "blacklisted": "블랙리스트에 가입했다", + "reject_message": "상대방을 블랙리스트에 추가하고 상대방의 메시지 수신을 거부했다", + "remove_blacklist": "블랙리스트 삭제", + "blacklist_removed": "블랙리스트 제거", + "receive_message": "상대방을 블랙리스트를 제거하고 소식을 거부한거도 취소했다", + "online": "온라인", + "paid_photo": "유료앨범", + "application_view": "보기 신청", + "passed": "통과했다", + "park": "공원", + "radio": "라디오 방송", + "news": "소식", + "me": "나", + "more_operations": "더 많은 조작", + "anonymous_report": "익명신고", + "certified_video": "인증영상", + "passed_video": "이미 영상을 통해 진실성을 인증했다", + "not_video": "아직 신분의 진실성을 인증하지 않았다", + "her_appointment": "그녀가 데이트를 신청했어요", + "pay_join": "그는 유료로 가입했습니다", + "passed_review": "신분 안전 심사를 통과했다", + "invited_user": "그는 경력많은 사용자/s1 증정 초대 번호로 가입한다", + "his_appointment": "그는 데이트를 신청했어요", + "her_dynamics": "그녀의 동태", + "his_dynamics": "그의 동태", + "low_key": "그녀는 매우 겸손하다 ", + "low_key2": "그는 매우 겸손하다 ", + "her_photo": "그녀의 앨범", + "his_photo": "그의 앨범", + "set_lock": "그는 앨범 자물쇠를 설치했다", + "set_lock2": "그녀는 앨범 자물쇠를 설치했다", + "free_unlock": "앨범 해제(/s1),회원 무료", + "unlock_user": "앨범 해제/s1", + "pay_unlock": "비용을 지불 해제(/s1H화폐)", + "become_member": "회원을 되면 공짜 해제", + "consumption_once": "한 번 기회 사용 해제/s1앨범 여부?", + "remaining_once": "(당신이 오늘에 아직/s1한 번 기회 있다.)", + "no_times": "당신이 오늘 공짜 기회 다 썼습니다. 증정/S1로 /s2 모두자료를 해제할시겠습니까?", + "pay": "지불", + "view_user": "그는 제한을 설치하여 자료를 살펴보면 그의 동의를 요청해야 한다", + "view_user2": "그녀는 제한을 설치하여 자료를 살펴보면 그의 동의를 요청해야 한다", + "need_photo": "상대방에게 당신의 사진을 한 장 보내는 것을 신청합니다.걱정하지 마세요. 상대방이 스크린을 찍는 2초 후에 삭제할 거예요", + "choose_photo": "사진 선택", + "send_application": "신청 이미 발송했고 상대방이 확인한 후에 당신은 소식을 받겠습니다", + "not_authenticate": "당신이 아직 인증안 했습니다", + "after_authenticate": "당신의 진실성을 인증한 후에다른 사람과 연락할 수 있다", + "authenticate_now": "바로 인증", + "destroy_after": "본 후에 바로 삭제", + "destroyed": "삭제됨", + "red_photo1": "보고 삭제한 빨간 봉투 사진", + "ask_me": "단독 체팅으로 나한데 요청해 주세요", + "filled_in": "작성끝, 클릭 보기", + "unlock_information": "해제 모두 자료", + "unlock_choose": "공짜 해제 한번 사용하다", + "your_evaluation": "당신의 진실 평가", + "her_evaluation": "그녀의 진실 평가 ", + "his_evaluation": "그는 진실 평가 ", + "evaluate": "평가 ", + "friendly": "친절하다 ", + "interesting": "재미는 성격", + "readily": "상쾌하다", + "patient": "인내심", + "indifferent": "퉁명하다", + "bad_temper": "난폭한 성격", + "courtesy": "예의", + "generous": "대범하다 ", + "lie": "거짓말", + "unfriendly": "불친절한다", + "anonymous_evaluation": "무명평가 ", + "cant_evaluate": "그녀를 데이트 안했으니 평가 못 한다", + "cant_evaluate2": "그를 데이트 안했으니 평가 못 한다", + "bad_evaluate": "우리가 따라가서 확인하기 위해 관련 캡처를 제공하십시오", + "submit": "제출", + "evaluation_success": "평가 성공", + "private_chat": "단독 채팅", + "close_reminder": "메시지 닫기", + "closed_reminder": "메시지 닫기 성공", + "open_reminder": "메시지를 켜다", + "opened_reminder": "메시지를 켜다 성공", + "her_account": "그녀의 사교 아이디", + "his_account": "그의 사교 아이디", + "copy": "복제", + "send_account": "내 사교 아이디를 보내기", + "enter_account": "당신의 사교 아이디 입력하세요", + "for_example": "예하면:Wechat 아이다 abc", + "sent_she": "그녀에게 보내기 ", + "chat": "음성 통화", + "cantt_voice": "상대방이 인터넷 통화 기능을 꼈다", + "authentication_voice": "당신의 진실성을 인증한 후에야, 주동적인 인터넷 통화를 할 수 있다", + "requesting_voice": "인터넷 통화를 신청하는 중이에요", + "waitting_answer": "대기 중", + "answer": "받기 ", + "hang_up": "끄기 ", + "chatting": "통화중 ", + "handsfree": "면제", + "giving_gift": "상을 주기 ", + "give_success": "상을 주는 게 성공하다", + "others_gift": "상대방은 이미 상을 주었다", + "given_gift": "당신 가치/s1H 화폐 의선물을 주었다", + "earned_gift": "당신은 가치/s1H 화폐 의선물을 받았다", + "available_balance": "사용 가능 잔액/s1", + "recharge": "충전", + "give": "증정", + "balance_insufficien": "죄송합니다. 잔액이 부족합니다", + "first_recharge": "충전한 후에 선물을 증정하세요!", + "give_coin": "이번 통화 /s1H화폐 상을 주다", + "get_coin": "이번 통화 /s1H화폐 상을 받다", + "give_get": "이번 통화 /s1H화폐 상을 주고 /s2H화폐 상을 받다", + "chat_over": "통화가 끝나다.통화시간 /s1", + "message_center": "소식센터", + "can_chat": "당싱이 사용자 정보 페이지에서 개인 채팅을할 수 있습니다", + "text_chat": "채팅", + "system_information": "시스템 메시지", + "system_notification": "시스템 알림", + "report_failure": "신고한 사용자/s1상황이 사실이 아니라서 더 확실한 증거를 제공한 후에 신고하세요.감사합니다!", + "report_success": "신고한 사용자/s1가 상황이 사실이라서 시스템은 이미 이 사용자에 대한 처리하다", + "successful_application": "초대 신청 성공 !초청 코드【/s1】( 클릭 복사 가능)", + "successful_application2": "초청 코드 성공을 신청하다 ,믿을 만한 친구를 소개해 주셔서 감사합니다!초청 코드【/s1】(클릭 복사 가능).)", + "application_failed": "초청 번호 신청실패한다! 당신의 신청은 심사를 통과하지 못해서 아쉽다 ,진실 정보 작성을 효과적 으로 심사 통과율 을 높일 것 이다", + "important_notice": "중요 소식:", + "authentication_failed": "당신의 인증 자료 요구에 부합되지 않는다 , 수정하고 다시 제출해 주세요", + "request1": "1.인증 조권을 따라서 인증 영상 찍어주세요", + "request2": "2.앨범에 이목구비 또렷한 얼굴 본인 사진 올려주세요", + "successful_authentication": "축하합니다, 당신의 인증 신청은 이미 심사를 통과했습니다", + "re_upload": "당신이 새 올린 사진은 심사를 통과하지 않았으니 요구를 따라 다시 올려 주십시오", + "upload_success": "축하합니다.당신 새 올린 사진은 심사를 통과 성공했습니다", + "caveat": "데이트신청은 규칙 위반으로 삭제되었기 때문에, 여러 번 규칙 또는 플랜 심각한 시스템이 당신의 계좌에 대한 제한, 심지어는 봉호까지 지켜 주시기 바랍니다. 감사합니다", + "caveat2": "당신의 평론은 규칙 위반으로 삭제되었기 때문에, 여러 번 규칙 또는 플랜 심각한 시스템이 당신의 계좌에 제한되어 있으며, 심지어 봉호를 준수해 주십시오. 감사합니다", + "radio_message": "방송 소식", + "no_message": " 소식 없다", + "dating_news": "/s1가 /s2에게 데이트 소식을 발표하여 체크 를 클릭 하다", + "go_see": "가서 보기 ", + "thumbs_up": "/s1 당신의 동태를 칭찬했다", + "thumbs_up2": " /s1 당신의데이트 프로그램을 칭찬했다", + "comment1": "/s1 당신의 동태를 평론했다", + "comment2": "/s1 당신의 데이트 프로그램을평론했다", + "replied_comment": " /s1평론을 답장했다", + "signed_up": "/s1 당신의 데이트 프로그램 신청했다", + "favorite_user": "당신이 좋아하는 사용자 /s1 데이트를 발표하여 체크하기", + "favorite_user2": "당신이 좋아하는 사용자/s1동태를 발표하여, 체크하기", + "wallet_reminder": "지갑 알람", + "paid_you": "/s1 (/s2H화폐)비용을 지불하다 당신 빨간 봉투사진을 보았습니다", + "paid_you2": "/s1 (/s2H화폐)비용을 지불하다 당신의 앨범을 보았습니다", + "paid_you3": "/s1비용을 지불하다 당신의 모두 자료를 보았습니다", + "view_application": "보기 신청", + "view_application2": "/s1 자세한 페이지 보기 요청", + "aging": "허락(유한기간: 15일)", + "refuse": "거절하다", + "passed_request": "요청을 통관했다", + "l15_days": "/s1 이미 당신의 조사 신청을 통과하여 유효기간 15일", + "evaluation_notice": " 평가통지", + "rate_her": "/s1이미 약속하셨어요?빨리 평가하세요", + "received_evaluation": "연락떤 여자 사용자(익명)가 당신한테 평가를 했습니다. :/s1", + "received_evaluation2": "연락떤 남자사용자(익명)가 당신한테 평가를 했습니다. :/s1", + "application_appeal": "만약 평가가 사실이 아니라면, 당신이 상술한 것을 신청할 수 있으니, 우리는 확인할 것이다", + "appeal": "상술하다", + "appealed": "상술을 신청했다", + "waiting_results": "우리는 최대한 빨리 상황을 확인할 것이며, 편지를 통해 당신에게 처리 결과를 알려 줄 것이다", + "successful_appeal": "상술 평가 :/s1 상술 성공하면 우리 는 당신의평가 를 철회 할 것이다", + "social_account": "사교 아이디", + "get_account": "/s1에게 당신한테 사교 아이디 보냈다", + "edit_information": "자료를 편집하다", + "save": "보존", + "passed_verification1": "당신이 신분 안전 인정을 통관했다", + "by_code": "경력 많은사용자/s1초대 코드로 통해서 가입하다", + "by_paying": "비용을 지불으로 가입하다", + "passed_verification": "당신은 이미 영상을 통해서 신분의 진실성을 인증했다", + "not_certified": "당신이 아직 신분의 진실성릉 인증 안했다", + "verificating": "저희 당신의 진실성을 인증하는 중이다", + "real_girl": "인증을 통관했는 여자는 인기 더 많다", + "certificating": "인증중", + "re_upload2": "영상을 다시 올리겠습니다. ", + "update_certification": "업데이트 인증", + "enjoy_privileges": "회원존을 업그레이드 하여 특권을 있다", + "expires": "/s1만료", + "wallet": "지갑", + "setting": "프라이버시", + "my_dynamic": "나의 동태 ", + "my_album": "나의 앨범", + "first_photo": "제 첫 번째 사진을 올리다", + "no_photo": "사진이 있어야 남자를 사로잡을 수 있다", + "upload_photos": "사진을 올리다", + "upload_video": "영상을 올리다", + "upload": "사진 업로드", + "set_photo": "빨간 봉투 사진을 설치하다", + "photo_order": "화면을 누르고 끌면 사진을 정렬할 수 있다", + "my_evaluation": "나의 평가 ", + "my_show": "나의프로그램", + "i_like": "제가 좋아하는 거", + "your_favorite": "당신이 좋아하는 여자가 여기 나타난다", + "your_favorite2": "당신이 좋아하는 남자가 여기 나타난다", + "no_data": "데이터가 없습니다", + "historical_visitor": "역사 방문객", + "visit_you": "/s1 한 명이 당신을 본다", + "visit_photo": "누군가가/s1 당신의 사진을 삭제했다", + "recovery_photo": "단축 복구", + "setting2": "설치", + "apply_code": "친구대신 초대번호 신청하다", + "issue_choose": "초청 번호는 무료입니다. 우리는 당신의 역사적 소비에 따라 초청번호를 발송할지 평가할 것입니다.공원의 분위기를 유지하기 위해서 꼭 초청번호를 믿고 믿을 만한 친구에게 증정해 주십시오", + "successfully_submit": "신청을 성공 제출했다", + "share_app": "앱을 친구에게 공유하다", + "need_help": "질문이 있으니까 도움이 필요하다", + "need_help2": "고객을 연락하다", + "need_help3": "서비스 효율을 높이기 위해서 아래에 문제가 있으면 숫자를 바로 답장하십시오!", + "question1": "【1】아이디 동결된 이유는 무엇입니까 ?", + "answer1": " 아래 여러 상황이 나타나면 아이다가 동결될 수 있다 :① 사기꾼 ② 중개 ③ 소란 광고 ④ 많은 사람들이 신고하다 ⑤ 이미 기타 아이디 있다 ⑥ 여러번 위반 방송국 방송의 경고를 무시했다 ⑦ 사용자 스스로 취소 요구", + "question2": "【2】 지갑에 현금은 언제 제시할 수 있습니까?", + "answer2": "모든 수익은 지갑에 직접 들어가고, 현금을 꺼낸지 3일 걸린다(수취시간 계산에 따라 시작) , 사흘 후 받은 금액은 지갑, 금액 > = 10위안을 제시할 수 있다", + "question3": "【3】 내가 보낸 빨간 봉투는 왜 안 뜨다?", + "answer3": "인터넷 원인으로 인한 것 같다.안심해, 이런 상황에서 상대방이 당신의 돈을 받을 수 없어, 빨간 봉투는 24시간 후에 자동으로 당신의 지불 루트에 돌려줄 것이다", + "question4": "【4】 현금을 인출하려면 얼마나 걸립니까? ", + "answer4": "현금 인출 신청후 두 업무일 내에 장부를 제출하다 . 훈훈한 힌트: 현금 계좌번호 확인하세요 ! ", + "question5": "【5】 어떻게 익명 신고 기타 사용자/라디오 내용을 할수 있겠어요 ?", + "answer5": "상대방의 자세한 페이지에 들어가거나 어떤 라디오 를 선택하여 오른쪽 위 각 선택 을 클릭 (익명 신고서), 관련 제보 메시지 를 기입하면 제보할 수 있다", + "question6": "【6】어떻게 인증 사용자 될 수 있을까요?", + "answer6": "인증은 다음과 같은 요구를 충족시켜야 한다 :① 개인 자료는 유효 사교 아이디를 작성 하다 ②앨범 적어도 본인의 또렷한 정면사진 한 장 올려 주세요. ③인증 페이지 검증 코드 보기, 종이에 닉네임+검증 코드 ④ 이 종이를 들고 당신의 정면과 동영상을 맞추고 인증 영상을 업로드하는 것을 클릭하여 클릭하다", + "question7": "【7】인증 영상은 공개 안 해도 돼요?", + "answer7": "설정에서 공개 여부: 사용자 중심 - 인증 동영상을 클릭 - 왼쪽 밑 구석'인증 영상을 내 자세한 페이지에 표시할 수 있다.'", + "question8": "【8】인증 취소를 피하는 방법?", + "answer8": " 앨범에 적어도본인 사진으로 표기된 사진이 한 장 있다", + "question9": "【9】 라디오 방송 삭제의 원인?", + "answer9": "라디오 방송에 민감한 도를 발표하지 못하고 예민한 단어는 암시나 명시적인 단어에 한정되지 않고 개인정보 (포함 프로필, 닉네임, 연락처) 를 발포할 수 없다. 방송은 삭제될 것이다", + "question10": "【10】어떻게 아이디를 취소합니까?", + "answer10": "아이디를 취소한후에 APP 에서 로그인할 수 없습니다. 앞으로 서비스를 사용하려면 다시 아이디 만들어야 합니다. 신중히 고려하십시오.만약 당신이아이디를 취소를 결정한다면 ,번호【12】고객직원이랑 연락 주세요 ", + "question11": "【11】암호 잊으면 어떡해요?", + "answer11": "핸드폰 번호를 통해서 등록하거나 핸드폰 번호를 바인든사용자 , 로그인 페이지 오른쪽 모서리를 통과할 수 있습니다. “ 암호 잊기 ” 기능 암호 초기화 . 사용자 납치되지 않음 핸드폰 번호를 묶어주세요. , 새 로그인 암호 다시 설정하다", + "question12": "【12】기타 질문 / 수동 고객 서비스 이전", + "answer12": "안녕하십니까?당신의 문제를 말해 주십시오 ( 고객지원 근무 시간은 매일 8:00-다음날 02:00, 상담 고객이 많아서, 답변을 기다려야 할 수도 있다. )", + "certification_center": "인증 센터", + "for_example2": " 인증 영상 촬영 방식 실례", + "certification_conditions": " 인증 조건", + "conditions1": "1.개인 이미지 양호", + "conditions2": "2.앨범 적어도 본인 사진 한장 올리다", + "verification_method": "인증 방식", + "method3": "1.종이 한 장에 당신의 닉네임과 이하 검증 코드를 쓰세요", + "method4": "2.이 종이 가지고 당신의 정면과 영상 찍으세요.(3~15초)", + "upload_video2": "인증 영상 올리다", + "after_authentication": "인증 성공한 후에 당신의 프로필은 real 로고를 표시하고 있다", + "show_video": "인증 영상을 내 자세한 페이지에 표시하세요", + "uploaded_video": "인증 영상 올린다", + "under_review": "심사중(24 시간 내에))", + "certification_status": " 인증 상태", + "certified": "당신은 인증 통과했다", + "wait_resubmitted": "인증은 다시 꺼내야 한다", + "reason_failure": "당신의 인증 영상은 요구에 맞지 않습니다. 원인은:", + "claim": "인증 요구를 따라 인증 영상 찍어주세요", + "claim2": "앨범에 이목구비 정면 본인 사진을 또렷하게 올려주세요", + "re_upload_video": "다시 인증 영상 올리세요", + "update_video": "인증 영상 업데이트", + "mask_coin": "H 화폐 ", + "get_way": "당신은 충전가치나 밀 개설 등의 경로를 통해 H 화폐를 받을 수 있다", + "coin_use": "H화는 음성 통화 및 보상에 사용할 수 있습니다.", + "coin_total": " H 화폐 총액", + "can_redeemed": "환전 가능", + "who_account": "/s1 아이디", + "bind_account": "/s1 아이디 연동", + "your_account": "당신의 /s1 아이디 ", + "get_coin2": "당신이 총지를 통해서 /s1H 화폐 받았다", + "viewed_your": "/s1 당신의 사교 아이디 보았다", + "give_gift": "/s1가 /s2 한 개 증정했다", + "add_coin": "+/s1H 화폐 ", + "give_one": "당신이 /s2에게 /s1 한 개 증정했다", + "less_coin": "-/s1H 화폐 ", + "exchange_cash": "현금을 제시하다", + "withdrawal_application": "출금 신청", + "redeem_choose": "당신의/s1H화폐 환전 가능 /s2, 태환 후 잉여 /s3H화폐. 환전신청 확실합니까", + "application_submitted": "출금 신청을 보냈다", + "working_days": "저희가 두 업무일 내에 처리할 것이며, 의문이 있으면 고객센터직원이랑 상담을 할 수 있다", + "cash": "현금", + "handling_fee": "당신이 채팅 페이지에 돈봉투를 받을 때마다 돈봉투 금액이 여기에 들어갑니다.금액이 입금된 후 3일 이내에 아무도 신고하지 않으면 현금을 인출할 수 있으며, 현금 인출은 5%의 수수료를 받게 됩니다", + "total_account": "계좌총액", + "cannot_redeemed": "금액이 부족하여, 환불할 수 없다", + "successful_redemption": "환불을 성공한다", + "redeem_choose2": "당신의 계좌 총액은 /s1위안입니다.이번에 현금을 인출할 수 있습니다./s2위안입니다.확실하세요?", + "personal_details": "개인 상세", + "public": " 공개 (추천)", + "paid_album": "앨범 유료 보기", + "must_pay": "다른 사람은 반드시 비용을 지불해야만 당신의 앨범을 볼 수 있고, 비용은 당신이 정하는데, 이것은 당신의 방문량을 낮출 수 있다", + "set_amount1": "보기 금액 설정", + "first_upload": "먼저 사진을 올리고 유료 앨범을 설정하십시오", + "need_permission": "보기 전에 내 검증을 통과해야 합니다", + "permission_choose": "다른 사람은 반드시 사진을 보내서 당신이 신분을 검증한 후에야 당신의 홈페이지를 볼 수 있게 해야 합니다, 확실합니까?", + "hide_me": "주변 사람들 목록에서 나를 숨 깁니다", + "hide_distance": "다른 사람에게 나의 거리를 숨기다", + "hide_account": "다른 사람에게 내 사교 아이디를 숨기다", + "chat_setting": "통화 제어", + "chat_me": "사적인 대화를 나눌 권한이 있는 사람이 나에게 통화를 일으키도록 허락하다", + "successfully_saved": "저장 성공", + "on_dynamic": "당신은 아직 동태를 발표한 적이 없다", + "release_dynamics": "동태를 발표하다", + "dynamic_details": "동태 상세", + "release": "발표하다", + "i_posted": "제가 발표한 거", + "delete_dynamic": "동태를 삭제하다", + "delete_choose": "이 동태를 삭제하시겠습니까?", + "posted_on": "/s1를 발표하다", + "thumbs_up3": "좋아요", + "already_praised": "이미 좋아했니다", + "comment": "댓글", + "send": "보내기 ", + "comment_closed": "댓글을 닫혔습니다", + "your_comment": "발표자만 당신의 댓글을 볼 수 있습니다", + "everyone_comment": "모두 사람 당신의 댓글을 볼 수 있다", + "prohibit_comments": "댓글 금지", + "comments_disabled": "댓글을 금지했다", + "open_comments": "댓글 개방", + "already_open": "댓글 개방했다", + "reply": "대답하다", + "report": "신고하다", + "report_choose": "이 댓글을 신고하는 것이 확실합니까?", + "successful_report": "신고를 성공했으니 최대한 빨리 처리해 드리겠습니다", + "successfully_deleted": "삭제 성공", + "please_civilization": "말투가 교양 있는 사람이 더 인기가 있으니, 저속하고 야한 거래를 발표하거나, 기타 사람의 프라이버시 내용을 폭로하지 마시오", + "same_sex": "동일한 성별의 사용자에 대해 숨김", + "member_free": " 회원은 무료, 비회원은 /s1H화폐 지불을 해야 한다", + "certified_free": "인증했는여사3회 무료이며, 그후에는 /s1H화폐 지불이 필요합니다", + "enter_something": "문자 내용을 입력하거나 사진을 선택하십시오", + "raid_release": "유료 발표(/s1H화폐)", + "become_member2": "회원이 되다 , 무료 발표", + "now_certification": "즉시 인증 ,무료 발표", + "successfully_released": "발표 성공", + "no_program": "당신은 아직 프로그램을 발표한 적이 없어요", + "program_details": "프로그램 상세", + "program_theme": "프로그램 주제", + "click_select": "클릭하여 선택", + "city": "도시 ", + "select_city": "도시 선택", + "time": "시간 ", + "select_date": "날짜 선택", + "select_time": "시간 선택", + "unlimited_time": "시간 제한 없음", + "supplementary_explanation": "보충 설명", + "image": "배치도", + "delete_program": " 프로그램 삭제", + "delete_choose2": "이 프로그램을 삭제하시겠습니까?", + "please_choose": "프로그램 주제를 선택하십시오", + "please_choose2": "원하는 이상형을 선택하십시오", + "please_choose3": "도시를 선택하세요", + "please_choose4": "날짜를 선택하십시오", + "please_choose5": "시간을 선택하세요", + "release_program": "프로그램을 발표하다", + "sign_up": "신청하다", + "end_registration": "신청을 마치다", + "end_choose": "데이트를 끝내는 게 확실해요?", + "contact_her": "그녀를 연락하다", + "talk_him": "단독 채팅하다", + "report_choose2": "이 신청을 신고하시겠습니까?", + "release_time": "발표 시간", + "activity_time": "활동 시간", + "any_sex": "성별에 제한이 없다", + "look_women": "여자만 보기", + "look_men": "남자만 보기", + "unlimited_area": "지역 제한이 없다", + "program_deleted": "이 프로그램은 이미 삭제되었다", + "cant_comment": "비회원 댓글할 수 없다", + "sign_up2": "신청하다", + "need_photo2": "신청하려면 당신의 정면 사진을 보내야 합니다(상대방만 볼 수 있음)", + "registration_success": "신청이 성공적으로 이루어졌는데, 상대방이 적절하다고 생각되면 연락드리겠습니다", + "has_ended": "이미 마치다", + "men_cant": "남자은 남자의 프로그램에 신청을 할 수 없다", + "ms_cant": "여자은 여자의 프로그램에 신청을 할 수 없다", + "men_cant2": "남자은 남자의 프로그램에 댓글을 할 수 없다", + "ms_cant2": "여자은 여자의 프로그램에 댓글을 할 수 없다", + "message_push": "소식이 추송한다,암호 수정", + "phone_number": "전화번호 ", + "bind_phone1": "핸드폰 번호를 묶다", + "more_safer": "휴대폰 번호를 묶어서 당신의 계좌를 더 안전하게 만들어요", + "modify_choose": "묶은 휴대폰 번호를 수정하고 싶으세요", + "change_password": "암호 수정 ", + "first_bind": "사용자는 먼저 휴대폰 번호를 묶어야 로그인 암호를 설정할 수 있습니다", + "old_password": "기본 암호", + "current_password": "현재 로그인 암호를 입력하십시오", + "new_password": "새 암호", + "set_new": "6자리보다 많은 새 암호를 설정하십시오", + "clear_cache": "사진 캐시 지우기", + "cleared_successfully": "제거 성공", + "user_agreement1": "사용자 협의", + "sign_out": "로그아웃", + "out_choose": "로그아웃 계정이 확정되었습니까?", + "push_settings": "추송 설정", + "permission_denied": "권한이 거절되었습니다", + "push_setting2": "소식을 추송기 설정", + "private_chat2": "단독 채팅 소식", + "new_date": "새 데이트", + "passed_request2": "어떤 여자가 나의 관찰 요청을 통과하였다", + "men_view": "내 자료 페이지를 볼남자분이 신청하셨어요", + "men_view2": "내 사교 아이디을 볼남자분이 있어요", + "men_view3": "내 빨간봉투 사진을 본 남자분이 있어요", + "men_view4": "이미 자료를 본남자분이 나에게 사교 아이디를 보내 줬어요", + "applied_successfully": "요청 코드 신청을 성공했다", + "after_open": "열기 후 응답 메시지 형식 보내다", + "if_something": "만약 당신이 최근 3일 동안 그녀/그에게 비용을 지불한 적이 있다면, 우리가 제보를 심사한 후에, 시스템은 자동적으로 당신에게 소비 금액을 반송할 것입니다", + "advertise": "광고하다", + "false_photo": "허위 사진", + "erotic_vulgarity": "색정적이고 저속하다", + "harassment": "소란을 피우고 욕설을 퍼붓다", + "she_liar": "그녀는 사기꾼이다", + "he_liar": "그는 사기꾼이다", + "provide_screenshots": "우리가 확인에 따를 수 있도록 관련 캡처를 제공하십시오", + "describe_details": "자세한 내용을 묘사하십시오(200자 이내)", + "report_reason": "신고의 원인을 선택하세요", + "report_success2": "신고가 성공했다", + "successfully_modified": "수정 성공", + "boy": "남자 ", + "girl": "여자", + "already_applied": "신청했다", + "view_registration": "신청 보기 ", + "expand": "펼치다", + "collapse": "닫다", + "application_notice": "소식 신청 ", + "agrees_application": "당신의 신청에 동의하는 사용자가 있습니다", + "red_photo": "빨간봉투 사진", + "dont": "불법노출 저속한 사진/동영상을 올리지 마십시오, 심각한 경우 아이디 차단됩니다", + "current_version": "현재 버전", + "bank_card": "은행 카드를 묶다", + "choose_bank": "계좌의개설한 은행을 선택하십시오", + "bank_number": "은행 카드 번호 입력하세요", + "id_number": "증건 번호 입력하세요", + "name": "성명 ", + "bank_number2": "은행 카드 번호 ", + "license_number": "증건 번호 ", + "bind_phone": "묶은 전화번호 ", + "his_homepage": "그의 홈페이지", + "her_homepage": "그녀의 홈페이지", + "wechat_pay": "Wechat 지불", + "facebook_pay": "facebook 지불", + "google_pay": "google 지불", + "payment_successful": "지불 성공", + "set_amount": "인출 금액 설정", + "enter_amount": "H 코인의 수를 입력하십시오", + "can_withdraw": "인출 가능하다", + "language_set": "음성 설정 ", + "user_agreement": "사용자 협의 ", + "renewal_fee": "속비", + "open_immediately": "즉시 개통", + "total": "합계", + "half_month": "반 개월", + "month2": " /s1 개월 ", + "cancel_shield": "차단 취소", + "blacklist2": "블랙리스트", + "longTime": "(회원이 6초까지 연장 가능)", + "longClick": "화면을 눌러 보기", + "stop_program": "발효 중인 프로그램을 먼저 종료하세요", + "not_love": "남자은 남자를 소장할 수 없다", + "not_love2": "여자은 여자를 소장할 수 없다", + "women_free": "여신은 무료 발표할 수 있다", + "not_up_man": "그는 아직 사진을 올리지 않았다", + "not_up_women": "그녀는 아직 사진을 올리지 않았다", + "not_illage": "请플랫폼을 통해 불법 거래를 하지 마십시오. 신고 상황이 사실이면 아이디 차단됩니다", + "alreay_join": "신청했다", + "sure_delete": "이 사진 삭제할 건 확실하세요?", + "white_now": "즉시 입력하다", + "personal": "당신은 아직 개인소개를 작성하지 않았는데, 사람을 끄는 개인소개는 데이트 성공에 큰 영향을 많다", + "success": "성공", + "fail": "실패", + "moneyPageTip": "인증된 사용자만 빨간봉투 사진을 설정할 수 있음", + "alreadyJoin": "당신은 이미 신청을 했는데, 상대방이 적합하다고 느끼면 연락할 것이다", + "waring": "반칙 경고", + "userPravicy": "사용자의 프라이버시를 존중하며 캡처하지 마십시오.다음에 있으면, 당신이 다른 사용자의 사진을 보는 것을 금지할 것이다", + "outTime": "약속시간이 지났으니 수정해주세요", + "reviewing": "심사중 ", + "reviewed": "심사 성공", + "reviewedFail": "심사 실패", + "needCard": "사용자는 먼저 은행 카드를 묶어야 현금을 인출할 수 있다", + "women_not_d": "여자는 여성의 동태를 댓글할 수 없다", + "man_not_d": "남자는 남자의 동태를 댓글할 수 없다", + "have_picture": "사진이 있어야 여자를 끌어들일 수 있어요", + "up_cancle": "업로드 전송 취소 ", + "msg_not": "소식을 비워둘 수 없다", + "need_record": "이 기능은 녹음 권한을 부여해야 합니다", + "downloading_video": "동영상 파일을 다운로드하는 중이다", + "reinput": "문제 번호를 다시 입력하십시오", + "dy_delete": "당신의 동태는 사용자에게 익명으로 신고되어 시스템을 확인하고 이 동태를 삭제하고 다시는 규칙을 위반한 조작을 하지 마시오", + "pro_delete": "당신의 프로그램은 사용자에게 익명으로 신고되어 시스템을 확인하여 이미 이 프로그램을 삭제하였다 , 다시는 규칙을 위반한 조작을 하지 마시오", + "con_delete": "당신의 평론은 사용자 익명에 의해 신고되어 시스템이 확인되어 이 평론을 삭제했습니다 , 다시는 규칙을 위반한 조작을 하지 마시오 ", + "coin_returen": "익명 사용자 신고를 거쳐 시스템에 당신은 최근에 불법 행위가 존재하고 있음을 확인하다 , 이미 당신 최근의H 화폐로 반환했다. 다음에 또 있으면 계좌가 동결될 것이다", + "voicing": "통화중에 음란물 및 음란물과 같은 불법 행위는 금지됩니다.발견하면 아이디 영구성 참겨 처리하다", + "help": "고객 서비스", + "translate_on": "인공 번역 개시", + "translate_off": "인공 번역 폐쇄", + "becomeSvip": "/s1 H 화폐를 쓰고 충전하며, SVIP된다", + "need_svip": "svip 권한 개시 가능다", + "cannot_vip": "SVIP 는 VIP 로 속비할 수 없습니다", + "offline": "연결 안돼서 소식 못 보내고 못 받다", + "otherLogin": "아이디가 다른 장비에 로그인되어 있습니다. 탈출했다", + "no_new": "아직 새 소식 없다", + "over": "번역 완료", + "bad_ev": "이 번역을 안 좋은 평가 하시겠습니까?", + "right5": "더 재밌게 얘기하다", + "right6": "더 즐겁게 쓰다", + "man_vi": "오빠", + "women_vi": "누나", + "kf_tips": "서비스 효율을 높이기 위해서 문제가 있으면 숫자를 바로 답장하십시오!", + "rejected": "거절했다", + "buy_vip": "당신은/s1H화폐 회원 구매", + "buy_program": "/s1H 화폐 게시동적 프로그램을 구매했다", + "del_add_money": "당신이H 화폐 인출 신청은 이미 처리되었으니, 이미 이체되었다. /s1 당신의 은행 통장에 도착하니, 알아봐 주십시오. ", + "adding_money": "당신이 추출한/s1H화폐를 신청하고 있다", + "free_translate": "무료 전문번역사 즐시 번역", + "personalTraff": "고객서비스를 전문적으로 드리다", + "ManTranslate": "인공 번역 중…", + "robotTranslate": "기계 번역 중…", + "translated": "인공 번역 완료", + "delete_progarm": "건강 교류, 저속한 내용을 방송하지 말고, 발견하면 삭제 처리가 될 것이다", + "open_location": "위치 권한을 열리지 않다", + "get_location": "휴댚폰 설정에서 위치 권한을 설치하여 다른 사용자와 거리를 알수 있다", + "confirm_exit": "한번 더 누르면 탈출다", + "free_program": "하루에 /s1번 기회 공짜 방송", + "picture": "사진", + "camera": "카메라", + "video": "영상", + "red_money": "빨간봉투", + "stick": "붙이다", + "press_say": "키 를 누르고 말하다", + "get_money": "/s1님이 당신의 빨간 봉투을 받았다", + "you_get_money": "/s1의빨간 봉투를 받았다", + "ones_money": "/s1 빨간 봉투", + "money_over": "빨간 봉투가 기한 지났다", + "downloading_fail": "영상 파일 다운로드 실패", + "downloading": "영상 파일 다운로드 중", + "back_money": "아직 받지 않은 빨간 봉투,2 4시간 후에 환불할 예정입니다", + "no_money": "빨간 봉투 없다", + "already_money": "빨간 봉투을 받았다", + "back_user": "기한 시간 지났으니 다시 당신의계좌로 환불되었다", + "waiting_user": "상대방이 받기를 기다리다", + "other_get": "상대방이 이미 받았다", + "little": "작은 생각, 파도를 타고", + "put_money": "돈을 빨간 봉투에 넣다", + "mount": "금액", + "over_time": "기한 지났다", + "has_get": "이미 받았다", + "no_gift": "아직 선물 없다", + "sent_gift": "상을 주기", + "fill_tips": "작성에 성공하면 /s1H 화폐를 받을 수 있으며, 연동한 후에수정할 수 없습니다", + "bind_code": "초대 번호연동", + "invide_code": "초대 번호", + "confirm_delete": "확인 삭제", + "has_eva": "당신이 이미 평가했습나다", + "open": "오픈", + "voice": "음성", + "release_send": "손을 놓으면 발송하다", + "time_little": "녹음시간 너무 짧다", + "not_online": "상대방이 온라인 하지 않아서 통화할 수 없다", + "give_red_money": "당신이 /s1에게 /s2H 화폐 빨간 봉투를 보냈다", + "get_red_money": "당신이 /s1준 /s2H 화폐 빨간 봉투 받았다", + "give_other_money": "당신이 /s1에게 /s2H화폐상을 줬다", + "get_other_money": " 당신이 /S1의 /s2H 화폐상 받았다", + "svip": "슈퍼 회원", + "recommend": "추천", + "paid_you4": "당신이(/s2H)비용을 지불했습니다/s1의 빨간 봉투 사진을 보기", + "paid_you5": "당신이(/s2H)비용을 지불했습니다/s1의 사진을 보기", + "paid_you6": "당신이 /s1무두 자료 해제를 지불했다", + "UG_LINE0": "흔호 앱 허락및 서비스 협의", + "UG_LINE1": "[제1부 및 안내]", + "UG_LINE2": "Qianhai Youlong Technology Co., Ltd(하명“Qianhai Youlong Technology Co., Ltd.”) 에서 사용자에게 자세하게 읽고 충분히 이해할 것 을 일깨워 준다 본《 서비스 협의》( 하명 《 협의 >》)사용자는 자세하게 읽고, 본 《협의》의 각 조항을 충분히 이해해야 한다. 면제 또는 제한 포함 Qianhai Youlong Technology Co., Ltd. 책임의 면책 조항 및 사용자에 대한 권리 제한 조항. 신중하게 읽고 받아들이거나 본 협의를 받아들이지 않는 것을 선택하십시오 (미성년자는 법정 보호자가 함께 읽으십시오). 이 협의 모든 조항을 받아들이지 않으면 등록, 로그인할 권리가 없습니다. 이 협의에 관한 서비스를 사용할 수 없습니다. 귀하의 등록,사용 등은 본 협의에 대한 받아들이고, 이 《 협의 》 각 조항의 구속에 동의할 것이다. ", + "UG_LINE3": "본 '협의'는 귀하(이하 '사용자'라 함)와 Qianhai Youlong Technology Co., Ltd. 간에 사용자 등록, 로그인, 이용'흔호 서비스에 관해 수립된 프로토콜입니다.본 '합의'는 Qianhai Youlong Technology Co., Ltd.와 사용자 사이의 'Hibok 서비스 관련 권리 의무'에 대해 기술합니다.\"사용자\"는 본 서비스를 등록, 로그인, 사용, 브라우징하는 개인 또는 조직을 의미합니다.본 협약에 대한 귀하의 수락 즉, 전체 조항에 의해 구속되며, 임의 서비스 약관에 대해 Qianhai Youlong Technology Co., Ltd.가 언제든지 할 수 있는 어떠한 수정도 수용하는 것을 포함합니다.본 《합의》는 Qianhai Youlong Technology Co., Ltd.가 수시로 갱신할 수 있으며, 갱신 후 합의 조항이 공표되는 즉시 원래의 합의 조항을 대체하므로 더 이상 별도로 통지하지 않고, 사용자는 본 APP에서 최신 버전의 합의 조항을 열람할 수 있습니다.Qianhai Youlong Technology Co., Ltd.에서 프로토콜 조항이 수정된 후 사용자가 수정된 조항을 수락하지 않을 경우, Qianhai Youlong Technology Co., Ltd.가 제공한 서비스를 사용 중지하고 사용자가 계속해서 Qianhai Youlong Technology Co., Ltd.가 제공한 서비스를 받은 것으로 간주됩니다", + "UG_LINE4": "一、사용 규칙", + "UG_LINE5": "1、사용자가 충분히 알고 동의하는 것은 오직 사용자가 정보를 공유, 전송 및 획득할 수 있는 플랫폼을 제공하는 것 뿐이며, 사용자는 자신이 계정을 등록한 아래의 모든 행위에 책임을 져야 하며, 그러나 당신이 전송한 어떤 콘텐츠는 물론 그로 인해 발생하는 어떤 결과도 포함됩니다", + "UG_LINE6": "2、사용자가 서비스 중이거나 서비스로 전송되는 어떠한 내용도 Qianhai Youlong Technology Co., Ltd.의 관점이나 정책을 반영하지 않으며, Qianhai Youlong Technology Co., Ltd.는 이에 대해 어떠한 책임도 지지 않습니다", + "UG_LINE7": "3、사용자가 충분히 알고 동의하면, 사용자 관계망에 기반한 소셜 정보 뷰 제품이며, 사용자는 위에 있는 등록 정보의 진실성, 적법성, 유효성에 대해 모든 책임을 져야 하며, 사용자는 다른 사람의 이름을 사칭하여 어떠한 정보를 전파해서는 안 된다", + "UG_LINE8": "4、사용자는 위에서 전송한 정보의 진실성, 적법성, 무해성, 유효성 등에 대해 전적으로 책임을 져야 하며, 사용자가 전파하는 정보와 관련된 어떠한 법적 책임은 사용자 스스로가 져야 하며, Qianhai Youlong Technology Co., Ltd.와는 관련이 없다", + "UG_LINE9": "5、 Qianhai Youlong Technology Co., Ltd. 보류는 업무 발전의 필요에 따라 일방적으로 본 서비스의 전부 또는 일부에 대해 어떠한 통지도 없이 서비스를 변경, 일시 중지, 제한, 종료 또는 철회할 수 있는 권리를 사용자가 부담해야 합니다", + "UG_LINE10": "6、제공되는 서비스에는 광고가 포함될 수 있으며 사용자는 사용 중 제3자 공급업체, 파트너가 제공하는 광고와 함께 표시하기로 동의합니다", + "UG_LINE11": "7、사용자는 다음과 같은 내용을 작성, 업로드, 복사, 전송하거나 서비스를 이용할 수 없습니다:", + "UG_LINE12": "(1 )헌법 의 확정 된 기본 원칙 에 반대 하다.;", + "UG_LINE13": "(2)국가 의 안전 을 해치고 국가 의 비밀 을 유출 하여 국가 정권 을 전복시키다 ,국가 통일 파괴;", + "UG_LINE14": "(3)국가의 명예와 이익을 해치다;", + "UG_LINE15": "(4)민족 적개심, 민족 차별을 선동하여 민족 단결을 파괴하다;", + "UG_LINE16": "(5)국가 종교 정책을 파괴하고 사교와 봉건 미신을 선양하다;", + "UG_LINE17": "(6)헛소문을 퍼뜨려 사회 질서를 어지럽히고, 사회 안정을 파괴하다;", + "UG_LINE18": "(7)음란, 포르노, 도박, 폭력, 살인, 공포 또는 범죄를 교사하다;", + "UG_LINE19": "(8)다른 사람을 모욕하거나 비방하며, 타인의 합법적 권익을 침해하다;", + "UG_LINE20": "(9)법과 행정 법규가 금지하는 기타 내용을 포함한 정보", + "UG_LINE21": "8、Qianhai Youlong Technology Co., Ltd.는 그 합리적인 판단에 따라, 관련된 법률적 법규나 본 협약의 약속을 위반하거나, 침해하거나, 그 누구의 권리나 안전을 저해하거나, 위협할 수 있는 내용을 위반하거나, 타인의 행위를 허위로 하는 경우, Qianhai Youlong Technology Co., Ltd.는 합리적으로 판단한다. 위반자 의 멤버 자격 을 종지할 수 없다, 모든 또는 일부 서비스를 막고 법률 법규에 근거하여 관련 정보를 보존하고 관련 부서에 보고하는 등", + "UG_LINE22": "9、사용자 권리 및 의무:", + "UG_LINE23": "(1 )Qianhai Youlong Technology Co., Ltd. 아이디의 소유권은 Qianhai Youlong Technology Co., Ltd.에게 있으며, 사용자는 등록 요청을 완료한 후 계정의 사용권을 얻게 되며, 이 사용권은 초기 신청 등록인에 속하며, 증여, 차용, 대여 또는 대여를 금지합니다.Qianhai Youlong Technology Co., Ltd.는 운영상 필요에 따라 사용자의 계정을 회수하고 사용자 사진, 동영상, 음성 등을 사용하여 제품 홍보 활동을 할 수 있는 권한을 가지고 있습니다", + "UG_LINE24": "(2)사용자는 Qianhai Youlong Technology Co., Ltd..에 있는 개인 자료, 등록 정보 및 전송 내용 등을 변경, 삭제할 권한이 있지만, 해당 정보를 삭제하는 동시에 귀하가 시스템에 저장한 어떤 문자와 그림도 삭제할 수 있다는 점에 유의해야 합니다.사용자가 이 위험을 부담해야 합니다", + "UG_LINE25": "(3)사용자는 등록 계정 정보 및 계정 암호의 보안을 적절하게 보관해야 할 책임이 있으며, 사용자는 등록 계정 그리고 암호 하의 행위에 대해 법적 책임을 져야 합니다.사용자는 어떤 경우에도 다른 구성원의 계정이나 암호를 사용하지 않기로 동의합니다.다른 사람이 당신의 계정이나 비밀번호를 사용하고 있다고 의심했을 때, 당신은 Qianhai Youlong Technology Co., Ltd.에게 즉시 통지하는 것에 동의합니다", + "UG_LINE26": "(4)사용자는 본 협약의 각 조항을 준수하여 본 서비스를 정확하고 적절하게 이용해야 하며, 사용자가 본 협약의 어떤 조항을 위반하였을 경우 Qianhai Youlong Technology Co., Ltd.는 협약에 의거하여 위약 사용자 Qianhai Youlong Technology Co., Ltd. 계정에 대한 서비스를 중지할 권리가 있습니다.아울러 Qianhai Youlong Technology Co., Ltd.는 언제든지 Qianhai Youlong Technology Co., Ltd. 계정, 사용자 이름을 회수할 권리를 보유합니다", + "UG_LINE27": "(5)사용자가 자신의 상용 영문 계정을 가지고 있다면, 사용자는 이 영문 계정을 우선적으로 계정으로 등록할 권리가 있지만, 사용자가 서비스에 접속한 후 일정 기간 동안 계정을 등록하지 않았거나, 사용자가 위신 계정으로 등록할 권리가 있지만, 이 영문 계정을 사용하는 것은 아닙니다. 낭비를 초래하지 않도록 이 계정을 회수할 권한이 있으며, 이로 인한 문제는 사용자 스스로 부담합니다", + "UG_LINE28": "(6)사용자가 계정을 등록한 후 장기간 이 계정에 로그인하지 않으면 Qianhai Youlong Technology Co., Ltd.는 리소스 낭비를 초래하지 않도록 이 계정을 회수할 권한이 있으며, 이로 인한 문제는 사용자 스스로 부담합니다", + "UG_LINE29": "(7)사용자 가 발생 한 분쟁 은 고발 기능 유지 사용자 플랫폼 권익 을 사용 할 수 있으며, 만약 사용자 가 신고하여 피드백 을 받을 수 있다면 , 사용자 에게 자발적 으로 알려 주거나 고객 에게 협조 할 의무 가 있다 , 신고 내용 확인 사실이 사실인지, 마스크 공원은 사용자 경고, 계좌 사용 기능 제한 등 사용자 위칙 행위를 구속할 권리가 있다 , 엄중위권자 데이트는 계좌를 직접 동결할 권리가 있고 계좌의 잔액은 반환하지 않는다.계좌가 동결되면, 고객은 고객에게 연락할 수 있다", + "UG_LINE30": "二、프라이버시 보호", + "UG_LINE31": "사용자 동의 개인 프라이버시 정보는 사용자를 개인 식별하거나 개인 통신을 할 수 있는 정보를 말하며 다음을 포함한다. 사용자의 실제 이름, 휴대폰 번호, 위챗 계정, 페이스북 계정, IP 주소.비개인 프라이버시 정보란 본 서비스에 대한 사용자의 조작 상태 및 사용 습관과 같은 일부 명확하고 객관적으로 Qianhai Youlong Technology Co., Ltd. 서버단에 반영되는 기본 기록 정보와 기타 모든 개인의 프라이버시 정보의 범위 밖의 일반 정보를 의미하며, 또한 이용자가 공개에 동의한다.이용자 개인의 프라이버시 정보의 사유성을 존중하는 것은 Qianhai Youlong Technology Co., Ltd.의 일관된 제도이며, Qianhai Youlong Technology Co., Ltd.는 이용자의 개인 프라이버시 정보 보호, 법률 또는 법률에 의한 권한 부여에 관한 정부부처의 요청 또는 사용자의 합리적인 조치를 강구하지 아니한다.그러나, 사용자가 등록할 때 동의를 선택하거나, 사용자와 Qianhai Youlong Technology Co., Ltd. 및 제휴 단위 간에 사용자의 개인 프라이버시 정보의 공개나 별도의 약정이 있는 예외를 사용하면서 사용자는 이로 인해 발생할 수 있는 어떠한 위험도 스스로 부담해야 한다.아울러 Qianhai Youlong Technology Co., Ltd.의 기술 및 서비스를 운영 및 개선하기 위해 Qianhai Youlong Technology Co., Ltd.는 사용자의 비개인 프라이버시 정보를 자체 수집하여 사용하거나 제3자에게 제공하는 데 도움이 될 수 있으며, 이는 Qianhai Youlong Technology Co., Ltd. Limited 사용자들에게 더 나은 서비스를 제공하는 데 도움이 될 것이다.Qianhai Youlong Technology Co., Ltd. 데이터 수집은 사용자와 Qianhai Youlong Technology Co., Ltd.의 인터렉션과 사용자의 선택에 따라 사용자의 프라이버시 설정 그리고 사용자가 사용하는 제품과 기능을 포함한다.Qianhai Youlong Technology Co., Ltd.가 수집한 데이터는 SDK/API/JS 코드 버전, IP 주소, 플랫폼, 타임스탬프, 애플리케이션 식별자, 애플리케이션 배포 채널, 독립 디바이스 식별자, iOS 광고를 포함할 수 있습니다.이는 Qianhai Youlong Technology Co., Ltd.가 내부 데이터 분석과 연구, 제3자 SDK 통계 서비스를 전개하고 Qianhai Youlong Technology Co., Ltd.의 제품 또는 서비스를 개선하는 데 도움이 될 것입니다.사용자의 신원 진실성을 확보하고 사용자에게 더 나은 안전 보장을 제공하기 위해 사용자가 제출해야 하는 신원 정보나 안면 특징과 같은 생체 인식 정보(모두 개인 민감한 정보)는 구체적인 제품 서비스를 완료하는 데 필요하거나 필요한 실제 사용자의 인증에만 사용될 것입니다.사용자가 제공한 . 상기 정보는 사용자가 본 서비스를 사용하는 동안 Qianhai Youlong Technology Co., Ltd.에게 지속적으로 권한을 부여합니다.사용자가 계정을 해지할 때 Qianhai Youlong Technology Co., Ltd.가 사용 중지됩니다.상술한 정보는 중화인민공화국 경내에 저장될 것이다.크로스오버 전송이 필요한 경우, Qianhai Youlong Technology Co., Ltd.는 사용자의 라이선스 동의를 별도로 구합니다.App 사용자 진정성 인증에는 사용자의 신원을 확인할 수 있는 일부 자료가 필요합니다.관련 자료는 플랫폼 심사만을 사용하여 어떠한 다른 사용자에게 공개되거나 상업적 용도로 사용되지 않으며, 법률 또는 관련 부서의 개입 요청만 제외됩니다", + "UG_LINE32": "三、 Qianhai Youlong Technology Co., Ltd. 상업 로고 정보", + "UG_LINE33": "Qianhai Youlong Technology Co., Ltd. 서비스에서 다루는 logo와 같은 그래픽, 문자 또는 그 구성, 그리고 기타 Qianhai Youlong Technology Co., Ltd. 로고 및 제품, 서비스 (이하 이름은 Qianhai Youlong Technology Co., Ltd.라는 상표입니다.)Qianhai Youlong Technology Co., Ltd.의 사전 서면 동의 없이, 사용자는 Qianhai Youlong Technology Co., Ltd. 표시를 어떤 방식으로든 보여지거나 사용하거나 다른 방법으로 처리하거나, 다른 사람에게 당신이 Cyhd를 전시, 사용할 권리가 있음을 나타내지 또는 기타 권한 있는 행위", + "UG_LINE34": "四、법적 책임 및 면책", + "UG_LINE35": "1、사용자는 본 <합의> 또는 관련된 서비스 약관의 규정을 위반하여 발생하거나 발생한 어떠한 제3자가 주장하는 어떠한 클레임, 요청 또는 손해에 대해서도 합리적인 변호사비를 포함하여 Qianhai Youlong Technology Co., Ltd.와 협력사, 관련 회사를 배상하고 손해를 피하는데 동의합니다", + "UG_LINE36": "2、Qianhai Youlong Technology Co., Ltd.及合作单位不承担责任。사용자가 전기통신 부문과 같은 제3자의 통신회선 고장, 기술 문제, 네트워크, 컴퓨터 고장, 시스템 불안정성 및 기타 여러 가지 불가항력적인 이유로 입은 모든 손실에 대해 Qianhai Youlong Technology Co., Ltd. 및 협력 단위는 책임을 지지 않습니다", + "UG_LINE37": "3、기술적 고장과 같은 불가항적인 사건으로 서비스의 정상 운영에 영향을 미치는 경우, Qianhai Youlong Technology Co., Ltd. 및 협력 단위는 제1시간 이내에 해당 기관과 협조하여 적시에 처리하고 복구할 것을 약속하지만, 사용자가 이로 인해 입은 모든 손해, Qianhai Youlong Technology Co., Ltd.는 책임을 지지 않습니다", + "UG_LINE38": "4、본 서비스는 대부분의 인터넷 서비스와 마찬가지로 이용자의 원인, 인터넷 서비스 품질, 사회 환경 등의 차이에 한정되지 않고, 타인이 이용자의 자료를 이용, 접속하는 경우, 이용자가 접속하는 경우, 이용자의 접속을 저해할 수 있다.이용자는 정보보안 및 이용자 자료의 보호의식을 강화해야 하며, 손해나 스토킹을 당하지 않도록 패스워드 보호 강화에 유의해야 한다", + "UG_LINE39": "5、사용자는 본 서비스 사용은 Internet 서비스에 관련된 것으로 인해 각 세션의 불안정한 요소에 의해 영향을 받을 수 있다는 것을 알아야 합니다.따라서 본 서비스는 불가항력, 컴퓨터 바이러스 또는 해킹, 시스템 불안정, 사용자의 위치, 사용자의 셧다운 그리고 기타 어떤 기술, 인터넷락, 통신회선 원인 등에 의한 서비스 중단 또는 사용자의 요구를 충족하지 못할 리스크가 있습니다.사용자는 위 위험을 감수해야 하며 Qianhai Youlong Technology Co., Ltd.는 보증하지 않습니다.이로 인해 사용자가 읽기 메시지를 보내고 받을 수 없게 되거나 잘못된 메시지를 수신하게 되는 것에 대해 Qianhai Youlong Technology Co., Ltd.는 어떠한 책임도 지지 않습니다", + "UG_LINE40": "6、사용자 사용을 알아야 하는 과정에서 본 서비스에는 존재하고 타인의 어떠한 위협적인 비방성을 포함한 것이다.,,거슬린 내용이나 불법 행위나 타인에 대한 권리를 침해하거나()의 지적 재산권을 포함한 정보의 익명성 또는 위험에 대리 가입자 이상을 부담하고 협력사 리스크에 대한 본 Qianhai Youlong Technology Co., Ltd..어떠한 유형의 부당 업무와 상관 없이 명확한 담보나 숨은 정보를 포함, 모든 관계자성, 진실성에 적합하다 이제 특정 용도로 사용하고 있다.아닌 소유권과 특허 침해와 묵시적 담보에 대한 조건으로 이로 인해 부당한 어떠한 불법 이용자에 따른 서비스를 이용하거나 직간접적으로, 우연히, 특수한 피해 및 후속도 책임을 지지 않고 있다", + "UG_LINE41": "7、Qianhai Youlong Technology Co., Ltd.가 정의하는 정보는 문자, 소프트웨어, 음성, 사진, 비디오, 그래프, 광고에서 전체 내용; Qianhai Youlong Technology Co., Ltd.가 사용자들에게 제공하는 상업적 정보, 기타 모든 것들을 저작권으로 보호한다.그래서 사용자는 Qianhai Youlong Technology Co., Ltd.와 광고주의 권한 하에서만 이러한 콘텐츠를 사용할 수 있으며, 이.약간의 내용을 무단으로 복사, 수정, 편찬하거나 콘텐츠와 관련된 파생상품을 창출할 수 없다", + "UG_LINE42": "8、어떠한 경우에도 Qianhai Youlong Technology Co., Ltd.는 어떠한 간접성, 결과성, 징벌성, 우발적, 특수성 또는 형벌적 피해에 대하여 사용자의 서비스 이용으로 인한 이익손실을 포함하여 책임을 부담한다(예: 이미 고지되었다 하더라도). 본 협약에 상반되는 규정이 포함될 수 있음에도 불구하고, Qianhai Youlong Technology Co., Ltd.가 귀하에게 부과하는 모든 책임은 어떠한 이유로든, 어떤 행위 방식으로든 귀하가 멤버십 기간 동안 서비스를 이용함으로써 Qianhai Youlong Technology Co., Ltd.에게 지불한 비용을 초과하지 않습니다", + "UG_LINE43": "五、회원 약관", + "UG_LINE44": "1、흔호 회원 평등로 회원 권리를 쓸 수 있으며, 또한 Qianhai Youlong Technology Co., Ltd. 의 각종 규범, 규칙을 지켜해야 하며, 이 서비스조항과 사용자협의에 제한되지 않는다", + "UG_LINE45": "2、Qianhai Youlong Technology Co., Ltd. < 사용자 협의 > 위반하면 회원 서비스 중단된 관련 손실은 사용자가 스스로 부담한다 ", + "UG_LINE46": "3、회원 은 회원 자격 유효 기간 내에 흔호 회원 의 각종 추가 서비스 를 쓸수 있다 ", + "UG_LINE47": "4、회원 자격 유효기간 내에 회원 자격 정지나 취소, Qianhai Youlong Technology Co., Ltd. 는 회원 잉여 회원 자격 유효기간에 대한 서비스 비용을 반환하지 않습니다", + "UG_LINE48": "5、회원은 흔호중 전송이랑정보 및 흔호 무료 서비스 또는 요금 서비스를 이용한 법률 책임, 회원은 흔호 서비스, 무료 서비스와 요금 서비스를 포함하는 행위를 포함하여, 모든 법률 법규, 규범, 규범성 서류를 지켜해야 한다", + "UG_LINE49": "6、회원 서비스가 개통된 후에는 양도 또는 취소를 할 수 없습니다", + "UG_LINE50": "7、회원은 Qianhai Youlong Technology Co., Ltd. 무료 서비스 또는 유료 서비스를 이용하면서 법적 법규를 위반하는 행위가 있기 때문에, Qianhai Youlong Technology Co., Ltd.는 해당 회원의 자격을 취소할 권리가 있으며, 그에 대한 보상은 일체가 없이, 그리고 회원은 스스로 책임을 져야 한다", + "UG_LINE51": "六、기타 조항", + "UG_LINE52": "1、Qianhai Youlong Technology Co., Ltd. 사용자 주의본 협의에서 Qianhai Youlong Technology Co., Ltd. 책임과 사용자 의무를 강화하는 조항은 사용자가 자세히 읽으십시오. 자율적으로 위험을 고려합니다. 미성년자는 법정 보호자의 배동에서 본 《협의》를 읽어야 한다.이상 각종 조항 내용 의 최종 해석권 및 수정권 은 Qianhai Youlong Technology Co., Ltd. 소유", + "UG_LINE53": "2、본 《협의》 가 정한 무두 조항의 일부나 전부효자 는 다른 조항의 효력 에 영향을 하지 않는다", + "UG_LINE54": "3、본 《협의》의 해석, 효력 및 분쟁의 해결, 중화인민공화국 법률에 적용된다. 사용자와 Qianhai Youlong Technology Co., Ltd. 사이의 어떤 분쟁이나 논란이 발생한다면 우선 우호적인 협상이 이루어지지 않는다면, 사용자는 분쟁이나 논란을 제기하거나 논란을 제기할 수 있는 Qianhai Youlong Technology Co., Ltd. 주소 인민법원 관할", + "UG_LINE55": "4、본 <협의>'의 판권은 Qianhai Youlong Technology Co., Ltd. 모든 해석과 권리 수정이 보유합니다", + "UG_LINE56": "Qianhai Youlong Technology Co., Ltd.", + "net_error": "네트워크 이상하다", + "enter_name": "이름을 입력하세요", + "translate": "번역", + "locate": "위치 ", + "voice_tips": "누르면 녹음하고 놓치면 보내다", + "unlock": "해제", + "input_content": "체팅내용 입력하세요", + "connecting": "연결중…", + "logining": "등록중…", + "reject_reply": "/s1 당신의 보기 신청을 거절했다", + "warning_text": "H 돈을 입금한지 3일 안에서 아무도 신고하지 않으면 즉시 환전할 수 있다 (1:1000베트남 동)", + "more_big": "입력한 개수는 /s1 많으면 안된다", + "little_min": "입력한 개수는 /s1 적으면 안된다", + "voice_msg": "/s1 통화를 요청합니다", + "send_gift": "당신은 상대방에게 상을 주었다 /s1개 /s2", + "receive_gift": "상대방이 너에게 상을 주었다 /s1개 /s2", + "cannot_join": "비회원 신청 못한다", + "alreay_back": "반품했다", + "video_more_big": "파일이 너무 크다", + "select_all": "무두 선택 ", + "re_connect": "다시 연결 ", + "voice_tips2": "열히면 보내다, 슬라이딩으면 취소하다", + "country": "나라", + "have_picture_view": "사진을 심사중", + "speaker_play": "스피커 방송", + "handset_playback": "수화기 방송", + "play_model": "수화기 모드", + "password_less": "암호가 너무 짧음", + "years_old": "나이", + "coin_returen1": "익명의 사용자의 제보로,시스템은 당신이 최근 위반행위를 한 것을 확인하였으므로,더 이상 위반을 하지 마십시오.다음이 있는 경우 계정 동결 진행할것이다.", + "already_new": "이미 최신 버전입니다.", + "test_it": "즉시 체험", + "found_new": "새 버전이 발견됨", + "ad": "광고", + "attention": "관심을 가지다", + "fans": "팬", + "apply_see": "/s1 내 자료 페이지 보기 요청.", + "agree_apply": "/s1 내 보기 요청을 통과했다.", + "see_redBag": "/s1 내 돈봉투 사진을 봤습니다.", + "notice": "상기", + "notice_open": "휴대폰 설정에서 알림을 받을 수 있도록 알림 권한을 켜십시오.", + "open_notice": "알림 권한이 켜져 있지 않음", + "not_open": "알림 권한이 켜져 있지 않아 알림을 수신할 수 없음", + "withdraw_fail": "당신이 인출을 신청한/s1H달러가 반송되었으니, 계좌를 묶는 것이 올바른지 확인하세요.", + "dynamics": "동태", + "Remark": "비고", + "setRemark": "비고 설치", + "content_num": "/s1 건 평론", + "Redeem": "포인트 태환 획득/s1H화폐", + "location_permission": "모바일 저장을 방문 권한이 없음", + "camera_permission": "카메라 방문 권한이 없음", + "photo_permission": "앨범 방문 권한이 없음", + "video_permission": "마이크를 방문 권한이 없음", + "your_redMoney_over": "당신이 보낸 돈봉투는 이미 기한이 지났다.", + "other_redMoney_over": "상대방이 보낸 돈봉투는 이미 기한이 지났다.", + "server_error_tips": "뭔가 문제가 생긴 것 같은데…", + "emoji": "표정", + "today_score": "오늘 수령 가능/s1 적분에 서명합니다.", + "sign_tips": "1. 매일 수령 가능한 포인트에 서명하고, 누적 일수가 많을수록 포인트가 높습니다. \n2.포인트는 H 화폐를 바꿀 수 있습니다. 포인트는 해당 포인트를 사용하므로 신중한 태환. \n3.매월 마지막 날 서명 초기화, 포인트가 적립, 잊지 말고 바로 교환하세요.", + "sign_in": "서명을 하다.", + "my_score": "내 포인트", + "signin_now": "즉시 서명하다.", + "sign_in_day": "누적된 서명/s1일", + "have_get": "기환", + "scan": "스캔", + "my_qr": "내 QR 코드", + "scan_and_add": "스캔하고 친구 추가", + "amap": "구다지도", + "baidumap": "바이두지도", + "googlemap": "구글지도", + "applemap": "애플지도", + "go_open": "열다", + "Preview": "미리 보기", + "Photo_album": "앨범", + "all_photo": "모두 사진", + "have_select": "당신이 /s1 장 사진을 선택했습니다.", + "loading": "로드 중 …", + "new_chat_msg": "새로운 채팅 메시지가 있습니다.", + "new_video_msg": "새로운 통화 메시지가 있습니다.", + "apply_friends": "/s1친구 되기 신청", + "applyed_friends": "/s1은 당신의 친구 요청을 통과했습니다.", + "contact_permission": "통신록을 방문할 권한이 없습니다.", + "contact": "통신록", + "search": "검색", + "contact_add": "통신록의 친구 추가", + "find": "발견", + "translate_robot": "번역 로봇", + "robot_hello": "안녕하세요, 번역로봇입니다…", + "Simplified_Chinese": "중국어(간체 )", + "traditional_Chinese": "중국어(번체)", + "english": "영어", + "Vietnamese": "베드남어", + "Korean": "한국어", + "Japanese": "일본어", + "add_friends": "친구 추가", + "stranger": "모른 사람", + "receive_stranger": "모른 사람 보낸 메시지를 수신", + "signin": "SignIn", + "stranger_close": "상대방은 낯선 사람이 보낸 소식을 수신하기를 거부하며, 모든 자료를 계속 잠글지 여부를 결정합니다.", + "add": "추가하다.", + "added": "추가했다.", + "stranger_close_tips": "상대방은 낯선 사람이 보낸 소식을 수신하기를 거부했다.", + "translate_fail": "번역에 실패하다.", + "no_photos": "먼저 사진을 업로드하고 돈봉투 사진을 설정하십시오.", + "successful_appeal1": "당신 항소의 평가: /s1 항소에 실패했습니다.", + "add_success": "추가 성공, 상대방 동의 대기.", + "other_pay": "다른 사람이 대신 지불하다.", + "friend_verification": "친구 검증", + "add_friends_tips": "당신은 이미 검증 신청을 보냈으니, 상대방이 통과할 때까지 기다려라.", + "i_am": "나는/s1", + "agree": "허락", + "privacyAgreement": "\"Hi\"는 당신이 <프라이버시 협약>에 동의해야 사용할 수 있다.", + "privacy": "프라이버시 협약", + "notification_addfriend": "Hi! 누군가가 너를 친구로 추가하자고 신청했어. 누군지 보세요.", + "distance_long": "얼굴을 마주해야 친구를 추가할 수 있어요", + "chat_tips": "번역 내용의 정확성을 위해서, 간단히 쓰지 마세요.", + "fans_list": "팬 목록", + "system_not_open": "기능 내측 중", + "service_withdraw_tips": "iOS 클라이언트는 현찰 인출을 당분간 지원하지 않으며, 당신은 안드로이드 클라이언트를 사용하여 현금을 인출하거나, 아래 버튼을 클릭하여 인출할 수 있다.", + "withdraw_tips": "현금 인출 클릭", + "add_member": "멤버 추가", + "delete_member": "멤버 삭제", + "change_group_name": "그룹 이름 수정", + "my_group_nickname": "이 그룹에 있는 내 닉네임", + "group_chat": "그룹 채팅", + "create_group_chat": "그룹 채팅 창건하다.", + "added_friends_tips": "너는 상대방이 통과할 때까지 검증 신청을 보내야 한다.", + "group_chat_name": "그룹 채팅 미름", + "my_group_nickname_tips": "여기서는 당신이 이 그룹에 있는 닉네임을 설정할 수 있으며, 이 닉네임은 이 그룹에만 표시됩니다.", + "man_gold": "남신 동태", + "woman_gold": "여신 동태", + "choose_group_owner": "새 그롭 주인 선택", + "group_announcement": "그롭 공고", + "chat_news": "채팅 소식", + "group_qr": "그롭 코드", + "group_setting": "그롭 관리", + "close_news_notice": "메시지 알림 비활성화", + "set_chat_top": "맨 위에 고정", + "show_group_member_name": "그룹 멤버의 닉네임을 표시합니다", + "quit_group_tips": "탈퇴 후 그롭 채팅 중 다른 멤버에게 통보하지 않으며, 더 이상 이 그롭 채팅 소식을 받지 않는다.", + "quit_and_delete": "삭제 후 종료", + "show_more_member": "멤버 더 보기 ", + "group_invite": "그롭 채팅 요청 확인", + "change_group_owner": "그롭 주인 관리권 양도", + "group_setting_tips": "부팅 후, 그룹 멤버는 그룹 소유자가 확인해야 친구를 그룹에 초대할 수 있습니다. 코드로 그롭 들어가는 것은 동시에 중지될 것이다.", + "invite_detail": "요청 상세", + "undefine_name": "이름 없다", + "group_qr_code": "그롭 코드 명함", + "group_qr_code_tips": "이 코드는 7일 이내(/s1월/s2일 전) 유효하며 재진입이 갱신됨", + "Goddess_heat": "여신 인기", + "Goddess_heat_tips": "누적 수확의 선물", + "new_friends": "새 친구", + "before_three_day": "3일 전", + "after_three_day": "근 3일", + "group_clean_chat_record": "채팅 기록 지우기", + "check": "보기", + "apply_fro_friends": "당신을 친구로 추가해 달라고 요청했습니다", + "no_vip_cannot_withdraw": "비회원은 현금을 인출할 수 없다.", + "not_true_woman": "이 사용자는 인증되지 않았으므로, 속지 않도록 주의한다.", + "join_group": "그롭 채팅 가입", + "sign_in_apple": "Apple로 등록", + "only_host": "그룹 소유자만 그룹 게시를 편집할 수 있습니다.", + "send_gift1": "당신은 상대방에게/s1개의 선물을 주고 받았다", + "receive_gift1": "상대방이 널/s 1개의 선물에 매겼어요.", + "not_in_group": "당신은 이미 이 그롭에 있지 않다.", + "creating_group": "만드는 중이니 잠시 기다려 주세요", + "article": "건", + "group_open_verification": "이 그롭은 이미 코드 검증을 시작했으며 요청을 통해서만 그롭에 들어갈 수 있습니다.", + "group_memeber": "그롭 멤버", + "invite_members": "초대/s1명의 친구를 그롭 채팅에 가입시키다", + "total_members": "총/s1명", + "qr_outtime": "코드 유한기 지났다.", + "no_goupr_info": "이 그룹 메시지 없음", + "you_invite": "당신이 /s1가 그롭 초청하여 그롭 채팅에 가입하게 했다.", + "invite_you": "당신은 /s1에 의해 그롭 채팅에 끌려들어갔어요.", + "invite_someone": " /s1가 /s2를 그롭 초청하여 그롭 채팅에 가입하게 했다.", + "you": "당신", + "delete_group": " /s1 를 /s2 그롭 채팅으로 나가 시켰다.", + "you_group_owner": "당신이 새 그롭 주인 되었다.", + "someone_group_owner": "/s1새 그롭 주인 되었다.", + "change_group_owner1": "그롭 이름은 /s1로 변경했다.", + "update_group_announce": "그롭 공지가 업데이트 되었습니다", + "you_qr": "당신은 스캔 코드를 통해 그롭 채팅에 가입한다.", + "others_qr": "/s1스캔 코드를 통해 그롭 채팅에 가입한다.", + "invite_confirm": "\"/s1\" 초대/s2명 친구 그롭 가입하고 싶다. \\$확인하세요.\\$ ", + "want_invite_confirm": " \"/s1\" 초데\"/s2\" 그롭 채팅 가입하고 싶다. ", + "join_group_confirm": "\"/s1\" 그롭 채팅 가입 확인 되었다.", + "you_invite_gourp": "당신은 /s1에 군담에 끌려들어갔다. ", + "someone_join_group": " \"/s1\" 그롭 채팅 가입 ", + "group_setting_tips1": "그룹 소유자가 이미\"그룹 채팅 요청 확인\",을(를) 열어서, 그룹 멤버가 그룹 소유자가 확인해야 친구를 그룹에 초대할 수 있습니다.", + "group_setting_tips2": "그롭 소유자는 이미 암묵적인 그롭에 들어가는 방식을 회복하였다.", + "members_max": "그롭 멤버 더 추가할 수 없다.", + "group_max": "그롭 수가 상한에 도달했습니다.", + "my_money_info": "내 계산서", + "my_left_money": "내 잔고", + "money_tips": "H화폐는 충전이나 환전으로 얻을 수 있고 현금인출이 불가능합니다.", + "get_money_detail": "소득명세", + "hibok_money": "Hibox소득", + "charge_h": "H화폐 교환", + "charge_tips": "인출 규칙", + "splash_tips1": "많은 편화 위치 改편리한 위치 변환", + "splash_tips2": "번역 로봇", + "splash_tips3": "친구 사귀기 앱", + "splash_tips_content1": "많은 편화 여신 改편리한 이성 변환", + "splash_tips_content2": "음성 인터랙티브", + "splash_tips_content3": "해결 언어 문제", + "splash_go": "즉시 채험", + "change_h_coin": "당신은 수입에 통했고/s1H화폐 교환됐다.", + "Representation_succes": "당신의 진술이 성공하여 시스템이 환불되었습니다.", + "system_give": "시스템 증정", + "exchange_fail": "당신의 인출 신청이 실패하여, 반송되었습니다.", + "hibok_exchange": "Hibox를 통해 환전/s1H화폐", + "bind_code_success": "성공적으로 초대 코드를 묶음", + "translate_money": "당신은/s1H화폐를 소모해서 인공번역을 합니다.", + "system_back": "시스템 취소 반송", + "you_give": "당신은 상대방에게 상을 주었다.", + "you_get": "상대방이 당신에게 상을 주었다.", + "enter_num_qian": "환전 금액(단위 K)", + "enter_num_qian1": "인출 금액(단위K)", + "daily_translate_voucher": "翻译券", + "msg_notice":"通知消息", + "select_notice_people":"选择提醒的人", + "search_phone":"查找手机号", + "not_have_user":"用户不存在", + "you_are_blaklisted":"对方已拉黑了你", + "confrim_recovery":"确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)", + "send_to": "發送到" +} \ No newline at end of file diff --git a/i18n/vi-VN.json b/i18n/vi-VN.json new file mode 100644 index 0000000..5d007ed --- /dev/null +++ b/i18n/vi-VN.json @@ -0,0 +1,1164 @@ +{ + "appName": "Hibok", + "login": "Đăng nhập", + "registration": "Đăng ký", + "other_login": "Cách đăng nhập khác", + "account": "Số tài khoản", + "enter_username": "Vui lòng nhập số tài khoản", + "password": "Mật khẩu", + "enter_password": "Nhập mật khẩu", + "forget_password": "Quên mật khẩu", + "reset_password": "Đặt lại mật khẩu", + "number_registration": "Đăng ký số điện thoại", + "enter_number": "Nhập số điện thoại", + "code": "Mã xác thực", + "enter_code": "Nhập mã xác thực", + "send_code": "Gửi mã xác thực", + "send_again": "Gửi lại", + "set_password": "Cài đặt mật khẩu", + "password_limit": "Mật khẩu không được dưới 6 ký tự", + "set_password2": "Xác lập mật khẩu", + "next_step": "Tiếp theo", + "agreed_agreement": "Click vào đây để xác nhận bạn đã đọc và đồng ý với \"điều khoản sử dụng\"", + "enter_password2": "Xin nhập mật khẩu đăng nhập", + "reset_now": "Cài đặt lại", + "choose_gender": "Chọn giới tính", + "who": "Bạn là", + "determine": "Xác định", + "cannot_modified": "không thể sủa đổi sau khi đã xác định giới tính", + "tip": "Nhắc nhở", + "choose_quit": "Bạn sắp hoàn tất đăng ký, bạn thực sự muốn bỏ cuộc?", + "confirm": "Xác nhận", + "use": "Sử dụng", + "cancel": "Hủy", + "close": "Đóng", + "delete": "Xóa", + "forget_it": "Bỏ qua", + "ok": "OK", + "choose_quit2": "Sau khi đăng ký bạn sẽ không thể sửa đổi giới tính của mình. Bạn có chắc không?", + "tip_content": "Nhắc nhở:bạn không thể tiến hành giao lưu với người dùng cùng giới", + "welcome": "Chào mừng bạn", + "enter_incode": "Vui lòng nhập mã mời", + "must_incode": "Hibok chỉ phục vụ khách hàng nam cung cấp mã mời", + "your_incode": "Mã mời của bạn", + "how_get": "Chưa có mã mời? Bạn có thể lấy mã mời theo những cách sau", + "method1": "Cách 1", + "free": "Đăng ký miễn phí", + "apply_now": "Đăng ký ngay", + "check_incode": "Nhận mã mời", + "so_get": "Bạn cần điền một số thông tin cá nhân, chúng tôi sẽ gửi mã mời cho bạn sau khi hoàn thành xét duyệt.", + "apply_incode": "Đăng ký mã mời", + "location": "Vị trí", + "cityname": "Thành phố bạn đang ở", + "message_channel": "Kênh thông tin", + "how_know": "Bạn biết đến APP này qua đâu?", + "wechat_number": "Wechat", + "your_wechat": "Tài khoản Wechat của bạn", + "facebook": "Facebook", + "your_facebook": "Facebook của bạn", + "submit_application": "Gửi yêu cầu", + "enter_city": "Vui lòng nhập tên Thành Phố bạn đang ở", + "so_know": "Bạn biết APP này qua kênh thông tin nào?", + "your_social": "Xin cung cấp mạng xã hội của bạn cho chúng tôi", + "receive_incode": "Chúng tôi sẽ xử lý sớm yêu cầu của bạn.Nếu xét duyệt được thông qua chúng tôi sẽ gửi mã mời vào trung tâm tin nhắn của bạn.", + "wait_incode": "Mã mời vẫn chưa được gửi đi, sau khi hoàn tất thao tác gửi đơn yêu cầu, vui lòng chờ trong giây lát!", + "successful_application1": "Xin mã mời thành công", + "application_failed1": "Xin mã mời thất bại", + "successful_copy": "Sao chép thành công", + "method2": "Cách 2", + "joinvip": "Trở thành VIP", + "join_now": "Tham gia ngay", + "joined": "Đã tham gia", + "join_odds": "Sau khi gia nhập bạn sẽ có thêm nhiều đặc quyền, bao gồm đăng ký không cần mã mời", + "not_joinvip": "Bạn chưa gia nhập thành viên", + "join_after": "Sau khi gia nhập bạn có thể đăng ký mà không cần mã mời", + "incode_passed": "Hoàn tất xác nhận mã mời", + "welcome_join": "Chào mừng bạn tham gia! Xin đừng tiết lộ số tài khoản của bạn cho người khác, khi phát hiện đăng nhập bất thường tài khoản sẽ tự động đóng băng.", + "member_centre": "Trung tâm thành viên", + "members_privilege": "Đặc quyền của thành viên", + "see_more": "Right 1", + "unlimited_see": "Tài khoản không giới hạn số lượng xem mỗi ngày", + "see_cheaper": "Right 2", + "free10": "Xem album và tài khoản miễn phí /s1 lần trong một ngày", + "see_longer": "Right 3", + "towto6": "Thời gian xem ảnh tự hủy sẽ chỉnh từ 2 giây thành /s1 giây.", + "see_better": "Right 4", + "free_release": "Cơ hội miễn phí phát sóng 3/ngày.", + "choose_price": "Chọn các gói", + "pay_method": "Phương thức thanh toán", + "pay_amount": "Số tiền thanh toán", + "not_enough": "Số dư ví không đủ", + "confirm_pay": "Xác nhận thanh toán", + "complete_material": "Hoàn tất thông tin", + "basic_information": "Thông tin cơ bản", + "upload_avatar": "Tải ảnh đại diện", + "choose": "Vui lòng chọn", + "fill_out": "Vui lòng điền vào", + "choose_multiple": "Có thể chọn nhiều mục cùng lúc", + "optional": "Tùy chọn", + "least": "Điền vào ít nhất /s1", + "introduce_yourself": "Giới thiệu bản thân", + "most": "Chọn tối đa /s1", + "nickname": "Biệt danh", + "only1_8": "Biệt danh không được quá 20 ký tự", + "Resident_city": "TP hiện tại", + "Please_select_a_resident_city": "Vui lòng chọn thành phố hiện tại", + "City1": "Cần Thơ", + "City2": "Đà Nẵng", + "City3": "Hải Phòng", + "City4": "Hà Nội", + "City5": "Hồ Chí Minh", + "City6": "An Giang", + "City7": "Bắc Giang", + "City8": "Bắc Cạn", + "City9": "Bạc Liêu", + "City10": "Bắc Ninh", + "City11": "Bà Rịa- Vũng Tàu", + "City12": "Bến Tre", + "City13": "Bình Định", + "City14": "Bình Dương", + "City15": "Bình Phước", + "City16": "Bình Thuận", + "City17": "Cà Mau", + "City18": "Cao Bằng", + "City19": "Đà Lạt", + "City20": "Đắc Nông", + "City21": "Điện Biên", + "City22": "Đồng Nai", + "City23": "Đồng Tháp", + "City24": "Gia Lai", + "City25": "Hà Giang", + "City26": "Hải Dương", + "City27": "Hà Nam", + "City28": "Hà Tĩnh", + "City29": "Hòa Bình", + "City30": "Hậu Giang", + "City31": "Hưng Yên", + "City32": "Khánh Hòa", + "City33": "Kiên Giang", + "City34": "Kon Tum", + "City35": "Lai Châu", + "City36": "Lâm Đồng", + "City37": "Lạng Sơn", + "City38": "Lào Cai", + "City39": "Long An", + "City40": "Nghệ An", + "City41": "Ninh Bình", + "City42": "Ninh Thuận", + "City43": "Phú Thọ", + "City44": "Phú Yên", + "City45": "Quảng Bình", + "City46": "Quảng Nam", + "City47": "Quảng Ngãi", + "City48": "Quảng Ninh", + "City49": "Quảng Trị", + "City50": "Sóc Trăng", + "City51": "Sơn La", + "City52": "Tây Ninh", + "City53": "Thái Bình", + "City54": "Thái Nguyên", + "City55": "Thanh Hóa", + "City56": "Thừa Thiên- Huế", + "City57": "Tiền Giang", + "City58": "Trà Vinh", + "City59": "Tuyên Quang", + "City60": "Vĩnh Long", + "City61": "Vĩnh Phúc", + "City62": "Yên Bái", + "City63": "Nam Định", + "birthday": "Ngày sinh", + "choose_birthday": "Chọn ngày sinh", + "year": "Năm", + "month": "Tháng", + "day": "Ngày", + "hour": "Giờ", + "minute": "Phút", + "second": "Giây", + "just": "Mới đây", + "minute_ago": "/s1 phút trước", + "hour_ago": "/s1 giờ trước", + "day_ago": "/s1 ngày trước", + "week_ago": "/s1 tuần trước", + "month_ago": "/s1 tháng trước", + "morning": "Sáng", + "noon": "Trưa", + "afternoon": "Chiều", + "night": "Tối", + "all_day": "Cả ngày", + "yesterday": "Hôm qua", + "two_yesterday": "Hôm trước", + "overnight": "Sáng đêm", + "one": "Cái", + "ten": "Mười", + "hundred": "Trăm", + "thousand": "Nghìn", + "ten_thousand": "Mười nghìn", + "aries": "Chòm sao Bạch Dương", + "taurus": "Chòm sao Kim Ngưu", + "gemini": "Chòm sao Song Tử", + "cancer": "Chòm sao Cự Giải", + "leo": "Chòm sao Sư Tử", + "virgo": "Chòm sao Xử Nữ", + "libra": "Chòm sao Thiên Bình", + "scorpio": "Chòm sao Bọ Cạp", + "sagittarius": "Chòm sao Nhân Mã", + "capricorn": "Chòm sao Ma Kết", + "aquarius": "Chòm sao Bảo Bình", + "pisces": "Chòm sao Song Ngư", + "monday": "Thứ hai", + "tuesday": "Thứ ba", + "wednesday": "Thứ tư", + "thursday": "Thứ năm", + "friday": "Thứ sáu", + "saturday": "Thứ bảy", + "sunday": "Chủ nhật", + "job": "chuyên nghiệp", + "choose_career": "Chọn một nghề nghiệp", + "career1": "Công nghệ thông tin", + "career2": "Internet", + "career3": "CNTT", + "career4": "Hoạt động viễn thông", + "career5": "Trò chơi trực tuyến", + "career6": "Bảo hiểm tài chính", + "career7": "Đầu tư", + "career8": "Quỹ đầu tư", + "career9": "Bảo hiểm", + "career10": "Ngân hàng", + "career11": "Thế chấp/ cầm cố", + "career12": "Dịch vụ kinh doanh", + "career13": "Tư vấn", + "career14": "Kinh doanh cá thể", + "career15": "Beauty salon", + "career16": "Du lịch", + "career17": "Khách sạn- nhà hàng", + "career18": "Giải trí", + "career19": "Thương mại", + "career20": "Xe hơi", + "career21": "Bất động sản", + "career22": "Quản lý tòa nhà", + "career23": "Trang trí nội thất", + "career24": "Thám tử", + "career25": "Công trình sản xuất", + "career26": "Kiến Trúc", + "career27": "Xây dựng dân dụng", + "career28": "Chế tạo cơ khí", + "career29": "Điện tử", + "career30": "Khoa học Y Sinh", + "career31": "Thực phẩm", + "career32": "Trang Phục", + "career33": "Năng lượng", + "career34": "Giao thông vận tải", + "career35": "Hàng không", + "career36": "Đường sắt", + "career37": "Vận tải hàng hải", + "career38": "Giao thông công cộng", + "career39": "Vận tải hàng hóa", + "career40": "Kênh truyền thông văn hóa", + "career41": "Nhà xuất bản", + "career42": "Thiết kế", + "career43": "Truyền bá văn hóa", + "career44": "Quảng cáo sáng tạo", + "career45": "Anime", + "career46": "Quảng bá triển lãm", + "career47": "Nhiếp ảnh", + "career48": "Thể thao giải trí", + "career49": "Phim ảnh", + "career50": "Thể thao thể thao", + "career51": "Âm nhạc", + "career52": "Người mẫu", + "career53": "Tiện ích công cộng", + "career54": "Y tế", + "career55": "Pháp luật", + "career56": "Giáo dục", + "career57": "Cơ quan chính phủ", + "career58": "Công ích", + "career59": "Học sinh/ Sinh viên", + "career60": "Không", + "program": "Chương trình", + "select_program": "Vui lòng chọn quốc tịch", + "healthy_exercise": "TDTT", + "night_party": "Tiệc đêm", + "gourmet_party": "Sành ăn", + "watch_movie": "Xem phim", + "play_games": "Chơi game", + "travel_together": "Du lịch", + "voice_chat": "Trò chuyện", + "other": "Khác", + "expect_lover": "Mẫu lý tưởng", + "choose_lover": "Vui lòng chọn mẫu người yêu lý tưởng của bạn", + "beautiful": "Gương mặt đẹp", + "rich": "Thổ hào", + "care_me": "Quan tâm và yêu thương tôi", + "look_feeling": "Cảm giác là trên hết", + "doesnt_matter": "Không quan trọng", + "least_account": "Vui lòng nhập ít nhất một tài khoản xã hội", + "hide_account1": "Ẩn tài khoản xã hội", + "more_information": "Những thông tin khác", + "height": "Chiều cao", + "weight": "Cân nặng", + "not_show": "Không hiển thị", + "self_introduction": "Giới thiệu", + "registration_success1": "Đăng ký thành công", + "exit": "Thoát?", + "exit_registration": "Bạn chưa hoàn thiện thông tin cá nhân. Lần sau đăng nhập trực tiếp bằng tài khoản đã đăng ký", + "cant_see": "Phai nam giới không thể xem thông tin của phái nam", + "cant_see2": "Phái nữ giới không thể xem thông tin của phái nữ!", + "see_one": "Bạn còn có thể xem /s1 quý cô ngày hôm nay", + "only_see": "Không phải thành viên chỉ có thể xem 15 quý cô mỗi ngày", + "continue_see": "Tiếp tục xem", + "user_frozen": "Tài khoản đã đóng băng", + "search_user": "Nhập biệt danh / nghề nghiệp để tìm kiếm", + "nearby": "Gần đây", + "member": "Thành viên", + "new_registration": "Bạn mới", + "authenticate": "Xác thực", + "first_online": "Trực tuyến", + "not_positioned": "Định vị là tắt, khoảng cách không thể được tính", + "unknown": "Vẫn chưa xác nhận", + "secrecy": "Bảo mật", + "collection": "Sưu tập", + "cancel_collection": "Hủy sưu tập", + "canceled_collection": "Đã hủy sưu tập", + "like": "Yêu thích", + "added_like": "Yêu thích", + "canceled_like": "Đã hủy yêu thích", + "blacklist": "Danh sách đen", + "blacklist_choose": "Bạn sẽ không thể thấy đối phương và hoạt động gần đây của họ, có chắc là bạn muốn thế không?", + "blacklisted": "Đã thêm vào danh sách đen", + "reject_message": "Bạn đã thêm đối Phương vào danh sách đen và từ chối nhận tin nhắn", + "remove_blacklist": "Xóa khỏi danh sách đen", + "blacklist_removed": "Đã xóa khỏi danh sách đen", + "receive_message": "Bạn đã xóa đối Phương khỏi danh sách đen và hủy chế độ từ chối tin nhắn", + "online": "Trực tuyến", + "paid_photo": "Album thu phí", + "application_view": "Xin", + "passed": "Đã duyệt", + "park": "Công viên", + "radio": "Radio", + "news": "Tin nhắn", + "me": "Tôi", + "more_operations": "Các thao tác khác", + "anonymous_report": "Báo cáo ẩn danh", + "certified_video": "Video", + "passed_video": "Em ấy đã được xác thực danh tính qua video", + "not_video": "Em ấy vẫn chưa xác thực danh tính", + "her_appointment": "Em ấy đang phát tin hẹn hò", + "pay_join": "Anh ta đã đóng phí để gia nhập", + "passed_review": "Anh ta đã thông qua xác nhận thân phận", + "invited_user": "Anh ấy đã gia nhập thông qua mã mời từ tài khoản VIP /s1", + "his_appointment": "Anh ấy đang phát tin hẹn hò", + "her_dynamics": "Hoạt động của em ấy", + "his_dynamics": "Hoạt động của anh ấy", + "low_key": "Em ấy rất khiêm nhường", + "low_key2": "Anh ấy rất khiêm nhường", + "her_photo": "Album ảnh của em ấy", + "his_photo": "Album ảnh của anh ấy", + "set_lock": "Anh ấy đã khóa album", + "set_lock2": "Em ấy đã khóa album", + "free_unlock": "Mở khóa album (/s1) miễn phí cho các thành viên", + "unlock_user": "Mở Khóa album của /s1", + "pay_unlock": "Mở khóa trả phí (/s1H coin)", + "become_member": "Miễn phí cho các thành viên", + "consumption_once": "Bạn muốn sử dụng 01 cơ hội để mở khóa album /s1", + "remaining_once": "(Hôm nay bạn vẫn còn /s1 cơ hội)", + "no_times": "Cơ hội miễn phí hôm nay của bạn đã hết, có muốn tặng tất cả thông tin mở khóa của /s2 cho /s1 không?", + "pay": "Thanh toán", + "view_user": "Anh ta đã thiết lập chế độ xem hạn chế, cần có sự đồng ý của anh ta để xem tiếp", + "view_user2": "Cô ta đã thiết lập chế độ xem hạn chế, cần có sự đồng ý của anh ta để xem tiếp", + "need_photo": "Muốn xem tiếp, bạn phải gửi một tấm ảnh của bạn cho đối phương. Hãy yên tâm, ảnh của bạn sẽ tự hủy sau 2 giây- tính từ lúc đối phương bấm nút xem.", + "choose_photo": "Chọn ảnh", + "send_application": "Yêu cầu đã được gửi đi, sau khi đối phương xác nhận bạn sẽ nhận được tin nhắn nhắc nhở", + "not_authenticate": "Bạn vẫn chưa tiến hành xác thực", + "after_authenticate": "Chỉ sau khi tính xác thực của bạn được chứng nhận, bạn mới có thể tương tác với người khác", + "authenticate_now": "Xác thực ngay", + "destroy_after": "Hủy sau khi xem", + "destroyed": "Đã hủy", + "red_photo1": "Ảnh lì xì sẽ được tiêu hủy sau khi xem", + "ask_me": "Hãy chat riêng để hỏi tôi", + "filled_in": "Đã nhập, bấm vào để xem", + "unlock_information": "Mở khóa tất cả dữ liệu", + "unlock_choose": "Sử dụng 1 mở khóa miễn phí", + "your_evaluation": "Nhận xét thực tế của bạn", + "her_evaluation": "Nhận xét thực tế của em ấy", + "his_evaluation": "Nhận xét thực tế của anh ấy", + "evaluate": "Nhận xét", + "friendly": "Thân thiện", + "interesting": "Thú vị", + "readily": "Thẳng thắn ", + "patient": "Kiên nhẫn", + "indifferent": "Thờ ơ", + "bad_temper": "Nóng nảy", + "courtesy": "Lịch sự", + "generous": "Hào phóng", + "lie": "Bốc đồng", + "unfriendly": "Unfriendly", + "anonymous_evaluation": "Đánh giá ẩn danh", + "cant_evaluate": "Bạn chưa hẹn hò với em ấy,không thể đánh giá", + "cant_evaluate2": "Anh ấy chưa hẹn hò với bạn không thể đánh giá", + "bad_evaluate": "Vui lòng cung cấp ảnh chụp màn hình liên quan để chúng tôi theo dõi và xác thực", + "submit": "Gửi", + "evaluation_success": "Đánh giá thành công", + "private_chat": "Trò chuyện", + "close_reminder": "Tắt chế độ tin nhắn nhắc nhở", + "closed_reminder": "Chế độ tin nhắn nhắc nhở đã tắt thành công", + "open_reminder": "Bật tin nhắn nhắc nhở", + "opened_reminder": "Chế độ tin nhắn nhắc nhở đã bật thành công", + "her_account": "Tài khoản mạng xà hội của em ấy", + "his_account": "Tài khoản mạng xà hội của anh ấy", + "copy": "Sao chép", + "send_account": "Gửi tài khoản mạng xã hội của tôi cho em ấy", + "enter_account": "Nhập số tài khoản mạng xã hội của bạn", + "for_example": "Tài khoản Wechat abc", + "sent_she": "Gửi cho em ấy", + "chat": "Nối mic", + "cantt_voice": "Đối phương đã tắt chức năng trò chuyện trực tuyến", + "authentication_voice": "Sau khi tính xác thực của bạn được chứng nhận, bạn mới có thể trò chuyện trực tuyến", + "requesting_voice": "Đang yêu cầu kết nối trò chuyện trực tuyến", + "waitting_answer": "Đang đợi đối phương kết nối", + "answer": "Kết nối", + "hang_up": "Ngắt kết nối", + "chatting": "Đang trò chuyện trực tuyên", + "handsfree": "Chế độ loa ngoài", + "giving_gift": "Thưởng", + "give_success": "Thưởng thành công", + "others_gift": "Đối phương đã tặng quà", + "given_gift": "Bạn đã thưởng cho đối phương một món quà trị giá /s1", + "earned_gift": "Bạn đã được tặng /s1H coin", + "available_balance": "Số dư khả dụng /s1", + "recharge": "Nạp tiền", + "give": "Quà tặng", + "balance_insufficien": "Xin lỗi số dư của bạn không đủ", + "first_recharge": "Vui lòng nạp tiền trước khi tặng quà", + "give_coin": "Thưởng /s1H coin cho lần trò chuyện trực tuyến này", + "get_coin": "Lần trò chuyện trực tuyến này, bạn được thưởng /s1H coin", + "give_get": "Lần trò chuyện trực tuyến này bạn thưởng đối phương /s1H coin và được thưởng /s2H coin", + "chat_over": "Thời lượng cuộc trò chuyện trực tuyến này là /s1", + "message_center": "Trung tâm tin nhắn", + "can_chat": "Bạn có thể mời đối phương trò chuyện riêng thông qua trang thông tin người dùng", + "text_chat": "Trò chuyện", + "system_information": "Tin nhắn hệ thông", + "system_notification": "Thông báo hệ thống", + "report_failure": "Báo cáo người dùng /s1 của bạn không xác thực. Vui lòng cung cấp bằng chứng xác thực hơn mới tiếp tục báo cáo, xin cảm ơn!", + "report_success": "Báo cáo người dùng /s1 của bạn là chính xác. Hệ thống đang tiến hành xử lý người dùng này!", + "successful_application": "Yêu cầu cấp mã mời của bạn đã được duyệt! Mã mời 【/s1】(click vào để sao chép)", + "successful_application2": "Yêu cầu cấp mã mời của bạn đã được duyệt! Cám ơn bạn đã giới thiệu bạn bè cho chúng tôi! Mã mời 【/s1】(click vào để sao chép)", + "application_failed": "Yêu cầu cấp mã mời thất bại! Rất tiếc, yêu cầu của bạn không được thông qua, xin cung cấp thông tin chính xác để mã mời được xét duyệt.", + "important_notice": "[Thông báo quan trọng]", + "authentication_failed": "Thông tin xác thực của bạn không phù hợp, yêu cầu chỉnh sửa và gửi lại cho chúng tôi!", + "request1": "1. Hãy quay video xác thực theo yêu cầu", + "request2": "2. Vui lòng tải ảnh có thể thấy rõ đặc điểm nhận dạng của bạn lên album", + "successful_authentication": "Xin chúc mừng! Yêu cầu xác thực của bạn đã được duyệt", + "re_upload": "Ảnh mới tải lên của bạn chưa được duyệt. Vui lòng tải lại theo yêu cầu", + "upload_success": "Xin chúc mừng, ảnh mới tải lên của bạn đã được duyệt", + "caveat": "Đăng ký hẹn hò của bạn đã bị xóa vì vi phạm. Nếu vi phạm nhiều lần hoặc trường hợp nghiêm trọng hệ thống sẽ tiến hành hạn chế thậm chí đóng tài khoản của bạn. Xin nhớ và tuân thủ! Cảm ơn bạn đã phối hợp!", + "caveat2": "Nhận xét của bạn đã bị xóa do vi phạm, Nếu vi phạm nhiều lần hoặc trường hợp nghiêm trọng hệ thống sẽ tiến hành hạn chế thậm chí đóng tài khoản của bạn. Xin nhớ và tuân thủ! Cảm ơn bạn đã phối hợp!", + "radio_message": "Tin nhắn radio", + "no_message": "Tạm thời không có tin nhắn như thế", + "dating_news": "/s1 đã gửi một tin nhắn hẹn hò trên /s2, nhấp vào đây để xem", + "go_see": "Vào xem", + "thumbs_up": "/s1 thích hoạt động của bạn", + "thumbs_up2": "/s1 thích chương trình hẹn hò của bạn", + "comment1": "/s1 đã nhận xét về hoạt động của bạn", + "comment2": "/s1 nhận xét về chương trình hẹn hò của bạn", + "replied_comment": "/s1 đã trả lời nhận xét của bạn", + "signed_up": "/s1 đã đăng ký tham gia chương trình của bạn", + "favorite_user": "Người dùng bạn yêu thích /s1 đã đăng một tin hẹn hò, nhấp vào đây để xem", + "favorite_user2": "Người dùng bạn yêu thích /s1 đã cập nhật hoạt động mới nhất, nhấp vào đây để xem", + "wallet_reminder": "Hãy chú ý ví của bạn", + "paid_you": "/s1 đã thanh toán (/s2H coin) để xem ảnh phong bì của bạn", + "paid_you2": "/s1 đã thanh toăn (/s2H coin) để xem album của bạn", + "paid_you3": "/s1 đã trả tiền để mở khóa tất cả thông tin của bạn", + "view_application": "Kiểm tra yêu cầu của bạn", + "view_application2": "/s1 muốn xem trang chủ của bạn", + "aging": "Cho phép (thời hạn 15 ngày)", + "refuse": "Từ chối", + "passed_request": "Yêu cầu đã được thông qua", + "l15_days": "Yêu cầu của /s1 đã được bạn cho phép, thời gian xem là 15 ngày", + "evaluation_notice": "Thông báo nhận xét", + "rate_her": "Bạn đã hẹn ò cùng /s1? Hãy nhanh chóng nhận xét em ấy nào!", + "received_evaluation": "Người đánh giá (ẩn danh) bạn là một phái nữ đã liên lạc với bạn: /s1", + "received_evaluation2": "Người đánh giá (ẩn danh) bạn là một đàn ông đã liên lạc với bạn: /s1", + "application_appeal": "Nếu đánh giá không đúng sự thật, bạn có thể báo cáo, chúng tôi sẽ tiến hành xác thực!", + "appeal": "Tôi muốn báo cáo", + "appealed": "Đã báo cáo", + "waiting_results": "Chúng tôi sẽ nhanh chóng xác tìm hiểu, kết quả sẽ được gửi đến hệ thông tin nhắn của bạn.", + "successful_appeal": "/s1 báo cáo thành công, đánh giá sẽ bị xóa đi", + "social_account": "Tài khoản mạng xà hội", + "get_account": "/s1 đã gửi cho bạn tài khoản mạng xã hội của anh ấy", + "edit_information": "Chỉnh sử thông tin", + "save": "Lưu lại", + "passed_verification1": "Bạn đã thông qua xác minh bảo mật danh tính", + "by_code": "Bạn tham gia thông qua mã mời của người dùng VIP /s1", + "by_paying": "Bạn đã thông qua bằng cách đóng phí gia nhập", + "passed_verification": "Tính xác thực của bạn đã được chứng nhận thông qua video", + "not_certified": "Danh tính của bạn vẫn chưa được xác thực", + "verificating": "Chúng tôi đang xác nhận tính xác thực của bạn", + "real_girl": "Phái nữ đã được xác thực sẽ được chào đón hơn", + "certificating": "Đang xác thực", + "re_upload2": "Vui lòng tải lại video", + "update_certification": "Cập nhật xác thực", + "enjoy_privileges": "Nâng cấp hội viên để có thêm đặc quyền", + "expires": "/s1 hết hạn", + "wallet": "Ví", + "setting": "Quyền riêng tư", + "my_dynamic": "Hoạt động của tôi", + "my_album": "Album của tôi", + "first_photo": "Tải hình ảnh đầu tiên của tôi", + "no_photo": "Có hình ảnh bạn có thể thu hút hơn đối với phái nam", + "upload_photos": "Tải ảnh", + "upload_video": "Tải video", + "upload": "Tải ảnh", + "set_photo": "Cài đặt ảnh phong bì", + "photo_order": "Nhấn giữ và kéo ảnh để thay đổi vị trí của chúng", + "my_evaluation": "Nhận xét của tôi", + "my_show": "Chương trình của tôi", + "i_like": "Sở thích của tôi", + "your_favorite": "Cô gái bạn yêu thích sẽ hiển thị ở đây", + "your_favorite2": "Chàng trai bạn yêu thích sẽ hiển thị ở đây", + "no_data": "Không có dữ liệu", + "historical_visitor": "Danh sách đã ghé thăm bạn", + "visit_you": "Có /s1 người đã ghé thăm bạn", + "visit_photo": "Có /s1 người đã hủy ảnh của bạn", + "recovery_photo": "Nhấp để phục hồi", + "setting2": "Cài đặt", + "apply_code": "Đăng ký mã mời cho bạn bè", + "issue_choose": "Mã mời sẽ được cấp miễn phí, chúng tôi sẽ cấp mã mời thông qua đánh giá lịch sử chi tiêu của bạn. Để duy trì bầu không khí trong công viên, vui lòng chỉ gửi mã mời cho người mà bạn tin cậy.", + "successfully_submit": "Yêu cầu của bạn đang được xử lý", + "share_app": "Chia sẻ ứng dụng với bạn bè", + "need_help": "Có vấn đề và cần giúp đỡ", + "need_help2": "Liên hệ nhân viên CSKH", + "need_help3": "Xin chào bạn, để nâng cao chất lượng phục vụ, nếu dưới đây có thắc mắc của bạn, vui lòng trả lời bằng cách nhập số thứ tự.", + "question1": "[1]Tại sao tài khoản bị đóng băng?", + "answer1": "\"xuất hiện một trong những tình trạng sau, tài khoản sẽ bị khóa: ① Lừa đảo② Môi giới③Quảng cáo quấy nhiễu④Bị nhiều người dùng báo cáo⑤Đã có tài khoản khác⑥Nhiều lần đăng tin radio sai phạm, xem thường cảnh cáo.⑦Người dùng tự yêu cầu xóa tài khoản.\"", + "question2": "[2]Khi nào mới có thể rút số dư trong ví?", + "answer2": "Tất cả số tiền nhận được sẽ được chuyển trực tiếp vào ví, rút tiền phải mất ba ngày (bắt đầu từ thời điểm nhận tiền). Số tiền nhận được sau ba ngày sẽ chuyển vào ví. Bạn được phép rút khi số dư > = 10 nhân dân tệ ", + "question3": "[3]Sao không hiển thị lì xì tôi đã gửi.", + "answer3": "Có thể do lỗi mạng. Hãy yên tâm, trường hợp này đối phương không thể nhận được phong bì của bạn. Phong bì sẽ tự động trả về trong vòng 24 giờ.", + "question4": "[4]Rút tiền về tài khoản ngân hàng/ ví tiền mặt phải mất mấy ngày?", + "answer4": "Trong vòng 2 ngày tiền sẽ vào tài khoản sau khi bạn yêu cầu rút tiền mặt. Vui lòng nhập đúng số tài khoản ngân hàng/ ví tiền mặt khi rút tiền mặt.", + "question5": "[5]Làm thế nào để báo cáo tài khoản khác / nội dung phát tán trên radio?", + "answer5": "Vào trang chi tiết cùa đối phương hoặc chọn nội dung tin tức mà bạn muốn báo cáo, nhấp vào góc phải phía trên, chọn \"báo cáo ẩn danh\", sau đó điền đầy đủ các thông tin liên quan.", + "question6": "[6]Làm sao để trở thành tài khoản được xác thực?", + "answer6": "\"Xác nhận tài khoản cần thỏa mãn các yêu cầu sau: ①Thông tin cá nhân có tài khoản mạng xã hội hợp lệ.②Có ít nhất một tấm ảnh rõ ràng trong album.③Kiểm tra mã xác thực trong trang xác thực, ghi mã xác thực + biệt danh của bạn lên một mảnh giấy.④Cầm mảnh giấy này trên tay, quay một đoạn video có thể nhìn thấy khuôn mặt chính diện của bạn và nội dung trên giấy. Tải video lên để xác thực.\"", + "question7": "[7]Video xác thực có thể không công khai không ?", + "answer7": "Bạn có thể cài đặt công khai hoặc không công khai:Trung tâm người dùng- Nhấp vào góc dưới bên trái video xác thực, chọn \"Video xác thực hiển thị trong trang chi tiết của tôi\"", + "question8": "[8]Làm thế nào để tránh bị hủy xác thực?", + "answer8": "Album ít nhất có một tấm ảnh của bản thân được gắn thẻ tag.", + "question9": "[9]Tại sao tin radio của bạn bị xóa?", + "answer9": "Radio không được phát tán tin tức, hình ảnh và các từ ngữ nhạy cảm, bao gồm cả nghĩa bóng lẫn nghĩa đen. Không được đăng thông tin cá nhân (bao gồm ảnh đại diện, biệt danh và phuơng pháp liên hệ). Vi phạm các quy định này kênh radio của bạn sẽ bị xóa.", + "question10": "[10] Làm thế nào để hủy tài khoản?", + "answer10": "Nếu hủy tài khoản bạn sẽ không thể đăng nhập vào ứng dụng. Sau này muốn tiếp tục sử dụng bạn phải đăng ký lại. Vui lòng xem xét cẩn thận, nếu bạn vẫn quyết định hủy tài khoản của mình vui lòng trả lời theo số thứ tự【12】 liên hệ hotline hỗ trợ người dùng.", + "question11": "[11]Quên mật khẩu, làm thế nào?", + "answer11": "Đối với người dùng đăng ký tài khoản bằng số điện thoại di động hoặc đã liên kết số điện thoại di động, có thể vào trang đăng nhập, chọn \"quên mật khẩu\" để cài đặt lại mật khẩu.,Đối với người dùng chưa liên kết số điện thoại di động, xin vui lòng liên kêt số điện thoại di động, sau đó cài đặt lại mật khẩu mới.", + "question12": "[12]Các vấn đề khác/ chuyển đến hotline nhân viên hỗ trợ khách hàng.", + "answer12": "Chào bạn, chúng tôi có thể giúp gì cho bạn? Xin nêu vấn đề của bạn (thời gian làm việc của bộ phận chăm sóc khách hàng 08:00 hôm nay- 02:00AM hôm sau, do số người cần tư vấn khá đông, bạn vui lòng đợi trong giây lát.)", + "certification_center": "Trung tâm xác thực", + "for_example2": "Mẫu video xác thực", + "certification_conditions": "Điều kiện xác thực", + "conditions1": "1. Hình tượng cá nhân tốt.", + "conditions2": "2. Có ít nhất một tấm ảnh cá nhân trong album.", + "verification_method": "Phương thức xác thực", + "method3": "1. Lấy một tờ giấy để viết tên hiệu của bạn và mã xác minh sau:", + "method4": "2. Giữ mảnh giấy này trong tay và quay một đoạn video thấy rõ chính diện khuôn mặt bạn (3 - 15 giây)", + "upload_video2": "Tải video xác thực", + "after_authentication": "Sau khi xác thực thành công ảnh đại diện của bạn sẽ hiển thị logo Real.", + "show_video": "Video xác thực hiển thị trong trang chi tiết của tôi.", + "uploaded_video": "Video xác thực đã được tải lên.", + "under_review": "Đang xét duyệt (trong vòng 24 giờ)", + "certification_status": "Trạng thái xác thực", + "certified": "Bạn đã thông qua xác thực", + "wait_resubmitted": "Đang chờ để xác thực lại", + "reason_failure": "Video chứng nhận của bạn không đáp ứng các yêu cầu do:", + "claim": "Vui lòng quay video xác thực theo yêu cầu.", + "claim2": "Vui lòng tải một tấm ảnh có thể nhìn thấy rõ khuôn mặt của bạn lên album.", + "re_upload_video": "Tải lại video xác thực.", + "update_video": "Cập nhật video xác thực.", + "mask_coin": "H coin", + "get_way": "Bạn có thể nạp h-coin trực tuyển hoặc chat online.", + "coin_use": "H-coin dùng trong chat online hoặc tặng cho người khác.", + "coin_total": "Tổng số H-coin", + "can_redeemed": "Số coin có thể rút ", + "who_account": "Tài khoản /s1", + "bind_account": "Liên kết tài khoản /s1", + "your_account": "Tài khoản /s1 của bạn", + "get_coin2": "Bạn đã nhận được /s1H coin bằn cách nạp tiền vào tài khoản.", + "viewed_your": "/s1 đã xem tài khoản mạng xã hội của bạn", + "give_gift": "1 coin/s2", + "add_coin": "+/s1H coin", + "give_one": "Bạn đã tặng 1 cái /s1 cho /s2", + "less_coin": "-/s1H coin ", + "exchange_cash": "Rút tiền mặt", + "withdrawal_application": "Yêu cầu rút tiền mặt", + "redeem_choose": "Bạn có /s1H coin có thể đổi thành /s2, sau khi đổi bạn còn /s3H coin, bạn có muốn đổi không?", + "application_submitted": "Yêu cầu rút tiền của bạn đã được gửi đi.", + "working_days": "Chúng tôi sẽ xử lý trong vòn 02 ngày làm việc, có bất kỳ thắc mắc gì bạn có thể liên hệ hotline hỗ trợ người dùng.", + "cash": "Tiền mặt", + "handling_fee": "Khi bạn nhận được phong bi trong trang trò chuyện, số dư sẽ được chuyển vào đây. Trong vòng 3 ngày không ai báo cáo về số dư này, bạn có thể quy đổi thành tiền mặt, phí thủ tục là 5%.", + "total_account": "Tổng số dư", + "cannot_redeemed": "Số dư không đủ không thể quy đổi", + "successful_redemption": "Quy đổi thành công", + "redeem_choose2": "Tổng số dư của bạn là /s1, lần này bạn có thể đổi /s2, bạn muốn đổi chứ?", + "personal_details": "Thông tin cá nhân", + "public": "Công khai (được khuyến nghị)", + "paid_album": "Trả phí để xem album", + "must_pay": "Người dùng khác phải trả phí để xem album của bạn. Chi phí xem album do bạn đặt ra, tuy nhiên có thể làm thế có thể khiến cho số lượng người xem của bạn bị giảm đi.", + "set_amount1": "Cài đặt kiểm tra số dư", + "first_upload": "Vui lòng tải ảnh lên trước khi thiết lập album trả phí", + "need_permission": "Phải được tôi cho phép mới được xem", + "permission_choose": "Người khác phải gửi ảnh cho tôi xác nhận danh tính mới được phép xem trang chủ của bạn, bạn muốn như thế?", + "hide_me": "Giấu tôi khỏi danh sách những người gần đó", + "hide_distance": "Ẩn khoảng cách giữa tôi với người khác", + "hide_account": "Ẩn tài khoản của tôi với người khác", + "chat_setting": "Hạn chế trò chuyện trực tuyến", + "chat_me": "Cho phép người dùng \"được phép trò chuyện\" trò chuyện trực tuyến với tôi", + "successfully_saved": "Đã lưu thành công", + "on_dynamic": "Bạn chưa đăng bất kỳ cập nhật nào", + "release_dynamics": "Đăng hoạt động gần đây", + "dynamic_details": "Chi tiết hoạt động", + "release": "Đăng", + "i_posted": "Hoạt động của tôi", + "delete_dynamic": "Xóa hoạt động", + "delete_choose": "Bạn có chắc chắn muốn xóa hoạt động này?", + "posted_on": "Đăng trên /s1", + "thumbs_up3": "Like", + "already_praised": "Đã like", + "comment": "Nhận xét", + "send": "Gửi", + "comment_closed": "Bình luận đã đóng", + "your_comment": "Chỉ người đăng có thể nhìn thấy nhận xét của bạn", + "everyone_comment": "Mọi người đều có thể thấy nhận xét của bạn", + "prohibit_comments": "Cấm nhận xét", + "comments_disabled": "bật chế độ cấm nhận xét", + "open_comments": "Hủy chế độ cấm nhận xét", + "already_open": "Đã hủy chế độ cấm nhận xét", + "reply": "Trả lời", + "report": "Báo cáo", + "report_choose": "Bạn có chắc chắn muốn báo cáo nhận xét này?", + "successful_report": "Báo cáo thành công, chúng tôi sẽ giải quyết nó trong thời gian sớm nhất!", + "successfully_deleted": "Đã xóa thành công", + "please_civilization": "Những người ăn nói văn hóa thường được chào đón hơn. Xin đừng phát ngôn thô tục, đăng tải nội dung khiêu dâm hoặc tiết lộ sự riêng tư của người khác!", + "same_sex": "Không cho người cùng giới tính thấy tôi", + "member_free": "Thành viên miễn phí, không phải thành viên cần /s1H coin", + "certified_free": "Phái nữ đã xác thực được miễn phí 3 lần, sau đó cần phải trả /s1H coin", + "enter_something": "Vui lòng nhập văn bản hoặc chọn hình ảnh", + "raid_release": "Đăng tải thu phí (/s1H coin)", + "become_member2": "Miễn phí cho các thành viên", + "now_certification": "Lập tức xác thực và miễn phí đăng bài", + "successfully_released": "Đăng bài thành công", + "no_program": "Bạn vẫn chưa đăng chương trình nào", + "program_details": "Chi tiết chương trình", + "program_theme": "Chủ đề chương trình", + "click_select": "Nhấn vào đây để chọn", + "city": "Thành phố", + "select_city": "Chọn thành phố", + "time": "Thời gian", + "select_date": "Chọn ngày", + "select_time": "Chọn thời gian", + "unlimited_time": "Không giới hạn thời gian", + "supplementary_explanation": "Ghi chú", + "image": "Kèm hình", + "delete_program": "Xóa chương trình", + "delete_choose2": "Bạn có chắc chắn muốn xóa chương trình này?", + "please_choose": "Vui lòng chọn chủ đề cho chương trình", + "please_choose2": "Vui lòng chọn đối tượng mong muốn", + "please_choose3": "Vui lòng chọn một thành phố", + "please_choose4": "Vui lòng chọn một ngày", + "please_choose5": "Vui lòng chọn thời gian", + "release_program": "Đăng chương trình", + "sign_up": "Đăng ký", + "end_registration": "Kết thúc đăng ký", + "end_choose": "Bạn có chắc là muốn kết thúc hẹn hò?", + "contact_her": "Liên lạc với em ấy", + "talk_him": "Chat riêng với anh ấy", + "report_choose2": "Có chắc là bạn muốn báo cáo thông tin đăng ký này?", + "release_time": "Thời gian phát hành", + "activity_time": "Thời gian hoạt động", + "any_sex": "Không giới hạn giới tính", + "look_women": "Chỉ nhìn phái nữ", + "look_men": "Chỉ nhìn phái nam", + "unlimited_area": "Không giới hạn KV", + "program_deleted": "Chương trình đã bị xóa", + "cant_comment": "Không phải thành viên không thể nhận xét", + "sign_up2": "Đăng ký", + "need_photo2": "Đăng ký cần phải gửi ảnh chính diện khuôn mặt của bạn (chỉ đối phương có thể nhìn thấy)", + "registration_success": "Đăng ký thành công, nếu đối phương cảm thấy thích hợp sẽ liên hệ bạn", + "has_ended": "Đã kết thúc", + "men_cant": "Phái nam không thể đăng ký chương trình của phái nam", + "ms_cant": "Phái nữ không thể đăng ký chương trình của phái nữ", + "men_cant2": "Phái nam không thể nhận xét chương trình của phái nam", + "ms_cant2": "Phái nữ không thể nhận xét chương trình của phái nữ", + "message_push": "Đẩy tin nhắn, thay đổi mật khẩu", + "phone_number": "Số điện thoại di động", + "bind_phone1": "Số điện thoại liên kết", + "more_safer": "Liên kết số điện thoại sẽ giúp cho tài khoản của bạn an toàn hơn", + "modify_choose": "Bạn muốn thay đổi số điện thoại liên kết?", + "change_password": "Thay đổi mật khẩu", + "first_bind": "Người dùng cần liên kết số điện thoại di động trước khi cài đặt mật khẩu đăng nhập", + "old_password": "Nhập mật khẩu gốc", + "current_password": "Nhập mật khẩu đăng nhập hiện tại", + "new_password": "Nhập mật khẩu mới", + "set_new": "Mật khẩu mới không dưới 06 ký tự", + "clear_cache": "Xóa bộ nhớ cache hình ảnh", + "cleared_successfully": "Đã xóa thành công", + "user_agreement1": "Thỏa thuận người dùng", + "sign_out": "Thoát ra", + "out_choose": "Bạn có chắc chắn muốn đăng xuất?", + "push_settings": "Cài đặt lượt đẩy", + "permission_denied": "Quyền hạn đã bị từ chối", + "push_setting2": "Cài đặt đẩy tin nhắn", + "private_chat2": "Tin nhắn trờ chuyện riêng", + "new_date": "Có hẹn hò mới", + "passed_request2": "Có phái nữ yêu cầu xem dữ liệu", + "men_view": "Có phái nam yêu cầu xem dữ liệu", + "men_view2": "Có anh chàng nào đấy xem tài khoản mạng xã hội của tôi", + "men_view3": "Có phái nam yêu cầu xem avata", + "men_view4": "Có anh chàng đã xem dữ liệu và gửi cho tôi tài khoản xã hội", + "applied_successfully": "Yêu cầu cấp mã mời đã thành công", + "after_open": "Giới thiệu tin tức liên quan sau khi bật", + "if_something": "Nếu bạn đã thanh toán cho em ấy/ anh ấy trong 3 ngày gần đây, sau khi chúng tôi xác thực báo cáo, hệ thống sẽ tự động hoàn trả chi phí cho bạn.", + "advertise": "Đăng quảng cáo", + "false_photo": "Ảnh không đúng thực tế", + "erotic_vulgarity": "Khiêu dâm thô tục", + "harassment": "Quấy rối", + "she_liar": "Em ấy là một kẻ lừa đảo", + "he_liar": "Anh ấy là một kẻ lừa đảo", + "provide_screenshots": "Xin cung cấp ảnh chụp màn hình liên quan để chúng tôi theo dõi xác thực", + "describe_details": "Vui lòng mô tả chi tiết (trong vòng 100 từ)", + "report_reason": "Vui lòng chọn lý do báo cáo", + "report_success2": "Báo cáo thành công", + "successfully_modified": "Đã sửa đổi thành công", + "boy": "Nam", + "girl": "Nữ", + "already_applied": "Đã gửi yêu cầu", + "view_registration": "Xem đăng ký", + "expand": "Mở rộng", + "collapse": "Thu gọn", + "application_notice": "Yêu cầu thông báo", + "agrees_application": "Có tài khoản khác đồng ý với yêu cầu của bạn", + "red_photo": "Ảnh phong bì", + "dont": "Vui lòng không đăng tải hình ảnh/ video khỏa thân thô tục. Nếu vi phạm chúng tôi sẽ đóng tài khoản", + "current_version": "Phiên bản hiện tại", + "bank_card": "Liên kết thẻ ngân hàng", + "choose_bank": "Vui lòng chọn một ngân hàng", + "bank_number": "Vui lòng nhập số thẻ ngân hàng", + "id_number": "Vui lòng nhập số căn cước/ CMND", + "name": "Tên họ", + "bank_number2": "Số thẻ NH", + "license_number": "Số thẻ CMND", + "bind_phone": "Số ĐT liên kết", + "his_homepage": "Trang chủ của anh ấy", + "her_homepage": "Trang chủ của em ấy", + "wechat_pay": "Thanh toán WeChat", + "facebook_pay": "Thanh toán Facebook", + "google_pay": "Thanh toán bằng google", + "payment_successful": "Thanh toán thành công", + "set_amount": "Cài đặt sô tiền rút", + "enter_amount": "Vui lòng nhập số lượng xu H", + "can_withdraw": "Có thể rút tiền", + "language_set": "Cài đặt ngôn ngữ", + "user_agreement": "Thỏa thuận người dùng", + "renewal_fee": "Tiếp tục trả phí", + "open_immediately": "Mở ngay lập tức", + "total": "Tổng cộng", + "half_month": "Nửa tháng", + "month2": "/s1 tháng", + "cancel_shield": "Bỏ chặn", + "blacklist2": "Danh sách đen", + "longTime": "(Thành viên có thể kéo dài thời gian đến 06 giây)", + "longClick": "Nhấn và giữ màn hình để xem", + "stop_program": "Vui lòng kết thúc chương trình vẫn còn hiệu lực.", + "not_love": "Đàn ông không thể sưu tập đàn ông", + "not_love2": "Phái nữ không thể sưu tập phái nữ!", + "women_free": "Hotgirl có thể miễn phí đăng tin", + "not_up_man": "Anh ấy vẫn chưa tải hình ảnh", + "not_up_women": "Chị ấy vẫn chưa tải hình ảnh", + "not_illage": "Cảm ơn bạn không thực hiện những hành vi phạm pháp trên APP, nếu bị báo và phát hiện sẽ bị xử lý bằng cách khóa tài khoản", + "alreay_join": "Tôi đã ghi danh", + "sure_delete": "Bạn có chắc là muốn xóa tấm ảnh này", + "white_now": "Lập tức điền vào", + "personal": "Bạn vẫn chưa nhập vào mục \"giới thiệu bản thân\", lời giới thiệu thu hút người khác có sức ảnh hưởng rất lớn", + "success": "Thành công", + "fail": "Thất bại", + "moneyPageTip": "Chỉ người dùng đã xác thực mới có thể cài đặc ảnh phong bì", + "alreadyJoin": "Bạn đã đăng ký, đối phương sẽ liên lạc với bạn nếu họ cảm thấy phù hợp", + "waring": "Cảnh báo vi phạm", + "userPravicy": "Tôn trọng quyền riêng tư của người dùng, cấm chụp ảnh màn hình người khác. Nếu có vi phạm lần sau, bạn sẽ bị cấm xem ảnh người dùng khác.", + "outTime": "Thời gian hẹn hò đã hết hạn, vui lòng chỉnh sửa", + "reviewing": "Xác thực", + "reviewed": "Xét duyệt thành công", + "reviewedFail": "Xét duyệt thất bại", + "needCard": "Người dùng phải liên kết thể ngân hàng trước khi rút tiền mặt", + "women_not_d": "Phái nữ không thể nhận xét về hoạt động của phái nữ", + "man_not_d": "Phái nam không thể nhận xét về hoạt động của phái nam", + "have_picture": "Có hình ảnh bạn có thể thu hút hơn đối với phái nữ", + "up_cancle": "Trượt lên để hủy gửi", + "msg_not": "Tin nhắn không thể bỏ trống", + "need_record": "Chức năng này phải cho phép ghi âm", + "downloading_video": "Đang tải file video", + "reinput": "Xin nhập lại thứ tự câu hỏi", + "dy_delete": "Hoạt động của bạn bị báo cáo ẩn danh. Sau khi xác nhận, hệ thống đã xóa hoạt động này. Xin đừng tiến hàng thao tác sai trái!", + "pro_delete": "Chương trình của bạn bị báo cáo ẩn danh. Sau khi xác nhận, hệ thống đã xóa chương trình này. Xin đừng tiến hàng thao tác sai trái!", + "con_delete": "Nhận xét của bạn bị báo cáo ẩn danh. Sau khi xác nhận, hệ thống đã xóa nhận xét này. Xin đừng tiến hàng thao tác sai trái!", + "coin_returen": "Sau khi nhận được báo cáo từ người dùng ẩn danh, hệ thống xác nhận gần đây bạn đã có hành động sai trái, nên đã tiến hành hoàn trả những H-coin gần đây của bạn. Nếu tái phạm, chưng tôi sẽ khóa tài khoản.", + "voicing": "Cấm tất cả hành vi dâm ô trái pháp luật trong khi thực hiện cuộc gọi, một khi phát hiện chúng tôi sẽ tiến hành khóa tài khoản.", + "help": "Nhân viên CSKH", + "translate_on": "Mở chức năng người dịch", + "translate_off": "Tắt chức năng người dịch", + "becomeSvip": "Đã dùng /s1H coin để tái tục SIVP", + "need_svip": "Bật quyền hạn SIVP", + "cannot_vip": "Không thể tái tục SVIP, trở thành VIP", + "offline": "Bạn đã thoát, không thể gửi và nhận tin nhắn", + "otherLogin": "Tài khoản đăng nhặp trên thiết bị khác, bạn đã thoát", + "no_new": "Tạm thời chưa có tin nhắn mới", + "over": "Đã dịch xong", + "bad_ev": "Bạn có chắc là dislike ?", + "right5": "Right 5", + "right6": "Right 6", + "man_vi": "Anh ơi", + "women_vi": "Em ơi", + "kf_tips": "để nâng cao chất lượng phục vụ, nếu dưới đây có thắc mắc của bạn, vui lòng trả lời bằng cách nhập số thứ tự", + "rejected": "Đã từ chối", + "buy_vip": "Bạn đã tiêu thụ /s1 H tệ để mua thành viên.", + "buy_program": "Bạn đã tiêu thụ /s1 H tệ để đăng hoạt động.", + "del_add_money": "Yêu cầu rút tiền H của bạn đã được xử lý và chuyển /s1 vào tài khoản của bạn, vui lòng kiểm tra!", + "adding_money": "Yêu cầu rút tiền /s1 H của bạn đang được xét duyệt.", + "free_translate": "miễn phí hưởng nhân viên dịch thuật kịp thời", + "personalTraff": "Nhân viên CSKH vì bạn phục vụ", + "ManTranslate": "Người dịch đang dịch...", + "robotTranslate": "Máy đang dịch...", + "translated": "Người dịch đã hoàn thành", + "delete_progarm": "Giao tiếp lành mạnh, xin đừng phát nội dung thô tục, một khi phát hiện sẽ bị xóa.", + "open_location": "Quyền định vị chưa được bật", + "get_location": "Vui lòng bật quyền định vị trong cài đặt điện thoại của bạn để biết khoảng cách người khác.", + "confirm_exit": "Nhấn lần nữa để thoát", + "free_program": "Cơ hội miễn phí phát sóng /s1 /ngày ", + "picture": "Hình ảnh", + "camera": "Máy ảnh", + "video": "Video", + "red_money": "Tiền lì xì", + "stick": "Dán", + "press_say": "Giữ để nói ", + "get_money": "/s1 đã nhận được tiền lì xì của bạn", + "you_get_money": "Bạn đã nhận được tiền lì xì của /s1", + "ones_money": "Tiền lì xì của /s1 ", + "money_over": "Tiền lì xì đã hết hạn", + "downloading_fail": "Tải tập tin thất bại", + "downloading": "Đang tải tập tin video", + "back_money": "Tiền lì xì chưa nhận, sẽ được yêu cầu hoàn trả sau 24 giờ! ", + "no_money": "Tiền lì xì không tồn tại", + "already_money": "Tiền lì xì đã nhận", + "back_user": "Đã hết hạn, đã được hoàn trả vào tài khoản", + "waiting_user": "Đang chờ bên kia nhận", + "other_get": "Bên kia đã nhận", + "little": "Của ít lòng nhiều, cứ lấy mà tiêu", + "put_money": "Tăng thêm tiền mặt vào phong bì", + "mount": "Số tiền", + "over_time": "Đã hết hạn", + "has_get": "Đã nhận", + "no_gift": "Hiện tại không có phần quà nào", + "sent_gift": "Quà tặng", + "fill_tips": "Khi bạn điền thông tin thành công sẽ nhận được /s1H tề, không thể sửa đổi sau khi liên kết.", + "bind_code": "Liên kết mã mời", + "invide_code": "Mã mời", + "confirm_delete": "Xác nhận xóa", + "has_eva": "Bạn đã nhận xét rồi", + "open": "Mở", + "voice": "Giọng nói", + "release_send": "Buông ra để gửi", + "time_little": "Thời gian ghi âm quá ngắn", + "not_online": "Đối phương không trực tuyến, không thể kết nối mic", + "give_red_money": "Bạn đã gửi một lì xì /s2 H đến /s1", + "get_red_money": "Bạn đã nhận được một lì xì /s2 H của /s1", + "give_other_money": "Bạn đã thưởng /s1 /s2H", + "get_other_money": "Bạn đã nhận được lì xì /s2H của /s1", + "svip": "Siêu hội viên", + "recommend": "Đề xuất", + "paid_you4": "Bạn đã trả (/s2H xu) để xem ảnh phong bì màu đỏ của /s1", + "paid_you5": "Bạn đã trả (/s2H xu) để xem album của /s1", + "paid_you6": "Bạn đã trả tiền để mở khóa tất cả thông tin của /s1", + "UG_LINE0": "Hibok giấy phép và thỏa thuận dịch vụ", + "UG_LINE1": "[Đầu tiên và giới thiệu]", + "UG_LINE2": "Qianhai Youlong Technology Co., Ltd. (sau đây gọi tắt là Cy Qianhai Youlong Technology Co., Ltd.) sau đây nhắc nhở người dùng đọc kỹ và hiểu đầy đủ Thỏa thuận dịch vụ này (sau đây gọi là Thỏa thuận ràng buộc). Người dùng nên đọc kỹ và hiểu đầy đủ Thỏa thuận này. Các điều khoản, bao gồm miễn trừ hoặc giới hạn trách nhiệm pháp lý của Qianhai Youlong Technology Co., Ltd. và các hạn chế về quyền của người dùng. Vui lòng đọc kỹ và chọn chấp nhận hoặc không chấp nhận Thỏa thuận này (trẻ vị thành niên phải có người giám hộ hợp pháp kèm theo). Bạn không được phép đăng ký, đăng nhập hoặc sử dụng các dịch vụ trong Thỏa thuận này trừ khi bạn chấp nhận tất cả các điều khoản của Thỏa thuận này. Việc đăng ký, đăng nhập, sử dụng, v.v. của bạn sẽ được coi là chấp nhận Thỏa thuận này và bạn đồng ý bị ràng buộc bởi các điều khoản của Thỏa thuận này.", + "UG_LINE3": "Thỏa thuận này là một thỏa thuận giữa bạn (sau đây gọi là \"Người dùng\" và Qianhai Youlong Technology Co., Ltd. về việc đăng ký, đăng ký và sử dụng \"dịch vụ Hibok\". Thỏa thuận này mô tả mối quan hệ giữa Qianhai Youlong Technology Co., Ltd. và Người dùng về \"dịch vụ Hibok\". Quyền và nghĩa vụ. Người dùng có nghĩa là cá nhân hoặc tổ chức đăng ký, đăng nhập, sử dụng và duyệt Dịch vụ. Việc bạn chấp nhận Thỏa thuận này tuân theo tất cả các điều khoản và điều kiện, bao gồm mọi sửa đổi do Qianhai Youlong Technology Co., Ltd. thực hiện đối với mọi Điều khoản dịch vụ bất kỳ lúc nào. Thỏa thuận có thể được Qianhai Youlong Technology Co., Ltd. cập nhật bất cứ lúc nào. Các điều khoản cập nhật của thỏa thuận sẽ được thay thế bằng các điều khoản ban đầu của thỏa thuận mà không cần thông báo trước. Người dùng có thể kiểm tra các điều khoản của thỏa thuận mới nhất trong ứng dụng này. Sau khi Qianhai Youlong Technology Co., Ltd. sửa đổi các điều khoản của thỏa thuận, Nếu người dùng không chấp nhận các điều khoản sửa đổi, xin vui lòng ngừng sử dụng nó ngay lập tức dịch vụ Cyhd TNHH cung cấp, người dùng tiếp tục sử dụng dịch vụ Cyhd TNHH lời đề nghị sẽ được coi là đã chấp nhận thỏa thuận sửa đổi.", + "UG_LINE4": "Đầu tiên, việc sử dụng các quy tắc", + "UG_LINE5": "1、 Người dùng hoàn toàn hiểu và đồng ý rằng chỉ cung cấp nền tảng chia sẻ, truyền tải và thu thập thông tin cho người dùng. Người dùng phải chịu trách nhiệm cho tất cả các hành động trong tài khoản đã đăng ký, bao gồm nhưng không giới hạn bất kỳ nội dung nào bạn truyền và bất kỳ kết quả nào. .", + "UG_LINE6": "2、 Qianhai Youlong Technology Co., Ltd. không chịu trách nhiệm cho bất kỳ nội dung nào được truyền tải bởi hoặc thông qua các Dịch vụ không phản ánh quan điểm hoặc chính sách của Qianhai Youlong Technology Co., Ltd..", + "UG_LINE7": "3、 Người dùng hoàn toàn hiểu và đồng ý rằng đó là sản phẩm duyệt thông tin xã hội dựa trên mạng quan hệ người dùng. Người dùng phải chịu trách nhiệm hoàn toàn về tính xác thực, tính hợp pháp và tính hợp lệ của thông tin đã đăng ký và người dùng không được mạo danh người khác; Mọi thông tin sẽ được truyền đi dưới tên, không sử dụng độc hại tài khoản đã đăng ký có thể gây nhầm lẫn cho người dùng khác, nếu không, Qianhai Youlong Technology Co., Ltd. có quyền ngừng cung cấp dịch vụ ngay lập tức, phục hồi số tài khoản và chịu mọi trách nhiệm pháp lý phát sinh từ đó.", + "UG_LINE8": "4、Người dùng phải tự chịu trách nhiệm về tính xác thực, tính hợp pháp, vô hại và tính hợp lệ của thông tin được truyền trên trang web. Mọi trách nhiệm pháp lý liên quan đến thông tin do người dùng truyền tải sẽ do người dùng chịu và không liên quan đến Qianhai Youlong Technology Co., Ltd..", + "UG_LINE9": "5、Qianhai Youlong Technology Co., Ltd. có quyền thay đổi, đình chỉ, giới hạn, chấm dứt hoặc thu hồi dịch vụ của bất kỳ hoặc tất cả các dịch vụ của Dịch vụ bất cứ lúc nào mà không cần thông báo do nhu cầu phát triển kinh doanh và người dùng phải chịu rủi ro này.", + "UG_LINE10": "6、Các dịch vụ được cung cấp có thể bao gồm quảng cáo và người dùng đồng ý hiển thị quảng cáo được cung cấp bởi các nhà cung cấp và đối tác bên thứ ba trong quá trình sử dụng.", + "UG_LINE11": "7、 Người dùng không được sử dụng hoặc dịch vụ để thực hiện, tải lên, sao chép hoặc gửi nội dung sau:", + "UG_LINE12": "(1) chống lại các nguyên tắc cơ bản được thiết lập bởi Hiến pháp;", + "UG_LINE13": "(2) gây nguy hiểm cho an ninh quốc gia, tiết lộ bí mật nhà nước, lật đổ quyền lực nhà nước và phá hoại đoàn kết dân tộc;", + "UG_LINE14": "(3) làm tổn hại danh dự và lợi ích quốc gia;", + "UG_LINE15": "(4) Kích động hận thù dân tộc, phân biệt sắc tộc và phá hoại đoàn kết dân tộc;", + "UG_LINE16": "(5) Phá hủy các chính sách tôn giáo của nhà nước và thúc đẩy các giáo phái và mê tín phong kiến;", + "UG_LINE17": "(6) Truyền bá tin đồn, phá vỡ trật tự xã hội và phá hoại sự ổn định xã hội;", + "UG_LINE18": "(7) truyền bá những điều tục tĩu, khiêu dâm, đánh bạc, bạo lực, giết người, khủng bố hoặc xóa bỏ;", + "UG_LINE19": "(8) xúc phạm hoặc vu khống người khác và xâm phạm quyền và lợi ích hợp pháp của người khác;", + "UG_LINE20": "(9) Thông tin chứa nội dung khác bị cấm theo luật pháp và các quy định hành chính.", + "UG_LINE21": "8、Cyhd TNHH thể, trong phán quyết hợp lý của nó, vi phạm pháp luật liên quan và các quy định hoặc thoả thuận này; hoặc vi phạm, kiến, mối đe dọa của bất kỳ quyền hoặc sự an toàn, hoặc mạo danh, Cyhd TNHH ngay để ngăn chặn bất kỳ luật giao thông nói trên Và có quyền, theo toàn quyền quyết định của mình, có hành động pháp lý phù hợp với bất kỳ người nào vi phạm các Điều khoản này, bao gồm nhưng không giới hạn trong việc loại bỏ bất hợp pháp, vi phạm, không đúng cách, v.v. khỏi Dịch vụ, chấm dứt tư cách thành viên của những người vi phạm và ngăn chặn họ khỏi Sử dụng tất cả hoặc một phần của dịch vụ, và giữ thông tin liên quan và báo cáo cho các bộ phận liên quan theo luật pháp và quy định.", + "UG_LINE22": "9、Quyền và nghĩa vụ của người dùng: ", + "UG_LINE23": "(1) Tài khoản Cyhd TNHH thuộc sở hữu của tất cả Qianhai Youlong Technology Co., Ltd., sau khi người dùng hoàn thành việc áp dụng cho các thủ tục đăng ký, để có được quyền sử dụng các tài khoản, được cấp giấy phép cho người nộp đơn ban đầu cho đăng ký bị cấm món quà, cho mượn, cho thuê, chuyển nhượng hoặc bán. Cyhd Giới hạn do nhu cầu hoạt động, chúng tôi có quyền thu hồi tài khoản người dùng và truy cập vào ảnh của người dùng, video, âm thanh và các hoạt động quảng bá sản phẩm khác.", + "UG_LINE24": "(2) người dùng có quyền thay đổi, xóa trên Qianhai Youlong Technology Co., Ltd.. Dữ liệu cá nhân, thông tin đăng ký và nội dung chuyển nhượng, nhưng lưu ý rằng xóa thông tin cũng sẽ loại bỏ bất kỳ của bạn được lưu trữ trong hệ thống các văn bản và hình ảnh. Người dùng chịu trách nhiệm cho rủi ro này.", + "UG_LINE25": "(3) Người dùng chịu trách nhiệm bảo mật thông tin tài khoản đã đăng ký và mật khẩu tài khoản. Người dùng chịu trách nhiệm về tài khoản đã đăng ký và hành vi theo mật khẩu. Người dùng đồng ý không sử dụng số tài khoản hoặc mật khẩu của thành viên khác trong mọi trường hợp. Bạn đồng ý thông báo cho Qianhai Youlong Technology Co., Ltd. ngay lập tức nếu bạn nghi ngờ rằng ai đó đang sử dụng tài khoản hoặc mật khẩu của bạn.", + "UG_LINE26": "(4) Người dùng phải tuân thủ các điều khoản của Thỏa thuận này và sử dụng Dịch vụ một cách chính xác và phù hợp. Nếu Người dùng vi phạm bất kỳ điều khoản nào của Thỏa thuận này, Qianhai Youlong Technology Co., Ltd. có quyền chấm dứt dịch vụ của tài khoản Qianhai Youlong Technology Co., Ltd. của người dùng mặc định theo Thỏa thuận. Đồng thời, Qianhai Youlong Technology Co., Ltd. có quyền rút số tài khoản và tên người dùng Qianhai Youlong Technology Co., Ltd. bất cứ lúc nào.", + "UG_LINE27": "(5) Nếu người dùng có tài khoản tiếng Anh thông thường của mình, người dùng có quyền đăng ký tài khoản tiếng Anh trước tiên, nhưng nếu người dùng không đăng ký tài khoản sau khi dịch vụ trực tuyến hoặc người dùng đã đăng ký tài khoản WeChat, nhưng Nếu tài khoản tiếng Anh không được sử dụng làm tài khoản WeChat, người dùng được coi là đã từ bỏ quyền đăng ký tài khoản tiếng Anh dưới dạng tài khoản WeChat. Qianhai Youlong Technology Co., Ltd. có quyền tái chế và phân phối tài khoản tiếng Anh cho người dùng khác, để tránh lãng phí tài nguyên. Vấn đề là trách nhiệm của người dùng.", + "UG_LINE28": "(6) Nếu người dùng không đăng nhập vào tài khoản sau khi đăng ký tài khoản trong một thời gian dài, Qianhai Youlong Technology Co., Ltd. có quyền tái chế tài khoản, để tránh lãng phí tài nguyên và các sự cố do người dùng gây ra.", + "UG_LINE29": "(7) người dùng có thể sử dụng tính năng suy giảm tranh chấp duy trì sự quan tâm sử dụng trong nền tảng này, nếu các báo cáo sử dụng thông tin phản hồi nhận được, chủ động thông báo cho người sử dụng có nghĩa vụ báo cáo hoặc xác minh tình hình với các nhân viên dịch vụ khách hàng để báo cáo để xác minh các nội dung là đúng sự thật, mặt nạ đậu quyền những lời cảnh báo người sử dụng, hạn chế chức năng tài khoản và vi phạm hạn chế chế độ người dùng khác, người phạm tội nghiêm trọng Hibok hưởng trực tiếp đóng băng tài khoản, và số dư trong tài khoản sẽ không được trả lại. Nếu tài khoản bị đóng băng và cần được kháng cáo, người dùng có thể liên hệ với dịch vụ khách hàng.", + "UG_LINE30": "Thứ hai, bảo vệ quyền riêng tư", + "UG_LINE31": "Người dùng đồng ý rằng thông tin bảo mật cá nhân đề cập đến những thông tin có thể nhận dạng cá nhân người dùng hoặc liên quan đến giao tiếp cá nhân, bao gồm các thông tin sau: tên thật, số điện thoại di động, tài khoản WeChat, tài khoản facebook và địa chỉ IP. Thông tin riêng tư phi cá nhân đề cập đến thông tin chung mà người dùng phản ánh rõ ràng và khách quan thông tin hồ sơ cơ bản của máy chủ Qianhai Youlong Technology Co., Ltd. và tất cả thông tin bảo mật cá nhân khác và thông tin cá nhân nêu trên mà người dùng đồng ý tiết lộ. . Tôn trọng quyền riêng tư của thông tin cá nhân của người dùng là một hệ thống nhất quán của Qianhai Youlong Technology Co., Ltd.. Qianhai Youlong Technology Co., Ltd. sẽ thực hiện các bước hợp lý để bảo vệ thông tin cá nhân của người dùng. Qianhai Youlong Technology Co., Ltd., ngoài các yêu cầu pháp lý hoặc pháp lý hoặc sự đồng ý của chính phủ. Thông tin riêng tư cá nhân của người dùng sẽ không được tiết lộ hoặc tiết lộ cho các bên thứ ba ngoài đơn vị đối tác mà không có sự đồng ý của người dùng. Tuy nhiên, người dùng chọn đồng ý tại thời điểm đăng ký hoặc người dùng và Qianhai Youlong Technology Co., Ltd. và đơn vị hợp tác đã đồng ý khác về việc tiết lộ hoặc sử dụng thông tin cá nhân của người dùng và người dùng sẽ chịu mọi rủi ro có thể phát sinh, Qianhai Youlong Technology Co., Ltd. không Có trách nhiệm. Đồng thời, để vận hành và cải thiện công nghệ và dịch vụ của Qianhai Youlong Technology Co., Ltd., Qianhai Youlong Technology Co., Ltd. có thể thu thập hoặc cung cấp thông tin cá nhân cho người dùng của bên thứ ba, giúp Qianhai Youlong Technology Co., Ltd. cung cấp cho người dùng trải nghiệm người dùng tốt hơn và cải thiện Chất lượng dịch vụ của Qianhai Youlong Technology Co., Ltd.. Qianhai Youlong Technology Co., Ltd. thu thập dữ liệu dựa trên tương tác của người dùng với Qianhai Youlong Technology Co., Ltd. và các lựa chọn của người dùng, bao gồm các cài đặt quyền riêng tư của người dùng và các sản phẩm và tính năng được người dùng sử dụng. Dữ liệu do Qianhai Youlong Technology Co., Ltd. thu thập có thể bao gồm phiên bản mã SDK / API / JS, địa chỉ IP, nền tảng, dấu thời gian, số nhận dạng ứng dụng, phiên bản ứng dụng, kênh phân phối ứng dụng, số nhận dạng thiết bị độc lập, số nhận dạng quảng cáo iOS (IDFA), quảng cáo Android Số nhận dạng chính, địa chỉ card mạng (MAC), Nhận dạng thiết bị di động quốc tế (IMEI), kiểu thiết bị, nhà sản xuất thiết bị đầu cuối, phiên bản hệ điều hành thiết bị đầu cuối, thời gian bắt đầu / dừng phiên, vị trí ngôn ngữ, múi giờ và trạng thái mạng (WiFi, v.v.) Sử dụng đĩa cứng, CPU và pin, v.v. Điều này sẽ cho phép Qianhai Youlong Technology Co., Ltd. tiến hành phân tích và nghiên cứu dữ liệu nội bộ, dịch vụ thống kê SDK của bên thứ ba và cải thiện các sản phẩm hoặc dịch vụ của Qianhai Youlong Technology Co., Ltd.. Để đảm bảo tính xác thực của danh tính người dùng, để cung cấp bảo mật tốt hơn với các thông tin nhận dạng người dùng, hoặc đặc điểm khuôn mặt như thông tin người dùng sinh trắc học phải nộp (cả hai thuộc về thông tin cá nhân nhạy cảm) để hoàn thành các sản phẩm cụ thể yêu cầu hoặc dịch vụ cần thiết để sống chứng nhận. Thông tin trên sẽ chỉ được sử dụng để xác minh tính xác thực của danh tính người dùng. Thông tin trên do người dùng cung cấp sẽ tiếp tục được Qianhai Youlong Technology Co., Ltd. ủy quyền trong quá trình sử dụng Dịch vụ của người dùng. Qianhai Youlong Technology Co., Ltd. sẽ ngừng sử dụng nó khi người dùng đăng xuất khỏi tài khoản. Các thông tin trên sẽ được lưu trữ tại Cộng hòa Nhân dân Trung Hoa. Đối với truyền dẫn xuyên biên giới, Qianhai Youlong Technology Co., Ltd. sẽ có được sự cho phép của người dùng. Xác thực tính xác thực của người dùng ứng dụng yêu cầu người dùng cung cấp một số thông tin có thể xác minh tính xác thực của danh tính người dùng. Thông tin liên quan chỉ được sử dụng để đánh giá nền tảng và sẽ không được tiết lộ cho bất kỳ người dùng nào khác hoặc cho mục đích thương mại, ngoại trừ các bộ phận pháp lý hoặc liên quan yêu cầu can thiệp.", + "UG_LINE32": "Thông tin nhãn hiệu của Qianhai Youlong Technology Co., Ltd. Logo", + "UG_LINE33": "Ký tự hoặc các thành phần của chúng và các logo và sản phẩm và tên dịch vụ khác của Qianhai Youlong Technology Co., Ltd. có liên quan đến các dịch vụ của Qianhai Youlong Technology Co., Ltd. là các nhãn hiệu của Qianhai Youlong Technology Co., Ltd. (sau đây gọi là Logo Qianhai Youlong Technology Co., Ltd. Logo). Logo Qianhai Youlong Technology Co., Ltd. có thể không được hiển thị hoặc sử dụng hoặc xử lý theo bất kỳ cách nào nếu không có sự đồng ý trước bằng văn bản của Qianhai Youlong Technology Co., Ltd. và không được cho người khác biết rằng bạn có quyền hiển thị, sử dụng hoặc được ủy quyền để xử lý logo Qianhai Youlong Technology Co., Ltd..", + "UG_LINE34": "Thứ tư, trách nhiệm pháp lý và miễn trừ", + "UG_LINE35": "1. Người dùng vi phạm các quy định của Thỏa thuận này hoặc các điều khoản dịch vụ có liên quan, dẫn đến hoặc phát sinh từ bất kỳ khiếu nại, khiếu nại hoặc tổn thất nào được yêu cầu bởi bất kỳ bên thứ ba nào, bao gồm phí luật sư hợp lý và người dùng đồng ý bồi thường cho Qianhai Youlong Technology Co., Ltd. và công ty đối tác, các chi nhánh, Và bảo vệ nó khỏi thiệt hại.", + "UG_LINE36": "2. Qianhai Youlong Technology Co., Ltd. và các đối tác không chịu trách nhiệm cho bất kỳ tổn thất nào của người dùng do lỗi đường truyền, sự cố kỹ thuật, mạng, lỗi máy tính, mất ổn định hệ thống và các nguyên nhân bất khả kháng khác của các bên thứ ba như bộ phận viễn thông.", + "UG_LINE37": "3, do sự kiện thất bại bất khả kháng kỹ thuật ảnh hưởng đến hoạt động bình thường của dịch vụ, Qianhai Youlong Technology Co., Ltd. và cam kết đối tác với các đơn vị có liên quan trong lần đầu tiên với việc xử lý kịp thời sửa chữa, nhưng tất cả các tổn thất của người sử dụng và do đó, Qianhai Youlong Technology Co., Ltd. và Đơn vị đối tác không chịu trách nhiệm.", + "UG_LINE38": "4, các dịch vụ tương tự như hầu hết các dịch vụ Internet, tùy thuộc vào các yếu tố bao gồm, nhưng không giới hạn người sử dụng lý trí, chất lượng dịch vụ mạng, xã hội và sự khác biệt về môi trường chưa bị nhiễm khuẩn với một loạt các vấn đề an ninh, chẳng hạn như những người khác sử dụng dữ liệu của người dùng, dẫn đến trong cuộc sống thực Quấy rối, phần mềm khác được tải xuống hoặc cài đặt bởi người dùng hoặc các trang web khác được truy cập có chứa \"Trojan Horse\" và các vi-rút khác, đe dọa đến tính bảo mật của thông tin và dữ liệu máy tính của người dùng, do đó ảnh hưởng đến việc sử dụng dịch vụ thông thường. Người dùng nên tăng cường bảo mật thông tin và nhận thức bảo vệ thông tin người dùng và chú ý tăng cường bảo vệ mật khẩu để tránh mất mát và quấy rối.", + "UG_LINE39": "5. Người dùng phải hiểu rằng việc sử dụng dịch vụ này có thể bị ảnh hưởng bởi các yếu tố không ổn định trong các liên kết khác nhau do các dịch vụ Internet. Do đó, dịch vụ có nguy cơ bị gián đoạn dịch vụ hoặc không đáp ứng yêu cầu của người dùng do bất khả kháng, virus máy tính hoặc tin tặc tấn công, mất ổn định hệ thống, vị trí người dùng, tắt máy và bất kỳ lý do công nghệ, internet, đường truyền thông nào khác. Người dùng chịu trách nhiệm cho các rủi ro trên và Qianhai Youlong Technology Co., Ltd. không đảm bảo. Qianhai Youlong Technology Co., Ltd. không chịu trách nhiệm cho việc người dùng không thể gửi và nhận thông tin đọc hoặc nhận thông tin không chính xác.", + "UG_LINE40": "6, người dùng phải hiểu, có sử dụng quy trình dịch vụ này, trong đó có nội dung đe dọa, phỉ báng, xúc phạm hoặc bất hợp pháp hay hành vi của bất kỳ người nào khác, hoặc vi phạm quyền của người khác (kể cả sở hữu trí tuệ) của Qianhai Youlong Technology Co., Ltd. và công ty đối tác không thực hiện bất kỳ loại bảo đảm nào cho dịch vụ, dù rõ ràng hay ngụ ý, bao gồm tất cả tính xác thực thông tin liên quan, tính thương mại, phù hợp với một số nhất định Việc sử dụng cụ thể, tiêu đề và không vi phạm các bảo đảm và điều kiện ngụ ý sẽ không chịu trách nhiệm cho bất kỳ thiệt hại trực tiếp, gián tiếp, ngẫu nhiên, đặc biệt hoặc hậu quả nào từ việc sử dụng Dịch vụ không đúng hoặc bất hợp pháp của Người dùng.", + "UG_LINE41": "7.Nội dung thông tin được xác định bởi Qianhai Youlong Technology Co., Ltd. bao gồm: văn bản, phần mềm, âm thanh, hình ảnh, video, đồ họa, tất cả nội dung trong quảng cáo, thông tin thương mại do Qianhai Youlong Technology Co., Ltd. cung cấp cho người dùng, tất cả đều thuộc bản quyền, nhãn hiệu và các quyền sở hữu trí tuệ khác. Và việc bảo vệ luật sở hữu. Do đó, người dùng chỉ có thể được sử dụng theo Qianhai Youlong Technology Co., Ltd. và các nhà quảng cáo có thẩm quyền của nội dung, nhưng không sao chép trái phép, sửa đổi, biên soạn này. Những nội dung, hoặc tạo ra các sản phẩm phái sinh nội dung liên quan đến.", + "UG_LINE42": "8.trong mọi trường hợp, Cyhd TNHH chịu trách nhiệm về bất kỳ thiệt hại gián tiếp, gián tiếp, trừng phạt, ngẫu nhiên, đặc biệt hoặc trừng phạt, bao gồm cả lợi nhuận bị mất phải chịu đựng bởi người dùng sử dụng dịch vụ, trách nhiệm (ngay cả khi thông báo về Khả năng mất mát cũng vậy). Mặc dù thỏa thuận này có thể có điều khoản trái, Cyhd TNHH hoàn toàn trách nhiệm đối với cam kết của bạn, vì bất cứ lý do nào, hoặc những loại hành vi, không bao giờ vượt quá việc bạn sử dụng phí dịch vụ thanh toán cho các thành viên TNHH Cyhd trong giai đoạn này.", + "UG_LINE43": "Năm, điều khoản thành viên", + "UG_LINE44": "1. thành viên Hibok có quyền bình đẳng với các thành viên và sẽ tuân thủ các thông số và quy tắc của Qianhai Youlong Technology Co., Ltd., bao gồm nhưng không giới hạn trong các Điều khoản dịch vụ này và Thỏa thuận người dùng.", + "UG_LINE45": "2. Mất mát liên quan đến việc đình chỉ dịch vụ thành viên do vi phạm Thỏa thuận người dùng Qianhai Youlong Technology Co., Ltd. sẽ do người dùng chịu.", + "UG_LINE46": "3. Thành viên có thể tận hưởng các dịch vụ giá trị gia tăng của các thành viên Hibok trong thời gian thành viên.", + "UG_LINE47": "4. Nếu thành viên chủ động chấm dứt hoặc hủy bỏ tư cách thành viên trong thời gian hiệu lực của thành viên, Qianhai Youlong Technology Co., Ltd. không chịu trách nhiệm hoàn trả phí dịch vụ tương ứng với thời hạn hiệu lực của thành viên còn lại của thành viên.", + "UG_LINE48": "5, các thành viên truyền sinh trong Hibok, việc phát hành các thông tin và sử dụng các dịch vụ miễn phí trách nhiệm pháp lý Hibok hoặc trả thành viên dịch vụ để sử dụng dịch vụ Hibok, bao gồm các dịch vụ miễn phí và trả hành động dịch vụ, thực hiện theo tất cả các luật, quy định, quy chuẩn Tập tin.", + "UG_LINE49": "6. Sau khi dịch vụ thành viên được mở, nó không thể được chuyển nhượng hoặc hủy đăng ký.", + "UG_LINE50": "7, do các thành viên trong việc sử dụng Cyhd TNHH dịch vụ miễn phí, dịch vụ thanh toán, có những hành vi vi phạm pháp luật và các quy định, Cyhd TNHH có quyền hủy bỏ thành viên của thành viên mà không đưa ra bất kỳ bồi thường, và các thành viên phải chịu trách nhiệm hoàn toàn.", + "UG_LINE51": "Sáu điều khoản khác", + "UG_LINE52": "1. Qianhai Youlong Technology Co., Ltd. nhắc nhở người dùng chú ý đến các điều khoản của Thỏa thuận miễn trừ trách nhiệm pháp lý của Qianhai Youlong Technology Co., Ltd. và làm nặng thêm nghĩa vụ của người dùng. Vui lòng đọc kỹ và xem xét rủi ro. Người chưa thành niên nên đọc Thỏa thuận này kèm theo người giám hộ hợp pháp. Việc giải thích và sửa đổi cuối cùng các điều khoản và điều kiện trên thuộc sở hữu của Qianhai Youlong Technology Co., Ltd..", + "UG_LINE53": "2. Sự vô hiệu của một số hoặc tất cả các điều khoản được quy định trong Thỏa thuận này sẽ không ảnh hưởng đến hiệu lực của các điều khoản khác.", + "UG_LINE54": "3. Việc giải thích, hiệu lực và giải quyết tranh chấp trong Thỏa thuận này sẽ được áp dụng cho luật pháp của Cộng hòa Nhân dân Trung Hoa. Nếu bất kỳ tranh chấp hay tranh cãi giữa người dùng và Qianhai Youlong Technology Co., Ltd., trước hết phải được giải quyết thông qua hiệp thương hữu nghị, tư vấn thất bại, người sử dụng trong này hoàn toàn đồng ý đưa tranh chấp hoặc cãi Cyhd TNHH nơi cư trú có trách nhiệm thẩm quyền.", + "UG_LINE55": "4. Bản quyền của Thỏa thuận này thuộc sở hữu của Qianhai Youlong Technology Co., Ltd. và Qianhai Youlong Technology Co., Ltd. bảo lưu mọi quyền để giải thích và sửa đổi.", + "UG_LINE56": "Qianhai Youlong Technology Co., Ltd.", + "net_error": "Mạng bất thường", + "enter_name": "Vui lòng nhập tên", + "translate": "Dịch", + "locate": "Vị trí", + "voice_tips": "Giữ để nói, buông ra để gửi", + "unlock": "Mở khóa", + "input_content": "Nhập nội dung", + "connecting": "Đang kết nối...", + "logining": "Đang đăng nhập...", + "reject_reply": "/s1 đã từ chối yêu cầu để xem của bạn", + "warning_text": "Tròng vòng 3 ngầy nếu không có ai báo cáo, bạn có thể đổi H coin thành tiền mặt(1:1000Việt nam)", + "more_big": "Số lượng đầu vào không lớn hơn /s1", + "little_min": "Số lượng đầu vào không ít hơn /s1", + "voice_msg": "/s1 mời bạn gọi", + "send_gift": "Bạn đã thưởng cho đối phương /s1 cái /s2", + "receive_gift": "Đối phương đã thưởng cho bạn /s1 cái /s2", + "cannot_join": "Không phải thành viên không thể đăng ký", + "alreay_back": "Trả lại", + "video_more_big": "Tệp quá lớn", + "select_all": "Chọn tất cả", + "re_connect": "Kết nối lại", + "voice_tips2": "Buông ra để gửi, vuốt để hủy", + "country": "Quốc tịch", + "have_picture_view": "Đang xem xét", + "speaker_play": "Loa chơi", + "handset_playback": "Phát loa ngoài", + "play_model": "Chế độ loa ngoài", + "password_less": "Mật khẩu quá ngắn", + "years_old": "Tuổi", + "coin_returen1": "Khi bị người giấu tên tố cáo, hệ thống tiến hành kiểm tra và xác minh gần đây bạn có hành vi vi phạm xin hãy dừng lại hành động đó. Nếu tiếp tục vi phạm tài khoản của bạn của bạn sẽ bị đóng băng", + "already_new": "Đây là phiên bản mới nhất", + "test_it": "Trải nghiệm ngay", + "found_new": "Phát hiện phiên bản mới", + "ad": "Quảng cáo", + "attention": "Theo dõi", + "fans": "Fans", + "apply_see": "/s1 xin xem trang tài liệu của tôi.", + "agree_apply": "/s1 đã thông qua yêu cầu xem của tôi", + "see_redBag": "/s1 xem ảnh lì xì của tôi", + "notice": "Nhắc nhở", + "notice_open": "Vui lòng bật quyền thông báo trong cài đặt điện thoại của bạn để nhận thông báo", + "open_notice": "Quyền thông báo chưa được bật", + "not_open": "Quyền thông báo chưa được mở, không nhận được thông báo.", + "withdraw_fail": "coin /s1H mà bạn xin rút tiền đã được trả lại, xin xác nhận tài khoản liên kết của bạn có đúng không!", + "dynamics": "Hoạt động", + "Remark": "Ghi chú", + "setRemark": "Cài đặt ghi chú", + "content_num": "/s1 bình luận", + "Redeem": "Điểm sẽ đổi được /s1H coin ", + "location_permission": "Không có quyền truy cập vào bộ nhớ điện thoại", + "camera_permission": "Không có quyền truy cập camera", + "photo_permission": "Không có quyền truy cập vào album", + "video_permission": "Không có quyền truy cập micro", + "your_redMoney_over": "Lỉ xỉ bạn gửi đã hết hạn", + "other_redMoney_over": "Đồi phương gửi lì xì đã hết hạn ", + "server_error_tips": "Có vẻ đã xảy ra lỗi ...", + "emoji": "icon", + "today_score": "Báo danh trong ngày để nhận /s1 điểm tích lũy", + "sign_tips": "1. Báo danh hàng ngày để tích lũy điểm, số ngày tích lũy càng nhiều điêm tích lũy càng cao. \n2. Điểm tích lũy có thể đổi thành H coin, khi đổi sẽ tiêu hao điểm tích lũy tương đương, hãy thận trọng khi đổi. \n3.Báo danh sẽ được đặt lại vào ngày cuối cùng của tháng, xóa điểm tích lũy. Hãy kịp thời đổi điểm tích lũy nhé!", + "sign_in": "Báo danh", + "my_score": "Điểm tích lũy của tôi", + "signin_now": "Báo danh ngay", + "sign_in_day": "Tích lũy báo danh /s1 ngày", + "have_get": "Đã hối đổi", + "scan": "Quét mã", + "my_qr": "Mã QR của tôi", + "scan_and_add": "Quét mã và thêm bạn bè", + "amap": "Bản đồ Gouda", + "baidumap": "Bản đồ Yahoo", + "googlemap": "Bản đồ Google", + "applemap": "Bản đồ Apple", + "go_open": "Đi mở ra", + "Preview": "Xem trước", + "Photo_album": "Album ảnh", + "all_photo": "Tất cả hình ảnh ", + "have_select": "Bạn đã chọn /s1 hình ảnh", + "loading": "Đang tải ...", + "new_chat_msg": "Bạn có tin nhắn trò chuyện mới", + "new_video_msg": "Bạn có tin nhắn Liên mic mới", + "apply_friends": "/s1 xin kết bạn", + "applyed_friends": "/s1 đã thông qua yêu cầu kết bạn của bạn", + "contact_permission": "Không có quyền truy cập vào danh bạ", + "contact": "Danh bạ", + "search": "Tìm kiếm", + "contact_add": "Thêm bạn bè từ danh bạ", + "find": "Phát hiện", + "translate_robot": "Robot dịch", + "robot_hello": "Xin chào, tôi là robot dịch thuật ...", + "Simplified_Chinese": "Tiếng Trung giản thể", + "traditional_Chinese": "Tiếng Trung phồn thể", + "english": "Tiếng Anh", + "Vietnamese": "Tiếng Việt", + "Korean": "Tiếng Hàn", + "Japanese": "Tiếng Nhật", + "add_friends": "Thêm bạn bè", + "stranger": "Người lạ", + "receive_stranger": "Nhận tin nhắn từ người lạ", + "signin": "SignIn", + "stranger_close": "Đối phương từ chối nhận tin nhắn từ người lạ, bạn có tiếp tục mở khóa tất cả thông tin không.", + "add": "Thêm", + "added": "Đã thêm", + "stranger_close_tips": "Đối phương từ chối nhận tin nhắn từ người lạ.", + "translate_fail": "Lỗi dịch", + "no_photos": "Vui lòng tải ảnh lên trước khi cài đặt ảnh lì xì.", + "successful_appeal1": "Đánh giá kháng án của bạn: /s1 kháng án thất bại.", + "add_success": "Thêm thành công, đợi đối phương đồng ý", + "other_pay": "Người khác trả hộ", + "friend_verification": "Xác thực bạn bè", + "add_friends_tips": "Đơn xin xác thực của bạn đã gửi và chờ đối phương thông qua", + "i_am": "Tôi là/s1", + "agree": "Cho phép", + "privacyAgreement": "\"Hi\"Bạn cần đồng ý với \"Thỏa thuận quyền riêng tư\" để sử dụng", + "privacy": "Thỏa thuận quyền riêng tư", + "notification_addfriend": "Hi! có người yêu cầu thêm bạn, xem đó là ai", + "distance_long": "Thêm bạn bè cần đối diện với nhau mới thêm được ha", + "chat_tips": "Để nâng cao tính chính xác của nội dung dịch, vui lòng đừng viết tắt", + "fans_list": "Danh sách fans", + "system_not_open": "Đang kiểm tra chức năng", + "service_withdraw_tips": "Hiện tại khách hàng IOS chưa hỗ trợ chức năng rút tiền,bạn có thể sử dụng Android để rút hoặc click vào nút phía dưới", + "withdraw_tips": "Click vào đây để rút tiền", + "add_member": "Thêm thành viên", + "delete_member": "Xóa thành viên", + "change_group_name": "Sửa đổi tên nhóm", + "my_group_nickname": "Biệt danh của tôi trong nhóm ", + "group_chat": "Trò chuyện nhóm", + "create_group_chat": "Tạo nhóm trò chuyện", + "added_friends_tips": "Bạn cần gửi đơn xin xác thực và chờ đối phương thông qua", + "group_chat_name": "Tên nhóm trò chuyện", + "my_group_nickname_tips": "Tại đây bạn có thể đặt biệt hiệu của mình trong nhóm này, và biệt danh này chỉ được hiển thị trong nhóm này", + "man_gold": "Động thái nam thần", + "woman_gold": "Động thái nữ thần", + "choose_group_owner": "Chọn nhóm chủ mới", + "group_announcement": "Thông báo nhóm", + "chat_news": "Tin nhắn trò chuyện", + "group_qr": "Mã QR nhóm", + "group_setting": "Quản lý nhóm", + "close_news_notice": "Thông báo tắt tiếng", + "set_chat_top": "Dính ở trên đầu", + "show_group_member_name": "Hiển thị biệt danh thành viên nhóm", + "quit_group_tips": "Sau khi thoát nhóm sẽ không thông báo cho các thành viên khác trong cuộc trò chuyện nhóm, và không nhận được tin nhắn trò chuyện nhóm này nữa", + "quit_and_delete": "Thoát và xóa", + "show_more_member": "Xem thêm thành viên nhóm", + "group_invite": "Xác nhận lời mời trò chuyện nhóm", + "change_group_owner": "Chuyển quyền quản lý nhóm", + "group_setting_tips": "Sau khi kích hoạt, các thành viên nhóm mời bạn bè vào nhóm cần được sự đồng ý của chủ nhóm, đồng thời quét mã QR cũng ngưng sử dụng", + "invite_detail": "Chi tiết lời mời", + "undefine_name": "Chưa đặt tên", + "group_qr_code": "Danh thiếp mã QR nhóm", + "group_qr_code_tips": "Mã QR có hiệu lực trong vòng 7 ngày (ngày /s2 tháng /s1), nhập lại sẽ được cập nhật.", + "Goddess_heat": "Nhiệt độ nữ thần", + "Goddess_heat_tips": "Quà tặng tích lũy", + "new_friends": "Bạn mới", + "before_three_day": "3 ngày trước", + "after_three_day": "3 ngày gần đây ", + "group_clean_chat_record": "Xóa nội dung trò chuyện", + "check": "Xem thêm", + "apply_fro_friends": "Yêu cầu thêm bạn làm bạn bè", + "no_vip_cannot_withdraw": "Không phải thành viên không thể rút tiền mặt", + "not_true_woman": "Người dùng này chưa được xác thực, hãy cẩn thận với lừa đảo", + "join_group": "Tham gia trò chuyện nhóm", + "sign_in_apple": "Đăng nhập qua Apple", + "only_host": "Thông báo nhóm chỉ chủ nhóm mới có thể chỉnh sửa", + "send_gift1": "Bạn đã thưởng cho đối phương /s1 quà tặng", + "receive_gift1": "Đối phương thưởng cho bạn /s1 quà tặng", + "not_in_group": "Bạn đã không còn trong nhóm", + "creating_group": "Đang sáng lập, vui lòng đợi", + "article": "Điều", + "group_open_verification": "Nhóm này đã bật vào nhóm phải xác thực và chỉ có thể thông qua lời mời mới được tham gia ", + "group_memeber": "Thành viên nhóm", + "invite_members": "Đã mời /s1 bạn bè tham gia trò chuyện nhóm", + "total_members": "Tổng /s1 người", + "qr_outtime": "Mã QR đã hết hạn", + "no_goupr_info": "Không có thông tin nhóm này", + "you_invite": " Bạn đã mời /s1 tham gia trò chuyện nhóm", + "invite_you": "Bạn đã được mời vào trò chuyện nhóm này bởi /s1", + "invite_someone": "/s1 đã mời /s2 tham gia trò chuyện nhóm", + "you": "Bạn", + "delete_group": "/s1 đã xóa /s2 khỏi trò chuyện nhóm này", + "you_group_owner": " Bạn đã trở thành chủ nhóm mới của nhóm ", + "someone_group_owner": "/s1 đã trở thành chủ nhóm mới của nhóm này", + "change_group_owner1": " Tên nhóm được đổi thành /s1", + "update_group_announce": "Thông báo nhóm đã được cập nhật", + "you_qr": "Bạn tham gia trò chuyện nhóm bằng cách quét mã QR", + "others_qr": " /s1 Tham gia trò chuyện nhóm bằng cách quét mã QR", + "invite_confirm": "\"/s1\" muốn mời /s2 bạn bè vào nhóm trò chuyện \\$ Đi để xác nhận \\$", + "want_invite_confirm": " \"/s1\" Muốn mời \"/s2\" để tham gia trò chuyện nhóm", + "join_group_confirm": "\"/s1\" Tham gia trò chuyện nhóm Xác nhận", + "you_invite_gourp": "Bạn đã được mời vào một cuộc trò chuyện nhóm bởi /s1", + "someone_join_group": " \"/s1\"Tham gia trò chuyện nhóm ", + "group_setting_tips1": " Chủ nhóm đã bật \"Xác nhận lời mời trò chuyện nhóm \", các thành viên nhóm cần xác nhận từ chủ nhóm để mời bạn bè vào nhóm", + "group_setting_tips2": "Chủ nhóm đã khôi phục phương thức tham gia nhóm mặc định", + "members_max": " Số thành viên nhóm đã đạt đến giới hạn", + "group_max": "Số lượng nhóm đã đạt đến giới hạn", + "my_money_info": "Hóa đơn của tôi", + "my_left_money": "Số dư của tôi", + "money_tips": "H-coin có thể nạp trực tiếp hoặc hối đổi, nhưng không thể rút tiền mặt.", + "get_money_detail": "Thu nhập cụ thể", + "hibok_money": "Thu nhập Hibox", + "charge_h": "Hối đổi H-coin", + "charge_tips": "Quy tắc rút tiền", + "splash_tips1": "Định vị đa dạng", + "splash_tips2": "Robot dịch", + "splash_tips3": "APP hẹn hò", + "splash_tips_content1": "Nữ thần đa dạng, chọn bạn yêu thích", + "splash_tips_content2": "Cùng nhau chat voice", + "splash_tips_content3": "Giải quyết vấn đề ngôn ngữ", + "splash_go": "Trải nghiệm ngay", + "change_h_coin": "Bạn đã thông qua hối đổi thu nhập được /s1H coin", + "Representation_succes": "Yêu cầu của bạn đã thành công, và hệ thống đã hoàn tiền", + "system_give": "Hệ thống tặng", + "exchange_fail": "Yêu cầu rút tiền của bạn thất bại và đã được trả lại", + "hibok_exchange": "Thông qua thu nhập Hibox hối đổi được /s1H coin", + "bind_code_success": "Liên kết mã mời thành công", + "translate_money": "Bạn đã dành /s1H coin để sự dụng người dịch", + "system_back": "Hệ thống hủy bỏ trả lại", + "you_give": "Bạn thưởng cho đối phương", + "you_get": "Đối phương thưởng cho bạn", + "enter_num_qian": "Số lượng hối đổi (đơn vị K)", + "enter_num_qian1": "Số lượng tiền rút (đơn vị K)", + "daily_translate_voucher": "翻译券", + "msg_notice":"通知消息", + "select_notice_people":"选择提醒的人", + "search_phone":"查找手机号", + "not_have_user":"用户不存在", + "not_add_Myself":"你不能添加自己", + "you_are_blaklisted":"对方已拉黑了你", + "confrim_recovery":"确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)", + "send_to": "發送到" +} \ No newline at end of file diff --git a/i18n/zh-CN.json b/i18n/zh-CN.json new file mode 100644 index 0000000..da6c991 --- /dev/null +++ b/i18n/zh-CN.json @@ -0,0 +1,1164 @@ +{ + "appName": "Hi公园", + "login": "登录", + "registration": "注册", + "other_login": "其他登录", + "account": "账号", + "enter_username": "请输入账号", + "password": "密码", + "enter_password": "输入密码", + "forget_password": "忘记密码", + "reset_password": "重置密码", + "number_registration": "手机号注册", + "enter_number": "请输入手机号", + "code": "验证码", + "enter_code": "请输入收到的验证码", + "send_code": "发送验证码", + "send_again": "重新发送", + "set_password": "设置密码", + "password_limit": "密码不少于6位", + "set_password2": "请设置登录密码", + "next_step": "下一步", + "agreed_agreement": "点击进入表示你已阅读并同意《用户协议》", + "enter_password2": "请输入登录密码", + "reset_now": "立即重置", + "choose_gender": "选择性别", + "who": "你是...", + "determine": "确定", + "cannot_modified": "选择性别后无法修改", + "tip": "提示", + "choose_quit": "你即将完成注册,是否现在退出?", + "confirm": "确认", + "use": "使用", + "cancel": "取消", + "close": "关闭", + "delete": "删除", + "forget_it": "算了", + "ok": "好的", + "choose_quit2": "注册后将不能修改性别,确定么?", + "tip_content": "提示:你不能和同性别用户进行交流", + "welcome": "欢迎", + "enter_incode": "请填写邀请码", + "must_incode": "Hi仅向拥有邀请码的男士提供服务", + "your_incode": "你的邀请码", + "how_get": "没有邀请码?你可以通过以下方式获取", + "method1": "方式1", + "free": "免费申请", + "apply_now": "马上申请", + "check_incode": "查收邀请码", + "so_get": "你需要填写一些个人信息,审核通过后回给你发送邀请码", + "apply_incode": "申请邀请码", + "location": "所在地", + "cityname": "你所在的城市名称", + "message_channel": "信息渠道", + "how_know": "你从哪里知道APP", + "wechat_number": "微信号", + "your_wechat": "你的微信号", + "facebook": "facebook", + "your_facebook": "你的脸书", + "submit_application": "提交申请", + "enter_city": "请输入所在城市", + "so_know": "请告诉我们你获取APP的信息渠道", + "your_social": "请告诉我们你的社交账号", + "receive_incode": "我们将尽快处理你的申请。如果通过审核,你会在消息中心收到我们发放的邀请码", + "wait_incode": "邀请码还未发放,申请后请耐心等待!", + "successful_application1": "邀请码申请成功!", + "application_failed1": "邀请码申请失败!", + "successful_copy": "复制成功", + "method2": "方式2", + "joinvip": "加入会员", + "join_now": "立即加入", + "joined": "已加入", + "join_odds": "加入会员可享受各种特权,包括无需邀请码注册", + "not_joinvip": "你还没有加入会员", + "join_after": "加入会员后,即可不需要邀请码完成注册", + "incode_passed": "邀请码验证通过", + "welcome_join": "欢迎加入!请勿把你的账号泄露给他人,一经发现登录异常,账户会被自动冻结。", + "member_centre": "会员中心", + "members_privilege": "会员特权", + "see_more": "看的更多", + "unlimited_see": "每天不限次数查看用户", + "see_cheaper": "看的更省", + "free10": "每天/s1次免费机会查看付费相册或者社交账号", + "see_longer": "看的更久", + "towto6": "查看阅后即焚照片的时间从2秒提升到/s1秒", + "see_better": "看的更爽", + "free_release": "免费发布约会广播", + "choose_price": "选择套餐", + "pay_method": "支付方式", + "pay_amount": "支付金额", + "not_enough": "钱包余额不足", + "confirm_pay": "确认支付", + "complete_material": "完善资料", + "basic_information": "基本资料", + "upload_avatar": "上传头像", + "choose": "请选择", + "fill_out": "请填写", + "choose_multiple": "可以多选", + "optional": "选填", + "least": "最少填写/s1个", + "introduce_yourself": "介绍一下自己", + "most": "最多选择/s1个", + "nickname": "昵称", + "only1_8": "昵称只能1-20个字符", + "Resident_city": "当前城市", + "Please_select_a_resident_city": "请选择当前城市", + "City1": "芹苴", + "City2": "岘港", + "City3": "海防", + "City4": "河内", + "City5": "胡志明", + "City6": "安江", + "City7": "北江", + "City8": "北件", + "City9": "薄辽", + "City10": "北宁", + "City11": "巴地头顿", + "City12": "槟椥", + "City13": "平定", + "City14": "平阳", + "City15": "平福", + "City16": "平顺", + "City17": "金瓯", + "City18": "高平", + "City19": "得乐", + "City20": "得农", + "City21": "奠边", + "City22": "同奈", + "City23": "同塔", + "City24": "嘉莱", + "City25": "河江", + "City26": "海阳", + "City27": "河南", + "City28": "河静", + "City29": "和平", + "City30": "后江", + "City31": "兴安", + "City32": "庆和", + "City33": "坚江", + "City34": "昆嵩", + "City35": "莱州", + "City36": "林同", + "City37": "谅山", + "City38": "老街", + "City39": "隆安", + "City40": "乂安", + "City41": "宁平", + "City42": "宁顺", + "City43": "富寿", + "City44": "富安", + "City45": "广平", + "City46": "广南", + "City47": "广义", + "City48": "广宁", + "City49": "广治", + "City50": "朔庄", + "City51": "山罗", + "City52": "西宁", + "City53": "太平", + "City54": "太原", + "City55": "清化", + "City56": "承天顺化", + "City57": "前江", + "City58": "茶荣", + "City59": "宣光", + "City60": "永隆", + "City61": "永富", + "City62": "安沛", + "City63": "南定", + "birthday": "生日", + "choose_birthday": "请选择生日", + "year": "年", + "month": "月", + "day": "日", + "hour": "时", + "minute": "分", + "second": "秒", + "just": "刚刚", + "minute_ago": "/s1分钟前", + "hour_ago": "/s1小时前", + "day_ago": "/s1天前", + "week_ago": "/s1周前", + "month_ago": "/s1月前", + "morning": "上午", + "noon": "中午", + "afternoon": "下午", + "night": "晚上", + "all_day": "一整天", + "yesterday": "昨天", + "two_yesterday": "前天", + "overnight": "通宵", + "one": "个", + "ten": "十", + "hundred": "百", + "thousand": "千", + "ten_thousand": "万", + "aries": "白羊座", + "taurus": "金牛座", + "gemini": "双子座", + "cancer": "巨蟹座", + "leo": "狮子座", + "virgo": "处女座", + "libra": "天秤座", + "scorpio": "天蝎座", + "sagittarius": "射手座", + "capricorn": "摩羯座", + "aquarius": "水瓶座", + "pisces": "双鱼座", + "monday": "星期一", + "tuesday": "星期二", + "wednesday": "星期三", + "thursday": "星期四", + "friday": "星期五", + "saturday": "星期六", + "sunday": "星期天", + "job": "职业", + "choose_career": "请选择职业", + "career1": "信息技术", + "career2": "互联网", + "career3": "IT", + "career4": "电信运营", + "career5": "网络游戏", + "career6": "金融保险", + "career7": "投资", + "career8": "股票基金", + "career9": "保险", + "career10": "银行", + "career11": "信托担保", + "career12": "商业服务", + "career13": "咨询", + "career14": "个体经营", + "career15": "美容美发", + "career16": "旅游", + "career17": "酒店餐饮", + "career18": "休闲娱乐", + "career19": "贸易", + "career20": "汽车", + "career21": "房地产", + "career22": "物业管理", + "career23": "装修装潢", + "career24": "侦探", + "career25": "工程制造", + "career26": "建筑", + "career27": "土木工程", + "career28": "机械制造", + "career29": "电子", + "career30": "生物医学", + "career31": "食品", + "career32": "服装", + "career33": "能源", + "career34": "交通运输", + "career35": "航空", + "career36": "铁路", + "career37": "航运船舶", + "career38": "公共交通", + "career39": "物流运输", + "career40": "文化传媒", + "career41": "媒体出版", + "career42": "设计", + "career43": "文化传播", + "career44": "广告创意", + "career45": "动漫", + "career46": "公关会展", + "career47": "摄影", + "career48": "娱乐体育", + "career49": "影视", + "career50": "运动体育", + "career51": "音乐", + "career52": "模特", + "career53": "公共事业", + "career54": "医疗", + "career55": "法律", + "career56": "教育", + "career57": "政府机构", + "career58": "公益", + "career59": "学生", + "career60": "无", + "program": "节目", + "select_program": "请选择国籍", + "healthy_exercise": "健康运动", + "night_party": "夜蒲聚会", + "gourmet_party": "我是吃货", + "watch_movie": "看电影", + "play_games": "玩游戏", + "travel_together": "结伴旅行", + "voice_chat": "连麦聊天", + "other": "其他", + "expect_lover": "期望对象", + "choose_lover": "请选择期望对象", + "beautiful": "看脸", + "rich": "土豪", + "care_me": "关爱我", + "look_feeling": "看感觉", + "doesnt_matter": "无所谓", + "least_account": "请至少填写一种社交账号", + "hide_account1": "我的用户资料隐藏社交账号", + "more_information": "更多信息", + "height": "身高", + "weight": "体重", + "not_show": "不显示", + "self_introduction": "个人介绍", + "registration_success1": "注册成功", + "exit": "确定退出么", + "exit_registration": "你还未完善个人信息,现在退出下次进入请用已注册账号直接登录", + "cant_see": "男士无法查看其他男士详情", + "cant_see2": "女士无法查看其他女士详情", + "see_one": "你今天还能查看/s1位女士", + "only_see": "非会员用户每天只能查看15位女士", + "continue_see": "继续查看", + "user_frozen": "用户已冻结", + "search_user": "请输入昵称/职业进行搜索", + "nearby": "附近", + "member": "会员", + "new_registration": "新注册", + "authenticate": "认证", + "first_online": "在线", + "not_positioned": "未开启定位,无法计算与其他用户距离", + "unknown": "未知", + "secrecy": "保密", + "collection": "收藏", + "cancel_collection": "取消收藏", + "canceled_collection": "已取消收藏", + "like": "加入喜欢", + "added_like": "已加入喜欢", + "canceled_like": "已取消喜欢", + "blacklist": "拉黑", + "blacklist_choose": "你们将无法再看到对方和对方的动态,确定吗", + "blacklisted": "已加入黑名单", + "reject_message": "你已拉黑对方并拒收消息", + "remove_blacklist": "移除黑名单", + "blacklist_removed": "已移除黑名单", + "receive_message": "你将对方移除黑名单并取消拒收消息", + "online": "在线", + "paid_photo": "付费相册", + "application_view": "申请浏览", + "passed": "已通过", + "park": "公园", + "radio": "电台", + "news": "消息", + "me": "我", + "more_operations": "更多操作", + "anonymous_report": "匿名举报", + "certified_video": "认证视频", + "passed_video": "她已通过视频认证真实性", + "not_video": "她还没认证身份真实性", + "her_appointment": "她正在发起约会哦", + "pay_join": "他通过付费加入", + "passed_review": "他通过了身份安全审核", + "invited_user": "他通过资深用户/s1赠送的邀请码加入", + "his_appointment": "他正在发起约会哦", + "her_dynamics": "她的动态", + "his_dynamics": "他的动态", + "low_key": "她非常低调", + "low_key2": "他非常低调", + "her_photo": "她的相册", + "his_photo": "他的相册", + "set_lock": "他设置了相册锁", + "set_lock2": "她设置了相册锁", + "free_unlock": "解锁相册(/s1),会员免费", + "unlock_user": "解锁/s1的相册", + "pay_unlock": "付费解锁(/s1H币)", + "become_member": "成为会员,免费解锁", + "consumption_once": "是否使用1次机会解锁/s1的相册", + "remaining_once": "(你今天还有/s1次机会)", + "no_times": "你今天的免费机会已用完,是否赠送/s1解锁/s2的全部资料", + "pay": "支付", + "view_user": "他设置了限制,查看资料需要请求他的同意", + "view_user2": "她设置了限制,查看资料需要请求她的同意", + "need_photo": "申请查看需给对方发送一张你的照片。放心,你的照片会在对方长按屏幕查看的2秒后焚毁", + "choose_photo": "选择照片", + "send_application": "已发送申请,对方确认后你会收到消息提醒", + "not_authenticate": "你还没进行认证", + "after_authenticate": "认证你的真实性后,才能与他人互动", + "authenticate_now": "马上认证", + "destroy_after": "阅后即焚", + "destroyed": "已焚毁", + "red_photo1": "阅后即焚的红包照片", + "ask_me": "请通过私聊向我索取", + "filled_in": "已填写,点击查看", + "unlock_information": "解锁全部资料", + "unlock_choose": "使用1次免费解锁", + "your_evaluation": "你的真实评价", + "her_evaluation": "她的真实评价", + "his_evaluation": "他的真实评价", + "evaluate": "评价", + "friendly": "友好", + "interesting": "有趣", + "readily": "爽快", + "patient": "耐心", + "indifferent": "高冷", + "bad_temper": "爆脾气", + "courtesy": "礼貌", + "generous": "大方", + "lie": "口嗨", + "unfriendly": "不友好", + "anonymous_evaluation": "匿名评价", + "cant_evaluate": "你还没约过她,无法评价", + "cant_evaluate2": "他还没约过你,无法评价", + "bad_evaluate": "请提供相关截图,以便我们跟进核实", + "submit": "提交", + "evaluation_success": "评价成功", + "private_chat": "私聊", + "close_reminder": "关闭消息提醒", + "closed_reminder": "关闭消息提醒成功", + "open_reminder": "开启消息提醒", + "opened_reminder": "开启消息提醒成功", + "her_account": "她的社交账号", + "his_account": "他的社交账号", + "copy": "复制", + "send_account": "发送我的社交账号给她", + "enter_account": "输入你的社交账号", + "for_example": "比如:微信号abc", + "sent_she": "发送给她", + "chat": "连麦", + "cantt_voice": "对方关闭了连麦功能", + "authentication_voice": "认证你的真实性后,才能主动连麦", + "requesting_voice": "正在请求连麦", + "waitting_answer": "正在等待接听", + "answer": "接听", + "hang_up": "挂断", + "chatting": "连麦中", + "handsfree": "免提", + "giving_gift": "打赏", + "give_success": "打赏成功", + "others_gift": "对方已打赏", + "given_gift": "你已打赏价值/s1H币的礼物", + "earned_gift": "你已获赏/s1H币", + "available_balance": "可用余额/s1", + "recharge": "充值", + "give": "赠送", + "balance_insufficien": "抱歉,你的余额不足了", + "first_recharge": "请充值后再送礼物哦!", + "give_coin": "本次连麦打赏/s1H币", + "get_coin": "本次连麦获赏/s1H币", + "give_get": "本次连麦打赏/s1H币,获赏了/s2H币", + "chat_over": "连麦已结束,时长/s1", + "message_center": "消息中心", + "can_chat": "你可以在对方的用户详情页发起私聊", + "text_chat": "聊天", + "system_information": "系统消息", + "system_notification": "系统通知", + "report_failure": "你举报用户/s1的情况不属实,请提供更有效的证据后再次举报。谢谢!", + "report_success": "你举报用户/s1的情况属实,系统已对该用户进行处理", + "successful_application": "邀请码申请成功!邀请码【/s1】(点击可复制)", + "successful_application2": "邀请码申请成功,感谢你介绍靠谱的朋友!邀请码【/s1】(点击可复制)", + "application_failed": "邀请码申请失败!很遗憾您的申请未能通过审核,请填写真实信息将有效的提高审核通过率", + "important_notice": "【重要通知】:", + "authentication_failed": "你的认证资料不符合要求,请修改后重新提交。", + "request1": "1.请根据认证要求拍摄认证视频", + "request2": "2.请在相册上传五官清晰的正脸本人照片", + "successful_authentication": "恭喜,你的认证申请已通过审核", + "re_upload": "你新上传的照片没有通过审核,请根据要求重新上传", + "upload_success": "恭喜,你新上传的照片已成功通过审核", + "caveat": "您的约会报名因违规被删除,多次违规或情节严重系统将对您账号进行限制甚至封号,请遵守谨记,谢谢配合", + "caveat2": "您的评论因违规被删除,多次违规或情节严重系统将对您账号进行限制甚至封号,请遵守谨记,谢谢配合", + "radio_message": "电台消息", + "no_message": "暂时没有此类消息", + "dating_news": "/s1在/s2发布了一条约会消息,点击查看", + "go_see": "去看看", + "thumbs_up": "/s1赞了你的动态", + "thumbs_up2": "/s1赞了你的约会节目", + "comment1": "/s1评论了你的动态", + "comment2": "/s1评论了你的约会节目", + "replied_comment": "/s1回复了你的评论", + "signed_up": "/s1报名了你的约会节目", + "favorite_user": "你喜欢的用户/s1发布了一条约会,点击查看", + "favorite_user2": "你喜欢的用户/s1发布了一条动态,点击查看", + "wallet_reminder": "钱包提醒", + "paid_you": "/s1付费了(/s2H币)查看了你的红包照片", + "paid_you2": "/s1付费了(/s2H币)查看了你的相册", + "paid_you3": "/s1付费解锁了你的全部资料", + "view_application": "查看申请", + "view_application2": "/s1请求查看你的详情页", + "aging": "允许(有效期15天)", + "refuse": "拒绝", + "passed_request": "已通过请求", + "l15_days": "/s1已通过你的查看申请,有效期15天", + "evaluation_notice": "评价通知", + "rate_her": "已经约出/s1了吗?赶快评价一下她吧", + "received_evaluation": "联系过你的女士用户(匿名)对你进行了评价:/s1", + "received_evaluation2": "联系过你的男士用户(匿名)对你进行了评价:/s1", + "application_appeal": "如果评价不属实,你可申请上述,我们会进行核实", + "appeal": "我要上诉", + "appealed": "已申请上诉", + "waiting_results": "我们会尽快核实情况,并通过站内信告诉你处理结果", + "successful_appeal": "你上诉的评价:/s1上诉成功,我们将为你撤销此评价。", + "social_account": "社交账号", + "get_account": "/s1向你发送了他的社交账号", + "edit_information": "编辑资料", + "save": "保存", + "passed_verification1": "你通过了身份安全核实", + "by_code": "你通过资深用户/s1的邀请码加入", + "by_paying": "你通过付费加入", + "passed_verification": "你已通过视频认证身份真实性", + "not_certified": "你还没有认证身份真实性", + "verificating": "我们正在认证你的真实性", + "real_girl": "经过认证的女生更受欢迎哦", + "certificating": "认证中", + "re_upload2": "待重新上传视频", + "update_certification": "更新认证", + "enjoy_privileges": "升级会员尊享特权", + "expires": "/s1到期", + "wallet": "钱包", + "setting": "隐私", + "my_dynamic": "我的动态", + "my_album": "我的相册", + "first_photo": "上传我的第一张照片", + "no_photo": "有照片才能吸引男士哦", + "upload_photos": "上传照片", + "upload_video": "上传视频", + "upload": "上传照片", + "set_photo": "设置红包照片", + "photo_order": "长按拖动可对照片排序", + "my_evaluation": "我的评价", + "my_show": "我的节目", + "i_like": "我喜欢的", + "your_favorite": "你喜欢的女士会显示这里", + "your_favorite2": "你喜欢的男士会显示这里", + "no_data": "没有数据", + "historical_visitor": "历史访客", + "visit_you": "有/s1个人看过你", + "visit_photo": "已有/s1个人焚毁了你的照片", + "recovery_photo": "一键恢复", + "setting2": "设置", + "apply_code": "帮朋友申请邀请码", + "issue_choose": "申请邀请码是免费的,我们会根据你的历史消费来评估是否发放邀请码。为维持公园的氛围,请一定把邀请码赠与靠谱的朋友", + "successfully_submit": "成功递交申请", + "share_app": "分享APP给朋友", + "need_help": "有问题需要帮助", + "need_help2": "联系客服", + "need_help3": "为了提高服务效率,如果下面有您的问题,请直接回复序号数字哦!", + "question1": "【1】账号被冻结是什么原因?", + "answer1": "出现下述任意一种情况,账号都会被冻结:①骗子②中介③骚扰广告④多人举报⑤已有其他账号⑥多次发布违规电台广播无视警告⑦用户自己要求注销", + "question2": "【2】钱包现金什么时候才能提现?", + "answer2": "所有收益会直接进入到钱包,提现需要三天(按收取时间计算开始),三天后收取的金额将会进入到钱包,金额>=10元即可提现", + "question3": "【3】我发出的红包怎么没有显示?", + "answer3": "可能是网络原因导致。放心,这种情况对方无法领取你的红包,红包将在24小时后自动退还到你的支付渠道", + "question4": "【4】提现需要多久到账?", + "answer4": "提交提现申请后两个工作日内到账。温馨提示:提现时请确认账号无误!", + "question5": "【5】如何匿名举报其他用户/电台广播内容?", + "answer5": "进入对方详情页或选择某条电台广播,点击右上角选择【匿名举报】,请填写相关举报信息即可对其发起举报。", + "question6": "【6】如何成为认证用户?", + "answer6": "认证通过需满足以下要求:①个人资料填写有效社交账号②相册至少上传一张本人清晰的正脸照③在认证页面查看验证码,在纸上写上昵称+验证码④拿着这张纸,与你的正脸合拍一段视频,点击上传认证视频", + "question7": "【7】认证的视频可以不公开吗?", + "answer7": "可以在设置里选择是否公开:用户中心-点击认证视频-左下角'将认证视频显示在我的详情页'", + "question8": "【8】如何避免认证被取消?", + "answer8": "相册至少有一张被标记为本人的照片", + "question9": "【9】电台广播被删除是什么原因?", + "answer9": "电台广播不能发布敏感图,敏感词,包括但不限于暗示或明示性词语,不能发布个人信息(包括头像,昵称,联系方式),违规电台广播将被删除", + "question10": "【10】如何注销账号?", + "answer10": "注销账号将无法登录APP,以后再想使用服务则需要重新注册,请谨慎考虑。如果你仍然决定注销账号,请回复序号【12】联系客服", + "question11": "【11】忘记密码怎么办?", + "answer11": "通过手机号码注册或者绑定手机号码的用户,可以通过登录页面右上角的“忘记密码”功能重置密码。未绑定用户请先绑定手机号,再设置新的登录密码", + "question12": "【12】其他问题/转接人工客服", + "answer12": "你好,请问有什么问题可以帮你?请描述你的问题(客服上班时间为每天8:00-次日02:00,由于咨询人数较多,你可能需要等待回复)", + "certification_center": "认证中心", + "for_example2": "认证视频拍摄方式示例", + "certification_conditions": "认证条件", + "conditions1": "1.个人形象良好", + "conditions2": "2.相册中至少上传一张本人照片", + "verification_method": "认证方式", + "method3": "1.取一张纸,写上你的昵称和以下验证码:", + "method4": "2.拿着这张纸,与你的正脸合拍一段视频(3~15秒)", + "upload_video2": "上传认证视频", + "after_authentication": "认证成功后,你的头像会带有real标志", + "show_video": "将认证视频显示在我的详情页", + "uploaded_video": "已上传的认证视频", + "under_review": "审核中(24小时内)", + "certification_status": "认证状态", + "certified": "你已通过认证", + "wait_resubmitted": "认证待重提", + "reason_failure": "您的认证视频不符合要求,原因是:", + "claim": "请根据认证要求拍摄认证视频", + "claim2": "请在相册上传清晰展示五官的正脸本人照片", + "re_upload_video": "重新上传认证视频", + "update_video": "更新上传认证视频", + "mask_coin": "H币", + "get_way": "你可以通过充值或者开麦等途径获得H币。", + "coin_use": "H币可用于使用连麦服务,并且在连麦时进行打赏。", + "coin_total": "H币总额", + "can_redeemed": "可兑消", + "who_account": "/s1账号", + "bind_account": "绑定/s1账号", + "your_account": "你的/s1账号", + "get_coin2": "你通过充值获得了/s1H币", + "viewed_your": "/s1查看了你的社交账号", + "give_gift": "/s1赠送了礼物:1个/s2", + "add_coin": "+/s1H币", + "give_one": "你赠送了1个/s1给/s2", + "less_coin": "-/s1H币", + "exchange_cash": "提现", + "withdrawal_application": "提现申请", + "redeem_choose": "你有/s1枚H币可兑换成/s2,兑换后剩余/s3枚H币。确定申请兑换吗?", + "application_submitted": "提现申请已提交", + "working_days": "我们将在2个工作日内处理,有疑问可咨询客服", + "cash": "现金", + "handling_fee": "每当你再聊天页面收到红包,红包金额都会进入这里。金额进账后3天内没人举报你即可提现,提现将收取5%手续费", + "total_account": "账户总额", + "cannot_redeemed": "金额不足,无法兑消", + "successful_redemption": "兑消成功", + "redeem_choose2": "你的账户总额为/s1元,本次可提现/s2元,确定申请提现吗?", + "personal_details": "个人详情", + "public": "公开(推荐)", + "paid_album": "相册付费查看", + "must_pay": "他人必须付费才能查看你的相册,费用由你定,这可能会降低你的访问量", + "set_amount1": "设置查看金额", + "first_upload": "请先上传照片,再设置付费相册", + "need_permission": "查看前需通过我验证", + "permission_choose": "他人必须发照片让你验证身份后才能浏览你的主页,确定吗?", + "hide_me": "在附近的人列表隐藏我", + "hide_distance": "对他人隐藏我的距离", + "hide_account": "对他人隐藏我的社交账号", + "chat_setting": "连麦控制", + "chat_me": "允许有私聊权限的人对我发起连麦", + "successfully_saved": "保存成功", + "on_dynamic": "你还没有发布过动态", + "release_dynamics": "发布动态", + "dynamic_details": "动态详情", + "release": "发布", + "i_posted": "我发布的", + "delete_dynamic": "删除动态", + "delete_choose": "确定要删除这条动态吗?", + "posted_on": "发布于/s1", + "thumbs_up3": "赞", + "already_praised": "已经赞过了", + "comment": "评论", + "send": "发送", + "comment_closed": "评论已关闭", + "your_comment": "只有发布者能看见你的评论", + "everyone_comment": "大家都能看见你的评论", + "prohibit_comments": "禁止评论", + "comments_disabled": "已禁止评论", + "open_comments": "开放评论", + "already_open": "已开放评论", + "reply": "回复", + "report": "举报", + "report_choose": "确定举报这条评论吗?", + "successful_report": "举报成功,我们会尽快处理", + "successfully_deleted": "删除成功", + "please_civilization": "谈吐文明的人更受欢迎,请勿发布低俗、色情交易、或曝光他人隐私的内容", + "same_sex": "对同性别用户隐藏", + "member_free": "会员免费,非会员需/s1H币", + "certified_free": "已认证女士免费3次,之后需要支付/s1H币", + "enter_something": "请输入文字内容或选择图片", + "raid_release": "付费发布(/s1H币)", + "become_member2": "成为会员,免费发布", + "now_certification": "马上认证,免费发布", + "successfully_released": "发布成功", + "no_program": "你还没有发布过节目", + "program_details": "节目详情", + "program_theme": "节目主题", + "click_select": "点击选择", + "city": "城市", + "select_city": "选择城市", + "time": "时间", + "select_date": "选择日期", + "select_time": "选择时间", + "unlimited_time": "不限时间", + "supplementary_explanation": "补充说明", + "image": "配图", + "delete_program": "删除节目", + "delete_choose2": "确定要删除这条节目吗?", + "please_choose": "请选择节目主题", + "please_choose2": "请选择期望对象", + "please_choose3": "请选择城市", + "please_choose4": "请选择日期", + "please_choose5": "请选择时间", + "release_program": "发布节目", + "sign_up": "报名", + "end_registration": "结束报名", + "end_choose": "确定结束约会吗?", + "contact_her": "联系她", + "talk_him": "私聊他", + "report_choose2": "确定举报这条报名信息吗?", + "release_time": "发布时间", + "activity_time": "活动时间", + "any_sex": "不限性别", + "look_women": "只看女士", + "look_men": "只看男士", + "unlimited_area": "不限地区", + "program_deleted": "该节目已删除", + "cant_comment": "非会员不能评论", + "sign_up2": "我要报名", + "need_photo2": "报名需要发送你的正脸照片(只有对方能看到)", + "registration_success": "报名成功,如果对方觉得合适将会联系你", + "has_ended": "已结束", + "men_cant": "男士不能报名男士的节目", + "ms_cant": "女士不能报名女士的节目", + "men_cant2": "男士不能评论男士的节目", + "ms_cant2": "女士不能评论女士的节目", + "message_push": "消息推送、修改密码", + "phone_number": "手机号码", + "bind_phone1": "绑定手机号", + "more_safer": "绑定手机号,让你的账户更安全", + "modify_choose": "你想修改绑定的手机号码吗?", + "change_password": "修改密码", + "first_bind": "用户需要先绑定手机号码才可以设置登录密码", + "old_password": "原密码", + "current_password": "请输入当前登录密码", + "new_password": "新密码", + "set_new": "请设置新密码,不少于6位", + "clear_cache": "清除图片缓存", + "cleared_successfully": "清除成功", + "user_agreement1": "用户使用协议", + "sign_out": "退出登录", + "out_choose": "确定退出账号么?", + "push_settings": "推送设置", + "permission_denied": "权限已被拒绝", + "push_setting2": "消息推送设置", + "private_chat2": "私聊消息", + "new_date": "有新的约会", + "passed_request2": "有女士通过了我的查看请求", + "men_view": "有男士申请查看我的资料页", + "men_view2": "有男士查看我的社交账号", + "men_view3": "有男士查看我的红包照片", + "men_view4": "有已查看资料的男士给我发送社交账号", + "applied_successfully": "邀请码申请成功", + "after_open": "打开后将推送相应消息类型", + "if_something": "如果你在最近3天曾向她/他支付过费用,我们核实举报后,系统将自动向你退回消费金额", + "advertise": "发广告", + "false_photo": "虚假照片", + "erotic_vulgarity": "色情低俗", + "harassment": "骚扰谩骂", + "she_liar": "她是骗子", + "he_liar": "他是骗子", + "provide_screenshots": "请提供相关截图,以便我们跟进核实", + "describe_details": "请描述详情(100字内)", + "report_reason": "请选择举报原因", + "report_success2": "举报成功", + "successfully_modified": "修改成功", + "boy": "男生", + "girl": "女生", + "already_applied": "已申请", + "view_registration": "查看报名", + "expand": "展开", + "collapse": "收起", + "application_notice": "申请通知", + "agrees_application": "有用户同意你的申请", + "red_photo": "红包照片", + "dont": "请勿上传非法裸露低俗的照片/视频,严重者将封号", + "current_version": "当前版本", + "bank_card": "绑定银行卡", + "choose_bank": "请选择开户行", + "bank_number": "请输入银行卡号", + "id_number": "请输入证件号", + "name": "姓名", + "bank_number2": "银行卡号", + "license_number": "证件号", + "bind_phone": "绑定手机号", + "his_homepage": "他的主页", + "her_homepage": "她的主页", + "wechat_pay": "微信支付", + "facebook_pay": "facebook支付", + "google_pay": "google支付", + "payment_successful": "支付成功", + "set_amount": "设置提款金额", + "enter_amount": "请输入H币个数", + "can_withdraw": "可提现", + "language_set": "语言设置", + "user_agreement": "用户协议", + "renewal_fee": "续费", + "open_immediately": "立即开通", + "total": "总计", + "half_month": "半个月", + "month2": "/s1个月", + "cancel_shield": "取消屏蔽", + "blacklist2": "黑名单", + "longTime": "(会员可延长时间达6秒)", + "longClick": "按住屏幕查看", + "stop_program": "请先结束正在生效的节目", + "not_love": "男士不能收藏男士", + "not_love2": "女士不能收藏女士", + "women_free": "女神可以免费发布", + "not_up_man": "他还没有上传照片", + "not_up_women": "她还没有上传照片", + "not_illage": "请勿通过平台进行不法交易,如被举报核实将作封号处理", + "alreay_join": "已报名", + "sure_delete": "确定删除这张照片吗", + "white_now": "马上填写", + "personal": "你还没有填写个人介绍,吸引人的个人介绍对约会成功影响很大哦", + "success": "成功", + "fail": "失败", + "moneyPageTip": "只有认证用户才可以设置红包照片", + "alreadyJoin": "你已报名,如果对方觉得合适将会联系你", + "waring": "违规警告", + "userPravicy": "尊重用户隐私,请勿截图。如有下次,将禁止你查看其他用户照片", + "outTime": "约会时间已经过期了,请修改", + "reviewing": "审核中", + "reviewed": "审核成功", + "reviewedFail": "审核失败", + "needCard": "用户需要先绑定银行卡才可以提现", + "women_not_d": "女士不能评论女士的动态", + "man_not_d": "男士不能评论男士的动态", + "have_picture": "有照片才能吸引女士哦", + "up_cancle": "上滑取消发送", + "msg_not": "消息不能为空", + "need_record": "此功能需要授予录音权限", + "downloading_video": "正在下载视频文件", + "reinput": "请重新输入问题序号", + "dy_delete": "你的动态被用户匿名举报,经系统核实已将该动态删除,请勿再进行违规操作", + "pro_delete": "你的节目被用户匿名举报,经系统核实已将该节目删除,请勿再进行违规操作", + "con_delete": "你的评论被用户匿名举报,经系统核实已将该评论删除,请勿再进行违规操作", + "coin_returen": "经匿名用户举报,系统核实你近期存在违规行为,已将你近期收到H币进行返还。如有下次,将进行账号冻结", + "voicing": "通话中禁止出现色情淫秽等违法行为,一经发现将做封号处理", + "help": "客服", + "translate_on": "人工翻译开启", + "translate_off": "人工翻译关闭", + "becomeSvip": "消耗/s1 H币将续费为SVIP", + "need_svip": "svip权限可开启", + "cannot_vip": "SVIP无法续费为VIP", + "offline": "您已离线,无法发送和接收消息", + "otherLogin": "账号在其他设备登录,您已离线", + "no_new": "暂时没有新消息", + "over": "翻译完毕", + "bad_ev": "确定要对此条翻译进行差评么?", + "right5": "聊的更爽", + "right6": "用的更爽", + "man_vi": "小哥哥", + "women_vi": "小姐姐", + "kf_tips": "为了提高服务效率,如果下面有您的问题,请直接回复序号数字哦!", + "rejected": "已拒绝", + "buy_vip": "你消费了/s1H币购买会员", + "buy_program": "你消费了/s1H币发布动态节目", + "del_add_money": "你的H币提现申请已处理,已转账/s1到你的银行卡账号,请查收", + "adding_money": "你申请提现的/s1H币正在审批中", + "free_translate": "免费享受翻译专员实时翻译", + "personalTraff": "专享客服为你服务", + "ManTranslate": "人工翻译中...", + "robotTranslate": "机器翻译中...", + "translated": "人工翻译完毕", + "delete_progarm": "健康交流,请勿广播低俗内容,一经发现将作删除处理", + "open_location": "定位权限未开启", + "get_location": "请在手机设置中开启定位权限以获得其他用户距离", + "confirm_exit": "再按一次退出", + "free_program": "每天/s1次机会发布免费广播", + "picture": "图片", + "camera": "相机", + "video": "视频", + "red_money": "红包", + "stick": "粘贴", + "press_say": "按住说话", + "get_money": "/s1领取了你的红包", + "you_get_money": "你领取了/s1的红包", + "ones_money": "/s1的红包", + "money_over": "红包已过期", + "downloading_fail": "下载文件失败", + "downloading": "正在下载视频文件", + "back_money": "未领取的红包,将于24小时后发起退款", + "no_money": "红包不存在", + "already_money": "红包已领取", + "back_user": "已过期,已退到账户", + "waiting_user": "等待对方领取", + "other_get": "对方已领取", + "little": "小小意思,拿去浪吧", + "put_money": "塞钱进红包", + "mount": "金额", + "over_time": "已过期", + "has_get": "已领取", + "no_gift": "暂时没有礼物", + "sent_gift": "打赏礼物", + "fill_tips": "填写成功可以获得/s1H币,绑定后无法修改", + "bind_code": "绑定邀请码", + "invide_code": "邀请码", + "confirm_delete": "确认删除", + "has_eva": "您已经评价过了", + "open": "开", + "voice": "语音", + "release_send": "松开发送", + "time_little": "录音时间过短", + "not_online": "对方不在线,无法连麦", + "give_red_money": "你给/s1发送了/s2H币的红包", + "get_red_money": "你领取了/s1的/s2H币的红包", + "give_other_money": "你打赏了/s1/s2H币", + "get_other_money": "你获得了/s1的/s2H币的打赏", + "svip": "超级会员", + "recommend": "推荐", + "paid_you4": "你付费了(/s2H币)查看/s1的红包照片", + "paid_you5": "你付费了(/s2H币)查看/s1的相册", + "paid_you6": "你付费解锁了/s1的全部资料", + "UG_LINE0": "hiAPP许可及服务协议", + "UG_LINE1": "[首部及导言]", + "UG_LINE2": "前海游龙科技有限公司(以下简称“Qianhai Youlong Technology Co., Ltd.”)在此特别提醒用户认真阅读、充分理解本《服务协议》(下称 《协议》)一用户 应认真阅读、充分理解本《协议》中各条款,包括免除或者限制Qianhai Youlong Technology Co., Ltd.责任的免责条款及对用户的权利限制条款。请您审慎阅读并选择接受或不接受本《协议》(未成年人应在法定监护人陪同下阅读)。除非您接受本《协议》所有条款,否则您无权注册、登录或使用本协议所涉相关服务。您的注册、登录、使用等行为将视为对本《协议》的接受,并同意接受本《协议》各项条款的约束。", + "UG_LINE3": "本《协议》是您(下称“用户”与Qianhai Youlong Technology Co., Ltd.之间关于用户注册、登录、使用“hi服务所订立的协议。本《协议》描述Qianhai Youlong Technology Co., Ltd.与用户之间关于“hi服务相关方面的权利义务。“用户”是指注册、登录、使用、浏览本服务的个人或组织。您对本协议的接受即受全部条款的约束,包括接受Qianhai Youlong Technology Co., Ltd.对任意服务条款随时所做的任何修改。本《协议》可由Qianhai Youlong Technology Co., Ltd.随时更新,更新后的协议条款一旦公布即代替原来的协议条款,恕不再另行通知,用户可在本APP查阅最新版协议条款。在Qianhai Youlong Technology Co., Ltd.修改《协议》条款后,如果用户不接受修改后的条款,请立即停止使用Qianhai Youlong Technology Co., Ltd.提供的服务,用户继续使用Qianhai Youlong Technology Co., Ltd.提供的服务将被视为已接受了修改后的协议。", + "UG_LINE4": "一、使用规则", + "UG_LINE5": "1、用户充分了解并同意,仅为用户提供信息分享、传送及获取的平台,用户必须为自己注册帐号下的一切行为负责,包括但不限于您所传送的任何内容以及由此产生的任何结果。", + "UG_LINE6": "2、用户在服务中或通过服务所传送的任何内容并不反映Qianhai Youlong Technology Co., Ltd.的观点或政策,Qianhai Youlong Technology Co., Ltd.对此不承担任何责任。", + "UG_LINE7": "3、用户充分了解并同意,是一个基于用户关系网的社交信息浏览产品,用户须对在上的注册信息的真实性、合法性、有效性承担全部责任,用户不得冒充他人;不得利用他人的名义传播任何信息;不得恶意使用注册帐号导致其他用户误认;否则Qianhai Youlong Technology Co., Ltd.有权立即停止提供服务,收回帐号并由用户独自承担由此而产生的一切法律责任。", + "UG_LINE8": "4、用户须对在上所传送信息的真实性、合法性、无害性、有效性等全权负责,与用户所传播的信息相关的任何法律责任由用户自行承担,与Qianhai Youlong Technology Co., Ltd.无关。", + "UG_LINE9": "5、Qianhai Youlong Technology Co., Ltd.保留因业务发展需要,单方面对本服务的全部或部分服务内容在任何时候不经任何通知的情况下变更、暂停、限制、终止或撤销服务的权利,用户需承担此风险。", + "UG_LINE10": "6、提供的服务中可能包括广告,用户同意在使用过程中显示和第三方供应商、合作伙伴提供的广告。", + "UG_LINE11": "7、用户不得利用或服务制作、上载、复制、发送如下内容:", + "UG_LINE12": "(1 )反对宪法所确定的基本原则的;", + "UG_LINE13": "(2)危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家统一-的;", + "UG_LINE14": "(3)损害国家荣誉和利益的;", + "UG_LINE15": "(4)煽动民族仇恨、民族歧视,破坏民族团结的;", + "UG_LINE16": "(5)破坏国家宗教政策,宣扬邪教和封建迷信的;", + "UG_LINE17": "(6)散布谣言,扰乱社会秩序,破坏社会稳定的;", + "UG_LINE18": "(7)散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;", + "UG_LINE19": "(8)侮辱或者诽谤他人,侵害他人合法权益的;", + "UG_LINE20": "(9)含有法律、行政法规禁止的其他内容的信息。", + "UG_LINE21": "8、Qianhai Youlong Technology Co., Ltd.可依其合理判断,对违反有关法律法规或本协议约定;或侵犯、妨害、威胁任何人权利或安全的内容,或者假冒他人的行为,Qianhai Youlong Technology Co., Ltd.有权依法停止传输任何前述内容,并有权依其自行判断对违反本条款的任何人士采取适当的法律行动,包括但不限于从服务中删除具有违法性、侵权性、不当性等内容,终止违反者的成员资格,阻止其使用全部或部分服务,并且依据法律法规保存有关信息并向有关部门报告等。", + "UG_LINE22": "9、用户权利及义务:", + "UG_LINE23": "(1 )Qianhai Youlong Technology Co., Ltd.帐号的所有权归Qianhai Youlong Technology Co., Ltd.所有,用户完成申请注册手续后,获得帐号的使用权,该使用权属于初始申请注册人,禁止赠与、借用、租用、转让或售卖。Qianhai Youlong Technology Co., Ltd.因经营需要,有权回收用户的帐号,并有权使用用户照片、视频、语音等进行产品宣传活动。", + "UG_LINE24": "(2)用户有权更改、删除在Qianhai Youlong Technology Co., Ltd..上的个人资料、注册信息及传送内容等,但需注意,删除有关信息的同时也会删除任何您储存在系统中的文字和图片。用户需承担该风险。", + "UG_LINE25": "(3)用户有责任妥善保管注册帐号信息及帐号密码的安全,用户需要对注册帐号以及密码下的行为承担法律责任。用户同意在任何情况下不使用其他成员的帐号或密码。在您怀疑他人在使用您的帐号或密码时,您同意立即通知Qianhai Youlong Technology Co., Ltd.。", + "UG_LINE26": "(4)用户应遵守本协议的各项条款,正确、适当地使用本服务,如因用户违反本协议中的任何条款,Qianhai Youlong Technology Co., Ltd.有权依据协议终止对违约用户Qianhai Youlong Technology Co., Ltd.帐号提供服务。同时,Qianhai Youlong Technology Co., Ltd.保留在任何时候收回Qianhai Youlong Technology Co., Ltd.帐号、用户名的权利。", + "UG_LINE27": "(5)如果用户有自己的常用英文帐号,那么用户有优先将该英文帐号注册为帐号的权利,但是如果用户在服务上线后一段时间内没有注册帐号,或者用户虽然注册了微信帐号,但是并不是使用该英文帐号作为微信帐号的,视为用户放弃了将该英文帐号注册为微信帐号的权利,Qianhai Youlong Technology Co., Ltd.有权将该英文帐号回收并分配给其他用户使用,以免造成资源浪费,由此带来问题均由用户自行承担。", + "UG_LINE28": "(6)用户注册帐号后如果长期不登录该帐号,Qianhai Youlong Technology Co., Ltd.有权回收该帐号,以免造成资源浪费,由此带来问题均由用户自行承担。", + "UG_LINE29": "(7)用户发生纠纷可使用举报功能维护用户平台权益,若收到用户举报反馈,被举报用户有义务主动告知或配合客服人员核实情况,举报内容核实属实,面具公园有权对用户警告、限制账号使用功能等方式约束用户违规行为,严重违规者hi有权直接冻结账号,且账户内余额不返还。如果账号被冻结需申诉,用户可联系客服 。", + "UG_LINE30": "二、隐私保护", + "UG_LINE31": "用户同意个人隐私信息是指那些能够对用户进行个人辨识或涉及个人通信的信息,包括下列信息:用户真实姓名,手机号码,微信账号,facebook账号,IP地址。而非个人隐私信息是指用户对本服务的操作状态以及使用习惯等一些明确且客观反映在Qianhai Youlong Technology Co., Ltd.服务器端的基本记录信息和其他一切个人隐私信息范围外的普通信息;以及用户同意公开的上述隐私信息。尊重用户个人隐私信息的私有性是Qianhai Youlong Technology Co., Ltd.的一贯制度,Qianhai Youlong Technology Co., Ltd.将会采取合理的措施保护用户的个人隐私信息,除法律或有法律赋予权限的政府部门要求或用户同意等原因外,Qianhai Youlong Technology Co., Ltd.未经用户同意不向除合作单位以外的第三方公开、透露用户个人隐私信息。但是,用户在注册时选择同意,或用户与Qianhai Youlong Technology Co., Ltd.及合作单位之间就用户个人隐私信息公开或使用另有约定的除外,同时用户应自行承担因此可能产生的任何风险,Qianhai Youlong Technology Co., Ltd.对此不予负责。同时,为了运营和改善Qianhai Youlong Technology Co., Ltd.的技术和服务,Qianhai Youlong Technology Co., Ltd.将可能会自行收集使用或向第三方提供用户的非个人隐私信息,这将有助于Qianhai Youlong Technology Co., Ltd.向用户提供更好的用户体验和提高Qianhai Youlong Technology Co., Ltd.的服务质量。Qianhai Youlong Technology Co., Ltd.收集数据是根据用户与Qianhai Youlong Technology Co., Ltd.的互动和用户所做出的选择,包括用户的隐私设置以及用户使用的产品和功能。Qianhai Youlong Technology Co., Ltd.收集的数据可能包括SDK/API/JS代码版本、IP地址、平台、时间戳、应用标识符、应用程序版本、应用分发渠道、独立设备标识符、iOS广告标识符(IDFA)、 安卓广告主标识符、网卡(MAC) 地址、国际移动设备识别码(IMEI)、设备型号、终端制造厂商、终端设备操作系统版本、会话启动/停止时间、语言所在地、时区和网络状态(WiFi等)、 硬盘、 CPU和电池使用情况等。这将有助于Qianhai Youlong Technology Co., Ltd.开展内部数据分析和研究,第三方SDK统计服务,改善Qianhai Youlong Technology Co., Ltd.的产品或服务。为确保用户身份真实性,向用户提供更好的安全保障,用户需提交的身份信息或面部特征等生物识别信息(均属于个人敏感信息)来完成具体产品服务所需或必要的真人认证。.上 述信息将仅用于核实用户身份的真实性。用户提供的.上述信息,将在用户使用本服务期间持续授权Qianhai Youlong Technology Co., Ltd.使用。在用户注销账号时,Qianhai Youlong Technology Co., Ltd.将停止使用。上述信息将存储于中华人民共和国境内。如需跨境传输,Qianhai Youlong Technology Co., Ltd.将会单独征得用户的授权同意。App用户真实性认证需要用户提供能证实用户身份真实性的部分资料。相关资料只用做平台审核不会披露给任何其他用户或用于商业用途,仅法律或有关部门要求介入除外。", + "UG_LINE32": "三、Qianhai Youlong Technology Co., Ltd.商标信息", + "UG_LINE33": "Qianhai Youlong Technology Co., Ltd.服务中所涉及的logo等图形、文字或其组成,以及其他Qianhai Youlong Technology Co., Ltd.标志及产品、服务名称,均为Qianhai Youlong Technology Co., Ltd.之商标(以下简称“Qianhai Youlong Technology Co., Ltd.标识”)。未经Qianhai Youlong Technology Co., Ltd.事先书面同意,用户不得将Qianhai Youlong Technology Co., Ltd.标识以任何方式展示或使用或作其他处理,也不得向他人表明您有权展示、使用、或其他有权处理Qianhai Youlong Technology Co., Ltd.标识的行为。", + "UG_LINE34": "四、法律责任及免责", + "UG_LINE35": "1、用户违反本《协议》或相关的服务条款的规定,导致或产生的任何第三方主张的任何索赔、要求或损失,包括合理的律师费,用户同意赔偿Qianhai Youlong Technology Co., Ltd.与合作公司、关联公司,并使之免受损害。", + "UG_LINE36": "2、用户因第三方如电信部门的通讯线路故障、技术问题、网络、电脑故障、系统不稳定性及其他各种不可抗力原因而遭受的一切损失,Qianhai Youlong Technology Co., Ltd.及合作单位不承担责任。", + "UG_LINE37": "3、因技术故障等不可抗事件影响到服务的正常运行的,Qianhai Youlong Technology Co., Ltd.及合作单位承诺在第一时间内与相关单位配合,及时处理进行修复,但用户因此而遭受的一切损失,Qianhai Youlong Technology Co., Ltd.及合作单位不承担责任。", + "UG_LINE38": "4、本服务同大多数互联网服务一样,受包括但不限于用户原因、网络服务质量、社会环境等因素的差异影响,可能受到各种安全问题的侵扰,如他人利用用户的资料,造成现实生活中的骚扰;用户下载安装的其它软件或访问的其他网站中含有“特洛伊木马”等病毒,威胁到用户的计算机信息和数据的安全,继而影响本服务的正常使用等等。用户应加强信息安全及使用者资料的保护意识,要注意加强密码保护,以免遭致损失和骚扰。", + "UG_LINE39": "5、用户须明白,使用本服务因涉及Internet服务,可能会受到各个环节不稳定因素的影响。因此,本服务存在因不可抗力、计算机病毒或黑客攻击、系统不稳定、用户所在位置、用户关机以及其他任何技术、互联网络、通信线路原因等造成的服务中断或不能满足用户要求的风险。用户须承担以上风险,Qianhai Youlong Technology Co., Ltd.不作担保。对因此导致用户不能发送和接受阅读信息、或接发错信息,Qianhai Youlong Technology Co., Ltd.不承担任何责任。", + "UG_LINE40": "6、用户须明白,在使用本服务过程中存在有来自,任何他人的包括威胁性的、诽谤性的、令人反感的或非法的内容或行为或对他人权利的侵犯(包括知识产权)的匿名或冒名的信息的风险,用户须承担以上风险,Qianhai Youlong Technology Co., Ltd.和合作公司对本服务不作任何类型的担保,不论是明确的或隐含的,包括所有有关信息真实性、适商性、适于某一特定用途、所有权和非侵权性的默示担保和条件,对因此导致任何因用户不正当或非法使用服务产生的直接、间接、偶然、特殊及后续的损害,不承担任何责任。", + "UG_LINE41": "7、Qianhai Youlong Technology Co., Ltd.定义的信息内容包括:文字、软件、声音、相片、录像、图表;在广告中全部内容;Qianhai Youlong Technology Co., Ltd.为用户提供的商业信息,所有这些内容受版权、商标权、和其它知识产权和所有权法律的保护。所以,用户只能在Qianhai Youlong Technology Co., Ltd.和广告商授权下才能使用这些内容,而不能擅自复制、修改、编纂这.些内容、或创造与内容有关的衍生产品。", + "UG_LINE42": "8、在任何情况下,Qianhai Youlong Technology Co., Ltd.均不对任何间接性、后果性、惩罚性、偶然性、特殊性或刑罚性的损害,包括因用户使用服务而遭受的利润损失,承担责任(即使已被告知该等损失的可能性亦然)。 尽管本协议中可能含有相悖的规定,Qianhai Youlong Technology Co., Ltd.对您承担的全部责任,无论因何原因或何种行为方式,始终不超过您在成员期内因使用服务而支付给Qianhai Youlong Technology Co., Ltd.的费用。", + "UG_LINE43": "五、会员条款", + "UG_LINE44": "1、hi会员平等享有会员的权利,同时应遵守Qianhai Youlong Technology Co., Ltd.的各项规范、规则,包括但不限于本服务条款和《用户协议》。", + "UG_LINE45": "2、因违反Qianhai Youlong Technology Co., Ltd.《用户协议》而导致会员服务被暂停使用的相关损失,由用户自行承担。", + "UG_LINE46": "3、会员在会员资格有效期内可以享受hi会员的各项增值服务。", + "UG_LINE47": "4、如会员在会员资格有效期内主动终止或取消会员资格,Qianhai Youlong Technology Co., Ltd.不负责退还与该会员剩余会员资格有效期对应的服务费用。", + "UG_LINE48": "5、会员自行承担在hi中传送、发布信息及使用hi免费服务或收费服务的法律责任,会员使用hi服务,包括免费服务与收费服务的行为,均应遵守各项法律法规、规章、规范性文件。", + "UG_LINE49": "6、会员服务开通之后,不可进行转让或退订。", + "UG_LINE50": "7、因会员在使用Qianhai Youlong Technology Co., Ltd.免费服务或收费服务的过程中,存在违反法律法规的行为,Qianhai Youlong Technology Co., Ltd.有权取消该会员的会员资格而无须给予任何补偿,且该会员须自行承担全部责任。", + "UG_LINE51": "六、其他条款", + "UG_LINE52": "1、Qianhai Youlong Technology Co., Ltd.郑重提醒用户注意本《协议》中免除Qianhai Youlong Technology Co., Ltd.责任和加重用户义务的条款,请用户仔细阅读,自主考虑风险。未成年人应在法定监护人的陪同下阅读本《协议》。以上各项条款内容的最终解释权及修改权归Qianhai Youlong Technology Co., Ltd.所有。", + "UG_LINE53": "2、本《协议》所定的任何条款的部分或全部无效者,不影响其它条款的效力。", + "UG_LINE54": "3、本《协议》的解释、效力及纠纷的解决,适用于中华人民共和国法律。若用户和Qianhai Youlong Technology Co., Ltd.之间发生任何纠纷或争议,首先应友好协商解决,协商不成的,用户在此完全同意将纠纷或争议提交Qianhai Youlong Technology Co., Ltd.住所地的人民法院管辖。", + "UG_LINE55": "4、本《协议》的版权由Qianhai Youlong Technology Co., Ltd.所有,Qianhai Youlong Technology Co., Ltd.保留一切解释和修改权利。", + "UG_LINE56": "前海游龙科技有限公司", + "net_error": "网络异常", + "enter_name": "请输入姓名", + "translate": "译", + "locate": "位置", + "voice_tips": "按住录音,松开发送", + "unlock": "解锁", + "input_content": "请输入聊天内容", + "connecting": "连接中...", + "logining": "登陆中...", + "reject_reply": "/s1拒绝了你的查看申请", + "warning_text": "H币进账3天内没人举报你即可兑消(1:1000越南盾)", + "more_big": "输入个数不大于/s1", + "little_min": "输入个数不小于/s1", + "voice_msg": "/s1邀请你进行通话", + "send_gift": "你打赏了对方/s1个/s2", + "receive_gift": "对方打赏了你/s1个/s2", + "cannot_join": "非会员不能报名", + "alreay_back": "已退回", + "video_more_big": "文件过大", + "select_all": "选择所有", + "re_connect": "重新连接", + "voice_tips2": "松开发送,滑动取消", + "country": "国籍", + "have_picture_view": "有照片审核中", + "speaker_play": "扬声器播放", + "handset_playback": "听筒播放", + "play_model": "听筒模式", + "password_less": "密码过短", + "years_old": "岁", + "coin_returen1": "经匿名用户举报,系统核实你近期存在违规行为,请勿再进行违规操作。如有下次,将进行账号冻结", + "already_new": "已经是最新版本", + "test_it": "立即体验", + "found_new": "发现新版本", + "ad": "广告", + "attention": "关注", + "fans": "粉丝", + "apply_see": "/s1 申请查看我的资料页", + "agree_apply": "/s1 通过了我的查看请求", + "see_redBag": "/s1 查看了我的红包照片", + "notice": "提醒", + "notice_open": "请在手机设置中开启通知权限以获取消息通知", + "open_notice": "通知权限未开启", + "not_open": "未开启通知权限,无法接收通知", + "withdraw_fail": "你申请提现的的/s1H币已被退回,请确认绑定账户是否正确", + "dynamics": "动态", + "Remark": "备注", + "setRemark": "设置备注", + "content_num": "/s1条评论", + "Redeem": "积分兑换获得/s1H币", + "location_permission": "没有访问手机存储权限", + "camera_permission": "没有访问摄像头权限", + "photo_permission": "没有访问相册的权限", + "video_permission": "没有访问麦克风的权限", + "your_redMoney_over": "你发送的红包已过期", + "other_redMoney_over": "对方发送的红包已过期", + "server_error_tips": "貌似出了点问题...", + "emoji": "表情", + "today_score": "今日签到可领取/s1积分", + "sign_tips": "1、每日签到可领取积分,累计天数越多积分越高。\n2、积分可兑换H币,兑换将消耗对应积分,请慎重兑换。\n3、每月最后一天将重置签到,清零积分,请记得及时兑换。", + "sign_in": "签到", + "my_score": "我的积分", + "signin_now": "立即签到", + "sign_in_day": "已累积签到/s1天", + "have_get": "已兑换", + "scan": "扫一扫", + "my_qr": "我的二维码", + "scan_and_add": "扫一扫,加好友", + "amap": "高德地图", + "baidumap": "百度地图", + "googlemap": "谷歌地图", + "applemap": "苹果地图", + "go_open": "去开启", + "Preview": "预览", + "Photo_album": "相册", + "all_photo": "全部图片", + "have_select": "您已经选择了/s1张图片", + "loading": "加载中...", + "new_chat_msg": "您有新的聊天消息", + "new_video_msg": "您有新的连麦消息", + "apply_friends": "/s1申请成为你的好友", + "applyed_friends": "/s1通过了你的好友请求", + "contact_permission": "没有访问通讯录的权限", + "contact": "通讯录", + "search": "搜索", + "contact_add": "添加通讯录中的好友", + "find": "发现", + "translate_robot": "翻译机器人", + "robot_hello": "你好,我是翻译机器人...", + "Simplified_Chinese": "简体中文", + "traditional_Chinese": "繁体中文", + "english": "英语", + "Vietnamese": "越南语", + "Korean": "韩语", + "Japanese": "日语", + "add_friends": "添加好友", + "stranger": "陌生人", + "receive_stranger": "接收陌生人发送的消息", + "signin": "签到", + "stranger_close": "对方拒绝接收陌生人发送的消息,是否继续解锁全部资料。", + "add": "添加", + "added": "已添加", + "stranger_close_tips": "对方拒绝接收陌生人发送的消息。", + "translate_fail": "翻译失败", + "no_photos": "请先上传照片,再设置红包照片。", + "successful_appeal1": "你上诉的评价:/s1上诉失败。", + "add_success": "添加成功,等待对方同意", + "other_pay": "他人代付", + "friend_verification": "朋友验证", + "add_friends_tips": "你已发送验证申请,等对方通过", + "i_am": "我是/s1", + "agree": "允许", + "privacyAgreement": "\"Hibok\"需要您同意《隐私协议》方可使用", + "privacy": "隐私协议", + "notification_addfriend": "Hibok!有人申请添加你为好友,看看是谁吧", + "distance_long": "面对面才可以加好友哦", + "chat_tips": "为了翻译内容的准确性,请不要简写", + "fans_list": "粉丝列表", + "system_not_open": "功能内测中", + "service_withdraw_tips": "iOS客户端暂不支持提现,你可以使用安卓客户端提现,或点击下方按钮进行提现", + "withdraw_tips": "点击提现", + "add_member": "添加成员", + "delete_member": "删除成员", + "change_group_name": "修改群名称", + "my_group_nickname": "我在本群中的昵称", + "group_chat": "群聊", + "create_group_chat": "创建群聊", + "added_friends_tips": "你需要发送验证申请,等对方通过", + "group_chat_name": "群聊名称", + "my_group_nickname_tips": "在这里可以设置你在这个群里的昵称,这个昵称只会在此群内显示", + "man_gold": "男神动态", + "woman_gold": "女神动态", + "choose_group_owner": "选择新群主", + "group_announcement": "群公告", + "chat_news": "聊天消息", + "group_qr": "群二维码", + "group_setting": "群管理", + "close_news_notice": "消息免打扰", + "set_chat_top": "置顶聊天", + "show_group_member_name": "显示群成员昵称", + "quit_group_tips": "退出后不会通知群聊中其他成员,且不会再接收此群聊消息", + "quit_and_delete": "退出并删除", + "show_more_member": "查看更多群成员", + "group_invite": "群聊邀请确认", + "change_group_owner": "群主管理权转让", + "group_setting_tips": "启用后,群成员需群主确认才能邀请朋友进群。扫二维码进群将同时停用", + "invite_detail": "邀请详情", + "undefine_name": "未命名", + "group_qr_code": "群二维码名片", + "group_qr_code_tips": "该二维码7天内(/s1月/s2日前)有效,重新进入将更新", + "Goddess_heat": "女神热度", + "Goddess_heat_tips": "累计收获的礼物", + "new_friends": "新朋友", + "before_three_day": "三天前", + "after_three_day": "近三天", + "group_clean_chat_record": "清除聊天记录", + "check": "查看", + "apply_fro_friends": "请求添加你为好友", + "no_vip_cannot_withdraw": "非会员不能提现", + "not_true_woman": "该用户未认证,谨防被骗", + "join_group": "加入群聊", + "sign_in_apple": "通过Apple登录", + "only_host": "只有群主才能编辑群公告", + "send_gift1": "你打赏了对方/s1个礼物", + "receive_gift1": "对方打赏了你/s1个礼物", + "not_in_group": "你已不在该群", + "creating_group": "正在创建,请稍等", + "article": "条", + "group_open_verification": "该群已开启进群验证只能通过邀请进群", + "group_memeber": "群成员", + "invite_members": "邀请/s1位朋友加入群聊", + "total_members": "共/s1人", + "qr_outtime": "二维码已过期", + "no_goupr_info": "没有该群信息", + "you_invite": "你邀请/s1加入了群聊", + "invite_you": "你被/s1拉进了群聊", + "invite_someone": " /s1 邀请 /s2 加入了群聊", + "you": "你", + "delete_group": " /s1 将 /s2 移出了群聊", + "you_group_owner": "你已成为新群主", + "someone_group_owner": "/s1已成为新群主", + "change_group_owner1": "群名已更改为/s1", + "update_group_announce": "群公告已更新", + "you_qr": "你通过扫描二维码加入群聊", + "others_qr": "/s1通过扫描二维码加入群聊", + "invite_confirm": "\"/s1\" 想邀请/s2位朋友加入群聊 \\$去确认\\$ ", + "want_invite_confirm": " \"/s1\" 想邀请\"/s2\" 加入群聊 ", + "join_group_confirm": "\"/s1\" 加入群聊 已确认", + "you_invite_gourp": "你被 /s1 拉进了群聊 ", + "someone_join_group": " \"/s1\" 加入群聊 ", + "group_setting_tips1": "群主已开启\"群聊邀请确认\",群成员需群主确认才能邀请朋友进群", + "group_setting_tips2": "群主已恢复默认进群方式", + "members_max": "群成员已达上限", + "group_max": "群数量已达上限", + "my_money_info": "我的账单", + "my_left_money": "我的余额", + "money_tips": "H币可通过充值或兑换方式获得,无法进行提现", + "get_money_detail": "收入明细", + "hibok_money": "Hibox收入", + "charge_h": "兑换H币", + "charge_tips": "提款规则", + "splash_tips1": "百变定位", + "splash_tips2": "翻译机器人", + "splash_tips3": "交友APP", + "splash_tips_content1": "百变女神,选你所爱", + "splash_tips_content2": "语音互动一起聊", + "splash_tips_content3": "解决语言问题", + "splash_go": "立即体验", + "change_h_coin": "你通过收入兑换了/s1H币", + "Representation_succes": "您的申述成功,系统已退款", + "system_give": "系统赠送", + "exchange_fail": "您的提款申请失败,已退回", + "hibok_exchange": "通过Hibox收入兑换/s1H币", + "bind_code_success": "成功绑定代理优惠码", + "translate_money": "您消耗了/s1H币进行人工翻译", + "system_back": "系统取消退回", + "you_give": "你打赏了对方", + "you_get": "对方打赏了你", + "enter_num_qian": "兑换数量(单位K)", + "enter_num_qian1": "提现数量(单位K)", + "daily_translate_voucher": "翻译券", + "msg_notice": "通知消息", + "select_notice_people":"选择提醒的人", + "search_phone":"查找手机号", + "not_have_user":"用户不存在", + "not_add_Myself":"你不能添加自己", + "you_are_blaklisted":"对方已拉黑了你", + "confrim_recovery":"确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)", + "send_to": "发送到" +} \ No newline at end of file diff --git a/i18n/zh-HK.json b/i18n/zh-HK.json new file mode 100644 index 0000000..c1e6be8 --- /dev/null +++ b/i18n/zh-HK.json @@ -0,0 +1,1164 @@ +{ + "appName": "Hi公園", + "login": "登錄", + "registration": "注册", + "other_login": "其他登錄", + "account": "賬號", + "enter_username": "請輸入賬號", + "password": "密碼", + "enter_password": "輸入密碼", + "forget_password": "忘記密碼", + "reset_password": "重置密碼", + "number_registration": "手機號註冊", + "enter_number": "請輸入手機號", + "code": "驗證碼", + "enter_code": "請輸入收到的驗證碼", + "send_code": "發送驗證碼", + "send_again": "重新發送", + "set_password": "設置密碼", + "password_limit": "密碼不少於6位", + "set_password2": "請設置登錄密碼", + "next_step": "下一步", + "agreed_agreement": "點擊進入表示你已閱讀並同意《用戶協議》", + "enter_password2": "請輸入登錄密碼", + "reset_now": "立即重置", + "choose_gender": "選擇性別", + "who": "你是...", + "determine": "確定", + "cannot_modified": "選擇性別後無法修改", + "tip": "提示", + "choose_quit": "你即將完成註冊,是否現在退出?", + "confirm": "確認", + "use": "使用", + "cancel": "取消", + "close": "關閉", + "delete": "刪除", + "forget_it": "算了", + "ok": "好的", + "choose_quit2": "註冊後將不能修改性別,確定麼?", + "tip_content": "提示:你不能和同性別用戶進行交流", + "welcome": "歡迎", + "enter_incode": "請填寫邀請碼", + "must_incode": "Hi僅向擁有邀請碼的男士提供服務", + "your_incode": "你的邀請碼", + "how_get": "沒有邀請碼?你可以通過以下方式獲取", + "method1": "方式1", + "free": "免費申請", + "apply_now": "馬上申請", + "check_incode": "查收邀請碼", + "so_get": "你需要填寫一些個人信息,審核通過後回給你發送邀請碼", + "apply_incode": "申請邀請碼", + "location": "所在地", + "cityname": "你所在的城市名稱", + "message_channel": "信息渠道", + "how_know": "你從哪裡知道APP", + "wechat_number": "微信號", + "your_wechat": "你的微信號", + "facebook": "facebook", + "your_facebook": "你的臉書", + "submit_application": "提交申請", + "enter_city": "請輸入所在城市", + "so_know": "請告訴我們你獲取APP的信息渠道", + "your_social": "請告訴我們你的社交賬號", + "receive_incode": "我們將盡快處理你的申請。如果通過審核,你會在消息中心收到我們發放的邀請碼", + "wait_incode": "邀請碼還未發放,申請後請耐心等待!", + "successful_application1": "邀請碼申請成功!", + "application_failed1": "邀請碼申請失敗!", + "successful_copy": "複製成功", + "method2": "方式2", + "joinvip": "加入會員", + "join_now": "立即加入", + "joined": "已加入", + "join_odds": "加入會員可享受各種特權,包括無需邀請碼註冊", + "not_joinvip": "你還沒有加入會員", + "join_after": "加入會員後,即可不需要邀請碼完成註冊", + "incode_passed": "邀請碼驗證通過", + "welcome_join": "歡迎加入!請勿把你的賬號洩露給他人,一經發現登錄異常,賬戶會被自動凍結。", + "member_centre": "會員中心", + "members_privilege": "會員特權", + "see_more": "看的更多", + "unlimited_see": "每天不限次數查看用戶", + "see_cheaper": "看的更省", + "free10": "每天/s1次免費機會查看付費相冊或者社交賬號", + "see_longer": "看的更久", + "towto6": "查看閱後即焚照片的時間從2秒提升到/s1秒", + "see_better": "看的更爽", + "free_release": "免費發布約會廣播", + "choose_price": "選擇套餐", + "pay_method": "支付方式", + "pay_amount": "支付金額", + "not_enough": "錢包餘額不足", + "confirm_pay": "確認支付", + "complete_material": "完善資料", + "basic_information": "基本資料", + "upload_avatar": "上傳頭像", + "choose": "請選擇", + "fill_out": "請填寫", + "choose_multiple": "可以多選", + "optional": "選填", + "least": "最少填寫/s1個", + "introduce_yourself": "介紹一下自己", + "most": "最多選擇/s1個", + "nickname": "暱稱", + "only1_8": "暱稱只能1-20個字符", + "Resident_city": "當前城市", + "Please_select_a_resident_city": "請選擇當前城市", + "City1": "芹苴", + "City2": "峴港", + "City3": "海防", + "City4": "河內", + "City5": "胡志明", + "City6": "安江", + "City7": "北江", + "City8": "北件", + "City9": "薄遼", + "City10": "北寧", + "City11": "巴地頭頓", + "City12": "檳椥", + "City13": "平定", + "City14": "平陽", + "City15": "平福", + "City16": "平順", + "City17": "金甌", + "City18": "高平", + "City19": "得樂", + "City20": "得農", + "City21": "奠邊", + "City22": "同奈", + "City23": "同塔", + "City24": "嘉萊", + "City25": "河江", + "City26": "海陽", + "City27": "河南", + "City28": "河靜", + "City29": "和平", + "City30": "後江", + "City31": "興安", + "City32": "慶和", + "City33": "堅江", + "City34": "昆嵩", + "City35": "萊州", + "City36": "林同", + "City37": "諒山", + "City38": "老街", + "City39": "隆安", + "City40": "乂安", + "City41": "寧平", + "City42": "寧順", + "City43": "富壽", + "City44": "富安", + "City45": "廣平", + "City46": "廣南", + "City47": "廣義", + "City48": "廣寧", + "City49": "廣治", + "City50": "朔莊", + "City51": "山羅", + "City52": "西寧", + "City53": "太平", + "City54": "太原", + "City55": "清化", + "City56": "承天順化", + "City57": "前江", + "City58": "茶榮", + "City59": "宣光", + "City60": "永隆", + "City61": "永富", + "City62": "安沛", + "City63": "南定", + "birthday": "生日", + "choose_birthday": "請選擇生日", + "year": "年", + "month": "月", + "day": "日", + "hour": "時", + "minute": "分", + "second": "秒", + "just": "剛剛", + "minute_ago": "/s1分鐘前", + "hour_ago": "/s1小時前", + "day_ago": "/s1天前", + "week_ago": "/s1週前", + "month_ago": "/s1月前", + "morning": "上午", + "noon": "中午", + "afternoon": "下午", + "night": "晚上", + "all_day": "一整天", + "yesterday": "昨天", + "two_yesterday": "前天", + "overnight": "通宵", + "one": "個", + "ten": "十", + "hundred": "百", + "thousand": "千", + "ten_thousand": "萬", + "aries": "白羊座", + "taurus": "金牛座", + "gemini": "雙子座", + "cancer": "巨蟹座", + "leo": "獅子座", + "virgo": "處女座", + "libra": "天秤座", + "scorpio": "天蠍座", + "sagittarius": "射手座", + "capricorn": "摩羯座", + "aquarius": "水瓶座", + "pisces": "雙魚座", + "monday": "星期一", + "tuesday": "星期二", + "wednesday": "星期三", + "thursday": "星期四", + "friday": "星期五", + "saturday": "星期六", + "sunday": "星期天", + "job": "職業", + "choose_career": "請選擇職業", + "career1": "信息技術", + "career2": "互聯網", + "career3": "IT", + "career4": "電信運營", + "career5": "網絡遊戲", + "career6": "金融保險", + "career7": "投資", + "career8": "股票基金", + "career9": "保險", + "career10": "銀行", + "career11": "信託擔保", + "career12": "商業服務", + "career13": "諮詢", + "career14": "個體經營", + "career15": "美容美髮", + "career16": "旅遊", + "career17": "酒店餐飲", + "career18": "休閒娛樂", + "career19": "貿易", + "career20": "汽車", + "career21": "房地產", + "career22": "物業管理", + "career23": "裝修裝潢", + "career24": "偵探", + "career25": "工程製造", + "career26": "建築", + "career27": "土木工程", + "career28": "機械製造", + "career29": "電子", + "career30": "生物醫學", + "career31": "食品", + "career32": "服裝", + "career33": "能源", + "career34": "交通運輸", + "career35": "航空", + "career36": "鐵路", + "career37": "航運船舶", + "career38": "公共交通", + "career39": "物流運輸", + "career40": "文化傳媒", + "career41": "媒體出版", + "career42": "設計", + "career43": "文化傳播", + "career44": "廣告創意", + "career45": "動漫", + "career46": "公關會展", + "career47": "攝影", + "career48": "娛樂體育", + "career49": "影視", + "career50": "運動體育", + "career51": "音樂", + "career52": "模特", + "career53": "公共事業", + "career54": "醫療", + "career55": "法律", + "career56": "教育", + "career57": "政府機構", + "career58": "公益", + "career59": "學生", + "career60": "無", + "program": "節目", + "select_program": "請選擇國籍", + "healthy_exercise": "健康運動", + "night_party": "夜蒲聚會", + "gourmet_party": "我是吃貨", + "watch_movie": "看電影", + "play_games": "玩遊戲", + "travel_together": "結伴旅行", + "voice_chat": "連麥聊天", + "other": "其他", + "expect_lover": "期望對象", + "choose_lover": "請選擇期望對象", + "beautiful": "看臉", + "rich": "土豪", + "care_me": "關愛我", + "look_feeling": "看感覺", + "doesnt_matter": "無所謂", + "least_account": "請至少填寫一種社交賬號", + "hide_account1": "我的用戶資料隱藏社交賬號", + "more_information": "更多信息", + "height": "身高", + "weight": "體重", + "not_show": "不顯示", + "self_introduction": "個人介紹", + "registration_success1": "註冊成功", + "exit": "確定退出麼", + "exit_registration": "你還未完善個人信息,現在退出下次進入請用已註冊賬號直接登錄", + "cant_see": "男士無法查看其他男士詳情", + "cant_see2": "女士無法查看其他女士詳情", + "see_one": "你今天還能查看/s1位女士", + "only_see": "非會員用戶每天只能查看15位女士", + "continue_see": "繼續查看", + "user_frozen": "用戶已凍結", + "search_user": "請輸入暱稱/職業進行搜索", + "nearby": "附近", + "member": "會員", + "new_registration": "新註冊", + "authenticate": "認證", + "first_online": "在線", + "not_positioned": "未開啟定位,無法計算與其他用戶距離", + "unknown": "未知", + "secrecy": "保密", + "collection": "收藏", + "cancel_collection": "取消收藏", + "canceled_collection": "已取消收藏", + "like": "加入喜歡", + "added_like": "已加入喜歡", + "canceled_like": "已取消喜歡", + "blacklist": "拉黑", + "blacklist_choose": "你們將無法再看到對方和對方的動態,確定嗎", + "blacklisted": "已加入黑名單", + "reject_message": "你已拉黑對方並拒收消息", + "remove_blacklist": "移除黑名單", + "blacklist_removed": "已移除黑名單", + "receive_message": "你將對方移除黑名單並取消拒收消息", + "online": "在線", + "paid_photo": "付費相冊", + "application_view": "申請瀏覽", + "passed": "已通過", + "park": "公園", + "radio": "電台", + "news": "消息", + "me": "我", + "more_operations": "更多操作", + "anonymous_report": "匿名舉報", + "certified_video": "認證視頻", + "passed_video": "她已通過視頻認證真實性", + "not_video": "她還沒認證身份真實性", + "her_appointment": "她正在發起約會哦", + "pay_join": "他通過付費加入", + "passed_review": "他通過了身份安全審核", + "invited_user": "他通過資深用戶/s1贈送的邀請碼加入", + "his_appointment": "他正在發起約會哦", + "her_dynamics": "她的動態", + "his_dynamics": "他的動態", + "low_key": "她非常低調", + "low_key2": "他非常低調", + "her_photo": "她的相冊", + "his_photo": "他的相冊", + "set_lock": "他設置了相冊鎖", + "set_lock2": "她設置了相冊鎖", + "free_unlock": "解鎖相冊(/s1),會員免費", + "unlock_user": "解鎖/s1的相冊", + "pay_unlock": "付費解鎖(/s1 H幣)", + "become_member": "成為會員,免費解鎖", + "consumption_once": "是否使用1次機會解鎖/s1的相冊", + "remaining_once": "(你今天還有/s1次機會)", + "no_times": "你今天的免費機會已用完,是否贈送/s1解鎖/s2的全部資料", + "pay": "支付", + "view_user": "他設置了限制,查看資料需要請求他的同意", + "view_user2": "她設置了限制,查看資料需要請求她的同意", + "need_photo": "申請查看需給對方發送一張你的照片。放心,你的照片會在對方長按屏幕查看的2秒後焚毀", + "choose_photo": "選擇照片", + "send_application": "已發送申請,對方確認後你會收到消息提醒", + "not_authenticate": "你還沒進行認證", + "after_authenticate": "認證你的真實性後,才能與他人互動", + "authenticate_now": "馬上認證", + "destroy_after": "閱後即焚", + "destroyed": "已焚毀", + "red_photo1": "閱後即焚的紅包照片", + "ask_me": "請通過私聊向我索取", + "filled_in": "已填寫,點擊查看", + "unlock_information": "解鎖全部資料", + "unlock_choose": "使用1次免費解鎖", + "your_evaluation": "你的真實評價", + "her_evaluation": "她的真實評價", + "his_evaluation": "他的真實評價", + "evaluate": "評價", + "friendly": "友好", + "interesting": "有趣", + "readily": "爽快", + "patient": "耐心", + "indifferent": "高冷", + "bad_temper": "爆脾氣", + "courtesy": "禮貌", + "generous": "大方", + "lie": "口嗨", + "unfriendly": "不友好", + "anonymous_evaluation": "匿名評價", + "cant_evaluate": "你還沒約過她,無法評價", + "cant_evaluate2": "他還沒約過你,無法評價", + "bad_evaluate": "請提供相關截圖,以便我們跟進核實", + "submit": "提交", + "evaluation_success": "評價成功", + "private_chat": "私聊", + "close_reminder": "關閉消息提醒", + "closed_reminder": "關閉消息提醒成功", + "open_reminder": "開啟消息提醒", + "opened_reminder": "開啟消息提醒成功", + "her_account": "她的社交賬號", + "his_account": "他的社交賬號", + "copy": "複製", + "send_account": "發送我的社交賬號給她", + "enter_account": "輸入你的社交賬號", + "for_example": "比如:微信號abc", + "sent_she": "發送給她", + "chat": "連麥", + "cantt_voice": "對方關閉了連麥功能", + "authentication_voice": "認證你的真實性後,才能主動連麥", + "requesting_voice": "正在請求連麥", + "waitting_answer": "正在等待接聽", + "answer": "接聽", + "hang_up": "掛斷", + "chatting": "連麥中", + "handsfree": "免提", + "giving_gift": "打赏", + "give_success": "打賞成功", + "others_gift": "對方已打賞", + "given_gift": "你已打賞價值/s1H幣的禮物", + "earned_gift": "你已獲賞/s1H幣", + "available_balance": "可用餘額/s1", + "recharge": "充值", + "give": "贈送", + "balance_insufficien": "抱歉,你的餘額不足了", + "first_recharge": "請充值後再送禮物哦!", + "give_coin": "本次連麥打賞/s1H幣", + "get_coin": "本次連麥獲賞/s1H幣", + "give_get": "本次連麥打賞/s1H幣,獲賞了/s2H幣", + "chat_over": "連麥已結束,時長​/s1", + "message_center": "消息中心", + "can_chat": "你可以在對方的用戶詳情頁發起私聊", + "text_chat": "聊天", + "system_information": "系統消息", + "system_notification": "系統通知", + "report_failure": "你舉報用戶/s1的情況不屬實,請提供更有效的證據後再次舉報。謝謝!", + "report_success": "你舉報用戶/s1的情況屬實,系統已對該用戶進行處理", + "successful_application": "邀請碼申請成功!邀請碼【/s1】(點擊可複制)", + "successful_application2": "邀請碼申請成功,感謝你介紹靠譜的朋友!邀請碼【/s1】(點擊可複制)", + "application_failed": "邀請碼申請失敗!很遺憾您的申請未能通過審核,請填寫真實信息將有效的提高審核通過率", + "important_notice": "【重要通知】:", + "authentication_failed": "你的認證資料不符合要求,請修改後重新提交。", + "request1": "1.請根據認證要求拍攝認證視頻", + "request2": "2.請在相冊上傳五官清晰的正臉本人照片", + "successful_authentication": "恭喜,你的認證申請已通過審核", + "re_upload": "你新上傳的照片沒有通過審核,請根據要求重新上傳", + "upload_success": "恭喜,你新上傳的照片已成功通過審核", + "caveat": "您的約會報名因違規被刪除,多次違規或情節嚴重系統將對您賬號進行限制甚至封號,請遵守謹記,謝謝配合", + "caveat2": "您的評論因違規被刪除,多次違規或情節嚴重系統將對您賬號進行限制甚至封號,請遵守謹記,謝謝配合", + "radio_message": "電台消息", + "no_message": "暫時沒有此類消息", + "dating_news": "/s1在/s2發布了一條約會消息,點擊查看", + "go_see": "去看看", + "thumbs_up": "/s1讚了你的動態", + "thumbs_up2": "/s1讚了你的約會節目", + "comment1": "/s1評論了你的動態", + "comment2": "/s1評論了你的約會節目", + "replied_comment": "/s1回復了你的評論", + "signed_up": "/s1報名了你的約會節目", + "favorite_user": "你喜歡的用戶/s1發布了一條約會,點擊查看", + "favorite_user2": "你喜歡的用戶/s1發布了一條動態,點擊查看", + "wallet_reminder": "錢包提醒", + "paid_you": "/s1付費了(/s2H幣)查看了你的紅包照片", + "paid_you2": "/s1付費了(/s2H幣)查看了你的相冊", + "paid_you3": "/s1付費解鎖了你的全部資料", + "view_application": "查看申請", + "view_application2": "/s1請求查看你的詳情頁", + "aging": "允許(有效期15天)", + "refuse": "拒絕", + "passed_request": "已通過請求", + "l15_days": "/s1已通過你的查看申請,有效期15天", + "evaluation_notice": "評價通知", + "rate_her": "已經約出/s1了嗎?趕快評價一下她吧", + "received_evaluation": "聯繫過你的女士用戶(匿名)對你進行了評價:/s1", + "received_evaluation2": "聯繫過你的男士用戶(匿名)對你進行了評價:/s1", + "application_appeal": "如果評價不屬實,你可申請上述,我們會進行核實", + "appeal": "我要上訴", + "appealed": "已申請上訴", + "waiting_results": "我們會盡快核實情況,並通過站內信告訴你處理結果", + "successful_appeal": "你上訴的評價:/s1上訴成功,我們將為你撤銷此評價。", + "social_account": "社交賬號", + "get_account": "/s1向你發送了他的社交賬號", + "edit_information": "編輯資料", + "save": "保存", + "passed_verification1": "你通過了身份安全核實", + "by_code": "你通過資深用戶/s1的邀請碼加入", + "by_paying": "你通過付費加入", + "passed_verification": "你已通過視頻認證身份真實性", + "not_certified": "你還沒有認證身份真實性", + "verificating": "我們正在認證你的真實性", + "real_girl": "經過認證的女生更受歡迎哦", + "certificating": "認證中", + "re_upload2": "待重新上傳視頻", + "update_certification": "更新認證", + "enjoy_privileges": "升級會員尊享特權", + "expires": "/s1到期", + "wallet": "錢包", + "setting": "隱私", + "my_dynamic": "我的動態", + "my_album": "我的相冊", + "first_photo": "上傳我的第一張照片", + "no_photo": "有照片才能吸引男士哦", + "upload_photos": "上傳照片", + "upload_video": "上傳視頻", + "upload": "上傳照片", + "set_photo": "設置紅包照片", + "photo_order": "長按拖動可對照片排序", + "my_evaluation": "我的評價", + "my_show": "我的節目", + "i_like": "我喜歡的", + "your_favorite": "你喜歡的女士會顯示這裡", + "your_favorite2": "你喜歡的男士會顯示這裡", + "no_data": "沒有數據", + "historical_visitor": "歷史訪客", + "visit_you": "有/s1個人看過你", + "visit_photo": "已有/s1個人焚毀了你的照片", + "recovery_photo": "一鍵恢復", + "setting2": "設置", + "apply_code": "幫朋友申請邀請碼", + "issue_choose": "申請邀請碼是免費的,我們會根據你的歷史消費來評估是否發放邀請碼。為維持公園的氛圍,請一定把邀請碼贈與靠譜的朋友", + "successfully_submit": "成功遞交申請", + "share_app": "分享APP給朋友", + "need_help": "有問題需要幫助", + "need_help2": "聯繫客服", + "need_help3": "為了提高服務效率,如果下面有您的問題,請直接回复序號數字哦!", + "question1": "【1】賬號被凍結是什麼原因?", + "answer1": "出現下述任意一種情況,賬號都會被凍結:①騙子②中介③騷擾廣告④多人舉報⑤已有其他賬號⑥多次發布違規電台廣播無視警告⑦用戶自己要求註銷", + "question2": "【2】錢包現金什麼時候才能提現?", + "answer2": "所有收益會直接進入到錢包,提現需要三天(按收取時間計算開始),三天后收取的金額將會進入到錢包,金額>=10元即可提現", + "question3": "【3】我發出的紅包怎麼沒有顯示?", + "answer3": "可能是網絡原因導致。放心,這種情況對方無法領取你的紅包,紅包將在24小時後自動退還到你的支付渠道", + "question4": "【4】提現需要多久到賬?", + "answer4": "提交提現申請後兩個工作日內到賬。溫馨提示:提現時請確認賬號無誤!", + "question5": "【5】如何匿名舉報其他用戶/電台廣播內容?", + "answer5": "進入對方詳情頁或選擇某條電台廣播,點擊右上角選擇【匿名舉報】,請填寫相關舉報信息即可對其發起舉報。", + "question6": "【6】如何成為認證用戶?", + "answer6": "認證通過需滿足以下要求:①個人資料填寫有效社交賬號②相冊至少上傳一張本人清晰的正臉照③在認證頁面查看驗證碼,在紙上寫上暱稱+驗證碼④拿著這張紙,與你的正臉合拍一段視頻,點擊上傳認證視頻", + "question7": "【7】認證的視頻可以不公開嗎?", + "answer7": "可以在設置裡選擇是否公開:用戶中心-點擊認證視頻-左下角'將認證視頻顯示在我的詳情頁'", + "question8": "【8】如何避免認證被取消?", + "answer8": "相冊至少有一張被標記為本人的照片", + "question9": "【9】電台廣播被刪除是什麼原因?", + "answer9": "電台廣播不能發布敏感圖,敏感詞,包括但不限於暗示或明示性詞語,不能發布個人信息(包括頭像,暱稱,聯繫方式),違規電台廣播將被刪除", + "question10": "【10】如何註銷賬號?", + "answer10": "註銷賬號將無法登錄APP,以後再想使用服務則需要重新註冊,請謹慎考慮。如果你仍然決定註銷賬號,請回复序號【12】聯繫客服", + "question11": "【11】忘記密碼怎麼辦?", + "answer11": "通過手機號碼註冊或者綁定手機號碼的用戶,可以通過登錄頁面右上角的“忘記密碼”功能重置密碼。未綁定用戶請先綁定手機號,再設置新的登錄密碼", + "question12": "【12】其他問題/轉接人工客服", + "answer12": "你好,請問有什麼問題可以幫你?請描述你的問題(客服上班時間為每天8:00-次日02:00,由於諮詢人數較多,你可能需要等待回复)", + "certification_center": "認證中心", + "for_example2": "認證視頻拍攝方式示例", + "certification_conditions": "認證條件", + "conditions1": "1.個人形象良好", + "conditions2": "2.相冊中至少上傳一張本人照片", + "verification_method": "認證方式", + "method3": "1.取一張紙,寫上你的暱稱和以下驗證碼:", + "method4": "2.拿著這張紙,與你的正臉合拍一段視頻(3~15秒)", + "upload_video2": "上傳認證視頻", + "after_authentication": "認證成功後,你的頭像會帶有real標誌", + "show_video": "將認證視頻顯示在我的詳情頁", + "uploaded_video": "已上傳的認證視頻", + "under_review": "審核中(24小時內)", + "certification_status": "認證狀態", + "certified": "你已通過認證", + "wait_resubmitted": "認證待重提", + "reason_failure": "您的認證視頻不符合要求,原因是:", + "claim": "請根據認證要求拍攝認證視頻", + "claim2": "請在相冊上傳清晰展示五官的正臉本人照片", + "re_upload_video": "重新上傳認證視頻", + "update_video": "更新上傳認證視頻", + "mask_coin": "H幣", + "get_way": "你可以通過充值或者開麥等途徑獲得H幣。", + "coin_use": "H幣可用於使用連麥服務,並且在連麥時進行打賞。", + "coin_total": "H幣總額", + "can_redeemed": "可兌消", + "who_account": "/s1賬號", + "bind_account": "綁定/s1賬號", + "your_account": "你的/s1賬號", + "get_coin2": "你通過充值獲得了/s1H幣", + "viewed_your": "/s1查看了你的社交賬號", + "give_gift": "/s1贈送了禮物:1個/s2", + "add_coin": "+/s1H幣", + "give_one": "你贈送了1個/s1給/s2", + "less_coin": "-/s1H幣", + "exchange_cash": "提現", + "withdrawal_application": "提現申請", + "redeem_choose": "你有/s1枚H幣可兌換成/s2,兌換後剩餘/s3枚H幣。確定申請兌換嗎?", + "application_submitted": "提現申請已提交", + "working_days": "我們將在2個工作日內處理,有疑問可諮詢客服", + "cash": "現金", + "handling_fee": "每當你再聊天頁面收到紅包,紅包金額都會進入這裡。金額進賬後3天內沒人舉報你即可提現,提現將收取5%手續費", + "total_account": "賬戶總額", + "cannot_redeemed": "金額不足,無法兌消", + "successful_redemption": "兌消成功", + "redeem_choose2": "你的賬戶總額為/s1元,本次可提現/s2元,確定申請提現嗎?", + "personal_details": "個人詳情", + "public": "公開(推薦)", + "paid_album": "相冊付費查看", + "must_pay": "他人必須付費才能查看你的相冊,費用由你定,這可能會降低你的訪問量", + "set_amount1": "設置查看金額", + "first_upload": "請先上傳照片,再設置付費相冊", + "need_permission": "查看前需通過我驗證", + "permission_choose": "他人必鬚髮照片讓你驗證身份後才能瀏覽你的主頁,確定嗎?", + "hide_me": "在附近的人列表隱藏我", + "hide_distance": "對他人隱藏我的距離", + "hide_account": "對他人隱藏我的社交賬號", + "chat_setting": "連麥控制", + "chat_me": "允許有私聊權限的人對我發起連麥", + "successfully_saved": "保存成功", + "on_dynamic": "你還沒有發布過動態", + "release_dynamics": "發布動態", + "dynamic_details": "動態詳情", + "release": "發布", + "i_posted": "我發布的", + "delete_dynamic": "刪除動態", + "delete_choose": "確定要刪除這條動態嗎?", + "posted_on": "發佈於/s1", + "thumbs_up3": "贊", + "already_praised": "已經贊過了", + "comment": "評論", + "send": "發送", + "comment_closed": "評論已關閉", + "your_comment": "只有發布者能看見你的評論", + "everyone_comment": "大家都能看見你的評論", + "prohibit_comments": "禁止評論", + "comments_disabled": "已禁止評論", + "open_comments": "開放評論", + "already_open": "已經開放評論", + "reply": "回复", + "report": "舉報", + "report_choose": "確定舉報這條評論嗎?", + "successful_report": "舉報成功,我們會盡快處理", + "successfully_deleted": "刪除成功", + "please_civilization": "談吐文明的人更受歡迎,請勿發布低俗、色情交易、或曝光他人隱私的內容", + "same_sex": "對同性別用戶隱藏", + "member_free": "會員免費,非會員需/s1H幣", + "certified_free": "已認證女士免費3次,之後需要支付/s1H幣", + "enter_something": "請輸入文字內容或選擇圖片", + "raid_release": "付費發布(/s1H幣)", + "become_member2": "成為會員,免費發布", + "now_certification": "馬上認證,免費發布", + "successfully_released": "發布成功", + "no_program": "你還沒有發布過節目", + "program_details": "節目詳情", + "program_theme": "節目主題", + "click_select": "點擊選擇", + "city": "城市", + "select_city": "選擇城市", + "time": "時間", + "select_date": "選擇日期", + "select_time": "選擇時間", + "unlimited_time": "不限時間", + "supplementary_explanation": "補充說明", + "image": "配圖", + "delete_program": "刪除節目", + "delete_choose2": "確定要刪除這條節目嗎?", + "please_choose": "請選擇節目主題", + "please_choose2": "請選擇期望對象", + "please_choose3": "請選擇城市", + "please_choose4": "請選擇日期", + "please_choose5": "請選擇時間", + "release_program": "發布節目", + "sign_up": "報名", + "end_registration": "結束報名", + "end_choose": "確定結束約會嗎?", + "contact_her": "聯繫她", + "talk_him": "私聊他", + "report_choose2": "確定舉報這條報名信息嗎?", + "release_time": "發佈時間", + "activity_time": "活動時間", + "any_sex": "不限性別", + "look_women": "只看女士", + "look_men": "只看男士", + "unlimited_area": "不限地區", + "program_deleted": "該節目已刪除", + "cant_comment": "非會員不能評論", + "sign_up2": "我要報名", + "need_photo2": "報名需要發送你的正臉照片(只有對方能看到)", + "registration_success": "報名成功,如果對方覺得合適將會聯繫你", + "has_ended": "已結束", + "men_cant": "男士不能報名男士的節目", + "ms_cant": "女士不能報名女士的節目", + "men_cant2": "男士不能評論男士的節目", + "ms_cant2": "女士不能評論女士的節目", + "message_push": "消息推送、修改密碼", + "phone_number": "手機號碼", + "bind_phone1": "綁定手機號", + "more_safer": "綁定手機號,讓你的賬戶更安全", + "modify_choose": "你想修改綁定的手機號碼嗎?", + "change_password": "修改密碼", + "first_bind": "用戶需要先綁定手機號碼才可以設置登錄密碼", + "old_password": "原密碼", + "current_password": "請輸入當前登錄密碼", + "new_password": "新密碼", + "set_new": "請設置新密碼,不少於6位", + "clear_cache": "清除圖片緩存", + "cleared_successfully": "清除成功", + "user_agreement1": "用戶使用協議", + "sign_out": "退出登錄", + "out_choose": "確定退出賬號麼?", + "push_settings": "推送設置", + "permission_denied": "權限已被拒絕", + "push_setting2": "消息推送設置", + "private_chat2": "私聊消息", + "new_date": "有新的約會", + "passed_request2": "有女士通過了我的查看請求", + "men_view": "有男士申請查看我的資料頁", + "men_view2": "有男士查看我的社交賬號", + "men_view3": "有男士查看我的紅包照片", + "men_view4": "有已查看資料的男士給我發送社交賬號", + "applied_successfully": "邀請碼申請成功", + "after_open": "打開後將推送相應消息類型", + "if_something": "如果你在最近3天曾向她/他支付過費用,我們核實舉報後,系統將自動向你退回消費金額", + "advertise": "發廣告", + "false_photo": "虛假照片", + "erotic_vulgarity": "色情低俗", + "harassment": "騷擾謾罵", + "she_liar": "她是騙子", + "he_liar": "他是騙子", + "provide_screenshots": "請提供相關截圖,以便我們跟進核實", + "describe_details": "請描述詳情(100字內)", + "report_reason": "請選擇舉報原因", + "report_success2": "舉報成功", + "successfully_modified": "修改成功", + "boy": "男生", + "girl": "女生", + "already_applied": "已申請", + "view_registration": "查看報名", + "expand": "展開", + "collapse": "收起", + "application_notice": "申請通知", + "agrees_application": "有用戶同意你的申請", + "red_photo": "紅包照片", + "dont": "請勿上傳非法裸露低俗的照片/視頻,嚴重者將封號", + "current_version": "當前版本", + "bank_card": "綁定銀行卡", + "choose_bank": "請選擇開戶行", + "bank_number": "請輸入銀行卡號", + "id_number": "請輸入證件號", + "name": "姓名", + "bank_number2": "銀行卡號", + "license_number": "證件號", + "bind_phone": "綁定手機號", + "his_homepage": "他的主頁", + "her_homepage": "她的主頁", + "wechat_pay": "微信支付", + "facebook_pay": "facebook支付", + "google_pay": "google支付", + "payment_successful": "支付成功", + "set_amount": "設置提款金額", + "enter_amount": "請輸入H幣個數", + "can_withdraw": "可提現", + "language_set": "語言設置", + "user_agreement": "用戶協議", + "renewal_fee": "續費", + "open_immediately": "立即開通", + "total": "總計", + "half_month": "半 個 月", + "month2": "/s1 個 月", + "cancel_shield": "取消屏蔽", + "blacklist2": "黑名單", + "longTime": "(會員可延長時間達6秒)", + "longClick": "按住屏幕查看", + "stop_program": "請先結束正在生效的節目", + "not_love": "男士不能收藏男士", + "not_love2": "女士不能收藏女士", + "women_free": "女士可以免費發布", + "not_up_man": "他還沒有上傳照片", + "not_up_women": "她還沒有上傳照片", + "not_illage": "請勿通過平台進行不法交易,如被舉報核實將作封號處理", + "alreay_join": "已報名", + "sure_delete": "確定刪除這張照片嗎", + "white_now": "馬上填寫", + "personal": "你還沒有填寫個人介紹,吸引人的個人介紹對約會成功影響很大哦", + "success": "成功", + "fail": "失敗", + "moneyPageTip": "只有認證用戶才可以設置紅包照片", + "alreadyJoin": "你已報名,如果對方覺得合適將會聯繫你", + "waring": "違規警告", + "userPravicy": "尊重用戶隱私,請勿截圖。如有下次,將禁止你查看其他用戶照片", + "outTime": "約會時間已經過期了,請修改", + "reviewing": "審核中", + "reviewed": "審核成功", + "reviewedFail": "審核失敗", + "needCard": "用戶需要先綁定銀行卡才可以提現", + "women_not_d": "女士不能評論女士的動態", + "man_not_d": "男士不能評論男士的動態", + "have_picture": "有照片才能吸引女士哦", + "up_cancle": "上滑取消發送", + "msg_not": "消息不能為空", + "need_record": "此功能需要授予錄音權限", + "downloading_video": "正在下載視頻文件", + "reinput": "請重新輸入問題序號", + "dy_delete": "你的動態被用戶匿名舉報,經系統核實已將該動態刪除,請勿再進行違規操作", + "pro_delete": "你的節目被用戶匿名舉報,經系統核實已將該節目刪除,請勿再進行違規操作", + "con_delete": "你的評論被用戶匿名舉報,經系統核實已將該評論刪除,請勿再進行違規操作", + "coin_returen": "經匿名用戶舉報,系統核實你近期存在違規行為,已將你近期收到H幣進行返還。如有下次,將進行賬號凍結", + "voicing": "通話中禁止出現色情淫穢等違法行為,一經發現將做封號處理", + "help": "客服", + "translate_on": "人工翻譯開啟", + "translate_off": "人工翻譯關閉", + "becomeSvip": "消耗/s1 H幣將續費為SVIP", + "need_svip": "svip權限可開啟", + "cannot_vip": "SVIP無法續費為VIP", + "offline": "您已離線,無法發送和接收消息", + "otherLogin": "賬號在其他設備登錄,您已離線", + "no_new": "暫時沒有新消息", + "over": "翻譯完畢", + "bad_ev": "確定要對此條翻譯進行差評麼?", + "right5": "聊的更爽", + "right6": "用的更爽", + "man_vi": "小哥哥", + "women_vi": "小姐姐", + "kf_tips": "為了提高服務效率,如果下面有您的問題,請直接回复序號數字哦!", + "rejected": "已拒絕", + "buy_vip": "你消費了/s1H幣購買會員", + "buy_program": "你消費了/s1H幣發布動態節目", + "del_add_money": "你的H幣提現申請已處理,已轉賬/s1到你的賬號,請查收", + "adding_money": "你申請提現的/s1H幣正在審批中", + "free_translate": "免費享受翻譯專員實時翻譯", + "personalTraff": "專享客服為你服務", + "ManTranslate": "人工翻譯中...", + "robotTranslate": "機器翻譯中...", + "translated": "人工翻譯完畢", + "delete_progarm": "健康交流,請勿廣播低俗內容,一經發現將作刪除處理", + "open_location": "定位權限未開啟", + "get_location": "請在手機設置中開啟定位權限以獲得其他用戶距離", + "confirm_exit": "再按一次退出", + "free_program": "每天/s1次機會發布免費廣播", + "picture": "圖片", + "camera": "相機", + "video": "視頻", + "red_money": "紅包", + "stick": "粘貼", + "press_say": "按住說話", + "get_money": "/s1領取了你的紅包", + "you_get_money": "你領取了/s1的紅包", + "ones_money": "/s1的紅包", + "money_over": "紅包已過期", + "downloading_fail": "下載文件失敗", + "downloading": "正在下載視頻文件", + "back_money": "未領取的紅包,將於24小時後發起退款", + "no_money": "紅包不存在", + "already_money": "紅包已領取", + "back_user": "已過期,已退到賬戶", + "waiting_user": "等待對方領取", + "other_get": "對方已領取", + "little": "小小意思,拿去浪吧", + "put_money": "塞錢進紅包", + "mount": "金額", + "over_time": "已過期", + "has_get": "已領取", + "no_gift": "暫時沒有禮物", + "sent_gift": "打賞禮物", + "fill_tips": "填寫成功可以獲得/s1H幣,綁定後無法修改", + "bind_code": "綁定邀請碼", + "invide_code": "邀請碼", + "confirm_delete": "確認刪除", + "has_eva": "您已經評價過了", + "open": "開", + "voice": "語音", + "release_send": "鬆開發送", + "time_little": "錄音時間過短", + "not_online": "對方不在線,無法連麥", + "give_red_money": "你給/s1發送了/s2H幣的紅包", + "get_red_money": "你領取了/s1的/s2H幣的紅包", + "give_other_money": "你打賞了/s1/s2H幣", + "get_other_money": "你獲得了/s1的/s2H幣的打賞", + "svip": "超級會員", + "recommend": "推薦", + "paid_you4": "你付費了(/s2H幣)查看/s1的紅包照片", + "paid_you5": "你付費了(/s2H幣)查看/s1的相冊", + "paid_you6": "你付費解鎖了/s1的全部資料", + "UG_LINE0": "hiAPP許可及服務協議", + "UG_LINE1": "[首部及導言]", + "UG_LINE2": "前海遊龍科技有限公司(以下簡稱“Qianhai Youlong Technology Co., Ltd.”)在此特別提醒用戶認真閱讀、充分理解本《服務協議》(下稱《協議》)一用戶應認真閱讀、充分理解本《協議》中各條款,包括免除或者限制Qianhai Youlong Technology Co., Ltd.責任的免責條款及對用戶的權利限制條款。請您審慎閱讀並選擇接受或不接受本《協議》(未成年人應在法定監護人陪同下閱讀)。除非您接受本《協議》所有條款,否則您無權註冊、登錄或使用本協議所涉相關服務。您的註冊、登錄、使用等行為將視為對本《協議》的接受,並同意接受本《協議》各項條款的約束。", + "UG_LINE3": "本《協議》是您(下稱“用戶”與Qianhai Youlong Technology Co., Ltd.之間關於用戶註冊、登錄、使用“hi服務所訂立的協議。本《協議》描述Qianhai Youlong Technology Co., Ltd.與用戶之間關於“hi服務相關方面的權利義務。“用戶”是指註冊、登錄、使用、瀏覽本服務的個人或組織。您對本協議的接受即受全部條款的約束,包括接受Qianhai Youlong Technology Co., Ltd.對任意服務條款隨時所做的任何修改。本《協議》可由Qianhai Youlong Technology Co., Ltd.隨時更新,更新後的協議條款一旦公佈即代替原來的協議條款,恕不再另行通知,用戶可在本APP查閱最新版協議條款。在Qianhai Youlong Technology Co., Ltd.修改《協議》條款後,如果用戶不接受修改後的條款,請立即停止使用Qianhai Youlong Technology Co., Ltd.提供的服務,用戶繼續使用Qianhai Youlong Technology Co., Ltd.提供的服務將被視為已接受了修改後的協議。", + "UG_LINE4": "一、使用規則", + "UG_LINE5": "1、用戶充分了解並同意,僅為用戶提供信息分享、傳送及獲取的平台,用戶必須為自己註冊帳號下的一切行為負責,包括但不限於您所傳送的任何內容以及由此產生的任何結果。", + "UG_LINE6": "2、用戶在服務中或通過服務所傳送的任何內容並不反映Qianhai Youlong Technology Co., Ltd.的觀點或政策,Qianhai Youlong Technology Co., Ltd.對此不承擔任何責任。", + "UG_LINE7": "3、用戶充分了解並同意,是一個基於用戶關係網的社交信息瀏覽產品,用戶須對在上的註冊信息的真實性、合法性、有效性承擔全部責任,用戶不得冒充他人;不得利用他人的名義傳播任何信息;不得惡意使用註冊帳號導致其他用戶誤認;否則Qianhai Youlong Technology Co., Ltd.有權立即停止提供服務,收回帳號並由用戶獨自承擔由此而產生的一切法律責任。", + "UG_LINE8": "4、用戶須對在上所傳送信息的真實性、合法性、無害性、有效性等全權負責,與用戶所傳播的信息相關的任何法律責任由用戶自行承擔,與Qianhai Youlong Technology Co., Ltd.無關。", + "UG_LINE9": "5、Qianhai Youlong Technology Co., Ltd.保留因業務發展需要,單方面對本服務的全部或部分服務內容在任何時候不經任何通知的情況下變更、暫停、限制、終止或撤銷服務的權利,用戶需承擔此風險。", + "UG_LINE10": "6、提供的服務中可能包括廣告,用戶同意在使用過程中顯示和第三方供應商、合作夥伴提供的廣告。", + "UG_LINE11": "7、用戶不得利用或服務製作、上載、複製、發送如下內容:", + "UG_LINE12": "(1 )反對憲法所確定的基本原則的;", + "UG_LINE13": "(2)危害國家安全,洩露國家秘密,顛覆國家政權,破壞國家統一-的;", + "UG_LINE14": "(3)損害國家榮譽和利益的;", + "UG_LINE15": "(4)煽動民族仇恨、民族歧視,破壞民族團結的;", + "UG_LINE16": "(5)破壞國家宗教政策,宣揚邪教和封建迷信的;", + "UG_LINE17": "(6)散佈謠言,擾亂社會秩序,破壞社會穩定的;", + "UG_LINE18": "(7)散佈淫穢、色情、賭博、暴力、兇殺、恐怖或者教唆犯罪的;", + "UG_LINE19": "(8)侮辱或者誹謗他人,侵害他人合法權益的;", + "UG_LINE20": "(9)含有法律、行政法規禁止的其他內容的信息。", + "UG_LINE21": "8、Qianhai Youlong Technology Co., Ltd.可依其合理判斷,對違反有關法律法規或本協議約定;或侵犯、妨害、威脅任何人權利或安全的內容,或者假冒他人的行為,Qianhai Youlong Technology Co., Ltd.有權依法停止傳輸任何前述內容,並有權依其自行判斷對違反本條款的任何人士採取適當的法律行動,包括但不限於從服務中刪除具有違法性、侵權性、不當性等內容,終止違反者的成員資格,阻止其使用全部或部分服務,並且依據法律法規保存有關信息並向有關部門報告等。", + "UG_LINE22": "9、用戶權利及義務:", + "UG_LINE23": "(1 )Qianhai Youlong Technology Co., Ltd.帳號的所有權歸Qianhai Youlong Technology Co., Ltd.所有,用戶完成申請註冊手續後,獲得帳號的使用權,該使用權屬於初始申請註冊人,禁止贈與、借用、租用、轉讓或售賣。 Qianhai Youlong Technology Co., Ltd.因經營需要,有權回收用戶的帳號,並有權使用用戶照片、視頻、語音等進行產品宣傳活動。", + "UG_LINE24": "(2)用戶有權更改、刪除在Qianhai Youlong Technology Co., Ltd.上的個人資料、註冊信息及傳送內容等,但需注意,刪除有關信息的同時也會刪除任何您儲存在系統中的文字和圖片。用戶需承擔該風險。", + "UG_LINE25": "(3)用戶有責任妥善保管註冊帳號信息及帳號密碼的安全,用戶需要對註冊帳號以及密碼下的行為承擔法律責任。用戶同意在任何情況下不使用其他成員的帳號或密碼。在您懷疑他人在使用您的帳號或密碼時,您同意立即通知Qianhai Youlong Technology Co., Ltd.。", + "UG_LINE26": "(4)用戶應遵守本協議的各項條款,正確、適當地使用本服務,如因用戶違反本協議中的任何條款,Qianhai Youlong Technology Co., Ltd.有權依據協議終止對違約用戶Qianhai Youlong Technology Co., Ltd.帳號提供服務。同時,Qianhai Youlong Technology Co., Ltd.保留在任何時候收回Qianhai Youlong Technology Co., Ltd.帳號、用戶名的權利。", + "UG_LINE27": "(5)如果用戶有自己的常用英文帳號,那麼用戶有優先將該英文帳號註冊為帳號的權利,但是如果用戶在服務上線後一段時間內沒有註冊帳號,或者用戶雖然註冊了微信帳號,但是並不是使用該英文帳號作為微信帳號的,視為用戶放棄了將該英文帳號註冊為微信帳號的權利,Qianhai Youlong Technology Co., Ltd.有權將該英文帳號回收並分配給其他用戶使用,以免造成資源浪費,由此帶來問題均由用戶自行承擔。", + "UG_LINE28": "(6)用戶註冊帳號後如果長期不登錄該帳號,Qianhai Youlong Technology Co., Ltd.有權回收該帳號,以免造成資源浪費,由此帶來問題均由用戶自行承擔。", + "UG_LINE29": "(7)用戶發生糾紛可使用舉報功能維護用戶平台權益,若收到用戶舉報反饋,被舉報用戶有義務主動告知或配合客服人員核實情況,舉報內容核實屬實,面具公園有權對用戶警告、限制賬號使用功能等方式約束用戶違規行為,嚴重違規者hi有權直接凍結賬號,且賬戶內餘額不返還。如果賬號被凍結需申訴,用戶可聯繫客服 。", + "UG_LINE30": "二、隱私保護", + "UG_LINE31": "用戶同意個人隱私信息是指那些能夠對用戶進行個人辨識或涉及個人通信的信息,包括下列信息:用戶真實姓名,手機號碼,微信賬號,facebook賬號,IP地址。而非個人隱私信息是指用戶對本服務的操作狀態以及使用習慣等一些明確且客觀反映在Qianhai Youlong Technology Co., Ltd.服務器端的基本記錄信息和其他一切個人隱私信息範圍外的普通信息;以及用戶同意公開的上述隱私信息。尊重用戶個人隱私信息的私有性是Qianhai Youlong Technology Co., Ltd.的一貫制度,Qianhai Youlong Technology Co., Ltd.將會採取合理的措施保護用戶的個人隱私信息,除法律或有法律賦予權限的政府部門要求或用戶同意等原因外,Qianhai Youlong Technology Co., Ltd.未經用戶同意不向除合作單位以外的第三方公開、透露用戶個人隱私信息。但是,用戶在註冊時選擇同意,或用戶與Qianhai Youlong Technology Co., Ltd.及合作單位之間就用戶個人隱私信息公開或使用另有約定的除外,同時用戶應自行承擔因此可能產生的任何風險,Qianhai Youlong Technology Co., Ltd.對此不予負責。同時,為了運營和改善Qianhai Youlong Technology Co., Ltd.的技術和服務,Qianhai Youlong Technology Co., Ltd.將可能會自行收集使用或向第三方提供用戶的非個人隱私信息,這將有助於Qianhai Youlong Technology Co., Ltd.向用戶提供更好的用戶體驗和提高Qianhai Youlong Technology Co., Ltd.的服務質量。 Qianhai Youlong Technology Co., Ltd.收集數據是根據用戶與Qianhai Youlong Technology Co., Ltd.的互動和用戶所做出的選擇,包括用戶的隱私設置以及用戶使用的產品和功能。 Qianhai Youlong Technology Co., Ltd.收集的數據可能包括SDK/API/JS代碼版本、IP地址、平台、時間戳、應用標識符、應用程序版本、應用分發渠道、獨立設備標識符、iOS廣告標識符(IDFA)、 安卓廣告主標識符、網卡(MAC) 地址、國際移動設備識別碼(IMEI)、設備型號、終端製造廠商、終端設備操作系統版本、會話啟動/停止時間、語言所在地、時區和網絡狀態(WiFi等)、硬盤、 CPU和電池使用情況等。這將有助於Qianhai Youlong Technology Co., Ltd.開展內部數據分析和研究,第三方SDK統計服務,改善Qianhai Youlong Technology Co., Ltd.的產品或服務。為確保用戶身份真實性,向用戶提供更好的安全保障,用戶需提交的身份信息或面部特徵等生物識別信息(均屬於個人敏感信息)來完成具體產品服務所需或必要的真人認證。 .上 述信息將僅用於核實用戶身份的真實性。用戶提供的.上述信息,將在用戶使用本服務期間持續授權Qianhai Youlong Technology Co., Ltd.使用。在用戶註銷賬號時,Qianhai Youlong Technology Co., Ltd.將停止使用。上述信息將存儲於中華人民共和國境內。如需跨境傳輸,Qianhai Youlong Technology Co., Ltd.將會單獨徵得用戶的授權同意。 App用戶真實性認證需要用戶提供能證實用戶身份真實性的部分資料。相關資料只用做平台審核不會披露給任何其他用戶或用於商業用途,僅法律或有關部門要求介入除外。", + "UG_LINE32": "三、Qianhai Youlong Technology Co., Ltd.商標信息", + "UG_LINE33": "Qianhai Youlong Technology Co., Ltd.服務中所涉及的logo等圖形、文字或其組成,以及其他Qianhai Youlong Technology Co., Ltd.標誌及產品、服務名稱,均為Qianhai Youlong Technology Co., Ltd.之商標(以下簡稱“Qianhai Youlong Technology Co., Ltd.標識”)。未經Qianhai Youlong Technology Co., Ltd.事先書面同意,用戶不得將Qianhai Youlong Technology Co., Ltd.標識以任何方式展示或使用或作其他處理,也不得向他人表明您有權展示、使用、或其他有權處理Qianhai Youlong Technology Co., Ltd.標識的行為。", + "UG_LINE34": "四、法律責任及免責", + "UG_LINE35": "1、用戶違反本《協議》或相關的服務條款的規定,導致或產生的任何第三方主張的任何索賠、要求或損失,包括合理的律師費,用戶同意賠償Qianhai Youlong Technology Co., Ltd.與合作公司、關聯公司,並使之免受損害。", + "UG_LINE36": "2、用戶因第三方如電信部門的通訊線路故障、技術問題、網絡、電腦故障、系統不穩定性及其他各種不可抗力原因而遭受的一切損失,Qianhai Youlong Technology Co., Ltd.及合作單位不承擔責任。", + "UG_LINE37": "3、因技術故障等不可抗事件影響到服務的正常運行的,Qianhai Youlong Technology Co., Ltd.及合作單位承諾在第一時間內與相關單位配合,及時處理進行修復,但用戶因此而遭受的一切損失,Qianhai Youlong Technology Co., Ltd.及合作單位不承擔責任。", + "UG_LINE38": "4、本服務同大多數互聯網服務一樣,受包括但不限於用戶原因、網絡服務質量、社會環境等因素的差異影響,可能受到各種安全問題的侵擾,如他人利用用戶的資料,造成現實生活中的騷擾;用戶下載安裝的其它軟件或訪問的其他網站中含有“特洛伊木馬”等病毒,威脅到用戶的計算機信息和數據的安全,繼而影響本服務的正常使用等等。用戶應加強信息安全及使用者資料的保護意識,要注意加強密碼保護,以免遭致損失和騷擾。", + "UG_LINE39": "5、用戶須明白,使用本服務因涉及Internet服務,可能會受到各個環節不穩定因素的影響。因此,本服務存在因不可抗力、計算機病毒或黑客攻擊、系統不穩定、用戶所在位置、用戶關機以及其他任何技術、互聯網絡、通信線路原因等造成的服務中斷或不能滿足用戶要求的風險。用戶須承擔以上風險,Qianhai Youlong Technology Co., Ltd.不作擔保。對因此導致用戶不能發送和接受閱讀信息、或接發錯信息,Qianhai Youlong Technology Co., Ltd.不承擔任何責任。", + "UG_LINE40": "6、用戶須明白,在使用本服務過程中存在有來自,任何他人的包括威脅性的、誹謗性的、令人反感的或非法的內容或行為或對他人權利的侵犯(包括知識產權)的匿名或冒名的信息的風險,用戶須承擔以上風險,Qianhai Youlong Technology Co., Ltd.和合作公司對本服務不作任何類型的擔保,不論是明確的或隱含的,包括所有有關信息真實性、適商性、適於某一特定用途、所有權和非侵權性的默示擔保和條件,對因此導致任何因用戶不正當或非法使用服務產生的直接、間接、偶然、特殊及後續的損害,不承擔任何責任。", + "UG_LINE41": "7、Qianhai Youlong Technology Co., Ltd.定義的信息內容包括:文字、軟件、聲音、相片、錄像、圖表;在廣告中全部內容;Qianhai Youlong Technology Co., Ltd.為用戶提供的商業信息,所有這些內容受版權、商標權、和其它知識產權和所有權法律的保護。所以,用戶只能在Qianhai Youlong Technology Co., Ltd.和廣告商授權下才能使用這些內容,而不能擅自複制、修改、編纂這.些內容、或創造與內容有關的衍生產品。", + "UG_LINE42": "8、在任何情況下,Qianhai Youlong Technology Co., Ltd.均不對任何間接性、後果性、懲罰性、偶然性、特殊性或刑罰性的損害,包括因用戶使用服務而遭受的利潤損失,承擔責任(即使已被告知該等損失的可能性亦然)。儘管本協議中可能含有相悖的規定,Qianhai Youlong Technology Co., Ltd.對您承擔的全部責任,無論因何原因或何種行為方式,始終不超過您在成員期內因使用服務而支付給Qianhai Youlong Technology Co., Ltd.的費用。", + "UG_LINE43": "五、會員條款", + "UG_LINE44": "1、hi會員平等享有會員的權利,同時應遵守Qianhai Youlong Technology Co., Ltd.的各項規範、規則,包括但不限於本服務條款和《用戶協議》。", + "UG_LINE45": "2、因違反Qianhai Youlong Technology Co., Ltd.《用戶協議》而導致會員服務被暫停使用的相關損失,由用戶自行承擔。", + "UG_LINE46": "3、會員在會員資格有效期內可以享受hi會員的各項增值服務。", + "UG_LINE47": "4、如會員在會員資格有效期內主動終止或取消會員資格,Qianhai Youlong Technology Co., Ltd.不負責退還與該會員剩餘會員資格有效期對應的服務費用。", + "UG_LINE48": "5、會員自行承擔在hi中傳送、發布信息及使用hi免費服務或收費服務的法律責任,會員使用hi服務,包括免費服務與收費服務的行為,均應遵守各項法律法規、規章、規範性文件。", + "UG_LINE49": "6、會員服務開通之後,不可進行轉讓或退訂。", + "UG_LINE50": "7、因會員在使用Qianhai Youlong Technology Co., Ltd.免費服務或收費服務的過程中,存在違反法律法規的行為,Qianhai Youlong Technology Co., Ltd.有權取消該會員的會員資格而無須給予任何補償,且該會員須自行承擔全部責任。", + "UG_LINE51": "六、其他條款", + "UG_LINE52": "1、Qianhai Youlong Technology Co., Ltd.鄭重提醒用戶注意本《協議》中免除Qianhai Youlong Technology Co., Ltd.責任和加重用戶義務的條款,請用戶仔細閱讀,自主考慮風險。未成年人應在法定監護人的陪同下閱讀本《協議》。以上各項條款內容的最終解釋權及修改權歸Qianhai Youlong Technology Co., Ltd.所有。", + "UG_LINE53": "2、本《協議》所定的任何條款的部分或全部無效者,不影響其它條款的效力。", + "UG_LINE54": "3、本《協議》的解釋、效力及糾紛的解決,適用於中華人民共和國法律。若用戶和Qianhai Youlong Technology Co., Ltd.之間發生任何糾紛或爭議,首先應友好協商解決,協商不成的,用戶在此完全同意將糾紛或爭議提交Qianhai Youlong Technology Co., Ltd.住所地的人民法院管轄。", + "UG_LINE55": "4、本《協議》的版權由Qianhai Youlong Technology Co., Ltd.所有,Qianhai Youlong Technology Co., Ltd.保留一切解釋和修改權利。", + "UG_LINE56": "前海遊龍科技有限公司", + "net_error": "網絡異常", + "enter_name": "請輸入姓名", + "translate": "譯", + "locate": "位置", + "voice_tips": "按住錄音,鬆開發送", + "unlock": "解鎖", + "input_content": "請輸入聊天內容", + "connecting": "連接中...", + "logining": "登陸中...", + "reject_reply": "/s1拒絕了你的查看申請", + "warning_text": "H幣進賬3天內沒人舉報你即可兌消(1:1000越南盾)", + "more_big": "輸入個數不大於/s1", + "little_min": "輸入個數不小於/s1", + "voice_msg": "/s1邀請你進行通話", + "send_gift": "你打賞了對方/s1個/s2", + "receive_gift": "對方打賞了你/s1個/s2", + "cannot_join": "非會員不能報名", + "alreay_back": "已退回", + "video_more_big": "文件過大", + "select_all": "選擇所有", + "re_connect": "重新連接", + "voice_tips2": "鬆開發送,滑動取消", + "country": "國籍", + "have_picture_view": "有照片審核中", + "speaker_play": "揚聲器播放", + "handset_playback": "聽筒播放", + "play_model": "聽筒模式", + "password_less": "密碼過短", + "years_old": "歲", + "coin_returen1": "經匿名用戶舉報,系統核實你近期存在違規行為,請勿再進行違規操作。如有下次,將進行賬號凍結", + "already_new": "已經是最新版本", + "test_it": "立即體驗", + "found_new": "發現新版本", + "ad": "廣告", + "attention": "關注", + "fans": "粉絲", + "apply_see": "/s1 申請查看我的資料頁", + "agree_apply": "/s1 通過了我的查看請求", + "see_redBag": "/s1 查看了我的紅包照片", + "notice": "提醒", + "notice_open": "請在手機設置中開啟通知權限以獲取消息通知", + "open_notice": "通知權限未開啟", + "not_open": "未開啟通知權限,無法接收通知", + "withdraw_fail": "你申請提現的的/s1H幣已被退回,請確認綁定賬戶是否正確", + "dynamics": "動態", + "Remark": "備註", + "setRemark": "設置備註", + "content_num": "/s1條評論", + "Redeem": "積分兌換獲得/s1H幣", + "location_permission": "沒有訪問手機存儲權限", + "camera_permission": "沒有訪問攝像頭權限", + "photo_permission": "沒有訪問相冊的權限", + "video_permission": "沒有訪問麥克風的權限", + "your_redMoney_over": "你發送的紅包已過期", + "other_redMoney_over": "對方發送的紅包已過期", + "server_error_tips": "貌似出了點問題...", + "emoji": "表情", + "today_score": "今日簽到可領取/s1積分", + "sign_tips": "1、每日簽到可領取積分,累計天數越多積分越高。\n2、積分可兌換H幣,兌換將消耗對應積分,請慎重兌換。\n3、每月最後一天將重置簽到,清零積分,請記得及時兌換。", + "sign_in": "簽到", + "my_score": "我的積分", + "signin_now": "立即簽到", + "sign_in_day": "已累積簽到/s1天", + "have_get": "已兌換", + "scan": "掃一掃", + "my_qr": "我的二維碼", + "scan_and_add": "掃一掃,加好友", + "amap": "高德地圖", + "baidumap": "百度地圖", + "googlemap": "谷歌地圖", + "applemap": "蘋果地圖", + "go_open": "去開啟", + "Preview": "預覽", + "Photo_album": "相冊", + "all_photo": "全部圖片", + "have_select": "您已經選擇了/s1張圖片", + "loading": "加載中...", + "new_chat_msg": "您有新的聊天消息", + "new_video_msg": "您有新的連麥消息", + "apply_friends": "/s1申請成為你的好友", + "applyed_friends": "/s1通過了你的好友請求", + "contact_permission": "沒有訪問通訊錄的權限", + "contact": "通訊錄", + "search": "搜索", + "contact_add": "添加通訊錄中的好友", + "find": "發現", + "translate_robot": "翻譯機器人", + "robot_hello": "你好,我是翻譯機器人...", + "Simplified_Chinese": "簡體中文", + "traditional_Chinese": "繁體中文", + "english": "英語", + "Vietnamese": "越南語", + "Korean": "韓語", + "Japanese": "日語", + "add_friends": "添加好友", + "stranger": "陌生人", + "receive_stranger": "接收陌生人發送的消息", + "signin": "簽到", + "stranger_close": "對方拒絕接收陌生人發送的消息,是否繼續解鎖全部資料。", + "add": "添加", + "added": "已添加", + "stranger_close_tips": "對方拒絕接收陌生人發送的消息。", + "translate_fail": "翻譯失敗", + "no_photos": "請先上傳照片,再設置紅包照片。", + "successful_appeal1": "你上訴的評價:/s1上訴失敗。", + "add_success": "添加成功,等待對方同意", + "other_pay": "他人代付", + "friend_verification": "朋友驗證", + "add_friends_tips": "你已發送驗證申請,等對方通過", + "i_am": "我是/s1", + "agree": "允許", + "privacyAgreement": "\"Hibok\"需要您同意《隱私協議》方可使用", + "privacy": "隱私協議", + "notification_addfriend": "Hibok!有人申請添加你為好友,看看是誰吧", + "distance_long": "面對面才可以加好友哦", + "chat_tips": "為了翻譯內容的準確性,請不要簡寫", + "fans_list": "粉絲列表", + "system_not_open": "功能內測中", + "service_withdraw_tips": "iOS客戶端暫不支持提現,你可以使用安卓客戶端提現,或點擊下方按鈕進行提現", + "withdraw_tips": "點擊提現", + "add_member": "添加成員", + "delete_member": "刪除成員", + "change_group_name": "修改群名稱", + "my_group_nickname": "我在本群中的暱稱", + "group_chat": "群聊", + "create_group_chat": "創建群聊", + "added_friends_tips": "你需要發送驗證申請,等對方通過", + "group_chat_name": "群聊名稱", + "my_group_nickname_tips": "在這裡可以設置你在這個群裡的暱稱,這個暱稱只會在此群內顯示", + "man_gold": "男神動態", + "woman_gold": "女神動態", + "choose_group_owner": "選擇新群主", + "group_announcement": "群公告", + "chat_news": "聊天消息", + "group_qr": "群二維碼", + "group_setting": "群管理", + "close_news_notice": "消息免打擾", + "set_chat_top": "置頂聊天", + "show_group_member_name": "顯示群成員暱稱", + "quit_group_tips": "退出後不會通知群聊中其他成員,且不會再接收此群聊消息", + "quit_and_delete": "退出並刪除", + "show_more_member": "查看更多群成員", + "group_invite": "群聊邀請確認", + "change_group_owner": "群主管理權轉讓", + "group_setting_tips": "啟用後,群成員需群主確認才能邀請朋友進群。掃二維碼進群將同時停用", + "invite_detail": "邀請詳情", + "undefine_name": "未命名", + "group_qr_code": "群二維碼名片", + "group_qr_code_tips": "該二維碼7天內(/s1月/s2日前)有效,重新進入將更新", + "Goddess_heat": "女神熱度", + "Goddess_heat_tips": "累計收穫的禮物", + "new_friends": "新朋友", + "before_three_day": "三天前", + "after_three_day": "近三天", + "group_clean_chat_record": "清除聊天記錄", + "check": "查看", + "apply_fro_friends": "請求添加你為好友", + "no_vip_cannot_withdraw": "非會員不能提現", + "not_true_woman": "該用戶未認證,謹防被騙", + "join_group": "加入群聊", + "sign_in_apple": "使用Apple登錄", + "only_host": "只有群主才能編輯群公告", + "send_gift1": "你打賞了對方/s1個禮物", + "receive_gift1": "對方打賞了你/s1個禮物", + "not_in_group": "你已不在該群", + "creating_group": "正在創建,請稍等", + "article": "條", + "group_open_verification": "該群已開啟進群驗證只能通過邀請進群", + "group_memeber": "群成員", + "invite_members": "邀請/s1位朋友加入群聊", + "total_members": "共/s1人", + "qr_outtime": "二維碼已過期", + "no_goupr_info": "沒有該群信息", + "you_invite": "你邀請/s1加入了群聊", + "invite_you": "你被/s1拉進了群聊", + "invite_someone": " /s1 邀請 /s2 加入了群聊", + "you": "你", + "delete_group": " /s1 將 /s2 移出了群聊", + "you_group_owner": "你已成為新群主", + "someone_group_owner": "/s1已成為新群主", + "change_group_owner1": "群名已更改為/s1", + "update_group_announce": "群公告已更新", + "you_qr": "你通過掃描二維碼加入群聊", + "others_qr": "/s1通過掃描二維碼加入群聊", + "invite_confirm": "\"/s1\" 想邀請/s2位朋友加入群聊 \\$去確認\\$ ", + "want_invite_confirm": " \"/s1\" 想邀請\"/s2\" 加入群聊", + "join_group_confirm": "\"/s1\" 加入群聊 已確認", + "you_invite_gourp": "你被 /s1 拉進了群聊", + "someone_join_group": " \"/s1\" 加入群聊", + "group_setting_tips1": "群主已開啟\"群聊邀請確認\",群成員需群主確認才能邀請朋友進群", + "group_setting_tips2": "群主已恢復默認進群方式", + "members_max": "群成員已達上限", + "group_max": "群數量已達上限", + "my_money_info": "我的賬單", + "my_left_money": "我的餘額", + "money_tips": "H幣可通過充值或兌換方式獲得,無法進行提現", + "get_money_detail": "收入明細", + "hibok_money": "Hibox收入", + "charge_h": "兌換H幣", + "charge_tips": "提款規則", + "splash_tips1": "百變定位", + "splash_tips2": "翻譯機器人", + "splash_tips3": "交友APP", + "splash_tips_content1": "百變女神,選你所愛", + "splash_tips_content2": "語音互動一起聊", + "splash_tips_content3": "解決語言問題", + "splash_go": "立即體驗", + "change_h_coin": "你通過收入兌換了/s1H幣", + "Representation_succes": "您的申述成功,系統已退款", + "system_give": "系統贈送", + "exchange_fail": "您的提款申請失敗,已退回", + "hibok_exchange": "通過Hibox收入兌換/s1H幣", + "bind_code_success": "成功綁定代理優惠碼", + "translate_money":"您消耗了/s1H幣進行人工翻譯", + "system_back": "系統取消退回", + "you_give": "你打賞了對方", + "you_get":"對方打賞了你", + "enter_num_qian":"兑换数目(单位K)", + "enter_num_qian1":"提现数目(单位K)", + "daily_translate_voucher": "翻譯券", + "msg_notice":"通知消息", + "select_notice_people":"選擇提醒的人", + "search_phone":"查找手機號", + "not_have_user":"用戶不存在", + "not_add_Myself":"你不能添加自己", + "you_are_blaklisted":"對方已拉黑了你", + "confrim_recovery":"確定恢復已被焚毀的照片嗎?\n(已經看過的用戶可以再看一次)", + "send_to": "發送到" +} \ No newline at end of file diff --git a/i18nconfig.json b/i18nconfig.json new file mode 100644 index 0000000..8c8c9ad --- /dev/null +++ b/i18nconfig.json @@ -0,0 +1,22 @@ +{ + "defaultLocale": "en-US", + "locales": [ + "en-US", + "vi-VN", + "zh-HK", + "zh-CN", + "ko-KR", + "ja-JP" + ], + "localePath": "i18n", + "generatedPath": "lib/generated", + "ltr": [ + "en-US", + "vi-VN", + "zh-HK", + "zh-CN", + "ko-KR", + "ja-JP" + ], + "rtl": [] +} \ No newline at end of file diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..58e65f9 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..c242b3d --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/Flutter.podspec b/ios/Flutter/Flutter.podspec new file mode 100644 index 0000000..5ca3041 --- /dev/null +++ b/ios/Flutter/Flutter.podspec @@ -0,0 +1,18 @@ +# +# NOTE: This podspec is NOT to be published. It is only used as a local source! +# + +Pod::Spec.new do |s| + s.name = 'Flutter' + s.version = '1.0.0' + s.summary = 'High-performance, high-fidelity mobile apps.' + s.description = <<-DESC +Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS. + DESC + s.homepage = 'https://flutter.io' + s.license = { :type => 'MIT' } + s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } + s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } + s.ios.deployment_target = '8.0' + s.vendored_frameworks = 'Flutter.framework' +end diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..6f07b31 --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/flutter_export_environment.sh b/ios/Flutter/flutter_export_environment.sh new file mode 100755 index 0000000..4496333 --- /dev/null +++ b/ios/Flutter/flutter_export_environment.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=/Users/random/sdk/flutter_sdk" +export "FLUTTER_APPLICATION_PATH=/Users/random/code/flutter/project/qunliao" +export "FLUTTER_TARGET=/Users/random/code/flutter/project/qunliao/lib/main.dart" +export "FLUTTER_BUILD_DIR=build" +export "SYMROOT=${SOURCE_ROOT}/../build/ios" +export "FLUTTER_FRAMEWORK_DIR=/Users/random/sdk/flutter_sdk/bin/cache/artifacts/engine/ios" +export "FLUTTER_BUILD_NAME=1.0.5" +export "FLUTTER_BUILD_NUMBER=6" +export "TRACK_WIDGET_CREATION=true" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..e428bce --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,90 @@ +# Uncomment this line to define a global platform for your project + platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def parse_KV_file(file, separator='=') + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return []; + end + generated_key_values = {} + skip_line_start_symbols = ["#", "/"] + File.foreach(file_abs_path) do |line| + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } + plugin = line.split(pattern=separator) + if plugin.length == 2 + podname = plugin[0].strip() + path = plugin[1].strip() + podpath = File.expand_path("#{path}", file_abs_path) + generated_key_values[podname] = podpath + else + puts "Invalid plugin specification: #{line}" + end + end + generated_key_values +end + +target 'Runner' do + use_frameworks! + use_modular_headers! + + # Flutter Pod + + copied_flutter_dir = File.join(__dir__, 'Flutter') + copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') + copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') + unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) + # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. + # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. + # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. + + generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') + unless File.exist?(generated_xcode_build_settings_path) + raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) + cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; + + unless File.exist?(copied_framework_path) + FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) + end + unless File.exist?(copied_podspec_path) + FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) + end + end + + # Keep pod path relative so it can be checked into Podfile.lock. + pod 'Flutter', :path => 'Flutter' + + # Plugin Pods + + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock + # referring to absolute paths on developers' machines. + system('rm -rf .symlinks') + system('mkdir -p .symlinks/plugins') + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.each do |name, path| + symlink = File.join('.symlinks', 'plugins', name) + File.symlink(path, symlink) + pod name, :path => File.join(symlink, 'ios') + end +end + +# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. +install! 'cocoapods', :disable_input_output_paths => true + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['ENABLE_BITCODE'] = 'NO' + end + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..291308e --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,391 @@ +PODS: + - agora_rtc_engine (1.0.6): + - AgoraRtcEngine_iOS (= 2.9.1) + - Flutter + - AgoraRtcEngine_iOS (2.9.1) + - amap_location (0.0.1): + - AMapLocation + - Flutter + - AMapFoundation (1.6.2) + - AMapLocation (2.6.4): + - AMapFoundation (~> 1.6.1) + - android_intent (0.0.1): + - Flutter + - app_installer (0.1.0): + - Flutter + - apple_sign_in (0.0.1): + - Flutter + - audioplayer (0.0.1): + - Flutter + - auto_orientation (0.0.1): + - Flutter + - Bugly (2.5.2) + - city_pickers (0.0.1): + - Flutter + - connectivity (0.0.1): + - Flutter + - Reachability + - easy_contact_picker (0.0.1): + - Flutter + - FBSDKCoreKit (5.13.1): + - FBSDKCoreKit/Basics (= 5.13.1) + - FBSDKCoreKit/Core (= 5.13.1) + - FBSDKCoreKit/Basics (5.13.1) + - FBSDKCoreKit/Core (5.13.1): + - FBSDKCoreKit/Basics + - FBSDKLoginKit (5.13.1): + - FBSDKLoginKit/Login (= 5.13.1) + - FBSDKLoginKit/Login (5.13.1): + - FBSDKCoreKit (~> 5.0) + - file_picker (0.0.1): + - Flutter + - Flutter (1.0.0) + - flutter_app_badger (0.0.1): + - Flutter + - flutter_audio_recorder (0.5.4): + - Flutter + - flutter_bugly (0.0.1): + - Bugly + - Flutter + - flutter_facebook_login (0.0.1): + - FBSDKCoreKit (~> 5.5) + - FBSDKLoginKit (~> 5.5) + - Flutter + - flutter_ijkplayer (0.0.1): + - Flutter + - FlutterIJK (~> 0.1.0) + - flutter_image_compress (0.0.1): + - Flutter + - Mantle + - flutter_inapp_purchase (0.0.1): + - Flutter + - flutter_local_notifications (0.0.1): + - Flutter + - flutter_plugin_android_lifecycle (0.0.1): + - Flutter + - flutter_qr_reader (0.0.1): + - Flutter + - flutter_webview_plugin (0.0.1): + - Flutter + - FlutterIJK (0.1.0) + - fluwx_no_pay (0.0.1): + - Flutter + - FMDB (2.7.5): + - FMDB/standard (= 2.7.5) + - FMDB/standard (2.7.5) + - geolocator (5.1.5): + - Flutter + - google_api_availability (2.0.1): + - Flutter + - google_maps_flutter (0.0.1): + - Flutter + - GoogleMaps + - GoogleMaps (3.7.0): + - GoogleMaps/Maps (= 3.7.0) + - GoogleMaps/Base (3.7.0) + - GoogleMaps/Maps (3.7.0): + - GoogleMaps/Base + - image_cropper (0.0.2): + - Flutter + - TOCropViewController (~> 2.5.2) + - image_gallery_saver (0.0.1): + - Flutter + - image_picker (0.0.1): + - Flutter + - JCore (2.1.8) + - JPush (3.2.8): + - JCore (< 3.0.0, >= 2.0.0) + - jpush_flutter (0.0.2): + - Flutter + - JPush + - keyboard_utils (0.0.1): + - Flutter + - libwebp (1.0.3): + - libwebp/demux (= 1.0.3) + - libwebp/mux (= 1.0.3) + - libwebp/webp (= 1.0.3) + - libwebp/demux (1.0.3): + - libwebp/webp + - libwebp/mux (1.0.3): + - libwebp/demux + - libwebp/webp (1.0.3) + - location (0.0.1): + - Flutter + - location_permissions (2.0.3): + - Flutter + - Mantle (2.1.0): + - Mantle/extobjc (= 2.1.0) + - Mantle/extobjc (2.1.0) + - open_file (0.0.1): + - Flutter + - package_info (0.0.1): + - Flutter + - path_provider (0.0.1): + - Flutter + - permission_handler (4.0.0): + - Flutter + - photo_manager (0.0.1): + - Flutter + - Reachability (3.2) + - receive_sharing_intent (0.0.1): + - Flutter + - share (0.5.2): + - Flutter + - shared_preferences (0.0.1): + - Flutter + - shared_preferences_macos (0.0.1): + - Flutter + - shared_preferences_web (0.0.1): + - Flutter + - sqflite (0.0.1): + - Flutter + - FMDB (~> 2.7.2) + - TOCropViewController (2.5.2) + - url_launcher (0.0.1): + - Flutter + - video_player (0.0.1): + - Flutter + - video_thumbnail (0.0.1): + - Flutter + - libwebp + - wifi_info_plugin (0.0.1): + - Flutter + +DEPENDENCIES: + - agora_rtc_engine (from `.symlinks/plugins/agora_rtc_engine/ios`) + - amap_location (from `.symlinks/plugins/amap_location/ios`) + - android_intent (from `.symlinks/plugins/android_intent/ios`) + - app_installer (from `.symlinks/plugins/app_installer/ios`) + - apple_sign_in (from `.symlinks/plugins/apple_sign_in/ios`) + - audioplayer (from `.symlinks/plugins/audioplayer/ios`) + - auto_orientation (from `.symlinks/plugins/auto_orientation/ios`) + - city_pickers (from `.symlinks/plugins/city_pickers/ios`) + - connectivity (from `.symlinks/plugins/connectivity/ios`) + - easy_contact_picker (from `.symlinks/plugins/easy_contact_picker/ios`) + - file_picker (from `.symlinks/plugins/file_picker/ios`) + - Flutter (from `Flutter`) + - flutter_app_badger (from `.symlinks/plugins/flutter_app_badger/ios`) + - flutter_audio_recorder (from `.symlinks/plugins/flutter_audio_recorder/ios`) + - flutter_bugly (from `.symlinks/plugins/flutter_bugly/ios`) + - flutter_facebook_login (from `.symlinks/plugins/flutter_facebook_login/ios`) + - flutter_ijkplayer (from `.symlinks/plugins/flutter_ijkplayer/ios`) + - flutter_image_compress (from `.symlinks/plugins/flutter_image_compress/ios`) + - flutter_inapp_purchase (from `.symlinks/plugins/flutter_inapp_purchase/ios`) + - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) + - flutter_plugin_android_lifecycle (from `.symlinks/plugins/flutter_plugin_android_lifecycle/ios`) + - flutter_qr_reader (from `.symlinks/plugins/flutter_qr_reader/ios`) + - flutter_webview_plugin (from `.symlinks/plugins/flutter_webview_plugin/ios`) + - fluwx_no_pay (from `.symlinks/plugins/fluwx_no_pay/ios`) + - geolocator (from `.symlinks/plugins/geolocator/ios`) + - google_api_availability (from `.symlinks/plugins/google_api_availability/ios`) + - google_maps_flutter (from `.symlinks/plugins/google_maps_flutter/ios`) + - image_cropper (from `.symlinks/plugins/image_cropper/ios`) + - image_gallery_saver (from `.symlinks/plugins/image_gallery_saver/ios`) + - image_picker (from `.symlinks/plugins/image_picker/ios`) + - jpush_flutter (from `.symlinks/plugins/jpush_flutter/ios`) + - keyboard_utils (from `.symlinks/plugins/keyboard_utils/ios`) + - location (from `.symlinks/plugins/location/ios`) + - location_permissions (from `.symlinks/plugins/location_permissions/ios`) + - open_file (from `.symlinks/plugins/open_file/ios`) + - package_info (from `.symlinks/plugins/package_info/ios`) + - path_provider (from `.symlinks/plugins/path_provider/ios`) + - permission_handler (from `.symlinks/plugins/permission_handler/ios`) + - photo_manager (from `.symlinks/plugins/photo_manager/ios`) + - receive_sharing_intent (from `.symlinks/plugins/receive_sharing_intent/ios`) + - share (from `.symlinks/plugins/share/ios`) + - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) + - shared_preferences_macos (from `.symlinks/plugins/shared_preferences_macos/ios`) + - shared_preferences_web (from `.symlinks/plugins/shared_preferences_web/ios`) + - sqflite (from `.symlinks/plugins/sqflite/ios`) + - url_launcher (from `.symlinks/plugins/url_launcher/ios`) + - video_player (from `.symlinks/plugins/video_player/ios`) + - video_thumbnail (from `.symlinks/plugins/video_thumbnail/ios`) + - wifi_info_plugin (from `.symlinks/plugins/wifi_info_plugin/ios`) + +SPEC REPOS: + trunk: + - AgoraRtcEngine_iOS + - AMapFoundation + - AMapLocation + - Bugly + - FBSDKCoreKit + - FBSDKLoginKit + - FlutterIJK + - FMDB + - GoogleMaps + - JCore + - JPush + - libwebp + - Mantle + - Reachability + - TOCropViewController + +EXTERNAL SOURCES: + agora_rtc_engine: + :path: ".symlinks/plugins/agora_rtc_engine/ios" + amap_location: + :path: ".symlinks/plugins/amap_location/ios" + android_intent: + :path: ".symlinks/plugins/android_intent/ios" + app_installer: + :path: ".symlinks/plugins/app_installer/ios" + apple_sign_in: + :path: ".symlinks/plugins/apple_sign_in/ios" + audioplayer: + :path: ".symlinks/plugins/audioplayer/ios" + auto_orientation: + :path: ".symlinks/plugins/auto_orientation/ios" + city_pickers: + :path: ".symlinks/plugins/city_pickers/ios" + connectivity: + :path: ".symlinks/plugins/connectivity/ios" + easy_contact_picker: + :path: ".symlinks/plugins/easy_contact_picker/ios" + file_picker: + :path: ".symlinks/plugins/file_picker/ios" + Flutter: + :path: Flutter + flutter_app_badger: + :path: ".symlinks/plugins/flutter_app_badger/ios" + flutter_audio_recorder: + :path: ".symlinks/plugins/flutter_audio_recorder/ios" + flutter_bugly: + :path: ".symlinks/plugins/flutter_bugly/ios" + flutter_facebook_login: + :path: ".symlinks/plugins/flutter_facebook_login/ios" + flutter_ijkplayer: + :path: ".symlinks/plugins/flutter_ijkplayer/ios" + flutter_image_compress: + :path: ".symlinks/plugins/flutter_image_compress/ios" + flutter_inapp_purchase: + :path: ".symlinks/plugins/flutter_inapp_purchase/ios" + flutter_local_notifications: + :path: ".symlinks/plugins/flutter_local_notifications/ios" + flutter_plugin_android_lifecycle: + :path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios" + flutter_qr_reader: + :path: ".symlinks/plugins/flutter_qr_reader/ios" + flutter_webview_plugin: + :path: ".symlinks/plugins/flutter_webview_plugin/ios" + fluwx_no_pay: + :path: ".symlinks/plugins/fluwx_no_pay/ios" + geolocator: + :path: ".symlinks/plugins/geolocator/ios" + google_api_availability: + :path: ".symlinks/plugins/google_api_availability/ios" + google_maps_flutter: + :path: ".symlinks/plugins/google_maps_flutter/ios" + image_cropper: + :path: ".symlinks/plugins/image_cropper/ios" + image_gallery_saver: + :path: ".symlinks/plugins/image_gallery_saver/ios" + image_picker: + :path: ".symlinks/plugins/image_picker/ios" + jpush_flutter: + :path: ".symlinks/plugins/jpush_flutter/ios" + keyboard_utils: + :path: ".symlinks/plugins/keyboard_utils/ios" + location: + :path: ".symlinks/plugins/location/ios" + location_permissions: + :path: ".symlinks/plugins/location_permissions/ios" + open_file: + :path: ".symlinks/plugins/open_file/ios" + package_info: + :path: ".symlinks/plugins/package_info/ios" + path_provider: + :path: ".symlinks/plugins/path_provider/ios" + permission_handler: + :path: ".symlinks/plugins/permission_handler/ios" + photo_manager: + :path: ".symlinks/plugins/photo_manager/ios" + receive_sharing_intent: + :path: ".symlinks/plugins/receive_sharing_intent/ios" + share: + :path: ".symlinks/plugins/share/ios" + shared_preferences: + :path: ".symlinks/plugins/shared_preferences/ios" + shared_preferences_macos: + :path: ".symlinks/plugins/shared_preferences_macos/ios" + shared_preferences_web: + :path: ".symlinks/plugins/shared_preferences_web/ios" + sqflite: + :path: ".symlinks/plugins/sqflite/ios" + url_launcher: + :path: ".symlinks/plugins/url_launcher/ios" + video_player: + :path: ".symlinks/plugins/video_player/ios" + video_thumbnail: + :path: ".symlinks/plugins/video_thumbnail/ios" + wifi_info_plugin: + :path: ".symlinks/plugins/wifi_info_plugin/ios" + +SPEC CHECKSUMS: + agora_rtc_engine: 653a2211f179b00e5b696410829febafa046f8b4 + AgoraRtcEngine_iOS: b2eedd8f9ab47b71163f3285e836bd23feb43fff + amap_location: a3e2a140bb25950d4e97560ce1b00e53a121e4f4 + AMapFoundation: 672dc3a4759cb733f447c1e1b020f7ba2729f4ab + AMapLocation: b4162db67f813508a14ee7e05c7ee4073785221d + android_intent: f144b3783d533cc5bc2cd04cdbd1dc2b6950bd69 + app_installer: c0d3e58ec1f19df67307d7e988d5e0ccf8a47a52 + apple_sign_in: 7716c7ddfa195aeab7dec0dc374ef4ff45d1adb4 + audioplayer: f4462b84216b9c55f02bbbdc7ab60eec7427b2d4 + auto_orientation: 2941c44ebe5c3d41016001597ab03e81a92a26ce + Bugly: dbac48b55ad469a97cc4321045cd50df8f63d44f + city_pickers: b0370f4c35c201723b5b7fcce10ec29b59d5bc35 + connectivity: 6e94255659cc86dcbef1d452ad3e0491bb1b3e75 + easy_contact_picker: 9ab9dc70e8ddde6e76a19ffc482d7bf899868730 + FBSDKCoreKit: 8fb98209109fb684937f05d534305edb18c20207 + FBSDKLoginKit: c7c6ffd9ca9ea45aee32361840af040ad8f6706a + file_picker: 408623be2125b79a4539cf703be3d4b3abe5e245 + Flutter: 0e3d915762c693b495b44d77113d4970485de6ec + flutter_app_badger: 65de4d6f0c34a891df49e6cfb8a1c0496426fa68 + flutter_audio_recorder: eb998d4e75e59b39d9e3ca1818a5e0f3a82f5836 + flutter_bugly: c9800f4d5bc5bdc27ffdde3417a26ba44266e0c3 + flutter_facebook_login: cfb5659f686b1c575ef205c6b6fd20db9679d3c4 + flutter_ijkplayer: ef9006131553deb6d8ae6d7fbd3bcbf93b135930 + flutter_image_compress: f69d0e0e078ce52b4810695593bc861ee319ae7d + flutter_inapp_purchase: 5c6a1ac3f11b11d0c8c0321c0c41c1f05805e4c8 + flutter_local_notifications: 9e4738ce2471c5af910d961a6b7eadcf57c50186 + flutter_plugin_android_lifecycle: 47de533a02850f070f5696a623995e93eddcdb9b + flutter_qr_reader: 254fd9eea45a65ef461e050d6607daf9cfb753e8 + flutter_webview_plugin: ed9e8a6a96baf0c867e90e1bce2673913eeac694 + FlutterIJK: 68b00c1d11162b5016f3611853aa699e198bd1d2 + fluwx_no_pay: 50ed1ec3cb01457042232905b851071dfb3b84a7 + FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + geolocator: 80aba2bb48f8c7dfc5a8b70b9d13fc3edc8399c4 + google_api_availability: 163b30f802e6148c67f092aa4501c90ddd8eec8d + google_maps_flutter: d0dd62f5a7d39bae61057eb9f52dd778d99c7c6c + GoogleMaps: 55da829c68aa931f3ae982b9e341cc2f3d89c587 + image_cropper: 3c16d7651730ffe85897f5a1c4e2547e6b54989a + image_gallery_saver: 73b3cd8ad9c950c739878af9c311744d1bf5405d + image_picker: e3eacd46b94694dde7cf2705955cece853aa1a8f + JCore: a7f1dead960d77a97717c73ea8b0aa5b33706491 + JPush: 8ce888d6dedfa417e90c8b6bc87405a16ce2e699 + jpush_flutter: 69133df35eaf9135e540549b154d992c44f8ee44 + keyboard_utils: ab24bc711be9e91a5937c20489056b8dd650fecc + libwebp: 057912d6d0abfb6357d8bb05c0ea470301f5d61e + location: 3a2eed4dd2fab25e7b7baf2a9efefe82b512d740 + location_permissions: 195ff2a1182fa9029ef3f2653156961ee5a1e40b + Mantle: 2fa750afa478cd625a94230fbf1c13462f29395b + open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d + package_info: 48b108e75b8802c2d5e126f208ef540561c98aef + path_provider: fb74bd0465e96b594bb3b5088ee4a4e7bb1f2a9d + permission_handler: 0fb88b8a3c23e31e5de45b8f1bb8b7de28cf8941 + photo_manager: f7c619c2cc8c2adb8d85c63363babac477de9c67 + Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 + receive_sharing_intent: c0d87310754e74c0f9542947e7cbdf3a0335a3b1 + share: bae0a282aab4483288913fc4dc0b935d4b491f2e + shared_preferences: 430726339841afefe5142b9c1f50cb6bd7793e01 + shared_preferences_macos: f3f29b71ccbb56bf40c9dd6396c9acf15e214087 + shared_preferences_web: 141cce0c3ed1a1c5bf2a0e44f52d31eeb66e5ea9 + sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0 + TOCropViewController: e9da34f484aedd4e5d5a8ab230ba217cfe16c729 + url_launcher: a1c0cc845906122c4784c542523d8cacbded5626 + video_player: 69c5f029fac4ffe4fc8a85ea7f7b793709661549 + video_thumbnail: c4e2a3c539e247d4de13cd545344fd2d26ffafd1 + wifi_info_plugin: ff6048382842ec5c7594460750ae96ad54bd3044 + +PODFILE CHECKSUM: 1a36abd97d6ef8a9a64844b75e3a41d456448dec + +COCOAPODS: 1.8.4 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..61ca478 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,875 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 5C60199023A719FD00D1DB1E /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 55B5585223A364C300531379 /* Info.plist */; }; + 5C95C0912406514F00CEBCE3 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C95C0902406514F00CEBCE3 /* ShareViewController.swift */; }; + 5C95C0942406514F00CEBCE3 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5C95C0922406514F00CEBCE3 /* MainInterface.storyboard */; }; + 5C95C0982406514F00CEBCE3 /* Share Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 5C95C08E2406514F00CEBCE3 /* Share Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 5CDF760323AB4AC2002E6DF9 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CDF760523AB4AC2002E6DF9 /* InfoPlist.strings */; }; + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; + 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + D34B099915D830BEECE2A21C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A31DC0BCE3BBDE9DB405FE6 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 5C95C0962406514F00CEBCE3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5C95C08D2406514F00CEBCE3; + remoteInfo = "Share Extension"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 5C95C0992406514F00CEBCE3 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 5C95C0982406514F00CEBCE3 /* Share Extension.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 1EFE82ACF3C79BC7EE01A8E9 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 5153B98FA78898F848ACB2BE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 55B5585223A364C300531379 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5C60198F23A717FB00D1DB1E /* Runner.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + 5C95C08E2406514F00CEBCE3 /* Share Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Share Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + 5C95C0902406514F00CEBCE3 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = ""; }; + 5C95C0932406514F00CEBCE3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = ""; }; + 5C95C0952406514F00CEBCE3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5C95C09E240655AF00CEBCE3 /* Share ExtensionProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Share ExtensionProfile.entitlements"; sourceTree = ""; }; + 5C95C09F240655F500CEBCE3 /* RunnerProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerProfile.entitlements; sourceTree = ""; }; + 5C95C0A0240754B900CEBCE3 /* Share Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Share Extension.entitlements"; sourceTree = ""; }; + 5CDF760423AB4AC2002E6DF9 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 5CDF760623AB4B55002E6DF9 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; }; + 5CDF760723AB872C002E6DF9 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/InfoPlist.strings; sourceTree = ""; }; + 5CFAF1B023AB8D140097F186 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/InfoPlist.strings"; sourceTree = ""; }; + 5CFAF1B123AB8D220097F186 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/InfoPlist.strings; sourceTree = ""; }; + 5CFAF1B223AB8D310097F186 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/InfoPlist.strings; sourceTree = ""; }; + 72F4344FD9917096E93A1968 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 8A31DC0BCE3BBDE9DB405FE6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5C95C08B2406514F00CEBCE3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + D34B099915D830BEECE2A21C /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 19BD53E34344AF42C09DC0A3 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8A31DC0BCE3BBDE9DB405FE6 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 5C95C08F2406514F00CEBCE3 /* Share Extension */ = { + isa = PBXGroup; + children = ( + 5C95C0A0240754B900CEBCE3 /* Share Extension.entitlements */, + 5C95C09E240655AF00CEBCE3 /* Share ExtensionProfile.entitlements */, + 5C95C0902406514F00CEBCE3 /* ShareViewController.swift */, + 5C95C0922406514F00CEBCE3 /* MainInterface.storyboard */, + 5C95C0952406514F00CEBCE3 /* Info.plist */, + ); + path = "Share Extension"; + sourceTree = ""; + }; + 8E51791D64FE2BD2495C930B /* Pods */ = { + isa = PBXGroup; + children = ( + 72F4344FD9917096E93A1968 /* Pods-Runner.debug.xcconfig */, + 1EFE82ACF3C79BC7EE01A8E9 /* Pods-Runner.release.xcconfig */, + 5153B98FA78898F848ACB2BE /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B80C3931E831B6300D905FE /* App.framework */, + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEBA1CF902C7004384FC /* Flutter.framework */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 5C95C08F2406514F00CEBCE3 /* Share Extension */, + 97C146EF1CF9000F007C117D /* Products */, + 8E51791D64FE2BD2495C930B /* Pods */, + 19BD53E34344AF42C09DC0A3 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 5C95C08E2406514F00CEBCE3 /* Share Extension.appex */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 5C95C09F240655F500CEBCE3 /* RunnerProfile.entitlements */, + 5C60198F23A717FB00D1DB1E /* Runner.entitlements */, + 55B5585223A364C300531379 /* Info.plist */, + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 5CDF760523AB4AC2002E6DF9 /* InfoPlist.strings */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 97C146F21CF9000F007C117D /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 5C95C08D2406514F00CEBCE3 /* Share Extension */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5C95C09D2406514F00CEBCE3 /* Build configuration list for PBXNativeTarget "Share Extension" */; + buildPhases = ( + 5C95C08A2406514F00CEBCE3 /* Sources */, + 5C95C08B2406514F00CEBCE3 /* Frameworks */, + 5C95C08C2406514F00CEBCE3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Share Extension"; + productName = "Share Extension"; + productReference = 5C95C08E2406514F00CEBCE3 /* Share Extension.appex */; + productType = "com.apple.product-type.app-extension"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 3350986A0786211686578BBB /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 74E44EF25DBCD813164B0D15 /* [CP] Embed Pods Frameworks */, + 72C47CA77DA3D0C2C0859F91 /* [CP] Copy Pods Resources */, + 5C95C0992406514F00CEBCE3 /* Embed App Extensions */, + ); + buildRules = ( + ); + dependencies = ( + 5C95C0972406514F00CEBCE3 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + DefaultBuildSystemTypeForWorkspace = Original; + LastSwiftUpdateCheck = 1130; + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 5C95C08D2406514F00CEBCE3 = { + CreatedOnToolsVersion = 11.3; + DevelopmentTeam = 76U6VCZ8JY; + ProvisioningStyle = Automatic; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = 76U6VCZ8JY; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + "zh-Hans", + vi, + "zh-Hant", + ja, + ko, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 5C95C08D2406514F00CEBCE3 /* Share Extension */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 5C95C08C2406514F00CEBCE3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5C95C0942406514F00CEBCE3 /* MainInterface.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5C60199023A719FD00D1DB1E /* Info.plist in Resources */, + 5CDF760323AB4AC2002E6DF9 /* InfoPlist.strings in Resources */, + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3350986A0786211686578BBB /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + }; + 72C47CA77DA3D0C2C0859F91 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 74E44EF25DBCD813164B0D15 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5C95C08A2406514F00CEBCE3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5C95C0912406514F00CEBCE3 /* ShareViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, + 97C146F31CF9000F007C117D /* main.m in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 5C95C0972406514F00CEBCE3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5C95C08D2406514F00CEBCE3 /* Share Extension */; + targetProxy = 5C95C0962406514F00CEBCE3 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 5C95C0922406514F00CEBCE3 /* MainInterface.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 5C95C0932406514F00CEBCE3 /* Base */, + ); + name = MainInterface.storyboard; + sourceTree = ""; + }; + 5CDF760523AB4AC2002E6DF9 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 5CDF760423AB4AC2002E6DF9 /* en */, + 5CDF760623AB4B55002E6DF9 /* zh-Hans */, + 5CDF760723AB872C002E6DF9 /* vi */, + 5CFAF1B023AB8D140097F186 /* zh-Hant */, + 5CFAF1B123AB8D220097F186 /* ja */, + 5CFAF1B223AB8D310097F186 /* ko */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 9; + DEVELOPMENT_TEAM = 76U6VCZ8JY; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + MARKETING_VERSION = 1.0.7; + PRODUCT_BUNDLE_IDENTIFIER = com.cyhd.henho; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; + VALID_ARCHS = "arm64 arm64e armv7s"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 5C95C09A2406514F00CEBCE3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 9; + DEVELOPMENT_TEAM = 76U6VCZ8JY; + ENABLE_BITCODE = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "Share Extension/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + MARKETING_VERSION = 1.0.7; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = ""; + PRODUCT_BUNDLE_IDENTIFIER = com.cyhd.henho.share; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 5C95C09B2406514F00CEBCE3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 9; + DEVELOPMENT_TEAM = 76U6VCZ8JY; + ENABLE_BITCODE = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "Share Extension/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + MARKETING_VERSION = 1.0.7; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = ""; + PRODUCT_BUNDLE_IDENTIFIER = com.cyhd.henho.share; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; + 5C95C09C2406514F00CEBCE3 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = "Share Extension/Share ExtensionProfile.entitlements"; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 9; + DEVELOPMENT_TEAM = 76U6VCZ8JY; + ENABLE_BITCODE = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "Share Extension/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + MARKETING_VERSION = 1.0.7; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = ""; + PRODUCT_BUNDLE_IDENTIFIER = com.cyhd.henho.share; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 9; + DEVELOPMENT_TEAM = 76U6VCZ8JY; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + MARKETING_VERSION = 1.0.7; + PRODUCT_BUNDLE_IDENTIFIER = com.cyhd.henho; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; + VALID_ARCHS = "arm64 arm64e armv7s"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 9; + DEVELOPMENT_TEAM = 76U6VCZ8JY; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + MARKETING_VERSION = 1.0.7; + PRODUCT_BUNDLE_IDENTIFIER = com.cyhd.henho; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; + VALID_ARCHS = "arm64 arm64e armv7s"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 5C95C09D2406514F00CEBCE3 /* Build configuration list for PBXNativeTarget "Share Extension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5C95C09A2406514F00CEBCE3 /* Debug */, + 5C95C09B2406514F00CEBCE3 /* Release */, + 5C95C09C2406514F00CEBCE3 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..59c6d39 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..41a8126 --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..6b30c74 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,10 @@ + + + + + BuildSystemType + Original + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.h b/ios/Runner/AppDelegate.h new file mode 100644 index 0000000..106c836 --- /dev/null +++ b/ios/Runner/AppDelegate.h @@ -0,0 +1,13 @@ +#import +#import + +@interface AppDelegate : FlutterAppDelegate +{ + +} +@property (nonatomic,assign) UIBackgroundTaskIdentifier task; +@property (nonatomic, strong) FlutterEventSink eventSink; + +@end + + diff --git a/ios/Runner/AppDelegate.m b/ios/Runner/AppDelegate.m new file mode 100644 index 0000000..2624940 --- /dev/null +++ b/ios/Runner/AppDelegate.m @@ -0,0 +1,271 @@ +#include "AppDelegate.h" +#include "GeneratedPluginRegistrant.h" +#import "GoogleMaps/GoogleMaps.h" +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application +didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [GMSServices provideAPIKey:@"AIzaSyAb9JNtW0BEZ_qLeDg87ZhvxSmZply-7hU"]; + + FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController; + + FlutterMethodChannel* channel = [FlutterMethodChannel + methodChannelWithName:@"make.photo.screen.hibok" + binaryMessenger:controller]; + + [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { + if ([@"makePhotoScreen" isEqualToString:call.method]) { + UIImage* img = [self makePhotoScreen: controller.view]; + + NSData *imageData = UIImageJPEGRepresentation(img, 0.8); + FlutterStandardTypedData* value = [FlutterStandardTypedData typedDataWithBytes:imageData]; + + result(value); + }else if([@"openMapForOth" isEqualToString:call.method]){ + NSDictionary* params = call.arguments; + NSString* mapType = params[@"mapType"]; + NSArray* latLng = params[@"latLng"]; + NSString* address = params[@"address"]; + + [self openMapForOth:mapType latLng:latLng adress:address]; + }else if([@"getListForMap" isEqualToString:call.method]){ + NSArray* supportMaps = [self getListForMap]; + result(supportMaps); + } + else + { + result(FlutterMethodNotImplemented); + } + }]; + + + // 创建eventChannel 代理方法里处理stream流 delegate设置为self + FlutterEventChannel *eventChannel = [FlutterEventChannel eventChannelWithName:@"com.file.hibok" binaryMessenger:controller]; + [eventChannel setStreamHandler:self]; + + [GeneratedPluginRegistrant registerWithRegistry:self]; + + + if(![[NSUserDefaults standardUserDefaults]objectForKey:@"Notification"]){ + [[UIApplication sharedApplication] cancelAllLocalNotifications]; + [[NSUserDefaults standardUserDefaults]setBool:YES forKey:@"Notification"]; + } + + // Override point for customization after application launch. + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + + + +#pragma mark - FlutterStreamHandler +- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments + eventSink:(FlutterEventSink)eventSink{ + self.eventSink = eventSink; + return nil; +} + +- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments { + return nil; +} + +- (UIImage*)makePhotoScreen:(UIView*)view { + + CGSize size = view.bounds.size; + UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); + [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + // CGImageRef imageRef =image.CGImage; + + // CGRect rect = CGRectMake(CGImageGetWidth(imageRef)/4, CGImageGetHeight(imageRef)/2-CGImageGetWidth(imageRef)/2, CGImageGetWidth(imageRef)/2, CGImageGetWidth(imageRef)/2);//这里可以设置想要截图的区域 + // + // CGImageRef imageRefRect =CGImageCreateWithImageInRect(imageRef, rect); + // + // UIImage *sendImage =[[UIImage alloc] initWithCGImage:imageRefRect]; + // + // + + return image; +} + +- (NSArray*)getListForMap{ + + NSMutableArray* maps = [[NSMutableArray alloc] init]; + + //苹果地图 + [maps addObject:@"apple"]; + + + //谷歌地图 + + if([[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:@"comgooglemaps://"]]) { + [maps addObject:@"google"]; + + } + + //高德地图 + + if([[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:@"iosamap://"]]) { + [maps addObject:@"minimap"]; + } + + //百度地图 + + if([[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:@"baidumap://"]]) { + [maps addObject:@"baidu"]; + } + + + + + + + return maps; + +} + +-(void) openMapForOth:(NSString *)mapType latLng:(NSArray*)latLng adress:(NSString*)adress { + + if([mapType isEqualToString:@"baidu"]){ + NSString*urlString = [[NSString stringWithFormat:@"baidumap://map/geocoder?location=%@f,%@f&coord_type=gcj02&src=com.cyhd.henhoandroid",latLng.firstObject, latLng.lastObject] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; + [[UIApplication sharedApplication] openURL: [NSURL URLWithString:urlString]]; + + }else if([mapType isEqualToString:@"minimap"]){ + + NSString*urlString = [[NSString stringWithFormat:@"iosamap://navi?sourceApplication= &lat=%@f&lon=%@f&dev=1",latLng.firstObject, latLng.lastObject] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; + + [[UIApplication sharedApplication] openURL: [NSURL URLWithString:urlString]]; + + }else if([mapType isEqualToString:@"apple"]){ + + NSString*urlString = [[NSString stringWithFormat:@"http://maps.apple.com/?daddr=%@f,%@f",latLng.firstObject, latLng.lastObject] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; + [[UIApplication sharedApplication] openURL: [NSURL URLWithString:urlString]]; + + }else if([mapType isEqualToString:@"google"]){ + + NSString*urlString = [[NSString stringWithFormat:@"comgooglemaps://?daddr=%@f,%@f",latLng.firstObject, latLng.lastObject] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; + [[UIApplication sharedApplication] openURL: [NSURL URLWithString:urlString]]; + } + +} + + +- (void)applicationDidEnterBackground:(UIApplication *)application { + + + self.task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + + [[UIApplication sharedApplication] endBackgroundTask:self.task]; + self.task = UIBackgroundTaskInvalid; + + }]; + + +// __block int count = 0; +// [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) { +// +// count ++; +// NSLog(@"%d",count); +// +// }]; + +} + + +//申请后台运行权限 +- (void)backGroundSpeech { + UIApplication *app = [UIApplication sharedApplication]; + __block UIBackgroundTaskIdentifier bgTask; + bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ + dispatch_async(dispatch_get_main_queue(), ^{ + if (bgTask != UIBackgroundTaskInvalid) + { + bgTask = UIBackgroundTaskInvalid; + } + }); + }]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + dispatch_async(dispatch_get_main_queue(), ^{ + if (bgTask != UIBackgroundTaskInvalid) + { + bgTask = UIBackgroundTaskInvalid; + } + }); + }); +} + + + + + + +#pragma mark ------------------ 结束后台任务 ------------------ +- (void)endBackgroundUpdateask{ + [[UIApplication sharedApplication] endBackgroundTask:self.task]; + self.task = UIBackgroundTaskInvalid; +} + + + + +- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options +{ + + NSLog(@"myurl %@",url.absoluteString); + +// if (url != nil) { +//// 不跟分享插件冲突 +// if ([url.absoluteString containsString:@"SharePhotos"]) { +// NSLog(@"myurl 存在"); +// +// } +// } + + if (url != nil && [url.absoluteString containsString:@"file:///private"]) { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths lastObject]; + if (url != nil) { + NSString *path = [url absoluteString]; + path = [path stringByRemovingPercentEncoding]; + NSMutableString *string = [[NSMutableString alloc] initWithString:path]; + if ([path hasPrefix:@"file:///private"]) { + [string replaceOccurrencesOfString:@"file:///private" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, path.length)]; + } + NSArray *tempArray = [string componentsSeparatedByString:@"/"]; + NSString *fileName = tempArray.lastObject; + NSString *sourceName = options[@"UIApplicationOpenURLOptionsSourceApplicationKey"]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",fileName]]; + if ([fileManager fileExistsAtPath:filePath]) { + NSLog(@"文件已存在"); + self.eventSink(filePath); + // [SVProgressHUD showErrorWithStatus:@"文件已存在"]; + return YES; + } + // [MRTools creatFilePathInManager:sourceName]; + + BOOL isSuccess = [fileManager copyItemAtPath:string toPath:filePath error:nil]; + if (isSuccess == YES) { + NSLog(@"拷贝成功"); + self.eventSink(filePath); + // [SVProgressHUD showSuccessWithStatus:@"文件拷贝成功"]; + } else { + NSLog(@"拷贝失败"); + // [SVProgressHUD showErrorWithStatus:@"文件拷贝失败"]; + } + } + }else{ + [super application:self openURL:url options:nil]; + return YES; + } + + + + NSLog(@"application:openURL:options:"); + return YES; +} + + +@end diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..193d0dc --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,158 @@ +{ + "images": [ + { + "size": "20x20", + "idiom": "iphone", + "filename": "icon-20@2x.png", + "scale": "2x" + }, + { + "size": "20x20", + "idiom": "iphone", + "filename": "icon-20@3x.png", + "scale": "3x" + }, + { + "size": "29x29", + "idiom": "iphone", + "filename": "icon-29.png", + "scale": "1x" + }, + { + "size": "29x29", + "idiom": "iphone", + "filename": "icon-29@2x.png", + "scale": "2x" + }, + { + "size": "29x29", + "idiom": "iphone", + "filename": "icon-29@3x.png", + "scale": "3x" + }, + { + "size": "40x40", + "idiom": "iphone", + "filename": "icon-40@2x.png", + "scale": "2x" + }, + { + "size": "40x40", + "idiom": "iphone", + "filename": "icon-40@3x.png", + "scale": "3x" + }, + { + "size": "57x57", + "idiom": "iphone", + "filename": "icon-57.png", + "scale": "1x" + }, + { + "size": "57x57", + "idiom": "iphone", + "filename": "icon-57@2x.png", + "scale": "2x" + }, + { + "size": "60x60", + "idiom": "iphone", + "filename": "icon-60@2x.png", + "scale": "2x" + }, + { + "size": "60x60", + "idiom": "iphone", + "filename": "icon-60@3x.png", + "scale": "3x" + }, + { + "size": "20x20", + "idiom": "ipad", + "filename": "icon-20-ipad.png", + "scale": "1x" + }, + { + "size": "20x20", + "idiom": "ipad", + "filename": "icon-20@2x-ipad.png", + "scale": "2x" + }, + { + "size": "29x29", + "idiom": "ipad", + "filename": "icon-29-ipad.png", + "scale": "1x" + }, + { + "size": "29x29", + "idiom": "ipad", + "filename": "icon-29@2x-ipad.png", + "scale": "2x" + }, + { + "size": "40x40", + "idiom": "ipad", + "filename": "icon-40.png", + "scale": "1x" + }, + { + "size": "40x40", + "idiom": "ipad", + "filename": "icon-40@2x.png", + "scale": "2x" + }, + { + "size": "50x50", + "idiom": "ipad", + "filename": "icon-50.png", + "scale": "1x" + }, + { + "size": "50x50", + "idiom": "ipad", + "filename": "icon-50@2x.png", + "scale": "2x" + }, + { + "size": "72x72", + "idiom": "ipad", + "filename": "icon-72.png", + "scale": "1x" + }, + { + "size": "72x72", + "idiom": "ipad", + "filename": "icon-72@2x.png", + "scale": "2x" + }, + { + "size": "76x76", + "idiom": "ipad", + "filename": "icon-76.png", + "scale": "1x" + }, + { + "size": "76x76", + "idiom": "ipad", + "filename": "icon-76@2x.png", + "scale": "2x" + }, + { + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "icon-83.5@2x.png", + "scale": "2x" + }, + { + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "icon-1024.png", + "scale": "1x" + } + ], + "info": { + "version": 1, + "author": "icon.wuruihong.com" + } +} \ No newline at end of file diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png new file mode 100644 index 0000000..ea7e0a5 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png new file mode 100644 index 0000000..e2ae424 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png new file mode 100644 index 0000000..20aa80a Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png new file mode 100644 index 0000000..20aa80a Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png new file mode 100644 index 0000000..3ceeebd Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png new file mode 100644 index 0000000..d7da6be Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png new file mode 100644 index 0000000..d7da6be Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png new file mode 100644 index 0000000..ff5e169 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png new file mode 100644 index 0000000..ff5e169 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png new file mode 100644 index 0000000..c9975c6 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png new file mode 100644 index 0000000..20aa80a Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png new file mode 100644 index 0000000..a68352b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png new file mode 100644 index 0000000..186fe66 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-50.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-50.png new file mode 100644 index 0000000..4591db4 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-50.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png new file mode 100644 index 0000000..ecd5652 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-57.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-57.png new file mode 100644 index 0000000..dafc433 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-57.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png new file mode 100644 index 0000000..89b3ff4 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png new file mode 100644 index 0000000..186fe66 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png new file mode 100644 index 0000000..a250e81 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-72.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-72.png new file mode 100644 index 0000000..e10aacf Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-72.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png new file mode 100644 index 0000000..21f1074 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png new file mode 100644 index 0000000..5092bd0 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png new file mode 100644 index 0000000..d2161c0 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png new file mode 100644 index 0000000..da0ae07 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..d08a4de --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..65a94b5 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..497371e --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..d50e550 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..a7fede0 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,194 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDocumentTypes + + + CFBundleTypeIconFiles + + CFBundleTypeName + OFFICE Document + LSHandlerRank + Owner + LSItemContentTypes + + com.microsoft.word.doc + com.microsoft.powerpoint.ppt + com.microsoft.excel.xls + com.adobe.pdf + org.openxmlformats.wordprocessingml.document + org.openxmlformats.presentationml.presentation + org.openxmlformats.spreadsheetml.sheet + public.data + + + + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Hibok + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleURLSchemes + + fb473720630090702 + + + + CFBundleTypeRole + Editor + CFBundleURLSchemes + + SharePhotos + wx02328a8853f058ad + + + + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + FacebookAppID + 473720630090702 + FacebookDisplayName + Hibok + LSApplicationQueriesSchemes + + weixin + weixinULAPI + fb-messenger-share-api + fbauth2 + fbapi + fbshareextension + iosamap + baidumap + comgooglemaps + + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSAllowsArbitraryLoadsInWebContent + + + NSAppleMusicUsageDescription + We use access to music responsibly + NSCalendarsUsageDescription + App need your agree, can visit your calendars + NSCameraUsageDescription + App need your agree, can visit your camera to take a picture and send it to a friend + NSContactsUsageDescription + App need your agree, can visit your contacts + NSLocationAlwaysUsageDescription + App need your agree, get your location to find nearby friends + NSLocationWhenInUseUsageDescription + App need your agree, get your location to find nearby friends + NSMicrophoneUsageDescription + App need your agree, can visit your microphone + NSMotionUsageDescription + App need your agree, can visit your motion + NSPhotoLibraryAddUsageDescription + App need your agree, can add photo + NSPhotoLibraryUsageDescription + App need your agree, can visit your photo library and send picture to friends + NSSpeechRecognitionUsageDescription + App need your agree, can visit your speech + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + UTExportedTypeDeclarations + + + UTTypeConformsTo + + public.data + public.composite-content + + UTTypeDescription + PDF文档 + UTTypeIdentifier + com.adobe.pdf + UTTypeTagSpecification + + public.filename-extension + + pdf + + public.mime-type + application/pdf + + + + UTTypeConformsTo + + public.data + + UTTypeDescription + Word文档 + UTTypeIdentifier + com.microsoft.word.doc + UTTypeTagSpecification + + public.filename-extension + + doc + docx + + public.mime-type + application/msword + + + + UTTypeConformsTo + + public.data + + UTTypeDescription + Excel Document + UTTypeIdentifier + com.microsoft.excel.xls + UTTypeTagSpecification + + public.filename-extension + + xls + + public.mime-type + application/vnd.ms-excel + + + + io.flutter.embedded_views_preview + + kTCCServiceMediaLibrary + App need your agree, can visit your music + + diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements new file mode 100644 index 0000000..96eb663 --- /dev/null +++ b/ios/Runner/Runner.entitlements @@ -0,0 +1,16 @@ + + + + + aps-environment + development + com.apple.developer.applesignin + + Default + + com.apple.security.application-groups + + group.com.cyhd.henho + + + diff --git a/ios/Runner/RunnerProfile.entitlements b/ios/Runner/RunnerProfile.entitlements new file mode 100644 index 0000000..96eb663 --- /dev/null +++ b/ios/Runner/RunnerProfile.entitlements @@ -0,0 +1,16 @@ + + + + + aps-environment + development + com.apple.developer.applesignin + + Default + + com.apple.security.application-groups + + group.com.cyhd.henho + + + diff --git a/ios/Runner/en.lproj/InfoPlist.strings b/ios/Runner/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..1852f04 --- /dev/null +++ b/ios/Runner/en.lproj/InfoPlist.strings @@ -0,0 +1,14 @@ +/* + InfoPlist.strings + Runner + + Created by 黄家豪 on 2019/12/19. + Copyright © 2019 The Chromium Authors. All rights reserved. +*/ +NSMicrophoneUsageDescription = "Allow voice chat in apps, create voice messages etc"; +NSCameraUsageDescription = "For scanning QR codes, taking pictures, uploading avatars, and sending pictures"; +NSLocationAlwaysUsageDescription = "After the location is acquired, we can provide you with more accurate recommendation services"; +NSLocationWhenInUseUsageDescription = "After the location is acquired, we can provide you with more accurate recommendation services"; +NSPhotoLibraryUsageDescription = "For uploading avatars, publishing programs, sending pictures etc."; +NSContactsUsageDescription = "You can add your phone buddies after getting your contacts"; +NSPhotoLibraryAddUsageDescription = "Used to save pictures sent by others"; diff --git a/ios/Runner/ja.lproj/InfoPlist.strings b/ios/Runner/ja.lproj/InfoPlist.strings new file mode 100644 index 0000000..c05dcd8 --- /dev/null +++ b/ios/Runner/ja.lproj/InfoPlist.strings @@ -0,0 +1,14 @@ +/* + InfoPlist.strings + Runner + + Created by 黄家豪 on 2019/12/19. + Copyright © 2019 The Chromium Authors. All rights reserved. +*/ +NSMicrophoneUsageDescription = "アプリでのボイスチャットの許可、ボイスメッセージの作成など"; +NSCameraUsageDescription = "QRコードのスキャン、写真の撮影、アバターのアップロード、写真の送信"; +NSLocationAlwaysUsageDescription = "場所を取得した後、より正確な推奨サービスを提供できます"; +NSLocationWhenInUseUsageDescription = "場所を取得した後、より正確な推奨サービスを提供できます"; +NSPhotoLibraryUsageDescription = "アバターのアップロード、プログラムの公開、写真の送信など。"; +NSContactsUsageDescription = "連絡先を取得した後、電話のメンバーを追加できます"; +NSPhotoLibraryAddUsageDescription = "他から送信された写真を保存するために使用"; diff --git a/ios/Runner/ko.lproj/InfoPlist.strings b/ios/Runner/ko.lproj/InfoPlist.strings new file mode 100644 index 0000000..7d6131e --- /dev/null +++ b/ios/Runner/ko.lproj/InfoPlist.strings @@ -0,0 +1,14 @@ +/* + InfoPlist.strings + Runner + + Created by 黄家豪 on 2019/12/19. + Copyright © 2019 The Chromium Authors. All rights reserved. +*/ +NSMicrophoneUsageDescription = "앱에서 음성 채팅 허용, 음성 메시지 작성 등"; +NSCameraUsageDescription = "QR 코드 스캔, 사진 촬영, 아바타 업로드 및 사진 전송"; +NSLocationAlwaysUsageDescription = "위치를 확보하면보다 정확한 추천 서비스를 제공 할 수 있습니다."; +NSLocationWhenInUseUsageDescription = "위치를 확보하면보다 정확한 추천 서비스를 제공 할 수 있습니다."; +NSPhotoLibraryUsageDescription = "아바타 업로드, 프로그램 게시, 사진 전송 등"; +NSContactsUsageDescription = "당신은 당신의 연락처를 얻은 후 전화 친구를 추가 할 수 있습니다"; +NSPhotoLibraryAddUsageDescription = "다른 사람이 보낸 사진을 저장하는 데 사용"; diff --git a/ios/Runner/main.m b/ios/Runner/main.m new file mode 100644 index 0000000..4618607 --- /dev/null +++ b/ios/Runner/main.m @@ -0,0 +1,9 @@ +#import +#import +#import "AppDelegate.h" + +int main(int argc, char* argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/ios/Runner/vi.lproj/InfoPlist.strings b/ios/Runner/vi.lproj/InfoPlist.strings new file mode 100644 index 0000000..f3e929f --- /dev/null +++ b/ios/Runner/vi.lproj/InfoPlist.strings @@ -0,0 +1,14 @@ +/* + InfoPlist.strings + Runner + + Created by 黄家豪 on 2019/12/19. + Copyright © 2019 The Chromium Authors. All rights reserved. +*/ +NSMicrophoneUsageDescription = "Cho phép trò chuyện bằng giọng nói trong ứng dụng, tạo tin nhắn thoại và hơn thế nữa"; +NSCameraUsageDescription = "Để quét mã QR, chụp ảnh, tải lên hình đại diện và gửi hình ảnh"; +NSLocationAlwaysUsageDescription = "Sau khi có được vị trí, chúng tôi có thể cung cấp cho bạn các dịch vụ đề xuất chính xác hơn"; +NSLocationWhenInUseUsageDescription = "Sau khi có được vị trí, chúng tôi có thể cung cấp cho bạn các dịch vụ đề xuất chính xác hơn"; +NSPhotoLibraryUsageDescription = "Để tải lên hình đại diện, chương trình xuất bản, gửi hình ảnh, vv"; +NSContactsUsageDescription = "Sau khi nhận được, chúng tôi có thể cung cấp cho bạn các dịch vụ đề xuất chính xác hơn"; +NSPhotoLibraryAddUsageDescription = "Được sử dụng để lưu hình ảnh được gửi bởi người khác"; diff --git a/ios/Runner/zh-Hans.lproj/InfoPlist.strings b/ios/Runner/zh-Hans.lproj/InfoPlist.strings new file mode 100644 index 0000000..7cc751d --- /dev/null +++ b/ios/Runner/zh-Hans.lproj/InfoPlist.strings @@ -0,0 +1,14 @@ +/* + InfoPlist.strings + Runner + + Created by 黄家豪 on 2019/12/19. + Copyright © 2019 The Chromium Authors. All rights reserved. +*/ +NSMicrophoneUsageDescription = "允许在应用中进行语音聊天、创建语音消息等"; +NSCameraUsageDescription = "用于扫描二维码、拍照上传头像、发送图片功能"; +NSLocationAlwaysUsageDescription = "位置获取后可以为您提供更精准的推荐服务"; +NSLocationWhenInUseUsageDescription = "位置获取后可以为您提供更精准的推荐服务"; +NSPhotoLibraryUsageDescription = "用于上传头像、发布节目、发送图片等功能"; +NSContactsUsageDescription = "通讯录获取后可以添加您的手机好友"; +NSPhotoLibraryAddUsageDescription = "用于保存别人发送的的图片"; diff --git a/ios/Runner/zh-Hant.lproj/InfoPlist.strings b/ios/Runner/zh-Hant.lproj/InfoPlist.strings new file mode 100644 index 0000000..4a51a22 --- /dev/null +++ b/ios/Runner/zh-Hant.lproj/InfoPlist.strings @@ -0,0 +1,14 @@ +/* + InfoPlist.strings + Runner + + Created by 黄家豪 on 2019/12/19. + Copyright © 2019 The Chromium Authors. All rights reserved. +*/ +NSMicrophoneUsageDescription = "允許在應用中進行語音聊天、創建語音消息等"; +NSCameraUsageDescription = "用於掃描二維碼、拍照上傳頭像、發送圖片功能"; +NSLocationAlwaysUsageDescription = "位置獲取後可以為您提供更精準的推薦服務"; +NSLocationWhenInUseUsageDescription = "位置獲取後可以為您提供更精準的推薦服務"; +NSPhotoLibraryUsageDescription = "用於上傳頭像、發布節目、發送圖片等功能"; +NSContactsUsageDescription = "通訊錄獲取後可以添加您的手機好友"; +NSPhotoLibraryAddUsageDescription = "用於保存別人發送的的圖片"; diff --git a/ios/Share Extension/Base.lproj/MainInterface.storyboard b/ios/Share Extension/Base.lproj/MainInterface.storyboard new file mode 100644 index 0000000..286a508 --- /dev/null +++ b/ios/Share Extension/Base.lproj/MainInterface.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Share Extension/Info.plist b/ios/Share Extension/Info.plist new file mode 100644 index 0000000..cd7fadf --- /dev/null +++ b/ios/Share Extension/Info.plist @@ -0,0 +1,46 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Share Extension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSExtension + + NSExtensionAttributes + + NSExtensionActivationRule + + NSExtensionActivationSupportsImageWithMaxCount + 100 + NSExtensionActivationSupportsMovieWithMaxCount + 100 + + PHSupportedMediaTypes + + Image + Video + + + NSExtensionMainStoryboard + MainInterface + NSExtensionPointIdentifier + com.apple.share-services + + + diff --git a/ios/Share Extension/Share Extension.entitlements b/ios/Share Extension/Share Extension.entitlements new file mode 100644 index 0000000..e149f21 --- /dev/null +++ b/ios/Share Extension/Share Extension.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.com.cyhd.henho + + + diff --git a/ios/Share Extension/Share ExtensionProfile.entitlements b/ios/Share Extension/Share ExtensionProfile.entitlements new file mode 100644 index 0000000..e149f21 --- /dev/null +++ b/ios/Share Extension/Share ExtensionProfile.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.com.cyhd.henho + + + diff --git a/ios/Share Extension/ShareViewController.swift b/ios/Share Extension/ShareViewController.swift new file mode 100644 index 0000000..1187f15 --- /dev/null +++ b/ios/Share Extension/ShareViewController.swift @@ -0,0 +1,283 @@ +import UIKit +import Social +import MobileCoreServices +import Photos + +class ShareViewController: SLComposeServiceViewController { + // TODO: IMPORTANT: This should be your host app bundle identifier + let hostAppBundleIdentifier = "com.cyhd.henho" + let sharedKey = "ShareKey" + var sharedMedia: [SharedMediaFile] = [] + var sharedText: [String] = [] + let imageContentType = kUTTypeImage as String + let videoContentType = kUTTypeMovie as String + let textContentType = kUTTypeText as String + let urlContentType = kUTTypeURL as String + + override func isContentValid() -> Bool { + return true + } + + override func viewDidLoad() { + // This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments. + + if let content = extensionContext!.inputItems[0] as? NSExtensionItem { + if let contents = content.attachments { + for (index, attachment) in (contents as! [NSItemProvider]).enumerated() { + + if attachment.hasItemConformingToTypeIdentifier(imageContentType) { + handleImages(content: content, attachment: attachment, index: index) + } else if attachment.hasItemConformingToTypeIdentifier(textContentType) { + handleText(content: content, attachment: attachment, index: index) + } else if attachment.hasItemConformingToTypeIdentifier(urlContentType) { + handleUrl(content: content, attachment: attachment, index: index) + } else if attachment.hasItemConformingToTypeIdentifier(videoContentType) { +// handleVideos(content: content, attachment: attachment, index: index) + } + } + } + } + } + + override func didSelectPost() { + print("didSelectPost"); + } + + override func configurationItems() -> [Any]! { + // To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here. + return [] + } + + private func handleText (content: NSExtensionItem, attachment: NSItemProvider, index: Int) { + attachment.loadItem(forTypeIdentifier: textContentType, options: nil) { [weak self] data, error in + + if error == nil, let item = data as? String, let this = self { + + this.sharedText.append(item) + + // If this is the last item, save imagesData in userDefaults and redirect to host app + if index == (content.attachments?.count)! - 1 { + let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)") + userDefaults?.set(this.sharedText, forKey: this.sharedKey) + userDefaults?.synchronize() + this.redirectToHostApp(type: .text) + } + + } else { + self?.dismissWithError() + } + } + } + + private func handleUrl (content: NSExtensionItem, attachment: NSItemProvider, index: Int) { + attachment.loadItem(forTypeIdentifier: urlContentType, options: nil) { [weak self] data, error in + + if error == nil, let item = data as? URL, let this = self { + + this.sharedText.append(item.absoluteString) + + // If this is the last item, save imagesData in userDefaults and redirect to host app + if index == (content.attachments?.count)! - 1 { + let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)") + userDefaults?.set(this.sharedText, forKey: this.sharedKey) + userDefaults?.synchronize() + this.redirectToHostApp(type: .text) + } + + } else { + self?.dismissWithError() + } + } + } + + private func handleImages (content: NSExtensionItem, attachment: NSItemProvider, index: Int) { + attachment.loadItem(forTypeIdentifier: imageContentType, options: nil) { [weak self] data, error in + + if error == nil, let url = data as? URL, let this = self { + + // Always copy + let fileExtension = this.getExtension(from: url, type: .image) + let newName = UUID().uuidString + let newPath = FileManager.default + .containerURL(forSecurityApplicationGroupIdentifier: "group.\(this.hostAppBundleIdentifier)")! + .appendingPathComponent("\(newName).\(fileExtension)") + let copied = this.copyFile(at: url, to: newPath) + if(copied) { + this.sharedMedia.append(SharedMediaFile(path: newPath.absoluteString, thumbnail: nil, duration: nil, type: .image)) + } + + // If this is the last item, save imagesData in userDefaults and redirect to host app + if index == (content.attachments?.count)! - 1 { + let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)") + userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey) + userDefaults?.synchronize() + this.redirectToHostApp(type: .media) + } + + } else { + self?.dismissWithError() + } + } + } + +// private func handleVideos (content: NSExtensionItem, attachment: NSItemProvider, index: Int) { +// attachment.loadItem(forTypeIdentifier: videoContentType, options: nil) { [weak self] data, error in +// +// if error == nil, let url = data as? URL, let this = self { +// +// // Always copy +// let fileExtension = this.getExtension(from: url, type: .video) +// let newName = UUID().uuidString +// let newPath = FileManager.default +// .containerURL(forSecurityApplicationGroupIdentifier: "group.\(this.hostAppBundleIdentifier)")! +// .appendingPathComponent("\(newName).\(fileExtension)") +// let copied = this.copyFile(at: url, to: newPath) +// if(copied) { +// guard let sharedFile = this.getSharedMediaFile(forVideo: newPath) else { +// return +// } +// this.sharedMedia.append(sharedFile) +// } +// +// // If this is the last item, save imagesData in userDefaults and redirect to host app +// if index == (content.attachments?.count)! - 1 { +// let userDefaults = UserDefaults(suiteName: "group.\(this.hostAppBundleIdentifier)") +// userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey) +// userDefaults?.synchronize() +// this.redirectToHostApp(type: .media) +// } +// +// } else { +// self?.dismissWithError() +// } +// } +// } + + private func dismissWithError() { + print("GETTING ERROR") + let alert = UIAlertController(title: "Error", message: "Error loading data", preferredStyle: .alert) + + let action = UIAlertAction(title: "Error", style: .cancel) { _ in + self.dismiss(animated: true, completion: nil) + } + + alert.addAction(action) + present(alert, animated: true, completion: nil) + extensionContext!.completeRequest(returningItems: [], completionHandler: nil) + } + + private func redirectToHostApp(type: RedirectType) { + let url = URL(string: "SharePhotos://dataUrl=\(sharedKey)#\(type)") + var responder = self as UIResponder? + let selectorOpenURL = sel_registerName("openURL:") + + while (responder != nil) { + if (responder?.responds(to: selectorOpenURL))! { + let _ = responder?.perform(selectorOpenURL, with: url) + } + responder = responder!.next + } + extensionContext!.completeRequest(returningItems: [], completionHandler: nil) + } + + enum RedirectType { + case media + case text + } + + func getExtension(from url: URL, type: SharedMediaType) -> String { + let parts = url.lastPathComponent.components(separatedBy: ".") + var ex: String? = nil + if (parts.count > 1) { + ex = parts.last + } + + if (ex == nil) { + switch type { + case .image: + ex = "PNG" + case .video: + ex = "MP4" + } + } + return ex ?? "Unknown" + } + + func copyFile(at srcURL: URL, to dstURL: URL) -> Bool { + do { + if FileManager.default.fileExists(atPath: dstURL.path) { + try FileManager.default.removeItem(at: dstURL) + } + try FileManager.default.copyItem(at: srcURL, to: dstURL) + } catch (let error) { + print("Cannot copy item at \(srcURL) to \(dstURL): \(error)") + return false + } + return true + } + +// private func getSharedMediaFile(forVideo: URL) -> SharedMediaFile? { +// let asset = AVAsset(url: forVideo) +// let duration = (CMTimeGetSeconds(asset.duration) * 1000).rounded() +// let thumbnailPath = getThumbnailPath(for: forVideo) +// +// if FileManager.default.fileExists(atPath: thumbnailPath.path) { +// return SharedMediaFile(path: forVideo.absoluteString, thumbnail: thumbnailPath.absoluteString, duration: duration, type: .video) +// } +// +// var saved = false +// let assetImgGenerate = AVAssetImageGenerator(asset: asset) +// assetImgGenerate.appliesPreferredTrackTransform = true +// // let scale = UIScreen.main.scale +// assetImgGenerate.maximumSize = CGSize(width: 360, height: 360) +// do { +// let img = try assetImgGenerate.copyCGImage(at: CMTimeMakeWithSeconds(1.0, 600), actualTime: nil) +// try UIImagePNGRepresentation(UIImage(cgImage: img))?.write(to: thumbnailPath) +// saved = true +// } catch { +// saved = false +// } +// +// return saved ? SharedMediaFile(path: forVideo.absoluteString, thumbnail: thumbnailPath.absoluteString, duration: duration, type: .video) : nil +// +// } + + private func getThumbnailPath(for url: URL) -> URL { + let fileName = Data(url.lastPathComponent.utf8).base64EncodedString().replacingOccurrences(of: "==", with: "") + let path = FileManager.default + .containerURL(forSecurityApplicationGroupIdentifier: "group.\(hostAppBundleIdentifier)")! + .appendingPathComponent("\(fileName).jpg") + return path + } + + class SharedMediaFile: Codable { + var path: String; // can be image, video or url path. It can also be text content + var thumbnail: String?; // video thumbnail + var duration: Double?; // video duration in milliseconds + var type: SharedMediaType; + + + init(path: String, thumbnail: String?, duration: Double?, type: SharedMediaType) { + self.path = path + self.thumbnail = thumbnail + self.duration = duration + self.type = type + } + } + + enum SharedMediaType: Int, Codable { + case image + case video + } + + func toData(data: [SharedMediaFile]) -> Data { + let encodedData = try? JSONEncoder().encode(data) + return encodedData! + } +} + +extension Array { + subscript (safe index: UInt) -> Element? { + return Int(index) < count ? self[Int(index)] : nil + } +} diff --git a/jsons/user.json b/jsons/user.json new file mode 100644 index 0000000..1ad1cae --- /dev/null +++ b/jsons/user.json @@ -0,0 +1,4 @@ +{ + "name": "John Smith", + "email": "john@example.com" +} \ No newline at end of file diff --git a/lib/chat/ChatPage.dart b/lib/chat/ChatPage.dart new file mode 100644 index 0000000..3b2e3c0 --- /dev/null +++ b/lib/chat/ChatPage.dart @@ -0,0 +1,535 @@ +import 'dart:io'; + +import 'package:chat/chat/translate_state.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/models/keyboard_provider.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/models/voucher_change.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/analyze_utils.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/blacklist_mgr.dart'; +import 'package:chat/utils/friend_list_mgr.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/net_state_widget.dart'; +import 'package:chat/utils/sound_util.dart'; +import 'package:chat/utils/sp_utils.dart'; +import 'package:chat/utils/sql_util.dart'; +import 'package:dio/dio.dart'; +import 'package:extended_text/extended_text.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; +import '../r.dart'; +import 'ChatPageItem.dart'; +import 'input_bar.dart'; +import 'package:chat/utils/PopUpMenu.dart' as myPop; +import 'package:chat/models/money_change.dart'; + + +class ChatPage extends StatefulWidget { + final int friendId; + final int enterType; // 0默认 1图片 + final dynamic enterContent; + ChatPage({Key key, this.friendId, this.enterType = 0, this.enterContent}) + : super(key: key); + + _ChatPageState createState() => _ChatPageState(); +} + +class _ChatPageState extends State { + ScrollController _scrollCtrl = ScrollController(); + + MessageMgr msgMgr = MessageMgr(); + + UserInfo friendInfo; + + List msgList; + + KeyboardIndexProvider _keyboardIndexProvider = KeyboardIndexProvider(); + + TextEditingController nickNameController = new TextEditingController(); + + //统计聊天时长 + int startTime; + + @override + void dispose() { + var endTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; + AnalyzeUtils.commitChatDuration(startTime, endTime); + + MessageMgr().off('Send CoinBag', _sendCoin); + msgMgr.off('New Chat Message', receiveMsg); + msgMgr.off('Keyboard Hide', dealWithKeyboardHide); + msgMgr.off('Delete Select Message', _deleteItem); + + MsgHandler.curActiveSession = 0; + SoundUtils().stop(); + nickNameController.dispose(); + _scrollCtrl.dispose(); + + super.dispose(); + } + + @override + void initState() { + super.initState(); + print('init chatpage'); + getDefaultSetting(); + getUserInfo(); + + startTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; + + msgList = ChatDataMgr().getRecord(); + + msgMgr.on('New Chat Message', receiveMsg); + msgMgr.on('Keyboard Hide', dealWithKeyboardHide); + msgMgr.on('Send CoinBag', _sendCoin); + msgMgr.on('Delete Select Message', _deleteItem); + } + + void _sendFile(File file) async { +// File file = await FilePicker.getFile(); + int fileSize = file.lengthSync(); + print('选择的文件 ${file.path} 大小 $fileSize'); + + if (fileSize > 33 * 1024 * 1024) { + showToast('文件大于33M'); + return; + } + + var fileName = file.path.split('/').last; + print('fileName $fileName'); + + var ext = ''; + var extList = fileName.split('.'); + if (extList.length > 1) { + ext = extList.last; + } + print('ext $ext'); + + var fileMsg = FileChat.create(); + fileMsg.type = ext; + fileMsg.size = fileSize; + fileMsg.name = fileName; + + var msg = MsgHandler.createSendMsg( + ChatType.FileChatType, fileMsg.writeToBuffer(), + friendId: widget.friendId, + localFile: file.path, + channelType: ChatChannelType.Session); + + sendMsg(msg); + } + + _sendCoin(args) async { + var res = await _checkCoinBeforeSend(args['amount']); + if (res != null) { + args['redNo'] = res['redNo']; + args['friendId'] = widget.friendId; + var msg = MsgHandler.createCoinBagMsg(args); + + sendMsg(msg); + } + } + +//校验 + _checkCoinBeforeSend(int amount) async { + Map data = { + "userId": UserData().basicInfo.userId, + "rUserId": friendInfo.userId, + "price": amount, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('red/packet/send', data: data); + if (res == null) { + return null; + } + Map resData = res.data; + if (resData['code'] == 0) { + print(resData['data']); + return resData['data']; + } + + return null; + } + + void getDefaultSetting() async { + bool soundPlayMode = + (await SPUtils.getBool(Constants.SOUND_PLAY_MODE)) ?? false; + + _keyboardIndexProvider.init(soundPlayMode); + } + + dealWithKeyboardHide(args) { + if (_keyboardIndexProvider.curKeyboardIndex == 0) { + hideKeyBoard(); + } + } + + getUserInfo() async { + //先从本地获取用户信息 + friendInfo = await HttpUtil().getFriendInfo(widget.friendId, true); + + //如果是新的聊天,向服务器发送创建会话消息 + if (msgList.length == 0) { + MsgHandler.getActiveSesstion( + [friendInfo.userId, UserData().basicInfo.userId]); + } + + if (mounted) { + setState(() {}); + } + + WidgetsBinding.instance.addPostFrameCallback((_) { + if (widget.enterType == 1) { + print('接收到的:${widget.enterContent}'); + + File file = new File(widget.enterContent); + if(file.existsSync()){ + print('接收到的文件--存在'); + }else{ + print('接收到的文件--不存在'); + } + + _sendFile(File(widget.enterContent)); + } + }); + } + + @override + Widget build(BuildContext context) { + print('build chatpage'); + + if (friendInfo == null) { + return Scaffold( + backgroundColor: const Color(0xFFE2E9F1), + body: SafeArea( + child: Center( + child: CircularProgressIndicator(), + ), + ), + ); + } + + List actions = []; + + int voucher = Provider.of(context).voucher; + actions.add(Row( + children: [ + CustomUI.buildImageLabel("assets/images/voucher.png", voucher, + imgOpc: 0.5, imgHeight: 13), + CustomUI.buildImageLabel( + R.assetsImagesCoin, Provider.of(context).money, + isLeft: false) + ], + )); + actions.add(TranslateSateWidget(friendId: friendInfo.userId)); + actions.add(Container( + margin: EdgeInsets.only(top: 1), + child: myPop.PopupMenuButton( + icon: Icon( + Icons.more_horiz, + size: 24, + ), + offset: Offset(0, 100), + onSelected: (int index) { + if (index == 2) { + AppNavigator.pushInformUserPage( + context, friendInfo.sex == 1, friendInfo.userId); + } else if (index == 1) { + nickNameController.text = Provider.of(context) + .getRefName(friendInfo.userId, friendInfo.nickName); + + var confirm = CustomUI.buildConfirmBotton( + I18n.of(context).determine, () async { + nickNameController.text = nickNameController.text.trim(); + if (nickNameController.text == null || + nickNameController.text.length > 25) { + showToast(I18n.of(context).only1_8); + return; + } + Provider.of(context).changeRefName( + friendInfo.userId, nickNameController.text, () { + Navigator.of(context).pop(); + }); + }); + var tip = Column( + children: [ + Container( + margin: EdgeInsets.only(top: 20), + child: Text( + I18n.of(context).setRemark, + textScaleFactor: 1.0, + style: TextStyle( + color: Constants.BlackTextColor, fontSize: 16), + ), + ), + Container( + margin: EdgeInsets.only(top: 23, bottom: 25), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.all(Radius.circular(8))), + child: TextField( + keyboardAppearance: Brightness.light, + controller: nickNameController, + textAlign: TextAlign.center, + textInputAction: TextInputAction.search, + style: TextStyle( + textBaseline: TextBaseline.alphabetic, + fontSize: 14), + decoration: InputDecoration( + hintText: friendInfo.nickName, + hintStyle: TextStyle(fontSize: 12), + filled: true, + contentPadding: EdgeInsets.only(top: 10, bottom: 10), + fillColor: Colors.transparent, + border: InputBorder.none, + ), + maxLines: 1, + inputFormatters: [LengthLimitingTextInputFormatter(15)], + ), + ) + ], + ); + var content = CustomUI.buildConfirmContent(tip, confirm); + CustomUI.buildTip(context, '', content); + } + }, + itemBuilder: (BuildContext context) { + return >[ + myPop.PopupMenuItem( + child: Container( + alignment: Alignment.center, + color: Colors.white, + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10), + child: Text(I18n.of(context).anonymous_report, + textScaleFactor: 1.0, + maxLines: 1, + style: TextStyle( + color: Color(AppColors.AppBarColor), fontSize: 12)), + ), + value: 2, + ), + myPop.PopupMenuItem( + child: Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide(width: 1, color: Colors.grey[300])), + color: Colors.white, + ), + alignment: Alignment.center, + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10), + child: Text(I18n.of(context).Remark, + textScaleFactor: 1.0, + maxLines: 1, + style: TextStyle( + color: Color(AppColors.AppBarColor), fontSize: 12)), + ), + value: 1, + ), + ]; + }))); + + return MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => _keyboardIndexProvider), + Provider.value(value: false), + Provider.value(value: widget.friendId), + ], + child: GestureDetector( + onTap: hideKeyBoard, + child: ExtendedTextSelectionPointerHandler( + ///选择文字,消除弹窗 + + builder: (states) { + return Listener( + child: Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: const Color(0xFFE2E9F1), + // appBar: PreferredSize( + // preferredSize: Size.fromHeight(58), + // child: Container( + // color: AppBarTheme.of(context).color, + // child: SafeArea( + // child: Container( + // height: 56, + // child: Row(children: [ + // SizedBox(width: 10), + // CustomUI.buildCustomLeading(context), + // Text( + // Provider.of(context) + // .getRefName(friendInfo.userId, + // friendInfo.nickName), + // textScaleFactor: 1.0, + // style: TextStyle( + // textBaseline: TextBaseline.ideographic, + // color: Constants.BlackTextColor, + // fontSize: 16.47), + // ), + // Expanded( + // child: Row( + // mainAxisAlignment: + // MainAxisAlignment.end, + // children: actions)) + // ]), + // )))), + appBar: AppBar( + title: Text( + '${Provider.of(context).getRefName(friendInfo.userId, friendInfo.nickName)}', + textScaleFactor: 1.0, + style: TextStyle( + color: Constants.BlackTextColor, + fontSize: 16.47), + ), + leading: CustomUI.buildCustomLeading(context), + titleSpacing: -10, + centerTitle: false, + elevation: 1, + actions: actions), + body: SafeArea( + child: Column( + children: [ + NetStateWidget(), + Expanded(child: _buildMessageList()), + InputBar(sendMsg: sendMsg), + ], + ))), + behavior: HitTestBehavior.translucent, + onPointerDown: (value) { + for (var state in states) { + if (!state.containsPosition(value.position)) { + //clear other selection + state.clearSelection(); + } + } + }, + onPointerMove: (value) { + //clear other selection + for (var state in states) { + if (!state.containsPosition(value.position)) { + //clear other selection + state.clearSelection(); + } + } + }, + ); + }, + ))); + } + + Widget _buildMessageList() { + return Container( + alignment: Alignment.topCenter, + child: msgList.length == 0 + ? Padding( + padding: EdgeInsets.all(8), + child: Text( + I18n.of(context).chat_tips, + textAlign: TextAlign.center, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.grey, fontSize: 12), + )) + : NotificationListener( + child: Scrollbar( + child: ListView.builder( + reverse: true, + shrinkWrap: true, + itemCount: msgList.length, + controller: _scrollCtrl, + padding: EdgeInsets.all(8.0), + itemBuilder: _buildItem, + )), + onNotification: (notification) { + if (notification is ScrollNotification) { + // var offset = notification.metrics.pixels; + // print('滚动事件 offset $offset'); + } + return true; + }, + ), + ); + } + + hideKeyBoard() { + _keyboardIndexProvider.changeSelectIndex(-1); + } + + readOnly() { + _keyboardIndexProvider.changeReadOnlyKey(true); + } + + sendMsg(MsgModel msg) { + print('对方是否拉黑你 ${friendInfo.isBlackened}'); + if (BlacklistMgr.isBlaklistMe(friendInfo.userId)) { + showToast(I18n.of(context).you_are_blaklisted); + return; + } + + if (BlacklistMgr.isInMyblaklist(friendInfo.userId)) { + showToast(I18n.of(context).reject_message); + return; + } + + if (!friendInfo.isCanStrangerNews && + !FriendListMgr().isMyFriend(friendInfo.userId)) { + showToast(I18n.of(context).stranger_close_tips); + return; + } + + MsgHandler.insertMsgToDB(msg); + MsgHandler.sendChatMsg(msg); + if (mounted) { + setState(() {}); + if (_scrollCtrl.hasClients) { + _scrollCtrl.animateTo(0, + duration: new Duration(milliseconds: 500), curve: Curves.ease); + } + } + } + + void receiveMsg(args) { + if (mounted) { + setState(() {}); + if (_scrollCtrl.hasClients) { + _scrollCtrl.animateTo(0, + duration: new Duration(milliseconds: 500), curve: Curves.ease); + } + } + } + + _deleteItem(msg) { + MessageMgr().emit('Cancel Request', msg); + print('#### 开始删除--'); + msgList.remove(msg); + setState(() {}); + SqlUtil().deleteSigleRecordWith(msg.sessionId, msg.time); + } + + Widget _buildItem(BuildContext context, int index) { + var lastMsgTime; + if (index < msgList.length - 1) { + lastMsgTime = msgList[index + 1].time; + } + + MsgModel msg = msgList[index]; + return ChatPageItem( + key: Key(msg.time.toString()), + msg: msg, + hideKeyboard: readOnly, + friendInfo: friendInfo, + lastMsgTime: lastMsgTime); + } +} diff --git a/lib/chat/ChatPageItem.dart b/lib/chat/ChatPageItem.dart new file mode 100644 index 0000000..50cb465 --- /dev/null +++ b/lib/chat/ChatPageItem.dart @@ -0,0 +1,1302 @@ +import 'dart:convert'; +import 'dart:math'; +import 'dart:typed_data'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/chat/download_item.dart'; +import 'package:chat/chat/file_msg_item.dart'; +import 'package:chat/chat/gift_msg_item.dart'; +import 'package:chat/chat/msg_state_widge.dart'; +import 'package:chat/chat/place_item.dart'; +import 'package:chat/chat/redbag_widget.dart'; +import 'package:chat/chat/upload_item.dart'; +import 'package:chat/chat/video_view.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/models/keyboard_provider.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/proto/chat.pbenum.dart'; +import 'package:chat/proto/chat.pbserver.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/date_utils.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sound_util.dart'; +import 'package:chat/utils/upload_util.dart'; +import 'package:chat/utils/video_anim.dart'; +import 'package:chat/utils/wpop/w_popup_menu.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; + +import '../r.dart'; +import 'full_img_view.dart'; +import 'upload_item.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/models/voucher_change.dart'; + +const double ChatRadius = 7.5; +const Color SendMsgBg = Color(0xFFD4F0FF); + +const double TextHeight = 1.2; + +const double PaddingLeft = 9.5; + +const Color ReciveBorderColor = Color(0xFFDCDCDC); + +const double FontSize = 15; + +class ChatPageItem extends StatefulWidget { + final MsgModel msg; + + final UserInfo friendInfo; + final int lastMsgTime; + + final Function hideKeyboard; + + const ChatPageItem( + {Key key, this.msg, this.lastMsgTime, this.friendInfo, this.hideKeyboard}) + : assert(msg != null), + super(key: key); + + @override + _ChatPageItemState createState() => _ChatPageItemState(); +} + +class _ChatPageItemState extends State + with SingleTickerProviderStateMixin { + int curTextType = 0; //文字、译文切换索引 + List textList = []; + + UserInfo friendInfo; + + String curSoundUrl; + + CancelToken _cancelToken = CancelToken(); + + bool isLongPressed = false; + @override + void initState() { + super.initState(); + friendInfo = widget.friendInfo; + + if (widget.msg.from == UserData().basicInfo.userId && + widget.msg.state == MsgState.None) { + print('重新发送消息'); + MsgHandler.sendChatMsg(widget.msg); + } + + textList = widget.msg.getTransTextList(); + + MessageMgr().on('Update Translate Message', updateTranslateMsg); + MessageMgr().on('Cancel Request', _deleteItem); + + MessageMgr().on('Cancel Request', _deleteItem); + } + + @override + void dispose() { + MessageMgr().off('Cancel Request', _deleteItem); + MessageMgr().off('Update Translate Message', updateTranslateMsg); + super.dispose(); + } + + _deleteItem(msg) { + if (msg == widget.msg) { + print(widget.msg.state); + if (widget.msg.state == MsgState.Uploading) { + print('取消上传'); + UploadUtil().cancelRequests(_cancelToken); + } + } + } + + updateTextList() { + textList.clear(); + curTextType = 0; + textList = widget.msg.getTransTextList(); + } + + updateTranslateMsg(msg) { + if (msg.time == widget.msg.time) { + if (mounted) { + updateTextList(); + if (!mounted) { + return; + } + setState(() { + print('更新翻译文字'); + }); + } + } + } + + getTodayTime(msgDate) { + String showTimeStr; + + var sendTime = widget.msg.time; + var today = DateTime.now(); + //今天 + if (msgDate.year == today.year && + msgDate.month == today.month && + msgDate.day == today.day) { + showTimeStr = + DateUtils().getFormartData(timeSamp: sendTime, format: 'HH:mm'); + } else { + showTimeStr = DateUtils() + .getFormartData(timeSamp: sendTime, format: 'yyyy/MM/dd HH:mm'); + } + + return showTimeStr; + } + + String getMsgTime() { + String showTimeStr; + + var sendTime = widget.msg.time; + + var msgDate = DateTime.fromMillisecondsSinceEpoch(sendTime); + if (widget.lastMsgTime == null) { + showTimeStr = getTodayTime(msgDate); + } else { + if (sendTime - widget.lastMsgTime > 3 * 60 * 1000) { + showTimeStr = getTodayTime(msgDate); + } + } + + return showTimeStr; + } + + @override + Widget build(BuildContext context) { + var showTime = getMsgTime(); + + return Container( + width: Screen.width, + margin: const EdgeInsets.symmetric(vertical: 10.0), + child: Column( + children: [ + showTime == null + ? SizedBox() + : Container( + decoration: BoxDecoration( + color: Color(0xFF2C2F36).withOpacity(0.25), + borderRadius: BorderRadius.all(Radius.circular(9.5))), + padding: + EdgeInsets.only(left: 7, right: 7, top: 3, bottom: 2), + child: Text(showTime, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 10.0, color: Colors.white)), + ), + SizedBox(height: 10), + _msgWidget() + ], + ), + ); + } + + _msgWidget() { + if (widget.msg.from == 0) { + return _serverNotifyMsg(); + } else { + if (widget.msg.from == UserData().basicInfo.userId) { + return _getSentMessageLayout(context); + } else { + return _getReceivedMessageLayout(context); + } + } + } + + _serverNotifyMsg() { + var type = widget.msg.msgType; + + if (type == ChatType.RedWalletChatType.value) { + RedWallet wallet = RedWallet.fromBuffer(widget.msg.msgContent); + + var msg = ''; + + if (wallet.state == RedWalletState.Received) { + if (wallet.tuId == friendInfo.userId) { + msg = I18n.of(context).get_money.replaceFirst( + '/s1', + Provider.of(context) + .getRefName(friendInfo.userId, friendInfo.nickName)); + } else { + msg = I18n.of(context).you_get_money.replaceFirst( + '/s1', + Provider.of(context) + .getRefName(friendInfo.userId, friendInfo.nickName)); + } + } else { + if (wallet.tuId == friendInfo.userId) { + msg = I18n.of(context).your_redMoney_over; + } else { + msg = I18n.of(context).other_redMoney_over; + } + } + + return Container( + alignment: Alignment.center, + constraints: BoxConstraints(maxWidth: Screen.width - 120), + child: extendedText(msg, color: Constants.GreyTextColor, fontSize: 12), + ); + } else { + if (type == ChatType.GroupChatNoticeType.value) { + var res = GroupChatNotice.fromBuffer(widget.msg.msgContent); + + var groupInfoModel = Provider.of(context); + var showStr = MsgHandler.getGroupNoticeMsg(res, groupInfoModel); + return Container( + alignment: Alignment.center, + constraints: BoxConstraints(maxWidth: Screen.width - 120), + child: Text( + showStr, + textScaleFactor: 1.0, + textAlign: TextAlign.center, + style: TextStyle(color: Constants.GreyTextColor, fontSize: 12), + ), + ); + } + } + return Container(); + } + + _textGif(List msgContent) { + var msg = utf8.decode(msgContent); + return Container( + constraints: BoxConstraints(maxWidth: Screen.width - 120), + child: extendedText( + msg, + hideKeyboard: widget.hideKeyboard, + fontSize: FontSize, + color: Colors.black, + ), + ); + } + + _textMsg(List msgContent) { + var msg = utf8.decode(msgContent); + + Widget text = Container( + constraints: BoxConstraints(maxWidth: Screen.width - 120), + child: extendedText( + msg, + hideKeyboard: widget.hideKeyboard, + fontSize: FontSize, + color: Colors.black, + ), + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + decoration: BoxDecoration( + color: isLongPressed ? Colors.grey[300] : SendMsgBg, + border: Border.all(color: Color(0xFFB9CBD7), width: 0.6), + borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), + ); + + if (widget.msg.refMsgContent != null && + widget.msg.refMsgContent.length > 0) { + QuoteMsg quoteMsg = QuoteMsg.fromBuffer(widget.msg.refMsgContent); + + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + text, + SizedBox(height: 2), + Container( + constraints: BoxConstraints(maxWidth: Screen.width - 120), + padding: EdgeInsets.symmetric(vertical: 1, horizontal: 3), + child: Text( + quoteMsg.content, + maxLines: 1, + textScaleFactor: 1.0, + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 12), + ), + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(5)), + ) + ], + ); + } else { + return text; + } + } + + _soundMsg() { + double time = widget.msg.extraInfo / 1000; + if (time > 60) { + time = 60.0; + } + bool isPlaying = false; + + var soundPath = widget.msg.localFile; + + isPlaying = SoundUtils().isPlaying(soundPath); + + var soundWidget = GestureDetector( + child: Container( + width: 120, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + alignment: Alignment.center, + padding: EdgeInsets.only(bottom: 2), + margin: EdgeInsets.only(right: 10), + width: 25.5, + height: 25.5, + decoration: BoxDecoration( + border: + Border.all(color: const Color(0xFF1B92C7), width: 0.5), + color: const Color(0xFF04A4FE), + shape: BoxShape.circle), + child: Icon( + IconData(isPlaying ? 0xe652 : 0xe653, + fontFamily: Constants.IconFontFamily), + size: isPlaying ? 15 : 18, + color: Colors.white, + ), + ), + isPlaying + ? Stack( + children: [ + Container( + height: 18, + width: 19, + ), + Positioned( + bottom: 0, + child: VideoAnim( + begin: 18, + start: 0.444, + end: 4.5, + )), + Positioned( + left: 7, + bottom: 0, + child: VideoAnim( + begin: 4.5, + end: 18, + )), + Positioned( + left: 14, + bottom: 0, + child: VideoAnim( + begin: 18, + end: 4.5, + )) + ], + ) + : Stack( + children: [ + Container( + height: 18, + width: 19, + ), + Positioned( + bottom: 0, child: CustomUI.buildAudioContaniner(12)), + Positioned( + left: 7, + bottom: 0, + child: CustomUI.buildAudioContaniner(4.5)), + Positioned( + left: 14, + bottom: 0, + child: CustomUI.buildAudioContaniner(18)) + ], + ), + Expanded(child: SizedBox()), + fixedText(time.toStringAsFixed(0), + color: Constants.BlackTextColor, fontSize: 16) + ], + ), + padding: EdgeInsets.symmetric(horizontal: 15, vertical: 12), + decoration: BoxDecoration( + color: SendMsgBg, + border: Border.all(color: Color(0xFFB9CBD7), width: 0.6), + borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), + ), + onTap: () async { + print('播放状态 : $isPlaying'); + print('当前文件$soundPath '); + if (isPlaying) { + SoundUtils().pause(); + } else { + SoundUtils().play(soundPath, onPlayed: () { + if (mounted) { + setState(() {}); + } + }, complete: () { + if (mounted) { + setState(() {}); + } + }); + } + }, + ); + + return UploadImgItem( + msg: widget.msg, + child: soundWidget, + isShowProgress: false, + ); + } + + Size _getImgSize() { + double aspectRatio = widget.msg.extraInfo / 100; + + var maxWidth = Screen.width * 0.65; + var maxHeight = Screen.height / 4; + + var width, height; + if (maxWidth / maxHeight > aspectRatio) { + height = maxHeight; + width = maxHeight * aspectRatio; + } else { + width = maxWidth; + height = maxWidth / aspectRatio; + } + + return Size(width, height); + } + + _imgMsg(List imgData) { + var imgSize = _getImgSize(); + + return GestureDetector( + child: ClipRRect( + child: UploadImgItem( + msg: widget.msg, + cancelToken: _cancelToken, + child: Container( + height: imgSize.height, + width: imgSize.width, + child: Image( + fit: BoxFit.contain, + image: MemoryImage(Uint8List.fromList(imgData)), + ), + )), + borderRadius: BorderRadius.circular(5), + ), + onTap: () async { + showFullImg(context, widget.msg); + }); + } + + _videoMsg(BuildContext context, List thumbnail) { + var imgSize = _getImgSize(); + return InkWell( + child: ClipRRect( + child: Stack( + alignment: Alignment.center, + children: [ + UploadImgItem( + msg: widget.msg, + cancelToken: _cancelToken, + child: Container( + width: imgSize.width, + height: imgSize.height, + child: Image( + fit: BoxFit.contain, + image: MemoryImage(Uint8List.fromList(thumbnail)), + ), + )) + ], + ), + borderRadius: BorderRadius.circular(5), + ), + onTap: () { + showVideoPage(context, widget.msg.localFile); + }, + ); + } + + _msgLayout(BuildContext context, MsgModel msg) { + Widget item; + + switch (ChatType.valueOf(msg.msgType)) { + case ChatType.TextChatType: + item = _textMsg(msg.msgContent); + break; + + case ChatType.EmoticonType: + item = _textGif(msg.msgContent); + break; + case ChatType.ImageChatType: + item = _imgMsg(msg.msgContent); + break; + case ChatType.ShortVideoChatType: + item = _videoMsg(context, msg.msgContent); + break; + case ChatType.ShortVoiceChatType: + item = _soundMsg(); + break; + case ChatType.RedWalletChatType: + item = RedBagItem( + Key(msg.time.toString()), UserData().basicInfo.userId, msg); + break; + case ChatType.PlaceChatType: + item = PlaceItem(isMe: true, placeContent: msg.msgContent); + break; + case ChatType.GiftChatType: + item = GiftMsgItem(msg.msgContent, true); + break; + case ChatType.FileChatType: + item = _fileMsgItem(); + break; + default: + } + + return wrapItemWithMenu(item); + } + + Widget _fileMsgItem() { + return UploadImgItem( + msg: widget.msg, + cancelToken: _cancelToken, + child: Container( + height: 100, + constraints: BoxConstraints(maxWidth: Screen.width - 120), + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + decoration: BoxDecoration( + color: isLongPressed ? Colors.grey[300] : SendMsgBg, + borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), + child: FileMsgItem(widget.msg))); + } + + Widget _getSentMessageLayout(BuildContext context) { + bool hasHeadImg = true; + if (UserData().basicInfo.headimgurl == null || + UserData().basicInfo.headimgurl.length == 0) { + hasHeadImg = false; + } + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + MsgStateWidget(widget.msg), + SizedBox(width: 3), + _msgLayout(context, widget.msg), + SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: hasHeadImg + ? CachedNetworkImage( + imageUrl: UserData().basicInfo.headimgurl, + width: 40, + height: 40, + ) + : SizedBox( + width: 40, + height: 40, + child: Image.asset(R.assetsImagesDefaultNorAvatar))), + ], + ) + ]); + } + + Widget wrapItemWithMenu(item) { + List actionsFunc = []; + List actions = [ + I18n.of(context).delete, + I18n.of(context).reply, + ]; + + actionsFunc.add(() { + MessageMgr().emit('Delete Select Message', widget.msg); + }); + actionsFunc.add(() { + print('发送引用的消息'); + MessageMgr().emit('Reply Select Message', widget.msg); + }); + + if (widget.msg.msgType == ChatType.TextChatType.value) { + actions.insert(0, I18n.of(context).copy); + actionsFunc.insert(0, () { + //复制当前的文字 + print('复制文字 ${textList[curTextType]}'); + ClipboardData clipboardData = + ClipboardData(text: textList[curTextType]); + Clipboard.setData(clipboardData); + }); + } + + if (widget.msg.msgType == ChatType.ShortVoiceChatType.value) { + var soundPlayMode = + Provider.of(context).soundPlayMode; + + actions.add(soundPlayMode + ? I18n.of(context).handset_playback + : I18n.of(context).speaker_play); + actionsFunc.add(() { + Provider.of(context) + .changeSoundPlayMode(!soundPlayMode); + SoundUtils.instance.savePlayModeConfig(soundPlayMode); + }); + } + + return WPopupMenu( + child: item, + actions: actions, + onLongPressStart: () { + isLongPressed = true; + setState(() {}); + }, + onLongPressEnd: () { + isLongPressed = false; + setState(() {}); + }, + onValueChanged: (int value) { + print('选择的是$value个菜单'); + if (value >= 0 && value < actionsFunc.length) { + actionsFunc[value](); + } + }, + ); + } + + //用户评价人工翻译,差评 + rateTranslateResult() async { + return await HttpUtil().rateTranslateResult(widget.msg, () { + if (mounted) { + setState(() {}); + } + }); + } + + _receiveJIF(MsgModel msg) { + var text = utf8.decode(msg.msgContent); + return extendedText(text, hideKeyboard: widget.hideKeyboard); + } + + double _getTextWidth(String text) { + var tp = TextPainter( + text: TextSpan(style: TextStyle(fontSize: FontSize), text: text), + textAlign: TextAlign.left, + textDirection: TextDirection.ltr, + textScaleFactor: 1, + ); + + tp.layout(maxWidth: Screen.width - 140); + + RegExp alterStr = RegExp(r'\[([0-9]+)\]'); + Iterable matches = alterStr.allMatches(text); + print('~~~~~~~~~~~~~~${matches.length}~~~~~~~~~~~~~~~'); + + double delta = 0; + for (Match m in matches) { + print('~~~~~~~~~~~~~~${m.group(1)}~~~~~~~~~~~~~~~'); + if (int.parse(m.group(1)) > 10) { + delta += 20 + 4 - 25; + } else { + delta += 20 + 4 - 16.8; + } + } + + return tp.width + delta; + } + + _receiveText(MsgModel msg) { + List showMsg = []; + if (textList.length > 0) { + showMsg.add(Container( + constraints: + BoxConstraints(maxWidth: Screen.width - 140, minHeight: 24), + alignment: Alignment.centerLeft, + child: extendedText( + textList[curTextType], + color: Constants.BlackTextColor, + hideKeyboard: widget.hideKeyboard, + fontSize: FontSize, + ))); + } + + var width = _getTextWidth(textList[curTextType]); + + var minWidth = width; + if (msg.transTag != 0) { + minWidth = 200; + showMsg.add(Padding( + padding: EdgeInsets.symmetric(vertical: 5), + child: Divider(color: Color(0xFFECECEC), height: 1))); + Widget tranWidget = _transProcessWidget(msg.transTag); + showMsg.add(tranWidget); + } + + ///todo + Widget text = Container( + width: width + 20, + constraints: + BoxConstraints(maxWidth: Screen.width - 120, minWidth: minWidth), + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: showMsg), + decoration: BoxDecoration( + border: Border.all(color: ReciveBorderColor, width: 0.5), + color: isLongPressed ? Colors.grey[300] : Colors.white, + borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), + ); + + if (msg.refMsgContent != null && msg.refMsgContent.length > 0) { + QuoteMsg quoteMsg = QuoteMsg.fromBuffer(msg.refMsgContent); + + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + text, + SizedBox(height: 2), + Container( + constraints: BoxConstraints(maxWidth: Screen.width - 120), + padding: EdgeInsets.symmetric(vertical: 1, horizontal: 3), + child: Text( + quoteMsg.content, + maxLines: 1, + textScaleFactor: 1.0, + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 12), + ), + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(5)), + ) + ], + ); + } else { + return text; + } + } + + _translateItemWidget(int code, String title, Function onTap) { + Color color = onTap == null ? Constants.GreyTextColor : Color(0xFF087FF3); + return InkWell( + onTap: onTap, + splashColor: Colors.red, + child: Container( + width: 80, + child: Row( + children: [ + Icon(IconData(code, fontFamily: Constants.IconFontFamily), + color: color, size: 20), + SizedBox(width: 5), + Expanded( + child: SizedBox( + child: Text( + title, + style: TextStyle(color: color, fontSize: 10), + textScaleFactor: 1.0, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + )) + ], + ))); + } + + bool isTranslating = false; + _transProcessWidget(int transTag) { + double width = 160; + + Widget userTranslateWidget; + Widget machineTranslateWidget; + + if (transTag == 1) { + //机器翻译中 + userTranslateWidget = _translateItemWidget(0xe670, '人工重译', null); + + machineTranslateWidget = + _translateItemWidget(0xe671, I18n.of(context).robotTranslate, null); + } else if (transTag == 2) { + //人工翻译中 + userTranslateWidget = _translateItemWidget(0xe670, '人工翻译中', null); + machineTranslateWidget = _translateItemWidget(0xe671, '机器重译', () { + setState(() { + curTextType += 1; + curTextType %= textList.length; + }); + }); + } else if (transTag == 3) { + //机器翻译完成 + userTranslateWidget = _translateItemWidget( + 0xe670, + '人工重译', + isTranslating + ? null + : () async { + isTranslating = true; + + int money = + Provider.of(context, listen: false) + .money; + + int voucher = + Provider.of(context, listen: false) + .voucher; + + int needMoney = widget.msg.getNeedMoney(); + + if (needMoney > voucher + money) { + showToast('翻译券和H币不足'); + return; + } + var res = await HttpUtil().getPersonalTranslate(widget.msg); + if (res) { + print('请求人工翻译成功,进行扣费'); + setState(() { + widget.msg.transTag = 2; + + //优先扣券 + if (voucher > 0) { + int costQuan = min(voucher, needMoney); + Provider.of(context, + listen: false) + .subVoucher(costQuan); + } + + //不足的话再扣H币 + if (needMoney > voucher) { + Provider.of(context, listen: false) + .subMoney(needMoney - voucher); + } + }); + } + }); + machineTranslateWidget = _translateItemWidget(0xe671, '机器重译', () { + setState(() { + curTextType += 1; + curTextType %= textList.length; + }); + }); + } else if (transTag == 4 || transTag == 10) { + //4人工翻译完成,未评论 10人工翻译完成已评论 + userTranslateWidget = InkWell( + onTap: () { + setState(() { + curTextType = 0; + }); + }, + child: Container( + width: width / 2, + child: Row( + children: [ + InkWell( + child: Icon( + IconData(0xe641, fontFamily: Constants.IconFontFamily), + size: 18, + color: + transTag == 10 ? Colors.grey : Color(0xFF087FF3)), + onTap: transTag == 10 + ? null + : () { + CustomUI.showIosDialog( + context, I18n.of(context).bad_ev, () async { + bool isSuccess = await rateTranslateResult(); + if (isSuccess) { + Navigator.of(context).pop(true); + showToast(I18n.of(context).success); + } else { + showToast(I18n.of(context).fail); + Navigator.of(context).pop(); + } + }, () { + Navigator.of(context).pop(); + }); + }, + ), + SizedBox(width: 5), + Expanded( + child: SizedBox( + child: Text( + I18n.of(context).over, + style: TextStyle(color: Color(0xFF087FF3), fontSize: 10), + textScaleFactor: 1.0, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + )) + ], + ))); + machineTranslateWidget = _translateItemWidget(0xe675, '查看原文', () { + setState(() { + curTextType = textList.length - 1; + }); + }); + } + + return Container( + height: 26, + alignment: Alignment.center, + child: Row( + children: [ + userTranslateWidget, + Expanded( + child: SizedBox(child: VerticalDivider(), height: 20, width: 2)), + machineTranslateWidget + ], + ), + ); + } + + _receiveImg(BuildContext context, List imgData, {String downloadData}) { + ImageProvider provider = MemoryImage(Uint8List.fromList(imgData)); + + var imgSize = _getImgSize(); + return GestureDetector( + child: Container( + width: imgSize.width, + height: imgSize.height, + child: ClipRRect( + child: Image( + image: provider ?? AssetImage(R.assetsImagesIcAlbum), + ), + borderRadius: BorderRadius.circular(5), + )), + onTap: () async { + showFullImg(context, widget.msg); + }); + } + + _receiveVideo(BuildContext context, List imgData, + {String downloadData}) { + ImageProvider provider = MemoryImage(Uint8List.fromList(imgData)); + var imgSize = _getImgSize(); + return InkWell( + onTap: () { + if (widget.msg.localFile != null) { + showVideoPage(context, widget.msg.localFile); + } + }, + child: DownloadItem( + isAutoDown: false, + msg: widget.msg, + child: Container( + width: imgSize.width, + height: imgSize.height, + child: ClipRRect( + child: Image( + image: provider ?? AssetImage(R.assetsImagesIcAlbum), + ), + borderRadius: BorderRadius.circular(5), + ), + ), + )); + } + + showVideoPage(BuildContext context, String filePath) { + widget.hideKeyboard(); + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return VideoPage(videoPath: filePath); + })); + } + + Widget _receiveFileMsgItem() { + return DownloadItem( + isAutoDown: false, + msg: widget.msg, + onComplete: () { + if (mounted) { + setState(() {}); + } + }, + child: Container( + height: 100, + constraints: BoxConstraints(maxWidth: Screen.width - 120), + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: ReciveBorderColor, width: 0.5), + borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), + child: FileMsgItem(widget.msg))); + } + + _receiveSound(BuildContext context, List soundData) { + print('收到语音消息'); + + MsgModel msg = widget.msg; + var time = widget.msg.extraInfo / 1000; + if (time > 60) { + time = 60.0; + } + bool isPlaying = false; + + if (curSoundUrl != null) { + isPlaying = SoundUtils().isPlaying(curSoundUrl); + } + + var soundWidget = InkWell( + onTap: () async { + bool isLocal = true; + + if (msg.localFile != null) { + isLocal = true; + curSoundUrl = msg.localFile; + } else { + isLocal = false; + var sessionId = msg.sessionId; + curSoundUrl = UploadUtil() + .getFullUrl(msg.extraFile, sessionId, msg.channelType); + } + + print('当前文件$curSoundUrl 本地?$isLocal'); + if (isPlaying) { + await SoundUtils().pause(); + } else { + print('开始播放'); + + if (widget.msg.soundListened == 0) { + widget.msg.updateSoundListened(); + } //设置为已经播放 + await SoundUtils().play(curSoundUrl, isLocal: isLocal, onPlayed: () { + if (mounted) { + this.setState(() {}); + } + }, complete: () { + if (mounted) { + this.setState(() {}); + } + }); + } + }, + child: Container( + width: 130, + child: Row(children: [ + Container( + alignment: Alignment.center, + padding: EdgeInsets.only(bottom: 2), + margin: EdgeInsets.only(right: 10), + width: 25.5, + height: 25.5, + decoration: BoxDecoration( + border: + Border.all(color: const Color(0xFF1B92C7), width: 0.5), + color: const Color(0xFF04A4FE), + shape: BoxShape.circle), + child: Icon( + IconData(isPlaying ? 0xe652 : 0xe653, + fontFamily: Constants.IconFontFamily), + size: isPlaying ? 15 : 18, + color: Colors.white, + ), + ), + isPlaying + ? Stack( + children: [ + Container( + height: 18, + width: 19, + ), + Positioned( + bottom: 0, + child: VideoAnim( + begin: 18, + start: 0.444, + end: 4.5, + )), + Positioned( + left: 7, + bottom: 0, + child: VideoAnim( + begin: 4.5, + end: 18, + )), + Positioned( + left: 14, + bottom: 0, + child: VideoAnim( + begin: 18, + end: 4.5, + )) + ], + ) + : Stack( + children: [ + Container( + height: 18, + width: 19, + ), + Positioned( + bottom: 0, child: CustomUI.buildAudioContaniner(12)), + Positioned( + left: 7, + bottom: 0, + child: CustomUI.buildAudioContaniner(4.5)), + Positioned( + left: 14, + bottom: 0, + child: CustomUI.buildAudioContaniner(18)) + ], + ), + Expanded(child: SizedBox()), + fixedText(time.toStringAsFixed(0), + color: Constants.BlackTextColor, fontSize: 16) + ])), + ); + + List showMsg = []; + + showMsg.add(DownloadItem( + msg: widget.msg, + child: soundWidget, + isShowProgress: false, + )); + + double width = 130; + double minWidth = 0; + if (textList.length > 0) { + width = _getTextWidth(textList[curTextType]) + 20; + width = min(width, Screen.width - 120); + + showMsg.add(Padding( + padding: EdgeInsets.symmetric(vertical: 5), + child: Divider( + height: 1, + ))); + showMsg.add(Container( + child: extendedText( + textList[curTextType], + color: Constants.BlackTextColor, + hideKeyboard: widget.hideKeyboard, + fontSize: FontSize, + ), + alignment: Alignment.centerLeft, + constraints: + BoxConstraints(maxWidth: Screen.width - 120, minHeight: 22), + )); + } + + if (msg.transTag != 0) { + minWidth = 200; + showMsg.add(Divider(color: Color(0xFFECECEC), height: 3)); + Widget tranWidget = _transProcessWidget(msg.transTag); + showMsg.add(tranWidget); + } + + return Container( + width: width + 20, + constraints: + BoxConstraints(maxWidth: Screen.width - 120, minWidth: minWidth), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: showMsg), + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: ReciveBorderColor, width: 0.5), + borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), + ); + } + + void showFullImg(BuildContext context, MsgModel msg) { + print('显示图片'); + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return PhotoPage(msg: msg); + })); + } + + _reveiveMsg(BuildContext context) { + Widget item; + switch (ChatType.valueOf(widget.msg.msgType)) { + case ChatType.TextChatType: + item = _receiveText(widget.msg); + break; + case ChatType.EmoticonType: + item = _receiveJIF(widget.msg); + break; + + case ChatType.ImageChatType: + if (widget.msg.extraFile != null) { + item = _receiveImg(context, widget.msg.msgContent, + downloadData: widget.msg.extraFile); + } else { + item = _receiveImg(context, widget.msg.msgContent); + } + break; + case ChatType.ShortVideoChatType: + item = _receiveVideo(context, widget.msg.msgContent, + downloadData: widget.msg.extraFile); + break; + case ChatType.ShortVoiceChatType: + item = _receiveSound(context, widget.msg.msgContent); + break; + + case ChatType.RedWalletChatType: + item = RedBagItem( + Key(widget.msg.time.toString()), friendInfo.userId, widget.msg); + break; + case ChatType.PlaceChatType: + item = PlaceItem(isMe: false, placeContent: widget.msg.msgContent); + break; + case ChatType.GiftChatType: + item = GiftMsgItem(widget.msg.msgContent, false); + break; + case ChatType.FileChatType: + item = _receiveFileMsgItem(); + break; + default: + } + + return wrapItemWithMenu(item); + } + + Widget _getReceivedMessageLayout(BuildContext context) { + bool hasHeadImg = true; + + if (friendInfo.headimgurl == null || friendInfo.headimgurl.length == 0) { + hasHeadImg = false; + } + + bool isShowSoundSate = + widget.msg.msgType == ChatType.ShortVoiceChatType.value && + widget.msg.soundListened == 0; + + return Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Container( + margin: const EdgeInsets.only(right: 8.0), + child: InkWell( + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: hasHeadImg + ? CachedNetworkImage( + imageUrl: friendInfo.headimgurl, + width: 40, + height: 40, + ) + : SizedBox( + width: 40, + height: 40, + child: Image.asset(R.assetsImagesDefaultNorAvatar))), + onTap: () { + AppNavigator.pushProfileInfoPage(context, friendInfo.userId, + fromWhere: 0); + }, + )), + _reveiveMsg(context), + isShowSoundSate + ? Container( + margin: EdgeInsets.only(left: 8), + width: 40, + height: 40, + alignment: Alignment.centerLeft, + child: CircleAvatar( + radius: 3.5, + backgroundColor: Colors.red, + )) + : Container() + ]); + } +} diff --git a/lib/chat/coin_bag_info.dart b/lib/chat/coin_bag_info.dart new file mode 100644 index 0000000..061ce8d --- /dev/null +++ b/lib/chat/coin_bag_info.dart @@ -0,0 +1,289 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sql_util.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; + +import '../utils/MessageMgr.dart'; + +class CoinBagInfoPage extends StatefulWidget { + final MsgModel msgModel; + final String titleStr; + CoinBagInfoPage(this.msgModel, {this.titleStr}); + @override + _CoinBagInfoPageState createState() => _CoinBagInfoPageState(); +} + +class _CoinBagInfoPageState extends State { + UserInfo friendInfo; + RedWallet wallet; + @override + void initState() { + super.initState(); + wallet = RedWallet.fromBuffer(widget.msgModel.msgContent); + getInfo(); + } + + getInfo() async { + int sendId = wallet.suId; + if (sendId == UserData().basicInfo.userId) { + friendInfo = UserData().basicInfo; + } else { + friendInfo = await HttpUtil().getFriendInfo(sendId); + setState(() {}); + } + + updateRedWalletState(); + } + + @override + Widget build(BuildContext context) { + var foreColor = const Color(0xEEF9E3B2); + + return Scaffold( + backgroundColor: Color(0xFFE86A52), + appBar: AppBar( + backgroundColor: Color(0xFFE86A52), + leading: CustomUI.buildCustomLeading(context), + ), + body: SafeArea( + child: Center( + child: friendInfo == null + ? CircularProgressIndicator( + backgroundColor: Colors.orange, + valueColor: AlwaysStoppedAnimation(Colors.orange)) + : Container( + padding: + EdgeInsets.symmetric(vertical: 40, horizontal: 20), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.symmetric( + vertical: 60, horizontal: 20), + child: Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: CachedNetworkImage( + imageUrl: friendInfo.headimgurl, + placeholder: (context, url) { + return Container( + padding: EdgeInsets.all(10), + child: CircularProgressIndicator( + valueColor: + AlwaysStoppedAnimation( + foreColor))); + }, + width: 100, + height: 100, + ), + ), + fixedText( + I18n.of(context).ones_money.replaceFirst( + '/s1', + Provider.of(context) + .getRefName(friendInfo.userId, + friendInfo.nickName)), + fontSize: 12, + color: foreColor), + SizedBox(height: 40), + Text( + widget.titleStr, + textScaleFactor: 1.0, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + color: foreColor, + fontWeight: FontWeight.w500), + ), + ], + ), + ), + SizedBox(height: 20), + _info(), + Expanded(child: SizedBox()), + fixedText(I18n.of(context).back_money, + fontSize: 12, color: foreColor) + ], + ), + )))); + } + + _info() { + var myId = UserData().basicInfo.userId; + if (wallet.suId != myId) { + //不是我发的 + if (wallet.state == RedWalletState.Uncollected) { + return _openBtn(); + } else { + return _getInfo(); + } + } else { + return _sendInfo(); + } + } + + _receiveCoinBag() async { + Map data = { + "userId": UserData().basicInfo.userId, + "redNo": wallet.orderId, + }; + data['sign'] = TokenMgr().getSign(data); + + print(DateTime.now()); + Response res = await HttpUtil().post('red/packet/receive', data: data); + + if (res == null) { + return null; + } + Map resData = res.data; + + if (resData['code'] == 0) { + //领取成功 + print(DateTime.now()); + wallet.state = RedWalletState.Received; + print('获得的金额${resData['data']['price']}'); + wallet.amount = resData['data']['price']; + + widget.msgModel.msgContent = wallet.writeToBuffer(); + + MessageMgr().emit('Update RedWalletState', wallet); + + SqlUtil().updateWalletState(widget.msgModel); + setState(() {}); + } else if (resData['code'] == -4) { + //红包已过期 + showToast(I18n.of(context).money_over); + } else if (resData['code'] == -5) { + //红包已领过或者领取失败 + showToast(I18n.of(context).already_money); + } else if (resData['code'] == -3) { + //红包不存在 + showToast(I18n.of(context).no_money); + } else { + showToast(resData['msg']); + } + + return null; + } + + _openBtn() { + return SizedBox( + width: 100, + height: 100, + child: RaisedButton( + padding: EdgeInsets.all(10.0), + onPressed: _receiveCoinBag, + shape: CircleBorder(), + elevation: 2.0, + child: Text(I18n.of(context).open, + style: TextStyle(fontSize: 28), + textAlign: TextAlign.center, + textScaleFactor: 1.0), + textColor: Color(0xFFD84F46), + color: Color(0xFFFFE3AF), + )); + } + + _getInfo() { + var infoStr = ''; + if (wallet.state == RedWalletState.Received) { + infoStr = I18n.of(context).already_money; + } else { + infoStr = I18n.of(context).money_over; + } + + return Container( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(wallet.amount.toString(), + textScaleFactor: 1.0, + style: TextStyle(fontSize: 50, color: Color(0xEEF9E3B2))), + Padding( + padding: EdgeInsets.only(left: 10, bottom: 15), + child: Image.asset(R.assetsImagesCoin, scale: 3)) + ], + ), + fixedText(infoStr, color: Color(0xEEF9E3B2)), + ], + ), + ); + } + + updateRedWalletState() async { + Map data = { + "userId": UserData().basicInfo.userId, + "redNo": wallet.orderId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('red/packet/status', data: data); + + if (res == null) { + return; + } + Map resData = res.data; + + if (resData['code'] == 0) { + wallet.state = RedWalletState.valueOf(resData['data']['status']); + if (wallet.state != RedWalletState.Uncollected) { + if (mounted) { + setState(() {}); + } + } + } + } + + _sendInfo() { + var msg; + switch (wallet.state) { + case RedWalletState.Expire: + msg = I18n.of(context).back_user; + break; + case RedWalletState.Uncollected: + msg = I18n.of(context).waiting_user; + break; + case RedWalletState.Received: + msg = I18n.of(context).other_get; + break; + default: + } + + return Container( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(wallet.amount.toString(), + textScaleFactor: 1.0, + style: TextStyle(fontSize: 50, color: Color(0xEEF9E3B2))), + Padding( + padding: EdgeInsets.only(left: 10, bottom: 15), + child: Image.asset(R.assetsImagesCoin, scale: 3)) + ], + ), + fixedText(msg, color: Color(0xEEF9E3B2)), + ], + ), + ); + } +} diff --git a/lib/chat/coin_bag_view.dart b/lib/chat/coin_bag_view.dart new file mode 100644 index 0000000..5057089 --- /dev/null +++ b/lib/chat/coin_bag_view.dart @@ -0,0 +1,237 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; + +class CoinBagPage extends StatefulWidget { + @override + _CoinBagPageState createState() => _CoinBagPageState(); +} + +class _CoinBagPageState extends State { + final TextEditingController _textCtrl = TextEditingController(); + + FocusNode editFocus = FocusNode(); + + final TextEditingController _amountCtrl = TextEditingController(); + + FocusNode amountFocus = FocusNode(); + + var curAmount = 0; + var curDesc = ''; + + @override + void initState() { + super.initState(); + print('CoinBagPage initState'); + } + + @override + void dispose() { + _textCtrl.dispose(); + amountFocus.dispose(); + _amountCtrl.dispose(); + editFocus.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (curDesc == '') { + curDesc = I18n.of(context).little; + } + + return Scaffold( + appBar: AppBar( + title: Text(I18n.of(context).red_money), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ), + body: SafeArea( + child: GestureDetector( + onTap: () { + if (editFocus.hasFocus) { + editFocus.unfocus(); + } + + if (amountFocus.hasFocus) { + amountFocus.unfocus(); + } + }, + child: SingleChildScrollView( + child: Center( + child: Column( + children: [ + Container( + padding: EdgeInsets.all(20), + child: Column( + children: [ + _buildAmountField(), + SizedBox(height: 10), + _buildTitleTextField(), + Padding( + padding: EdgeInsets.symmetric(vertical: 30), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '$curAmount', + textScaleFactor: 1.0, + style: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 30), + ), + //SizedBox(width: 5), + Text( + I18n.of(context).mask_coin, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 18), + ), + //Image.asset(R.assetsImagesCoin, scale: 2), + ], + )), + _buildSendBtn(), + ], + )) + ], + ), + )), + ))); + } + + _buildAmountField() { + return Container( + padding: const EdgeInsets.fromLTRB(8, 8, 0, 8), + height: 40.0, + width: Screen.width - 60, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.white, borderRadius: BorderRadius.circular(10.0)), + child: TextField( + keyboardAppearance: Brightness.light, + controller: _amountCtrl, + focusNode: amountFocus, + textAlign: TextAlign.right, + textAlignVertical: TextAlignVertical.center, + textInputAction: TextInputAction.done, + style: TextStyle(textBaseline: TextBaseline.alphabetic, fontSize: 16), + keyboardType: TextInputType.number, + inputFormatters: [ + LengthLimitingTextInputFormatter(10) //限制长度 + ], + onChanged: (String text) { + if (text.length == 0) { + curAmount = 0; + } else { + curAmount = int.parse(text); + } + + setState(() {}); + }, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(top: 8, bottom: 8), + hintText: curAmount.toString(), + hintStyle: + TextStyle(fontSize: 16, color: Constants.LightGreyTextColor), + prefixIcon: Container( + width: 65, + alignment: Alignment.centerLeft, + child: Text(I18n.of(context).mount), + ), + border: InputBorder.none, + suffixIcon: Container( + width: 50, + child: Image.asset(R.assetsImagesCoin, scale: 3), + alignment: Alignment.center, + ), + ), + ), + ); + } + + _buildTitleTextField() { + return Container( + padding: const EdgeInsets.fromLTRB(8, 8, 0, 8), + height: 100.0, + width: Screen.width - 60, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.white, borderRadius: BorderRadius.circular(12.0)), + child: TextField( + keyboardAppearance: Brightness.light, + controller: _textCtrl, + focusNode: editFocus, + textAlign: TextAlign.center, + style: TextStyle(textBaseline: TextBaseline.alphabetic, fontSize: 15), + maxLines: 4, + minLines: 1, + textInputAction: TextInputAction.done, + inputFormatters: [ + LengthLimitingTextInputFormatter(30) //限制长度 + ], + onChanged: (String text) { + curDesc = text; + }, + decoration: InputDecoration.collapsed( + hintText: curDesc, + hintStyle: + TextStyle(fontSize: 15, color: Constants.LightGreyTextColor)), + ), + ); + } + + _buildSendBtn() { + return SizedBox( + width: Screen.width * 2 / 3, + child: RaisedButton( + child: Text(I18n.of(context).put_money, + textAlign: TextAlign.center, + style: TextStyle(color: Colors.white, fontSize: 20)), + color: Color(0xFFdd643e), + padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 12), + disabledColor: Color(0xFFdd643e).withAlpha(160), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(8))), + onPressed: curAmount > 0 ? _sendCoin : null, + )); + } + + _sendCoin() { + if (curDesc == '') { + curDesc = I18n.of(context).little; + } + + if (curAmount <= 0) { + showToast(I18n.of(context).enter_amount); + return; + } else { + if (curAmount < 10) { + showToast( + I18n.of(context).little_min.replaceFirst('/s1', 10.toString())); + return; + } + if (curAmount > 999) { + showToast( + I18n.of(context).more_big.replaceFirst('/s1', 999.toString())); + return; + } + } + int curCoin = Provider.of(context).money; + if (curCoin >= curAmount) { + Provider.of(context).subMoney(curAmount); + MessageMgr() + .emit('Send CoinBag', {'amount': curAmount, 'title': curDesc}); + curAmount = 0; + Navigator.pop(context); + } else { + showToast(I18n.of(context).not_enough); + } + } +} diff --git a/lib/chat/company_server_view.dart b/lib/chat/company_server_view.dart new file mode 100644 index 0000000..c22ff0e --- /dev/null +++ b/lib/chat/company_server_view.dart @@ -0,0 +1,340 @@ +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:chat/chat/ChatPageItem.dart'; +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/photo/entity/options.dart'; +import 'package:chat/photo/photo.dart'; +import 'package:chat/proto/chat.pb.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/image_util.dart'; +import 'package:chat/utils/keyboard_utils.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:photo_manager/photo_manager.dart'; +import 'package:chat/utils/MessageMgr.dart'; + +class CompanyServerPage extends StatefulWidget { + @override + _CompanyServerPageState createState() => _CompanyServerPageState(); +} + +class _CompanyServerPageState extends State { + final TextEditingController _textCtrl = TextEditingController(); + FocusNode editFocus = NoKeyboardEditableTextFocusNode(); + bool _isComposingMessage = false; + + double keyboardHeight; + KeyboardBloc _bloc = KeyboardBloc(); + + ScrollController _scrollCtrl = ScrollController(); + + List msgList = []; + + static int companyId = 10000; + + UserInfo companyInfo = UserInfo( + userId: companyId, + headimgurl: R.assetsImagesServerIcon, + nickName: '反馈小助手'); + + @override + void initState() { + super.initState(); + + _bloc.start(); + + //10000号为服务小助手 + MsgHandler.updateActiveSesstion(companyId); + + msgList = ChatDataMgr().getRecord(); + + MessageMgr().on('New Chat Message', receiveMsg); + } + + @override + void dispose() { + MsgHandler.curActiveSession = 0; + _textCtrl.dispose(); + _bloc.dispose(); + editFocus.dispose(); + _scrollCtrl.dispose(); + + MessageMgr().off('New Chat Message', receiveMsg); + super.dispose(); + } + + receiveMsg(sessionId) { + print('收到反馈助手消息'); + if (mounted) { + setState(() {}); + if (_scrollCtrl.hasClients) { + _scrollCtrl.animateTo(0, + duration: new Duration(milliseconds: 500), curve: Curves.ease); + } + } + } + + hideKeyBoard() { + editFocus.unfocus(); + } + + bool checkMessage() { + if (_textCtrl.text.length == 0) { + showToast(I18n.of(context).msg_not); + return false; + } + return true; + } + + Future _textMessageSubmitted(String text) async { + if (!checkMessage()) { + _textCtrl.clear(); + return; + } + _textCtrl.clear(); + + _sendMessage(text); + } + + _sendTextMessage() { + if (!checkMessage()) { + return; + } + + var sendStr = _textCtrl.text; + + _textCtrl.clear(); + + _sendMessage(sendStr); + } + + _sendMessage(String messageText) { + MsgModel msg = MsgHandler.createSendMsg(ChatType.TextChatType, messageText, + friendId: companyId, channelType: ChatChannelType.CSD); + + setState(() { + _isComposingMessage = _textCtrl.text.length > 0; + }); + + sendMsg(msg); + } + + sendMsg(MsgModel msg) async { + ChatDataMgr().saveCompanyMsg(msg); + + if (mounted) { + setState(() {}); + + if (_scrollCtrl.hasClients) { + _scrollCtrl.animateTo(0, + duration: new Duration(milliseconds: 500), curve: Curves.ease); + } + } + + await HttpUtil().commitInfoToCompany(msg); + if (mounted) { + setState(() {}); + } + } + + void _openPhotoView() async { + var photos = await PhotoPicker.pickAsset( + context: context, + themeColor: Color(0xFFF0F0F0), + textColor: Color(0xFF3F3F3F), + pickType: PickType.onlyImage); + + if (photos != null && photos.length > 0) { + for (var i = 0; i < photos.length; i++) { + AssetEntity photoEntity = photos[i]; + var file = await photoEntity.file; + _sendPhotoFile(file); + } + } + } + + void _sendPhotoFile(File imgFile) async { + var imgSize = await imgFile.length(); + + print('图片大小:${imgSize / 1024}KB'); + var sendImg; + + if (imgSize > 33 * 1024 * 1024) { + showToast(I18n.of(context).video_more_big); + return; + } + bool isNeedUpload = false; + if (imgSize > ImgSizeLimit) { + print('图片大于 $ImgSizeLimit,压缩'); + //发送压缩图 + sendImg = await WidgetUtil.getCompressImg(imgFile.absolute.path); + isNeedUpload = true; + } else { + sendImg = imgFile.readAsBytesSync(); + } + + var rect = await WidgetUtil.getImageWH( + image: Image.memory(Uint8List.fromList(sendImg))); + print('图片大小 Rect : $rect'); + int aspectRatio = rect.width * 100 ~/ rect.height; + + var msg = MsgHandler.createSendMsg(ChatType.ImageChatType, sendImg, + localFile: isNeedUpload ? imgFile.absolute.path : null, + extra: aspectRatio, + friendId: companyId, + channelType: ChatChannelType.CSD); + + sendMsg(msg); + } + + _inputBar() { + Widget input = Container( + child: TextField( + keyboardAppearance: Brightness.light, + onChanged: (String messageText) { + setState(() { + _isComposingMessage = _textCtrl.text.length > 0; + }); + }, + cursorColor: Constants.BlueTextColor, + style: TextStyle( + fontSize: ScreenUtil().setSp(16), + textBaseline: TextBaseline.alphabetic), + maxLines: 3, + minLines: 1, + controller: _textCtrl, + textInputAction: TextInputAction.newline, + inputFormatters: [ + LengthLimitingTextInputFormatter(600) //限制长度 + ], + onSubmitted: _textMessageSubmitted, + focusNode: editFocus, + decoration: InputDecoration( + hintText: I18n.of(context).input_content, + hintStyle: TextStyle(color: const Color(0xffBDBDBD), fontSize: 16), + border: null, + hintMaxLines: 1, + contentPadding: EdgeInsets.only(left: 5, right: 5, top: 8, bottom: 8), + ), + ), + ); + + return GestureDetector( + onTap: () { + print('放置触控隐藏键盘'); + }, + child: Container( + width: Screen.width, + color: Colors.white, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 7, vertical: 7), + alignment: Alignment.topCenter, + decoration: BoxDecoration( + color: Colors.white, + border: Border(top: BorderSide(color: Color(0xFFDFDFDF)))), + child: Row( + children: [ + //输入框 + Expanded(child: input), SizedBox(width: 10), + _isComposingMessage + ? InkWell( + child: Padding( + padding: EdgeInsets.fromLTRB(50, 2, 10, 2), + child: Icon( + Icons.send, + color: Color(0xFF087FF3), + size: 28, + )), + onTap: _sendTextMessage) + : InkWell( + child: Icon( + IconData(0xe60c, + fontFamily: Constants.IconFontFamily), + color: Color(0xFF797A7C), + size: 26, + ), + onTap: () { + _openPhotoView(); + }), + ], + )))); + } + + Widget _buildMessageList() { + return Container( + alignment: Alignment.topCenter, + child: msgList.length == 0 + ? Padding( + padding: EdgeInsets.all(8), + child: Text( + '有什么问题都可以反馈给我哦', + textAlign: TextAlign.center, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.grey, fontSize: 12), + )) + : Scrollbar( + child: ListView.builder( + reverse: true, + shrinkWrap: true, + itemCount: msgList.length, + controller: _scrollCtrl, + padding: EdgeInsets.all(8.0), + itemBuilder: _buildItem, + )), + ); + } + + Widget _buildItem(BuildContext context, int index) { + var lastMsgTime; + if (index < msgList.length - 1) { + lastMsgTime = msgList[index + 1].time; + } + + MsgModel msg = msgList[index]; + + return ChatPageItem( + key: Key(msg.time.toString()), + msg: msg, + lastMsgTime: lastMsgTime, + friendInfo: companyInfo); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: hideKeyBoard, + child: Scaffold( + backgroundColor: const Color(0xFFE2E9F1), + appBar: AppBar( + title: Text( + '反馈小助手', + textScaleFactor: 1.0, + style: + TextStyle(color: Constants.BlackTextColor, fontSize: 16.47), + ), + leading: CustomUI.buildCustomLeading(context), + titleSpacing: -10, + centerTitle: false, + elevation: 1, + ), + body: SafeArea( + child: Column( + children: [ + Expanded(child: _buildMessageList()), + _inputBar(), + ], + ))), + ); + } +} diff --git a/lib/chat/custom_keyboard.dart b/lib/chat/custom_keyboard.dart new file mode 100644 index 0000000..d239128 --- /dev/null +++ b/lib/chat/custom_keyboard.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; + +class CustomKeyboardWidget extends StatefulWidget { + @override + _CustomKeyboardWidgetState createState() => _CustomKeyboardWidgetState(); +} + +class _CustomKeyboardWidgetState extends State { + @override + Widget build(BuildContext context) { + return Container( + + ); + } +} \ No newline at end of file diff --git a/lib/chat/dollar_text.dart b/lib/chat/dollar_text.dart new file mode 100644 index 0000000..24ecff4 --- /dev/null +++ b/lib/chat/dollar_text.dart @@ -0,0 +1,42 @@ +import 'package:extended_text_library/extended_text_library.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; + +class DollarText extends SpecialText { + static const String flag = "\$"; + final int start; + DollarText(TextStyle textStyle, SpecialTextGestureTapCallback onTap, + {this.start}) + : super(flag, flag, textStyle, onTap: onTap); + + @override + InlineSpan finishText() { + final String text = getContent(); + + return SpecialTextSpan( + text: text, + actualText: toString(), + start: start, + + ///caret can move into special text + deleteAll: true, + style: textStyle?.copyWith(color: Color(0xff3875E9)), + recognizer: TapGestureRecognizer() + ..onTap = () { + if (onTap != null) onTap(toString()); + }); + } +} + +List dollarList = [ + "\$Dota2\$", + "\$Dota2 Ti9\$", + "\$CN dota best dota\$", + "\$Flutter\$", + "\$CN dev best dev\$", + "\$UWP\$", + "\$Nevermore\$", + "\$FlutterCandies\$", + "\$ExtendedImage\$", + "\$ExtendedText\$", +]; diff --git a/lib/chat/dots_indicator.dart b/lib/chat/dots_indicator.dart new file mode 100644 index 0000000..d107f8a --- /dev/null +++ b/lib/chat/dots_indicator.dart @@ -0,0 +1,68 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +class DotsIndicator extends AnimatedWidget { + DotsIndicator({ + this.controller, + this.itemCount, + this.onPageSelected, + this.color: Colors.red, + }) : super(listenable: controller); + + /// The PageController that this DotsIndicator is representing. + final PageController controller; + + /// The number of items managed by the PageController + final int itemCount; + + /// Called when a dot is tapped + final ValueChanged onPageSelected; + + /// The color of the dots. + /// + /// Defaults to `Colors.white`. + final Color color; + + // The base size of the dots + static const double _kDotSize = 8.0; + + // The increase in the size of the selected dot + static const double _kMaxZoom = 2.0; + + // The distance between the center of each dot + static const double _kDotSpacing = 25.0; + + Widget _buildDot(int index) { + double selectedness = Curves.easeOut.transform( + max( + 0.0, + 1.0 - ((controller.page ?? controller.initialPage) - index).abs(), + ), + ); + double zoom = 1.0 + (_kMaxZoom - 1.0) * selectedness; + return new Container( + width: _kDotSpacing, + child: new Center( + child: new Material( + color: color, + type: MaterialType.circle, + child: new Container( + width: _kDotSize * zoom, + height: _kDotSize * zoom, + child: new InkWell( + onTap: () => onPageSelected(index), + ), + ), + ), + ), + ); + } + + Widget build(BuildContext context) { + return new Row( + mainAxisAlignment: MainAxisAlignment.center, + children: new List.generate(itemCount, _buildDot), + ); + } +} \ No newline at end of file diff --git a/lib/chat/download_item.dart b/lib/chat/download_item.dart new file mode 100644 index 0000000..f05a832 --- /dev/null +++ b/lib/chat/download_item.dart @@ -0,0 +1,138 @@ +import 'package:chat/chat/video_view.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/upload_util.dart'; +import 'package:flutter/material.dart'; +import 'package:percent_indicator/circular_percent_indicator.dart'; + +class DownloadItem extends StatefulWidget { + final MsgModel msg; + final Widget child; + final bool isShowProgress; + final bool isAutoDown; + final Function onComplete; + DownloadItem( + {this.msg, + this.child, + this.isShowProgress = true, + this.isAutoDown = true, + this.onComplete}); + @override + _DownloadItemState createState() => _DownloadItemState(); +} + +class _DownloadItemState extends State { + int downloadState = 0; //0,默认,1进行中,2成功,3失败 + + @override + void initState() { + super.initState(); + + if (widget.msg.localFile == null) { + if (widget.isAutoDown && + (widget.msg.state != MsgState.Downloading && + widget.msg.state != MsgState.DownloadSuccess)) { + downloadRes(); + } + } + } + + downloadRes() async { + print('开始下载文件${widget.msg.extraFile}'); + widget.msg.state = MsgState.Downloading; + + if (mounted) { + setState(() {}); + } + var filePath = await UploadUtil().downloadFile(widget.msg); + + if (filePath != null) { + print('下载完成'); + if (widget.onComplete != null) { + widget.onComplete(); + } + if (mounted) { + setState(() {}); + } + } else { + print('下载文件失败'); + + if (mounted) { + setState(() {}); + } + } + } + + showVideoPage(BuildContext context, String filePath) { + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return VideoPage(videoPath: filePath); + })); + } + + _downloadWidget() { + if (widget.msg.localFile != null) { + if (widget.msg.msgType == ChatType.ShortVideoChatType.value) { + return Icon(Icons.play_circle_outline, color: Colors.white); + } + } else { + if (widget.msg.state == MsgState.DownloadFailed) { + return Container( + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.grey.withAlpha(150), + borderRadius: BorderRadius.circular(8)), + child: Icon(Icons.refresh, color: Colors.white70), + ); + } else if (widget.msg.state == MsgState.Downloading && + widget.isShowProgress) { + return StreamBuilder( + stream: UploadUtil().getStream(widget.msg.extraFile).stream, + initialData: UploadUtil().streamLastPercentMap[widget.msg.extraFile], + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.data != null) { + if (snapshot.data >= 1) { + return SizedBox(width: 0, height: 0); + } + + return CircularPercentIndicator( + radius: 30.0, + lineWidth: 2.0, + percent: snapshot.data, + center: Padding( + padding: EdgeInsets.all(2), + child: fixedText( + "${(snapshot.data * 100).toStringAsFixed(0)}%", + fontSize: 9, + color: Colors.green)), + progressColor: Colors.green, + ); + } else { + return SizedBox(width: 0, height: 0); + } + }, + ); + } else if (widget.msg.state < MsgState.Downloading) { + if (widget.msg.msgType == ChatType.ShortVideoChatType.value) { + return Icon(Icons.play_circle_outline, color: Colors.white); + } + } + } + + return Container(width: 0, height: 0); + } + + @override + Widget build(BuildContext context) { + bool isNeedDown = widget.msg.localFile == null && + (widget.msg.state != MsgState.Downloading && + widget.msg.state != MsgState.DownloadSuccess); + return InkWell( + onTap: isNeedDown ? downloadRes : null, + child: Stack( + alignment: Alignment.center, + children: [widget.child, _downloadWidget()], + )); + } +} diff --git a/lib/chat/emoji_gif_text.dart b/lib/chat/emoji_gif_text.dart new file mode 100644 index 0000000..3bd0ca8 --- /dev/null +++ b/lib/chat/emoji_gif_text.dart @@ -0,0 +1,59 @@ +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:extended_text_library/extended_text_library.dart'; +import 'package:flutter/material.dart'; + +///emoji/image text +class EmojiGifText extends SpecialText { + static const String flag = "<*"; + final int start; + final isShowGif; + EmojiGifText(TextStyle textStyle, {this.start,this.isShowGif=true}) + : super(EmojiGifText.flag, ">", textStyle); + + + @override + InlineSpan finishText() { + var key = toString(); + if (EmojiGifUitl.instance.emojiMap.containsKey(key)) { + //fontsize id define image height + //size = 30.0/26.0 * fontSize + final double size = 118.0; + + ///fontSize 26 and text height =30.0 + //final double fontSize = 26.0; + return isShowGif?ImageSpan(AssetImage(EmojiGifUitl.instance.emojiMap[key]), + actualText: key, + imageWidth: size, + imageHeight: size, + start: start, + fit: BoxFit.fill, + margin: EdgeInsets.only(left: 2.0, top: 2.0, right: 2.0)):SpecialTextSpan(text:'[${I18n.of(LoadingManage.context).emoji}]', actualText: '' ); + +// return Image.asset(EmojiGifUitl.instance.emojiMap[key]); + + } + + return TextSpan(text: toString(), style: textStyle); + } +} + +class EmojiGifUitl { + final Map _emojiMap = new Map(); + + Map get emojiMap => _emojiMap; + + final String _emojiFilePath = "assets/images/sticker"; + + static EmojiGifUitl _instance; + static EmojiGifUitl get instance { + if (_instance == null) _instance = new EmojiGifUitl._(); + return _instance; + } + + EmojiGifUitl._() { + for (int i = 1; i < 31; i++) { + _emojiMap[EmojiGifText.flag+"_$i>"] = "$_emojiFilePath/sticker_$i.gif"; + } + } +} diff --git a/lib/chat/emoji_keyboard.dart b/lib/chat/emoji_keyboard.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/chat/emoji_text.dart b/lib/chat/emoji_text.dart new file mode 100644 index 0000000..851b454 --- /dev/null +++ b/lib/chat/emoji_text.dart @@ -0,0 +1,57 @@ +import 'package:extended_text_library/extended_text_library.dart'; +import 'package:flutter/material.dart'; + +///emoji/image text +class EmojiText extends SpecialText { + static const String flag = "["; + final int start; + final double emojiSize; + EmojiText(TextStyle textStyle, {this.start, this.emojiSize=20.0}) + : super(EmojiText.flag, "]", textStyle); + + @override + InlineSpan finishText() { + var key = toString(); + + if (EmojiUitl.instance.emojiMap.containsKey(key)) { + + //fontsize id define image height + //size = 30.0/26.0 * fontSize + final double size = emojiSize; + // ScreenUtil().setWidth(emojiSize); + ///fontSize 26 and text height =30.0 + //final double fontSize = 26.0; + return ImageSpan(AssetImage(EmojiUitl.instance.emojiMap[key]), + actualText: key, + imageWidth: size, + imageHeight: size, + start: start, + fit: BoxFit.contain, + margin: EdgeInsets.only(left: 2.0, top: 2.0, right: 2.0)); + } + + return TextSpan(text: toString(), style: textStyle); + } +} + +class EmojiUitl { ///emoji + final Map _emojiMap = new Map(); + + Map get emojiMap => _emojiMap; + + final String _emojiFilePath = "assets/images/emojiface"; + + static EmojiUitl _instance; + static EmojiUitl get instance { + if (_instance == null) _instance = new EmojiUitl._(); + return _instance; + } + + EmojiUitl._() { + for (int i = 1; i < 87; i++) { + + _emojiMap[EmojiText.flag+"$i]"] = "$_emojiFilePath/$i.png"; + } + + } +} diff --git a/lib/chat/file_msg_item.dart b/lib/chat/file_msg_item.dart new file mode 100644 index 0000000..f77cea2 --- /dev/null +++ b/lib/chat/file_msg_item.dart @@ -0,0 +1,115 @@ +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/proto/chat.pb.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:open_file/open_file.dart'; + +class FileMsgItem extends StatelessWidget { + final MsgModel msgModel; + FileMsgItem(this.msgModel); + + getTypeImage(String type) { + type = type.toLowerCase(); + switch (type) { + case 'pdf': + return R.assetsImagesExtPdf; + break; + case 'doc': + case 'docx': + return R.assetsImagesExtWord; + break; + case 'ppt': + return R.assetsImagesExtPpt; + break; + case 'xls': + case 'xlsx': + return R.assetsImagesExtExcel; + break; + case 'txt': + case 'xml': + case 'html': + case 'htm': + case '.h': + case '.cpp': + case '.conf': + case '.c': + return R.assetsImagesExtTxt; + break; + case 'tar': + case 'gz': + case 'gzip': + case 'tgz': + case 'zip': + return R.assetsImagesExtZip; + break; + case 'mp3': + case 'wav': + return R.assetsImagesExtSound; + break; + + case 'mp4': + case 'avi': + case 'mpg': + case 'wm': + case 'wmv': + return R.assetsImagesExtVideo; + break; + case 'apk': + return R.assetsImagesExtApk; + break; + default: + return R.assetsImagesExtUnknown; + } + } + + @override + Widget build(BuildContext context) { + var fileMsg = FileChat.fromBuffer(msgModel.msgContent); + var type = fileMsg.type; + var size = fileMsg.size; + var name = fileMsg.name; + + var sizeStr = '${(size / 1024).toStringAsFixed(1)}k'; + if (size > 1024 * 1024) { + sizeStr = '${(size / 1024 / 1024).toStringAsFixed(1)}m'; + } + return InkWell( + onTap: msgModel.localFile != null + ? () { + print('打开文件 ${msgModel.localFile}'); + OpenFile.open(msgModel.localFile); + } + : null, + child: Container( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Image.asset(getTypeImage(type), width: 45), + Padding( + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: fixedText(name, fontSize: 13), + constraints: BoxConstraints( + maxWidth: Screen.width - 120 - 122, maxHeight: 50), + ), + Expanded(child: SizedBox()), + fixedText(sizeStr, fontSize: 12, color: Colors.grey) + ], + )), + msgModel.localFile == null + ? Container( + constraints: BoxConstraints( + maxWidth: 40, + ), + child: fixedText('未下载', fontSize: 12, color: Colors.grey)) + : Container() + ], + ), + ), + ); + } +} diff --git a/lib/chat/full_img_view.dart b/lib/chat/full_img_view.dart new file mode 100644 index 0000000..141934d --- /dev/null +++ b/lib/chat/full_img_view.dart @@ -0,0 +1,168 @@ +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:chat/chat/download_item.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:flutter/material.dart'; +import 'package:image_gallery_saver/image_gallery_saver.dart'; +import 'package:oktoast/oktoast.dart'; + +import '../r.dart'; + +class PhotoPage extends StatefulWidget { + final MsgModel msg; + PhotoPage({this.msg}); + @override + _PhotoPageState createState() => _PhotoPageState(); +} + +class _PhotoPageState extends State + with SingleTickerProviderStateMixin { + AnimationController _controller; + Animation _animation; + Offset _offset = Offset.zero; + double _scale = 1.0; + Offset _normalizedOffset; + double _previousScale; + double _kMinFlingVelocity = 600.0; + + ImageProvider provider; + + @override + void initState() { + super.initState(); + + getImgData(); + _controller = AnimationController(vsync: this); + _controller.addListener(() { + setState(() { + _offset = _animation.value; + }); + }); + } + + getImgData() { + if (widget.msg.localFile != null) { + var fileData = File(widget.msg.localFile).readAsBytesSync(); + provider = MemoryImage(fileData); + } else { + provider = MemoryImage(Uint8List.fromList(widget.msg.msgContent)); + } + } + + @override + void dispose() { + _controller.stop(); + _controller.dispose(); + + super.dispose(); + } + + Offset _clampOffset(Offset offset) { + final Size size = context.size; + // widget的屏幕宽度 + final Offset minOffset = Offset(size.width, size.height) * (1.0 - _scale); + // 限制他的最小尺寸 + return Offset( + offset.dx.clamp(minOffset.dx, 0.0), offset.dy.clamp(minOffset.dy, 0.0)); + } + + void _handleOnScaleStart(ScaleStartDetails details) { + setState(() { + _previousScale = _scale; + _normalizedOffset = (details.focalPoint - _offset) / _scale; + // 计算图片放大后的位置 + _controller.stop(); + }); + } + + void _handleOnScaleUpdate(ScaleUpdateDetails details) { + setState(() { + _scale = (_previousScale * details.scale).clamp(1.0, 3.0); + // 限制放大倍数 1~3倍 + _offset = _clampOffset(details.focalPoint - _normalizedOffset * _scale); + // 更新当前位置 + }); + } + + void _handleOnScaleEnd(ScaleEndDetails details) { + final double magnitude = details.velocity.pixelsPerSecond.distance; + if (magnitude < _kMinFlingVelocity) return; + final Offset direction = details.velocity.pixelsPerSecond / magnitude; + // 计算当前的方向 + final double distance = (Offset.zero & context.size).shortestSide; + // 计算放大倍速,并相应的放大宽和高,比如原来是600*480的图片,放大后倍数为1.25倍时,宽和高是同时变化的 + _animation = _controller.drive(Tween( + begin: _offset, end: _clampOffset(_offset + direction * distance))); + _controller + ..value = 0.0 + ..fling(velocity: magnitude / 1000.0); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + Navigator.pop(context); + }, + onScaleStart: _handleOnScaleStart, + onScaleUpdate: _handleOnScaleUpdate, + onScaleEnd: _handleOnScaleEnd, + child: Material( + child: DownloadItem( + msg: widget.msg, + isAutoDown: false, + onComplete: () { + getImgData(); + setState(() {}); + }, + child: Transform( + transform: Matrix4.identity() + ..translate(_offset.dx, _offset.dy) + ..scale(_scale), + child: Stack( + children: [ + Image( + fit: BoxFit.fitWidth, + image: provider ?? AssetImage(R.assetsImagesIcAlbum), + ), + + Positioned( + right: 10, + bottom: 10, + child: InkWell( + onTap: saveToGallery, + child: Container( + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.grey.withAlpha(150), + borderRadius: BorderRadius.circular(8)), + child: Icon(Icons.save_alt, color: Colors.white70), + ))) + ], + )), + )), + ); + } + + saveToGallery() async { + if (widget.msg.localFile != null) { + var data= File(widget.msg.localFile).readAsBytesSync(); + ImageGallerySaver.saveImage(data).then((res) { + print(res); + if (res != null) { + showToast(I18n.of(context).successfully_saved); + } + }); + } else { + ImageGallerySaver.saveImage(Uint8List.fromList(widget.msg.msgContent)) + .then((res) { + print(res); + if (res != null) { + showToast(I18n.of(context).successfully_saved); + } + }); + } + } +} diff --git a/lib/chat/gift_msg_item.dart b/lib/chat/gift_msg_item.dart new file mode 100644 index 0000000..c6de421 --- /dev/null +++ b/lib/chat/gift_msg_item.dart @@ -0,0 +1,44 @@ +import 'package:chat/generated/i18n.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; + +class GiftMsgItem extends StatelessWidget { + final bool isMe; + final List msgContent; + GiftMsgItem(this.msgContent, this.isMe); + @override + Widget build(BuildContext context) { + GiftChat giftChat = GiftChat.fromBuffer(msgContent); + + var str = ''; + if (isMe) { + str = I18n.of(context) + .send_gift1 + .replaceFirst('/s1', giftChat.giftAmount.toString()); + } else { + str = I18n.of(context) + .receive_gift1 + .replaceFirst('/s1', giftChat.giftAmount.toString()); + } + + var imgPath = 'assets/images/gift_${giftChat.giftId}.png'; + + return Container( + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + constraints: BoxConstraints(maxWidth: Screen.width - 120), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + fixedText(str, fontSize: 14, color: Colors.white), + SizedBox(width: 10), + Image.asset(imgPath, height: 25, width: 25, fit: BoxFit.contain), + ], + ), + decoration: BoxDecoration( + color: Color(0xFFF92222).withAlpha(60), + border: Border.all(color: Color(0xFFB9CBD7), width: 0.6), + borderRadius: BorderRadius.all(Radius.circular(7.5))), + ); + } +} diff --git a/lib/chat/gift_page.dart b/lib/chat/gift_page.dart new file mode 100644 index 0000000..2c9b0ed --- /dev/null +++ b/lib/chat/gift_page.dart @@ -0,0 +1,46 @@ +import 'dart:math'; + +import 'package:chat/chat/gift_widget.dart'; +import 'package:chat/models/gift_item_model.dart'; +import 'package:chat/models/gift_select_provider.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class GiftPage extends StatelessWidget { + final List giftList; + final int pageIndex; + + GiftPage(this.giftList, this.pageIndex); + + @override + Widget build(BuildContext context) { + int length = giftList.length - pageIndex * 8; + length = min(length, 8); + + int curSelectIndex = + Provider.of(context).curSelectIndex; + + print('page $pageIndex curSelectIndex $curSelectIndex'); + return Container( + width: Screen.width, + height: 150, + child: Wrap( + direction: Axis.horizontal, + runSpacing: 5, + spacing: 10, + children: List.generate(length, (int i) { + int index = pageIndex * 8 + i; + return GestureDetector( + child: GiftItem( + itemModel: giftList[index], + isSelected: index == curSelectIndex), + onTap: () { + if (index != curSelectIndex) { + Provider.of(context) + .changeSelectIndex(index); + } + }); + }))); + } +} diff --git a/lib/chat/gift_select_widget.dart b/lib/chat/gift_select_widget.dart new file mode 100644 index 0000000..be4be8d --- /dev/null +++ b/lib/chat/gift_select_widget.dart @@ -0,0 +1,277 @@ +import 'package:chat/chat/gift_page.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/data/gift_data_mgr.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/gift_item_model.dart'; +import 'package:chat/models/gift_select_provider.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/proto/chat.pb.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/ChargeMoney.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/anim_effect_overlay.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; + +class GiftSelectWidget extends StatefulWidget { + final int friendId; + final Function sendMsg; + GiftSelectWidget(this.friendId, this.sendMsg); + @override + _GiftSelectWidgetState createState() => _GiftSelectWidgetState(); +} + +class _GiftSelectWidgetState extends State { + //打赏礼物信息 + List giftList; +//礼物数量 + int curGiftValue = 1; + + @override + void initState() { + super.initState(); + getGiftList(); + } + + getGiftList() async { + giftList = await GiftMgr().getGiftList(); + if (mounted) { + setState(() {}); + } + } + + _sendGift(BuildContext context) async { + int curSelectIndex = + Provider.of(context).curSelectIndex; + var curGift = giftList[curSelectIndex]; + + int price = curGift.price; + int giftId = curGift.id; + int total = curGiftValue * price; + if (total > Provider.of(context).money) { + showToast(I18n.of(context).not_enough); + return; + } + + int buyCount = 0; + if (curGiftValue > curGift.amount) { + buyCount = curGiftValue - curGift.amount; + } + Map data = { + "userId": UserData().basicInfo.userId, + "rUserId": widget.friendId, + "id": giftId, + "price": price, + "amount": curGiftValue, + "totalPrice": total, + "payNum": buyCount + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('reward/gift', data: data); + if (res == null) { + return; + } + Map resData = res.data; + + //showToast(resData['msg']); + + if (resData['code'] == 0) { + //赠送成功 + print('赠送金额:${resData['data']}'); + if (curGift.amount >= curGiftValue) { + curGift.amount -= curGiftValue; + } + + int receiveAmount = resData['data']; + + Provider.of(context, listen: false).subMoney(total); + AnimEffect.showEffect(context, giftId); + AnimEffect.showDashangEffect(context, true, curGiftValue, curGift.name); + + var msgContetnt = GiftChat.create(); + msgContetnt.giftAmount = curGiftValue; + msgContetnt.suId = UserData().basicInfo.userId; + msgContetnt.tuId = widget.friendId; + + msgContetnt.giftId = giftId; + msgContetnt.giftName = curGift.name; + msgContetnt.money = receiveAmount; + + var msg = MsgHandler.createSendMsg( + ChatType.GiftChatType, msgContetnt.writeToBuffer(), + friendId: widget.friendId, channelType: ChatChannelType.Session); + + widget.sendMsg(msg); + + setState(() {}); + } else { + print(resData['msg']); + } + } + + @override + Widget build(BuildContext context) { + return Container( + height: 320, + width: Screen.width, + decoration: BoxDecoration( + color: Colors.white, + ), + child: giftList == null + ? Center(child: Text(I18n.of(context).no_gift)) + : Column( + children: [ + Container( + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 20), + child: Row( + children: [ + Text(I18n.of(context).sent_gift, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Constants.BlackTextColor)), + Expanded( + child: SizedBox(), + ), + Image.asset( + R.assetsImagesCoin, + scale: 2, + ), + SizedBox( + width: 5, + ), + fixedText( + I18n.of(context) + .available_balance + .replaceFirst('/s1', ''), + color: Constants.GreyTextColor), + Consumer( + builder: + (context, MoneyChangeProvider counter, child) => + fixedText(counter.money.toString(), + color: Color(0xFFDB305D)), + ), + fixedText(I18n.of(context).mask_coin, + color: Color(0xFFDB305D)), + ], + ), + ), + Container( + alignment: Alignment.topCenter, + padding: EdgeInsets.all(10), + height: 150, + child: GiftPage(giftList, 0), + ), + Expanded(child: SizedBox()), + Padding( + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20), + child: Row( + children: [ + Expanded( + child: SizedBox( + height: 36, + child: RaisedButton( + padding: EdgeInsets.symmetric(horizontal: 5), + child: Text( + I18n.of(context).recharge, + textScaleFactor: 1.0, + maxLines: 1, + style: TextStyle( + fontSize: 16, fontWeight: FontWeight.bold), + ), + elevation: 2.0, + color: Colors.orangeAccent, + textColor: Colors.white, + onPressed: () { + ChargeMoney.showChargeSheet(context, () {}); + }, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.all(Radius.circular(20)), + ), + ), + )), + SizedBox(width: 20), + Expanded( + flex: 2, + child: Container( + height: 36, + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + blurRadius: 2.0, + color: Colors.white24) + ], + borderRadius: + BorderRadius.all(Radius.circular(20)), + border: Border.all(color: Colors.red)), + child: Row( + children: [ + Expanded( + child: DropdownButton( + isExpanded: true, + underline: Container(), + value: curGiftValue, + style: TextStyle(fontSize: 16), + iconEnabledColor: Colors.redAccent, + onChanged: (newValue) { + setState(() { + curGiftValue = newValue; + }); + }, + items: [1, 6, 8, 66] + .map((v) => + DropdownMenuItem( + value: v, + child: Container( + padding: EdgeInsets.only( + left: 20), + child: fixedText( + v.toString(), + color: v == + curGiftValue + ? Colors.redAccent + : Colors.black)))) + .toList(), + )), + Expanded( + child: InkWell( + child: Container( + decoration: BoxDecoration( + color: Color(0xFFFD6E8F), + borderRadius: BorderRadius.only( + topRight: Radius.circular(20), + bottomRight: Radius.circular(20)), + ), + height: 36, + alignment: Alignment.center, + child: Text( + I18n.of(context).give, + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.bold), + ), + ), + onTap: () { + _sendGift(context); + }, + )) + ], + ))) + ], + ), + ) + ], + )); + } +} diff --git a/lib/chat/gift_widget.dart b/lib/chat/gift_widget.dart new file mode 100644 index 0000000..ab9253c --- /dev/null +++ b/lib/chat/gift_widget.dart @@ -0,0 +1,88 @@ +import 'dart:math'; + +import 'package:chat/data/constants.dart'; +import 'package:chat/models/gift_item_model.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; + +class GiftItem extends StatelessWidget { + final GiftItemModel itemModel; + final isSelected; + + GiftItem({this.isSelected = false, this.itemModel}); + @override + Widget build(BuildContext context) { + var imgPath = 'assets/images/gift_${itemModel.id}.png'; + if (isSelected) { + imgPath = 'assets/images/gift_anim_${itemModel.id}.gif'; + } + + var curAmount = '0'; + if (itemModel.amount >= 100) { + curAmount = '99+'; + } else { + curAmount = itemModel.amount.toString(); + } + return ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Container( + width: 85, + height: 110, + decoration: BoxDecoration( + color: Colors.transparent, + border: Border.all( + color: isSelected ? Colors.orangeAccent : Colors.grey[200], + width: 1), + borderRadius: BorderRadius.circular(10), + ), + child: Stack( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + SizedBox(height: 10), + Image.asset(imgPath, + fit: BoxFit.contain, width: 75, height: 40), + Text( + itemModel.name, + textScaleFactor: 1.0, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 10), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + R.assetsImagesCoin, + scale: 5, + ), + SizedBox(width: 3), + fixedText(itemModel.price.toString(), + color: Constants.GreyTextColor), + ], + ), + SizedBox(height: 5) + ], + ), + Positioned( + left: -30, + top: 30, + child: Container( + height: 25, + width: 80, + transform: Matrix4.rotationZ(-pi / 4), + color: Color(0xFFFD6E8F), + ), + ), + Container( + width: 25, + height: 25, + alignment: Alignment.center, + child: fixedText(curAmount, + fontSize: 12, color: Colors.white)), + ], + ))); + } +} diff --git a/lib/chat/group_chat_item.dart b/lib/chat/group_chat_item.dart new file mode 100644 index 0000000..5240342 --- /dev/null +++ b/lib/chat/group_chat_item.dart @@ -0,0 +1,1322 @@ +import 'dart:convert'; +import 'dart:math'; +import 'dart:typed_data'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/chat/download_item.dart'; +import 'package:chat/chat/file_msg_item.dart'; +import 'package:chat/chat/msg_state_widge.dart'; +import 'package:chat/chat/place_item.dart'; +import 'package:chat/chat/redbag_widget.dart'; +import 'package:chat/chat/upload_item.dart'; +import 'package:chat/chat/video_view.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/utils/wpop/w_popup_menu.dart'; +import 'package:flutter/services.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/invite_detail_page.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/models/keyboard_provider.dart'; +import 'package:chat/proto/chat.pbenum.dart'; +import 'package:chat/proto/chat.pbserver.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/date_utils.dart'; +import 'package:chat/utils/group_member_model.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sound_util.dart'; +import 'package:chat/utils/upload_util.dart'; +import 'package:chat/utils/video_anim.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:chat/utils/HttpUtil.dart'; + +import '../r.dart'; +import 'full_img_view.dart'; +import 'upload_item.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/models/voucher_change.dart'; + +const double ChatRadius = 7.5; +const Color SendMsgBg = Color(0xFFD4F0FF); +const Color SendMsgText = Colors.black; +const double TextHeight = 1.2; + +const double PaddingLeft = 9.5; + +const Color ReciveBorderColor = Color(0xFFDCDCDC); + +const double FontSize = 15; + +class GroupChatPageItem extends StatefulWidget { + final MsgModel msg; + + final int lastMsgTime; + final GroupMemberModel memberModel; + final Function hideKeyboard; + const GroupChatPageItem( + {Key key, + this.msg, + this.lastMsgTime, + this.hideKeyboard, + this.memberModel}) + : assert(msg != null), + super(key: key); + + @override + _GroupChatPageItemState createState() => _GroupChatPageItemState(); +} + +class _GroupChatPageItemState extends State + with SingleTickerProviderStateMixin { + int curTextType = 0; //文字、译文切换索引 + List textList = []; + + String curSoundUrl; + + CancelToken _cancelToken = CancelToken(); + + bool isLongPressed = false; + + @override + void initState() { + super.initState(); + + if (widget.msg.from == UserData().basicInfo.userId && + widget.msg.state == MsgState.None) { + print('重新发送消息'); + MsgHandler.sendChatMsg(widget.msg); + } + + textList = widget.msg.getTransTextList(); + + MessageMgr().on('Update Translate Message', updateTranslateMsg); + MessageMgr().on('Cancel Request', _deleteItem); + } + + @override + void dispose() { + MessageMgr().off('Cancel Request', _deleteItem); + MessageMgr().off('Update Translate Message', updateTranslateMsg); + super.dispose(); + } + + _deleteItem(msg) { + if (msg == widget.msg) { + print(widget.msg.state); + if (widget.msg.state == MsgState.Uploading) { + print('取消上传'); + UploadUtil().cancelRequests(_cancelToken); + } + } + } + + updateTextList() { + textList.clear(); + curTextType = 0; + textList = widget.msg.getTransTextList(); + } + + updateTranslateMsg(msg) { + if (msg.time == widget.msg.time) { + if (mounted) { + updateTextList(); + if (!mounted) { + return; + } + setState(() { + print('更新翻译文字'); + }); + } + } + } + + getTodayTime(msgDate) { + String showTimeStr; + + var sendTime = widget.msg.time; + var today = DateTime.now(); + //今天 + if (msgDate.year == today.year && + msgDate.month == today.month && + msgDate.day == today.day) { + showTimeStr = + DateUtils().getFormartData(timeSamp: sendTime, format: 'HH:mm'); + } else { + showTimeStr = DateUtils() + .getFormartData(timeSamp: sendTime, format: 'yyyy/MM/dd HH:mm'); + } + + return showTimeStr; + } + + String getMsgTime() { + String showTimeStr; + + var sendTime = widget.msg.time; + + var msgDate = DateTime.fromMillisecondsSinceEpoch(sendTime); + if (widget.lastMsgTime == null) { + showTimeStr = getTodayTime(msgDate); + } else { + if (sendTime - widget.lastMsgTime > 3 * 60 * 1000) { + showTimeStr = getTodayTime(msgDate); + } + } + + return showTimeStr; + } + + @override + Widget build(BuildContext context) { + var showTime = getMsgTime(); + + return Container( + width: Screen.width, + margin: const EdgeInsets.symmetric(vertical: 10.0), + child: Column( + children: [ + showTime == null + ? SizedBox() + : Container( + decoration: BoxDecoration( + color: Color(0xFF2C2F36).withOpacity(0.25), + borderRadius: BorderRadius.all(Radius.circular(9.5))), + padding: + EdgeInsets.only(left: 7, right: 7, top: 3, bottom: 2), + child: Text(showTime, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 10.0, color: Colors.white)), + ), + SizedBox(height: 10), + _msgWidget() + ], + ), + ); + } + + _msgWidget() { + if (widget.msg.from == 0) { + return _serverNotifyMsg(); + } else { + if (widget.msg.from == UserData().basicInfo.userId) { + return _getSentMessageLayout(context); + } else { + return _getReceivedMessageLayout(context); + } + } + } + + _serverNotifyMsg() { + var type = widget.msg.msgType; + + if (type == ChatType.GroupChatNoticeType.value) { + var res = GroupChatNotice.fromBuffer(widget.msg.msgContent); + + var groupInfoModel = Provider.of(context); + var optId = res.operatuId; + var showStr = MsgHandler.getGroupNoticeMsg(res, groupInfoModel); + + return Container( + alignment: Alignment.center, + constraints: BoxConstraints(maxWidth: Screen.width - 120), + child: extendedText(showStr, + color: Constants.GreyTextColor, + fontSize: 12, onSpecialTextTap: (dynamic parameter) { +// print('点击事件 $parameter'); + if (parameter.startsWith("\$")) { +// showToast('点击: ${res.operateduId[0]}'); + + List list = []; + + for (int k = 0; k < res.operateduId.length; k++) { + list.add(GroupMemberModel.fromBaseInfo(res.operateduId[k])); + } + + AppNavigator.push( + context, + InviteDetailPage( + originalList: list, + opt: GroupMemberModel.fromBaseInfo(optId), + groupId: groupInfoModel.sessionId, + )); + } + }), + ); + } + + return Container(); + } + + _textGif(List msgContent) { + var msg = utf8.decode(msgContent); + return Container( + constraints: BoxConstraints(maxWidth: Screen.width - 120), + child: extendedText( + msg, + selectionEnabled: false, + hideKeyboard: widget.hideKeyboard, + fontSize: FontSize, + color: Colors.black, + ), + ); + } + + _textMsg(MsgModel msgModel) { + var msg = utf8.decode(msgModel.msgContent); + if (msg.contains('[ ')) { + msg = msg.replaceAll('[ ', '['); + } + if (msg.contains(' ]')) { + msg = msg.replaceAll(' ]', ']'); + } + Widget text = Container( + constraints: BoxConstraints(maxWidth: Screen.width - 120), + child: extendedText( + msg, + hideKeyboard: widget.hideKeyboard, + fontSize: FontSize, + color: SendMsgText, + ), + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + decoration: BoxDecoration( + color: isLongPressed ? Colors.grey[300] : SendMsgBg, + border: Border.all(color: Color(0xFFB9CBD7), width: 0.6), + borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), + ); + + if (msgModel.refMsgContent != null && msgModel.refMsgContent.length > 0) { + QuoteMsg quoteMsg = QuoteMsg.fromBuffer(msgModel.refMsgContent); + + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + text, + SizedBox(height: 2), + Container( + constraints: BoxConstraints(maxWidth: Screen.width - 120), + padding: EdgeInsets.symmetric(vertical: 1, horizontal: 3), + child: Text( + quoteMsg.content, + maxLines: 1, + textScaleFactor: 1.0, + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 12), + ), + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(5)), + ) + ], + ); + } else { + return text; + } + } + + _soundMsg() { + double time = widget.msg.extraInfo / 1000; + if (time > 60) { + time = 60.0; + } + bool isPlaying = false; + + var soundPath = widget.msg.localFile; + + isPlaying = SoundUtils().isPlaying(soundPath); + + var soundWidget = GestureDetector( + child: Container( + width: 120, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + alignment: Alignment.center, + padding: EdgeInsets.only(bottom: 2), + margin: EdgeInsets.only(right: 10), + width: 25.5, + height: 25.5, + decoration: BoxDecoration( + border: + Border.all(color: const Color(0xFF1B92C7), width: 0.5), + color: const Color(0xFF04A4FE), + shape: BoxShape.circle), + child: Icon( + IconData(isPlaying ? 0xe652 : 0xe653, + fontFamily: Constants.IconFontFamily), + size: isPlaying ? 15 : 18, + color: Colors.white, + ), + ), + isPlaying + ? Stack( + children: [ + Container( + height: 18, + width: 19, + ), + Positioned( + bottom: 0, + child: VideoAnim( + begin: 18, + start: 0.444, + end: 4.5, + )), + Positioned( + left: 7, + bottom: 0, + child: VideoAnim( + begin: 4.5, + end: 18, + )), + Positioned( + left: 14, + bottom: 0, + child: VideoAnim( + begin: 18, + end: 4.5, + )) + ], + ) + : Stack( + children: [ + Container( + height: 18, + width: 19, + ), + Positioned( + bottom: 0, child: CustomUI.buildAudioContaniner(12)), + Positioned( + left: 7, + bottom: 0, + child: CustomUI.buildAudioContaniner(4.5)), + Positioned( + left: 14, + bottom: 0, + child: CustomUI.buildAudioContaniner(18)) + ], + ), + Expanded(child: SizedBox()), + fixedText(time.toStringAsFixed(0), color: SendMsgText, fontSize: 16) + ], + ), + padding: EdgeInsets.symmetric(horizontal: 15, vertical: 12), + decoration: BoxDecoration( + color: SendMsgBg, + border: Border.all(color: Color(0xFFB9CBD7), width: 0.6), + borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), + ), + onTap: () async { + print('播放状态 : $isPlaying'); + print('当前文件$soundPath '); + if (isPlaying) { + SoundUtils().pause(); + } else { + SoundUtils().play(soundPath, onPlayed: () { + if (mounted) { + setState(() {}); + } + }, complete: () { + if (mounted) { + setState(() {}); + } + }); + } + }, + ); + + return UploadImgItem( + msg: widget.msg, + child: soundWidget, + isShowProgress: false, + ); + } + + Size _getImgSize() { + double aspectRatio = widget.msg.extraInfo / 100; + + var maxWidth = Screen.width * 0.65; + var maxHeight = Screen.height / 4; + + var width, height; + if (maxWidth / maxHeight > aspectRatio) { + height = maxHeight; + width = maxHeight * aspectRatio; + } else { + width = maxWidth; + height = maxWidth / aspectRatio; + } + + return Size(width, height); + } + + _imgMsg(List imgData) { + var imgSize = _getImgSize(); + + return GestureDetector( + child: ClipRRect( + child: UploadImgItem( + msg: widget.msg, + cancelToken: _cancelToken, + child: Container( + height: imgSize.height, + width: imgSize.width, + child: Image( + fit: BoxFit.contain, + image: MemoryImage(Uint8List.fromList(imgData)), + ), + )), + borderRadius: BorderRadius.circular(5), + ), + onTap: () async { + showFullImg(context, widget.msg); + }); + } + + _videoMsg(BuildContext context, List thumbnail) { + var imgSize = _getImgSize(); + return InkWell( + child: ClipRRect( + child: Stack( + alignment: Alignment.center, + children: [ + UploadImgItem( + msg: widget.msg, + cancelToken: _cancelToken, + child: Container( + width: imgSize.width, + height: imgSize.height, + child: Image( + fit: BoxFit.contain, + image: MemoryImage(Uint8List.fromList(thumbnail)), + ), + )) + ], + ), + borderRadius: BorderRadius.circular(5), + ), + onTap: () { + showVideoPage(context, widget.msg.localFile); + }, + ); + } + + _msgLayout(BuildContext context, MsgModel msg) { + Widget item; + switch (ChatType.valueOf(msg.msgType)) { + case ChatType.TextChatType: + item = _textMsg(msg); + break; + + case ChatType.EmoticonType: + item = _textGif(msg.msgContent); + break; + case ChatType.ImageChatType: + item = _imgMsg(msg.msgContent); + break; + case ChatType.ShortVideoChatType: + item = _videoMsg(context, msg.msgContent); + break; + case ChatType.ShortVoiceChatType: + item = _soundMsg(); + break; + case ChatType.RedWalletChatType: + item = RedBagItem( + Key(msg.time.toString()), UserData().basicInfo.userId, msg); + break; + case ChatType.PlaceChatType: + item = PlaceItem(isMe: true, placeContent: msg.msgContent); + break; + case ChatType.FileChatType: + item = _fileMsgItem(); + break; + default: + } + + return wrapItemWithMenu(item); + } + + Widget _fileMsgItem() { + return UploadImgItem( + msg: widget.msg, + cancelToken: _cancelToken, + child: Container( + height: 100, + constraints: BoxConstraints(maxWidth: Screen.width - 120), + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + decoration: BoxDecoration( + color: isLongPressed ? Colors.grey[300] : SendMsgBg, + borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), + child: FileMsgItem(widget.msg))); + } + + Widget wrapItemWithMenu(item) { + List actionsFunc = []; + List actions = [I18n.of(context).delete, I18n.of(context).reply]; + + actionsFunc.add(() { + MessageMgr().emit('Delete Select Message', widget.msg); + }); + actionsFunc.add(() { + print('发送引用的消息'); + MessageMgr().emit('Reply Select Message', widget.msg); + }); + + if (widget.msg.msgType == ChatType.TextChatType.value) { + actions.insert(0, I18n.of(context).copy); + actionsFunc.insert(0, () { + //复制当前的文字 + print('复制文字 ${textList[curTextType]}'); + ClipboardData clipboardData = + ClipboardData(text: textList[curTextType]); + Clipboard.setData(clipboardData); + }); + } + if (widget.msg.msgType == ChatType.ShortVoiceChatType.value) { + var soundPlayMode = + Provider.of(context).soundPlayMode; + + actions.add(soundPlayMode + ? I18n.of(context).handset_playback + : I18n.of(context).speaker_play); + actionsFunc.add(() { + Provider.of(context) + .changeSoundPlayMode(!soundPlayMode); + SoundUtils.instance.savePlayModeConfig(soundPlayMode); + }); + } + + return WPopupMenu( + child: item, + actions: actions, + onLongPressStart: () { + isLongPressed = true; + setState(() {}); + }, + onLongPressEnd: () { + isLongPressed = false; + setState(() {}); + }, + onValueChanged: (int value) { + print('选择的是$value个菜单'); + if (value >= 0 && value < actionsFunc.length) { + actionsFunc[value](); + } + }, + ); + } + + Widget _getSentMessageLayout(BuildContext context) { + bool hasHeadImg = true; + if (UserData().basicInfo.headimgurl == null || + UserData().basicInfo.headimgurl.length == 0) { + hasHeadImg = false; + } + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + MsgStateWidget(widget.msg), + SizedBox(width: 3), + _msgLayout(context, widget.msg), + SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: hasHeadImg + ? CachedNetworkImage( + imageUrl: UserData().basicInfo.headimgurl, + width: 40, + height: 40, + ) + : SizedBox( + width: 40, + height: 40, + child: Image.asset(R.assetsImagesDefaultNorAvatar))), + ], + ) + ]); + } + + _receiveJIF(MsgModel msg) { + var text = utf8.decode(msg.msgContent); + + return Container( + constraints: BoxConstraints(maxWidth: Screen.width - 120), + child: extendedText(text, + selectionEnabled: false, hideKeyboard: widget.hideKeyboard)); + } + + double _getTextWidth(String text) { + var tp = TextPainter( + text: TextSpan( + style: TextStyle(fontSize: FontSize), text: textList[curTextType]), + textAlign: TextAlign.left, + textDirection: TextDirection.ltr, + textScaleFactor: 1, + ); + + tp.layout(maxWidth: Screen.width - 140); + if (text.contains('[')) { + if (text.length < 5 && text.startsWith('[') && text.endsWith(']')) { + ///单表情 + return 25; + } + + int length = text.split('[').length; + if (length > 1) { + ///包含表情 + int scale = 6; + + if (length > 6) scale = 7; + + double width = tp.width + length * scale; + return width > (Screen.width - 140) ? Screen.width - 140 : width; + } + } + return tp.width; + + ///单文字 + } + + _receiveText(MsgModel msg) { + List showMsg = []; + if (textList.length > 0) { + showMsg.add(Container( + constraints: + BoxConstraints(maxWidth: Screen.width - 140, minHeight: 22), + alignment: Alignment.centerLeft, + child: extendedText( + textList[curTextType], + color: Constants.BlackTextColor, + hideKeyboard: widget.hideKeyboard, + fontSize: FontSize, + ))); + } + + var width = _getTextWidth(textList[curTextType]); + + var minWidth = width + 20; + if (msg.transTag != 0) { + minWidth = 200; + showMsg.add(Padding( + padding: EdgeInsets.symmetric(vertical: 5), + child: Divider(color: Color(0xFFECECEC), height: 1))); + Widget tranWidget = _transProcessWidget(msg.transTag); + showMsg.add(tranWidget); + } + + Widget text = Container( + width: width + 20, + constraints: + BoxConstraints(maxWidth: Screen.width - 120, minWidth: minWidth), + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: showMsg), + decoration: BoxDecoration( + border: Border.all(color: ReciveBorderColor, width: 0.5), + color: isLongPressed ? Colors.grey[300] : Colors.white, + borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), + ); + + if (msg.refMsgContent != null && msg.refMsgContent.length > 0) { + QuoteMsg quoteMsg = QuoteMsg.fromBuffer(msg.refMsgContent); + + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + text, + SizedBox(height: 2), + Container( + constraints: BoxConstraints(maxWidth: Screen.width - 120), + padding: EdgeInsets.symmetric(vertical: 1, horizontal: 3), + child: Text( + quoteMsg.content, + maxLines: 1, + textScaleFactor: 1.0, + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 12), + ), + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(5)), + ) + ], + ); + } else { + return text; + } + } + + //用户评价人工翻译,差评 + rateTranslateResult() async { + return await HttpUtil().rateTranslateResult(widget.msg, () { + if (mounted) { + setState(() {}); + } + }); + } + + _translateItemWidget(int code, String title, Function onTap) { + Color color = onTap == null ? Constants.GreyTextColor : Color(0xFF087FF3); + return InkWell( + onTap: onTap, + splashColor: Colors.red, + child: Container( + width: 80, + child: Row( + children: [ + Icon( + IconData(code, fontFamily: Constants.IconFontFamily), + color: color, + size: 20, + ), + SizedBox(width: 5), + Expanded( + child: SizedBox( + child: Text( + title, + style: TextStyle(color: color, fontSize: 10), + textScaleFactor: 1.0, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + )) + ], + ))); + } + + bool isTranslating = false; + + _transProcessWidget(int transTag) { + double width = 160; + + Widget userTranslateWidget; + Widget machineTranslateWidget; + + if (transTag == 1) { + //机器翻译中 + userTranslateWidget = _translateItemWidget(0xe670, '人工重译', null); + + machineTranslateWidget = + _translateItemWidget(0xe671, I18n.of(context).robotTranslate, null); + } else if (transTag == 2) { + //人工翻译中 + userTranslateWidget = _translateItemWidget(0xe670, '人工翻译中', null); + machineTranslateWidget = _translateItemWidget( + 0xe671, + '机器重译', + textList.length <= 1 + ? null + : () { + setState(() { + curTextType += 1; + curTextType %= textList.length; + }); + }); + } else if (transTag == 3) { + //机器翻译完成 + userTranslateWidget = _translateItemWidget( + 0xe670, + '人工重译', + isTranslating + ? null + : () async { + isTranslating = true; + + int money = + Provider.of(context, listen: false) + .money; + + int voucher = + Provider.of(context, listen: false) + .voucher; + + int needMoney = widget.msg.getNeedMoney(); + + if (needMoney > voucher + money) { + showToast('翻译券和H币不足'); + return; + } + var res = await HttpUtil().getPersonalTranslate(widget.msg); + if (res) { + print('请求人工翻译成功,进行扣费'); + setState(() { + widget.msg.transTag = 2; + + //优先扣券 + if (voucher > 0) { + int costQuan = min(voucher, needMoney); + Provider.of(context, + listen: false) + .subVoucher(costQuan); + } + + //不足的话再扣H币 + if (needMoney > voucher) { + Provider.of(context, listen: false) + .subMoney(needMoney - voucher); + } + }); + } + }); + machineTranslateWidget = _translateItemWidget( + 0xe671, + '机器重译', + textList.length <= 1 + ? null + : () { + setState(() { + curTextType += 1; + curTextType %= textList.length; + }); + }); + } else if (transTag == 4 || transTag == 10) { + //4人工翻译完成,未评论 10人工翻译完成已评论 + userTranslateWidget = InkWell( + onTap: () { + setState(() { + curTextType = 0; + }); + }, + child: Container( + width: width / 2, + child: Row( + children: [ + InkWell( + child: Icon( + IconData(0xe641, fontFamily: Constants.IconFontFamily), + size: 18, + color: + transTag == 10 ? Colors.grey : Color(0xFF087FF3)), + onTap: transTag == 10 + ? null + : () { + CustomUI.showIosDialog( + context, I18n.of(context).bad_ev, () async { + bool isSuccess = await rateTranslateResult(); + if (isSuccess) { + Navigator.of(context).pop(true); + showToast(I18n.of(context).success); + } else { + showToast(I18n.of(context).fail); + Navigator.of(context).pop(); + } + }, () { + Navigator.of(context).pop(); + }); + }, + ), + SizedBox(width: 5), + Expanded( + child: SizedBox( + child: Text( + I18n.of(context).over, + style: TextStyle(color: Color(0xFF087FF3), fontSize: 10), + textScaleFactor: 1.0, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + )) + ], + ))); + machineTranslateWidget = _translateItemWidget(0xe675, '查看原文', () { + setState(() { + curTextType = textList.length - 1; + }); + }); + } + + return Container( + height: 26, + alignment: Alignment.center, + child: Row( + children: [ + userTranslateWidget, + Expanded( + child: SizedBox(child: VerticalDivider(), height: 20, width: 2)), + machineTranslateWidget + ], + ), + ); + } + + _receiveImg(BuildContext context, List imgData, {String downloadData}) { + ImageProvider provider = MemoryImage(Uint8List.fromList(imgData)); + + var imgSize = _getImgSize(); + return GestureDetector( + child: Container( + alignment: Alignment.centerLeft, + width: imgSize.width, + height: imgSize.height, + child: ClipRRect( + child: Image( + image: provider ?? AssetImage(R.assetsImagesIcAlbum), + ), + borderRadius: BorderRadius.circular(5), + )), + onTap: () async { + widget.hideKeyboard(); + showFullImg(context, widget.msg); + }); + } + + _receiveVideo(BuildContext context, List imgData, + {String downloadData}) { + ImageProvider provider = MemoryImage(Uint8List.fromList(imgData)); + var imgSize = _getImgSize(); + return InkWell( + onTap: () { + if (widget.msg.localFile != null) { + widget.hideKeyboard(); + showVideoPage(context, widget.msg.localFile); + } + }, + child: DownloadItem( + isAutoDown: false, + msg: widget.msg, + child: Container( + width: imgSize.width, + height: imgSize.height, + child: ClipRRect( + child: Image( + image: provider ?? AssetImage(R.assetsImagesIcAlbum), + ), + borderRadius: BorderRadius.circular(5), + ), + ), + )); + } + + showVideoPage(BuildContext context, String filePath) { + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return VideoPage(videoPath: filePath); + })); + } + + _receiveSound(BuildContext context, List soundData) { + print(' build 收到的语音消息'); + + MsgModel msg = widget.msg; + var time = widget.msg.extraInfo / 1000; + if (time > 60) { + time = 60.0; + } + bool isPlaying = false; + + if (curSoundUrl != null) { + isPlaying = SoundUtils().isPlaying(curSoundUrl); + } + + var soundWidget = InkWell( + onTap: () async { + bool isLocal = true; + + if (msg.localFile != null) { + isLocal = true; + curSoundUrl = msg.localFile; + } else { + isLocal = false; + var sessionId = msg.sessionId; + curSoundUrl = UploadUtil() + .getFullUrl(msg.extraFile, sessionId, msg.channelType); + } + + print('当前文件$curSoundUrl 本地?$isLocal'); + if (isPlaying) { + await SoundUtils().pause(); + } else { + print('开始播放'); + if (widget.msg.soundListened == 0) { + widget.msg.updateSoundListened(); + } + await SoundUtils().play(curSoundUrl, isLocal: isLocal, onPlayed: () { + if (mounted) { + this.setState(() {}); + } + }, complete: () { + if (mounted) { + this.setState(() {}); + } + }); + } + }, + child: Container( + width: 130, + child: Row(children: [ + Container( + alignment: Alignment.center, + padding: EdgeInsets.only(bottom: 2), + margin: EdgeInsets.only(right: 10), + width: 25.5, + height: 25.5, + decoration: BoxDecoration( + border: + Border.all(color: const Color(0xFF1B92C7), width: 0.5), + color: const Color(0xFF04A4FE), + shape: BoxShape.circle), + child: Icon( + IconData(isPlaying ? 0xe652 : 0xe653, + fontFamily: Constants.IconFontFamily), + size: isPlaying ? 15 : 18, + color: Colors.white, + ), + ), + isPlaying + ? Stack( + children: [ + Container( + height: 18, + width: 19, + ), + Positioned( + bottom: 0, + child: VideoAnim( + begin: 18, + start: 0.444, + end: 4.5, + )), + Positioned( + left: 7, + bottom: 0, + child: VideoAnim( + begin: 4.5, + end: 18, + )), + Positioned( + left: 14, + bottom: 0, + child: VideoAnim( + begin: 18, + end: 4.5, + )) + ], + ) + : Stack( + children: [ + Container( + height: 18, + width: 19, + ), + Positioned( + bottom: 0, child: CustomUI.buildAudioContaniner(12)), + Positioned( + left: 7, + bottom: 0, + child: CustomUI.buildAudioContaniner(4.5)), + Positioned( + left: 14, + bottom: 0, + child: CustomUI.buildAudioContaniner(18)) + ], + ), + Expanded(child: SizedBox()), + fixedText(time.toStringAsFixed(0), + color: Constants.BlackTextColor, fontSize: 16) + ])), + ); + + List showMsg = []; + + showMsg.add(DownloadItem( + msg: widget.msg, + child: soundWidget, + isShowProgress: false, + )); + + double width = 130; + double minWidth = 0; + if (textList.length > 0) { + width = _getTextWidth(textList[curTextType]) + 20; + width = min(width, Screen.width - 120); + minWidth = max(width, 150); + + showMsg.add(Padding( + padding: EdgeInsets.symmetric(vertical: 5), + child: Divider( + height: 1, + ))); + showMsg.add(Container( + child: extendedText( + textList[curTextType], + color: Constants.BlackTextColor, + hideKeyboard: widget.hideKeyboard, + fontSize: FontSize, + ), + alignment: Alignment.centerLeft, + constraints: + BoxConstraints(maxWidth: Screen.width - 120, minHeight: 22), + )); + } + + if (msg.transTag != 0) { + minWidth = 200; + showMsg.add(Divider(color: Color(0xFFECECEC), height: 3)); + Widget tranWidget = _transProcessWidget(msg.transTag); + showMsg.add(tranWidget); + } + + return Container( + width: width + 20, + constraints: + msg.transTag != 0 ? BoxConstraints(minWidth: minWidth) : null, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: showMsg), + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: ReciveBorderColor, width: 0.5), + borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), + ); + } + + void showFullImg(BuildContext context, MsgModel msg) { + print('显示图片'); + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) { + return PhotoPage(msg: msg); + })); + } + + _reveiveMsg(BuildContext context) { + Widget item; + switch (ChatType.valueOf(widget.msg.msgType)) { + case ChatType.TextChatType: + item = _receiveText(widget.msg); + break; + case ChatType.EmoticonType: + item = _receiveJIF(widget.msg); + break; + + case ChatType.ImageChatType: + if (widget.msg.extraFile != null) { + item = _receiveImg(context, widget.msg.msgContent, + downloadData: widget.msg.extraFile); + } else { + item = _receiveImg(context, widget.msg.msgContent); + } + break; + case ChatType.ShortVideoChatType: + item = _receiveVideo(context, widget.msg.msgContent, + downloadData: widget.msg.extraFile); + break; + case ChatType.ShortVoiceChatType: + item = _receiveSound(context, widget.msg.msgContent); + break; + + case ChatType.PlaceChatType: + item = PlaceItem(isMe: false, placeContent: widget.msg.msgContent); + break; + + case ChatType.FileChatType: + item = _receiveFileMsgItem(); + break; + default: + } + return wrapItemWithMenu(item); + } + + Widget _receiveFileMsgItem() { + return DownloadItem( + isAutoDown: false, + msg: widget.msg, + onComplete: () { + if (mounted) { + setState(() {}); + } + }, + child: Container( + height: 100, + constraints: BoxConstraints(maxWidth: Screen.width - 120), + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: ReciveBorderColor, width: 0.5), + borderRadius: BorderRadius.all(Radius.circular(ChatRadius))), + child: FileMsgItem(widget.msg))); + } + + Widget _getReceivedMessageLayout(BuildContext context) { + bool hasHeadImg = true; + var memberModel = widget.memberModel; + if (memberModel == null) { + return Container(); + } + if (memberModel.avtar == null || memberModel.avtar.length == 0) { + hasHeadImg = false; + } + + GroupInfoModel infoModel = Provider.of(context); + + var refName = Provider.of(context) + .getGroupRefName(infoModel.sessionId, memberModel.memberId); + + bool isShowSoundSate = + widget.msg.msgType == ChatType.ShortVoiceChatType.value && + widget.msg.soundListened == 0; + + return Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Container( + margin: const EdgeInsets.only(right: 8.0), + child: GestureDetector( + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: hasHeadImg + ? CachedNetworkImage( + imageUrl: memberModel.avtar, + width: 40, + height: 40, + ) + : SizedBox( + width: 40, + height: 40, + child: Image.asset(R.assetsImagesDefaultNorAvatar))), + onTap: () { + AppNavigator.pushProfileInfoPage(context, memberModel.memberId, + fromWhere: 2,addMode: 1); + }, + onLongPress: () { + print('long press user'); + MessageMgr().emit('Alter User Message', memberModel); + }, + )), + infoModel.isShowName > 0 + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.only(left: 9), + child: fixedText(refName, fontSize: 12, color: Colors.grey), + ), + SizedBox(height: 2), + _reveiveMsg(context), + ], + ) + : _reveiveMsg(context), + isShowSoundSate + ? Container( + margin: EdgeInsets.only( + left: 8, top: infoModel.isShowName > 0 ? 38 : 20), + child: CircleAvatar( + radius: 3.5, + backgroundColor: Colors.red, + )) + : Container() + ]); + } +} diff --git a/lib/chat/group_chat_view.dart b/lib/chat/group_chat_view.dart new file mode 100644 index 0000000..64856ee --- /dev/null +++ b/lib/chat/group_chat_view.dart @@ -0,0 +1,516 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:chat/chat/group_chat_item.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/group_setting.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/models/keyboard_provider.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/models/voucher_change.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/analyze_utils.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/net_state_widget.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sound_util.dart'; +import 'package:chat/utils/sp_utils.dart'; +import 'package:chat/utils/sql_util.dart'; +import 'package:extended_text/extended_text.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; +import '../r.dart'; +import 'input_bar.dart'; +import 'package:chat/models/ref_name_provider.dart'; + + +class GroupChatPage extends StatefulWidget { + final GroupInfoModel groupInfoModel; + final int enterType; // 0默认 1图片 + final dynamic enterContent; + GroupChatPage( + {Key key, this.groupInfoModel, this.enterType = 0, this.enterContent}) + : super(key: key); + + _GroupChatPageState createState() => _GroupChatPageState(); +} + +class _GroupChatPageState extends State { + ScrollController _scrollCtrl = ScrollController(); + + MessageMgr msgMgr = MessageMgr(); + + List msgList; + + KeyboardIndexProvider _keyboardIndexProvider = KeyboardIndexProvider(); + + TextEditingController nickNameController = new TextEditingController(); + + //统计聊天时长 + int startTime; + + //子元素的对应偏移量 + Map itemOffsetMap = {}; + + @override + void dispose() { + var endTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; + AnalyzeUtils.commitChatDuration(startTime, endTime); + + msgMgr.off('New Chat Message', receiveMsg); + msgMgr.off('Keyboard Hide', dealWithKeyboardHide); + msgMgr.off('Update Group Info', updateGroupInfo); + msgMgr.off('Delete Select Message', _deleteItem); + MsgHandler.curActiveSession = 0; + SoundUtils().stop(); + _scrollCtrl.dispose(); + + super.dispose(); + } + + @override + void initState() { + super.initState(); + print('init group chat page ${widget.groupInfoModel.sessionId}'); + + getDefaultSetting(); + + startTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; + MsgHandler.updateActiveSesstion(widget.groupInfoModel.sessionId, + isGroup: true); + + msgList = ChatDataMgr().getGroupRecord(); + + + for(int k=0;k 33 * 1024 * 1024) { + showToast('文件大于33M'); + return; + } + + + var fileName = file.path.split('/').last; + print('fileName $fileName'); + + var ext = ''; + var extList = fileName.split('.'); + if (extList.length > 1) { + ext = extList.last; + } + print('ext $ext'); + + var fileMsg = FileChat.create(); + fileMsg.type = ext; + fileMsg.size = fileSize; + fileMsg.name = fileName; + + var msg = MsgHandler.createSendMsg(ChatType.FileChatType, fileMsg.writeToBuffer(), + friendId: 0, + localFile: file.path, + channelType: + ChatChannelType.Group); + + sendMsg(msg); + + } + + + updateGroupInfo(args) { + print('更新群信息'); + if (mounted) { + setState(() {}); + } + } + + void getDefaultSetting() async { + bool soundPlayMode = + (await SPUtils.getBool(Constants.SOUND_PLAY_MODE)) ?? false; + + _keyboardIndexProvider.init(soundPlayMode); + } + + dealWithKeyboardHide(args) { + if (_keyboardIndexProvider.curKeyboardIndex == 0) { + readOnly(); + } + } + + @override + Widget build(BuildContext context) { + List actions = []; + actions.add(Row( + children: [ + CustomUI.buildImageLabel("assets/images/voucher.png", + Provider.of(context).voucher, + imgOpc: 0.5, imgHeight: 13), + CustomUI.buildImageLabel( + R.assetsImagesCoin, Provider.of(context).money, + isLeft: false) + ], + )); + actions.add(widget.groupInfoModel.isInGroup + ? IconButton( + icon: Icon(Icons.more_horiz), + iconSize: 22, + onPressed: () { + //进入群管理界面 + hideKeyBoard(); + + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return GroupSetting( + groupInfoModel: widget.groupInfoModel, + ); + }, + ), + ); + }, + ) + : IconButton( + icon: Icon(Icons.delete), + iconSize: 22, + color: Colors.redAccent, + onPressed: () { + //进入群管理界面 + quiteGroup(); + }, + )); + + Map refMap = Provider.of(context).refMap; + + return MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => _keyboardIndexProvider), + Provider.value(value: true), + Provider.value(value: widget.groupInfoModel), + ], + child: GestureDetector( + onTap: hideKeyBoard, + child: ExtendedTextSelectionPointerHandler( + ///选择文字,消除弹窗 + builder: (states) { + return Listener( + child: Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: const Color(0xFFE2E9F1), + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + widget.groupInfoModel.getGroupName(refMap), + textScaleFactor: 1.0, + style: TextStyle( + color: Constants.BlackTextColor, + fontSize: 16.47), + ), + leading: CustomUI.buildCustomLeading(context), + titleSpacing: -10, + elevation: 1, + centerTitle: false, + actions: actions), + body: SafeArea( + child: Column( + children: [ + NetStateWidget(), + Expanded(child: _buildMessageList()), + InputBar(sendMsg: sendMsg), + ], + ))), + behavior: HitTestBehavior.translucent, + onPointerDown: (value) { + for (var state in states) { + if (!state.containsPosition(value.position)) { + //clear other selection + state.clearSelection(); + } + } + }, + onPointerMove: (value) { + //clear other selection + for (var state in states) { + if (!state.containsPosition(value.position)) { + //clear other selection + state.clearSelection(); + } + } + }, + ); + }, + ))); + } + + //更新各个子元素的偏移位置 + _updateMsgItemOffset() { + if (msgList.length == 0) { + return; + } + + var myId = UserData().basicInfo.userId; + double offset = 0; + for (var i = 0; i < msgList.length; i++) { + MsgModel msg = msgList[i]; + + double itemHeight = 40; + switch (ChatType.valueOf(msg.msgType)) { + case ChatType.TextChatType: + if (msg.from == myId) { + var text = utf8.decode(msg.msgContent); + itemHeight = 21 + _getTextHeight(text); + } else {} + break; + case ChatType.ShortVoiceChatType: + if (msg.from == myId) { + itemHeight = 22.5 + 24; + } else {} + break; + case ChatType.ImageChatType: + itemHeight = _getImgHeight(msg); + break; + case ChatType.ShortVideoChatType: + itemHeight = _getImgHeight(msg); + break; + case ChatType.EmoticonType: + itemHeight = 40; + break; + case ChatType.RedWalletChatType: + print('红包消息'); + itemHeight = 70; + break; + case ChatType.PlaceChatType: + itemHeight = 100 + 40.0; + break; + case ChatType.GroupChatNoticeType: + itemHeight = 40; + break; + case ChatType.GiftChatType: + itemHeight = 40; + break; + case ChatType.FileChatType: + itemHeight = 80; + break; + default: + } + + itemOffsetMap[i] = offset; + offset += itemHeight; + } + } + + double _getTextHeight(String text) { + var tp = TextPainter( + text: TextSpan(style: TextStyle(fontSize: 15), text: text), + textAlign: TextAlign.left, + textDirection: TextDirection.ltr, + textScaleFactor: 1, + ); + + tp.layout(maxWidth: Screen.width - 140); + + return tp.height; + } + + double _getImgHeight(MsgModel msg) { + double aspectRatio = msg.extraInfo / 100; + + var maxWidth = Screen.width * 0.65; + var maxHeight = Screen.height / 4; + + double height; + if (maxWidth / maxHeight > aspectRatio) { + height = maxHeight; + } else { + height = maxWidth / aspectRatio; + } + + return height; + } + + Widget _buildMessageList() { + return Container( + alignment: Alignment.topCenter, + child: msgList.length == 0 + ? Padding( + padding: EdgeInsets.all(10), + child: Text( + I18n.of(context).chat_tips, + textAlign: TextAlign.center, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.grey), + )) + : Scrollbar(child: ListView.builder( + reverse: true, + shrinkWrap: true, + itemCount: msgList.length, + controller: _scrollCtrl, + padding: EdgeInsets.all(8.0), + itemBuilder: _buildItem, + )), + ); + } + + hideKeyBoard() { + _keyboardIndexProvider.changeSelectIndex(-1); + } + + readOnly() { + _keyboardIndexProvider.changeReadOnlyKey(true); + } + + sendMsg(MsgModel msg) { + if (!widget.groupInfoModel.isInGroup) { + //如果不在该群 + showToast(I18n.of(context).not_in_group); + return; + } + + MsgHandler.insertMsgToDB(msg); + MsgHandler.sendChatMsg(msg); + if (mounted) { + setState(() {}); + } + + if (_scrollCtrl.hasClients) { + _scrollCtrl.animateTo(0, + duration: new Duration(milliseconds: 500), curve: Curves.ease); + } + } + + void receiveMsg(args) { + if (args != widget.groupInfoModel.sessionId) { + return; + } + if (mounted) { + setState(() {}); + if (_scrollCtrl.hasClients) { + _scrollCtrl.animateTo(0, + duration: new Duration(milliseconds: 500), curve: Curves.ease); + } + } + } + + _deleteItem(msg) { + MessageMgr().emit('Cancel Request', msg); + print('#### 开始删除--'); + msgList.remove(msg); + setState(() {}); + SqlUtil().deleteSigleRecordWith(msg.sessionId, msg.time); + } + + Widget _buildItem(BuildContext context, int index) { + var lastMsgTime; + if (index < msgList.length - 1) { + lastMsgTime = msgList[index + 1].time; + } + + MsgModel msg = msgList[index]; + + if (msg.from == 0) { + return GroupChatPageItem( + key: Key(msg.time.toString()), msg: msg, lastMsgTime: lastMsgTime); + } else { + return GroupChatPageItem( + key: Key(msg.time.toString()), + msg: msg, + memberModel: widget.groupInfoModel.getMember(msg.from), + hideKeyboard: readOnly, + lastMsgTime: lastMsgTime); + } + } + + quiteGroup() { + var function = () { + GroupInfoMgr().deleteGroup(widget.groupInfoModel.sessionId); + MessageMgr().emit('Quit Group', widget.groupInfoModel.sessionId); + Navigator.of(context).popUntil(ModalRoute.withName('/main')); + MsgHandler.quitGroup(widget.groupInfoModel.sessionId); + }; + + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + builder: (BuildContext context) { + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(13), topRight: Radius.circular(13))), + height: 225, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.fromLTRB(15, 15, 15, 13), + child: Text( + I18n.of(context).quit_group_tips, + style: TextStyle(fontSize: 12, color: Color(0xff777777)), + ), + ), + Divider( + color: Color(0xffE5E5E5), + ), + InkWell( + onTap: function, + child: Container( + height: 60, + alignment: Alignment.center, + child: Text(I18n.of(context).determine, + style: TextStyle( + fontSize: 18, color: Constants.ConfrimButtonColor)), + ), + ), + Container( + color: Color(0xffF2F2F2), + height: 4, + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + height: 60, + alignment: Alignment.center, + child: Text(I18n.of(context).cancel, + style: TextStyle(fontSize: 18, color: Color(0xff4B4B4B))), + ), + ) + ], + ), + ); + }, + ); + } +} diff --git a/lib/chat/input_bar.dart b/lib/chat/input_bar.dart new file mode 100644 index 0000000..5790394 --- /dev/null +++ b/lib/chat/input_bar.dart @@ -0,0 +1,895 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:chat/chat/keyboard_icon.dart'; +import 'package:chat/chat/my_extended_text_selection_controls.dart'; +import 'package:chat/chat/record_view.dart'; +import 'package:chat/chat/util_keyboard.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/alter_select_view.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/models/keyboard_provider.dart'; +import 'package:chat/photo/entity/options.dart'; +import 'package:chat/photo/photo.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/group_member_model.dart'; +import 'package:chat/utils/image_util.dart'; +import 'package:chat/utils/keyboard_utils.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sound_util.dart'; +import 'package:extended_text_field/extended_text_field.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:photo_manager/photo_manager.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import 'emoji_gif_text.dart'; +import 'emoji_text.dart'; +import 'my_special_text_span_builder.dart'; + +class InputBar extends StatefulWidget { + final Function sendMsg; + + InputBar({this.sendMsg}); + + @override + InputBarState createState() => InputBarState(); +} + +class InputBarState extends State + with SingleTickerProviderStateMixin { + final TextEditingController _textCtrl = TextEditingController(); + FocusNode editFocus = NoKeyboardEditableTextFocusNode(); + bool _isComposingMessage = false; + + PageController pageController; + + double keyboardHeight; + KeyboardBloc _bloc = KeyboardBloc(); + GlobalKey _key = GlobalKey(); + + int currentStickersPage = 0; + + //回复相关 + MsgModel refMsg; + + //@成员数组 + List alterMemberList = []; + + int lastTxtLen = 0; + + @override + void initState() { + super.initState(); + + print('~~~~~~~~~~inputbar initState~~~~~~~~~~~'); + pageController = new PageController(); + getKeyboardHeight(); + _bloc.start(); + + //处理引用事件 + MessageMgr().on('Reply Select Message', replySelectMsg); + + //处理@事件 + MessageMgr().on('Alter User Message', alterOtherMember); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + editFocus?.requestFocus(); + } + + //获取键盘高度,之前保存的 + getKeyboardHeight() async { + var sp = await SharedPreferences.getInstance(); + keyboardHeight = sp.getDouble(Constants.KeyboardHeight); + + if (keyboardHeight == null || keyboardHeight < 100) { + keyboardHeight = 280; + } + } + + @override + void dispose() { + _key = null; + + _textCtrl.dispose(); + _bloc.dispose(); + editFocus.dispose(); + editFocus = null; + MessageMgr().off('Reply Select Message', replySelectMsg); + MessageMgr().off('Alter User Message', alterOtherMember); + super.dispose(); + } + + //引用某句话 + replySelectMsg(args) async { + refMsg = args; + print('处理引用消息'); + + setState(() { + showKeyBoard(); + }); + } + + //快捷@某成员 + alterOtherMember(memberInfo) { + if (!alterMemberList.contains(memberInfo)) { + alterMemberList.add(memberInfo); + } + + print('选中的成员~~~~~~~~~~~~ ${memberInfo.refName}'); + String textStr; + if (_textCtrl.text.length > 0) { + textStr = '${_textCtrl.text} @${memberInfo.refName} '; + } else { + textStr = '@${memberInfo.refName} '; + } + + _textCtrl.value = TextEditingValue( + text: textStr, + selection: + TextSelection.fromPosition(TextPosition(offset: textStr.length))); + + setState(() { + showKeyBoard(); + _isComposingMessage = _textCtrl.text.length > 0; + }); + } + + //显示键盘 + showKeyBoard() { + Provider.of(context, listen: false) + .changeSelectIndex(0); + editFocus.requestFocus(); + Provider.of(context, listen: false) + .changeReadOnlyKey(false); + // SystemChannels.textInput.invokeMethod('TextInput.show'); + } + + _getRefShortText() { + if (refMsg == null) { + return null; + } + String desc = ''; + + if (refMsg == null || refMsg.msgType == null) { + return ''; + } + + switch (ChatType.valueOf(refMsg.msgType)) { + case ChatType.TextChatType: + desc = utf8.decode(refMsg.msgContent); + break; + case ChatType.EmoticonType: + desc = '[${I18n.of(context).emoji}]'; + break; + case ChatType.ImageChatType: + desc = '[${I18n.of(context).picture}]'; + break; + case ChatType.ShortVideoChatType: + desc = '[${I18n.of(context).video}]'; + break; + case ChatType.PlaceChatType: + desc = '[${I18n.of(context).locate}]'; + break; + case ChatType.ShortVoiceChatType: + desc = '[${I18n.of(context).voice}]'; + break; + + case ChatType.GiftChatType: + GiftChat giftChat = GiftChat.fromBuffer(refMsg.msgContent); + + if (giftChat.tuId == UserData().basicInfo.userId) { + desc = I18n.of(context).you_get; + } else { + desc = I18n.of(context).you_give; + } + + break; + + case ChatType.RedWalletChatType: + desc = '[${I18n.of(context).red_money}]'; + break; + + case ChatType.GroupChatNoticeType: + desc = '[${I18n.of(context).msg_notice}]'; + + break; + + case ChatType.FileChatType: + desc = '[文件]'; + + break; + default: + } + + GroupInfoModel groupInfoModel = Provider.of(context); + var member = groupInfoModel.getMember(refMsg.from); + + return '${member.refName}: $desc'; + } + + bool isReceiver = false; + + @override + Widget build(BuildContext context) { + int curKeyboardIndex = + Provider.of(context).curKeyboardIndex; + bool readOnly = + Provider.of(context, listen: false).readOnly; + + bool isGroup = Provider.of(context); + + Widget centerWidget; + + Widget input = Container( + child: ExtendedTextField( + textSelectionControls: MyExtendedMaterialTextSelectionControls(), + keyboardAppearance: Brightness.light, + onChanged: (String messageText) { + if (_textCtrl.text.length > 0) { + var last = messageText.substring(_textCtrl.text.length - 1); + + if (last == '@' && _textCtrl.text.length > lastTxtLen) { + editFocus.unfocus(); + _openAlterSelectPage(); + } + } + lastTxtLen = _textCtrl.text.length; + + setState(() { + _isComposingMessage = _textCtrl.text.length > 0; + }); + }, + key: _key, + readOnly: readOnly, + autofocus: true, + cursorColor: Constants.BlueTextColor, + style: TextStyle( + fontSize: ScreenUtil().setSp(16), + textBaseline: TextBaseline.alphabetic), + maxLines: 3, + minLines: 1, + specialTextSpanBuilder: MySpecialTextSpanBuilder( + showAtBackground: true, + ), + controller: _textCtrl, + textInputAction: TextInputAction.newline, + inputFormatters: [ + LengthLimitingTextInputFormatter(600) //限制长度 + ], + onSubmitted: _textMessageSubmitted, + focusNode: editFocus, + onTap: () { + showKeyBoard(); + Provider.of(context, listen: false) + .changeReadOnlyKey(false); + }, + decoration: InputDecoration( + hintText: I18n.of(context).input_content, + hintStyle: TextStyle(color: const Color(0xffBDBDBD), fontSize: 16), + border: null, + hintMaxLines: 1, + contentPadding: EdgeInsets.only(left: 5, right: 5, top: 8, bottom: 8), + ), + ), + ); + if (refMsg == null) { + centerWidget = input; + } else { + var desc = _getRefShortText(); + centerWidget = Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Row(mainAxisSize: MainAxisSize.min, children: [ + Container( + child: Text( + desc, + maxLines: 1, + overflow: TextOverflow.ellipsis, + textScaleFactor: 1.0, + ), + constraints: BoxConstraints(maxWidth: Screen.width - 220), + ), + InkWell( + child: Container( + child: Icon(Icons.close, size: 10), + padding: EdgeInsets.fromLTRB(10, 5, 5, 5), + ), + onTap: () { + refMsg = null; + setState(() {}); + }, + ) + ]), + padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2), + decoration: BoxDecoration( + color: Colors.grey[200], + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(10))), + input + ], + ); + } + return GestureDetector( + onTap: () { + print('放置触控隐藏键盘'); + }, + child: Container( + width: Screen.width, + color: Colors.white, + child: Column( + children: [ + Container( + padding: EdgeInsets.symmetric(horizontal: 7, vertical: 7), + alignment: Alignment.topCenter, + decoration: BoxDecoration( + color: Colors.white, + border: Border(top: BorderSide(color: Color(0xFFDFDFDF)))), + child: Row( + children: [ + //emoji图标 + KeyboardIcon( + iconCode: 0xe64d, + selectIconCode: 0xe651, + isSelect: curKeyboardIndex == 1, + size: 27, + onTap: () { + isReceiver = !isReceiver; + SoundUtils.instance.setReceiver(isReceiver); +// + if (curKeyboardIndex == 1) { + Provider.of(context, + listen: false) + .changeReadOnlyKey(false); + showKeyBoard(); + } else { + Provider.of(context, + listen: false) + .changeSelectIndex(1); + + currentStickersPage = 0; + } + }), + + SizedBox(width: 10), + + //输入框 + Expanded(child: centerWidget), SizedBox(width: 10), + _isComposingMessage + ? InkWell( + child: Padding( + padding: EdgeInsets.fromLTRB(50, 2, 10, 2), + child: Icon( + Icons.send, + color: Color(0xFF087FF3), + size: 28, + )), + onTap: _sendTextMessage) + : Container( + child: Row( + children: [ + KeyboardIcon( + iconCode: 0xe64b, + isSelect: curKeyboardIndex == 2, + size: 28, + onTap: () { + if (curKeyboardIndex == 2) { + showKeyBoard(); + } else { + Provider.of( + context, + listen: false) + .changeSelectIndex(2); + } + }), + SizedBox(width: 10), + KeyboardIcon( + iconCode: 0xe64f, + isSelect: curKeyboardIndex == 3, + size: 28, + onTap: () { + if (curKeyboardIndex == 3) { + showKeyBoard(); + } else { + Provider.of( + context, + listen: false) + .changeSelectIndex(3); + } + }), + SizedBox(width: 10), + KeyboardIcon( + iconCode: 0xe60c, + isSelect: curKeyboardIndex == 4, + size: 26, + onTap: () { + _openPhotoView(); + }), + ], + ), + ) + ], + ), + ), + Divider(height: 1, color: const Color(0xffE0E0E0)), + StreamBuilder( + stream: _bloc.stream, + builder: (BuildContext context, AsyncSnapshot snapshot) { + double keyHeight = MediaQuery.of(context).viewInsets.bottom; + if (keyHeight > 10) { + keyboardHeight = keyHeight; + UserData().setKeyboardHeight(keyHeight); + } + return Container( + width: double.infinity, + color: Colors.white, + height: curKeyboardIndex == -1 || curKeyboardIndex == 4 + ? 0 + : keyboardHeight, + child: curKeyboardIndex >= 1 && curKeyboardIndex < 4 + ? IndexedStack( + children: [ + Container( + color: Colors.white, + width: double.infinity, + height: double.infinity, + child: InkWell( + onTap: () {}, + child: Container( + height: keyboardHeight, + child: Column( + children: [ + Container( + height: keyboardHeight - 50, + child: PageView.custom( + controller: pageController, + onPageChanged: (page) { + setState(() { + currentStickersPage = + page; + }); + }, + childrenDelegate: + new SliverChildBuilderDelegate( + (context, index) { + return index == 0 + ? buildEmojiGird() + : buildGifGird(); + }, + childCount: 2, + )), + ), + Divider( + height: 1, + color: Color(0xffE0E0E0), + ), + Container( + height: 49, + child: Row( + children: [ + InkWell( + child: Container( + width: 59, + padding: + EdgeInsets.all(10), + color: + currentStickersPage == + 0 + ? const Color( + 0xFFEDEDED) + : Colors.white, + child: Image.asset( + 'assets/images/chat/emoji.png'), + ), + onTap: () { + pageController + .jumpToPage(0); + }, + ), + InkWell( + child: Container( + padding: + EdgeInsets.all(8), + width: 59, + color: + currentStickersPage == + 1 + ? const Color( + 0xFFEDEDED) + : Colors.white, + child: Image.asset( + 'assets/images/chat/onion.png'), + ), + onTap: () { + pageController + .jumpToPage(1); + }, + ) + ], + ), + ), + ], + ), + ), + )), + UtilKeyboard( + keyboardHeight: keyboardHeight, + isGroup: isGroup, + sendMsg: widget.sendMsg), + RecordView( + keyboardHeight: keyboardHeight, + sendMsg: _sendSoundMsg), + ], + index: curKeyboardIndex - 1, + ) + : Container()); + }, + ) + ], + )), + ); + } + + Widget buildEmojiGird() { + return Container( + height: keyboardHeight, + child: Stack( + children: [ + Padding( + padding: EdgeInsets.fromLTRB(5, 8, 50, 0), + child: GridView.builder( + controller: new ScrollController(keepScrollOffset: false), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 7, crossAxisSpacing: 0, mainAxisSpacing: 0), + itemBuilder: (context, index) { + return GestureDetector( + child: Container( + padding: EdgeInsets.all(7), + child: Image.asset(EmojiUitl + .instance.emojiMap[EmojiText.flag + "${index + 1}]"]), + ), + behavior: HitTestBehavior.translucent, + onTap: () { + insertText(EmojiText.flag + "${index + 1}]", _textCtrl); + + setState(() { + _isComposingMessage = _textCtrl.text.length > 0; + }); + }, + ); + }, + itemCount: EmojiUitl.instance.emojiMap.length, + padding: EdgeInsets.all(5.0), + ), + ), + Positioned.fill( + child: Container( + padding: EdgeInsets.fromLTRB(0, 0, 0, 14), + alignment: Alignment(1, 1), + child: InkWell( + onTap: () { + deleteText(_textCtrl); + + setState(() { + _isComposingMessage = _textCtrl.text.length > 0; + }); + }, + child: Container( + decoration: BoxDecoration( + color: Color(0x4d0E0E10), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(4.0), + bottomLeft: Radius.circular(4))), + width: 37, + height: 28, + child: Icon( + IconData( + 0xe679, + fontFamily: 'iconfont', + ), + size: 16, + color: Colors.white, + ), + ), + ), + )), + ], + ), + ); + } + + Widget buildGifGird() { + return Container( + padding: EdgeInsets.fromLTRB(8, 6, 8, 0), + height: keyboardHeight, + child: GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 5, crossAxisSpacing: 12.0, mainAxisSpacing: 12.0), + itemBuilder: (context, index) { + return GestureDetector( + child: Image.asset(EmojiGifUitl + .instance.emojiMap[EmojiGifText.flag + "_${index + 1}>"]), + behavior: HitTestBehavior.translucent, + onTap: () { + _sendMessage(EmojiGifText.flag + "_${index + 1}>", true); + }, + ); + }, + itemCount: EmojiGifUitl.instance.emojiMap.length, + padding: EdgeInsets.all(5.0), + ), + ); + } + + void _openAlterSelectPage() async { + bool isGroup = Provider.of(context); + + if (isGroup) { + GroupInfoModel groupInfoModel = Provider.of(context); + + editFocus.unfocus(); + Provider.of(context, listen: false) + .changeReadOnlyKey(true); + + GroupMemberModel member = + await AlterSelectPage.pickAlterUser(context, groupInfoModel); + + if (member != null) { + print('选中的成员~~~~~~~~~~~~ ${member.refName}'); + _textCtrl.text = '${_textCtrl.text}${member.refName} '; + alterMemberList.add(member); + } + + editFocus.requestFocus(); + Provider.of(context, listen: false) + .changeReadOnlyKey(false); + } + } + + List getAlterUsers(String messageText) { + List alterUserList = []; + RegExp alterStr = RegExp(r'@+(\S+)'); + Iterable matches = alterStr.allMatches(messageText); + print('~~~~~~~~~~~~~~${matches.length}~~~~~~~~~~~~~~~'); + for (Match m in matches) { + print('~~~~~~~~~~~~~~${m.group(1)}~~~~~~~~~~~~~~~'); + alterUserList.add(m.group(1)); + } + + List finalAlterList = []; + for (var member in alterMemberList) { + if (alterUserList.contains(member.refName)) { + finalAlterList.add(member.memberId); + print('有效成员 ${member.refName}'); + } + } + + return finalAlterList; + } + + void _openPhotoView() async { + Provider.of(context, listen: false) + .changeSelectIndex(4); + + var photos = await PhotoPicker.pickAsset( + context: context, + themeColor: Color(0xFFF0F0F0), + textColor: Color(0xFF3F3F3F), + pickType: PickType.onlyImage); + + if (photos != null && photos.length > 0) { + for (var i = 0; i < photos.length; i++) { + AssetEntity photoEntity = photos[i]; + var file = await photoEntity.file; + _sendPhotoFile(file); + } + } + + ///防止再点键盘不谈 + } + + void _sendSoundMsg(String soundPath, int duration) { + bool isGroup = Provider.of(context); + int friendId = 0; + if (!isGroup) { + friendId = Provider.of(context); + } + + print('群聊模式 $isGroup'); + var msg = MsgHandler.createSendMsg( + ChatType.ShortVoiceChatType, Uint8List(0), + localFile: soundPath, + friendId: friendId, + extra: duration, + channelType: isGroup ? ChatChannelType.Group : ChatChannelType.Session); + widget.sendMsg(msg); + } + + void _sendPhotoFile(File imgFile) async { + var imgSize = await imgFile.length(); + + print('图片大小:${imgSize / 1024}KB'); + var sendImg; + + if (imgSize > 33 * 1024 * 1024) { + showToast(I18n.of(context).video_more_big); + return; + } + bool isNeedUpload = false; + if (imgSize > ImgSizeLimit) { + print('图片大于 $ImgSizeLimit,压缩'); + //发送压缩图 + sendImg = await WidgetUtil.getCompressImg(imgFile.absolute.path); + isNeedUpload = true; + } else { + sendImg = imgFile.readAsBytesSync(); + } + + var rect = await WidgetUtil.getImageWH( + image: Image.memory(Uint8List.fromList(sendImg))); + print('图片大小 Rect : $rect'); + int aspectRatio = rect.width * 100 ~/ rect.height; + + bool isGroup = Provider.of(context); + + print('群聊输入模式 $isGroup'); + int friendId = 0; + if (!isGroup) { + friendId = Provider.of(context); + } + + var msg = MsgHandler.createSendMsg(ChatType.ImageChatType, sendImg, + localFile: isNeedUpload ? imgFile.absolute.path : null, + extra: aspectRatio, + friendId: friendId, + channelType: isGroup ? ChatChannelType.Group : ChatChannelType.Session); + + widget.sendMsg(msg); + } + + Future _textMessageSubmitted(String text) async { + if (!checkMessage()) { + _textCtrl.clear(); + alterMemberList.clear(); + lastTxtLen = 0; + return; + } + _textCtrl.clear(); + + _sendMessage(text); + } + + _sendTextMessage() { + if (!checkMessage()) { + return; + } + + var sendStr = _textCtrl.text; + + _textCtrl.clear(); + + _sendMessage(sendStr); + } + + bool checkMessage() { + if (_textCtrl.text.length == 0) { + showToast(I18n.of(context).msg_not); + return false; + } + return true; + } + + _sendMessage(String messageText, [bool isGift = false]) { + bool isGroup = Provider.of(context); + + int friendId = 0; + List alterUsers; + if (!isGroup) { + friendId = Provider.of(context); + } else { + if (!isGift) { + //检查@的人员 + alterUsers = getAlterUsers(messageText); + } + } + + MsgModel msg = MsgHandler.createSendMsg( + isGift ? ChatType.EmoticonType : ChatType.TextChatType, messageText, + friendId: friendId, + refMsg: refMsg, + refShortTxt: _getRefShortText(), + altUsers: alterUsers, + channelType: isGroup ? ChatChannelType.Group : ChatChannelType.Session); + + widget.sendMsg(msg); + + if (!isGift) { + if (refMsg != null) { + refMsg = null; + } + alterMemberList.clear(); + lastTxtLen = 0; + } + + setState(() { + _isComposingMessage = _textCtrl.text.length > 0; + }); + } + + ///emoji插入表情-处理换行 + static void insertText(String text, TextEditingController _textCtrl) { + var value = _textCtrl.value; + var start = value.selection.baseOffset; + var end = value.selection.extentOffset; + if (value.selection.isValid) { + String newText = ""; + if (value.selection.isCollapsed) { + if (end > 0) { + newText += value.text.substring(0, end); + } + newText += text; + if (value.text.length > end) { + newText += value.text.substring(end, value.text.length); + } + } else { + newText = value.text.replaceRange(start, end, text); + end = start; + } + + _textCtrl.value = value.copyWith( + text: newText, + selection: value.selection.copyWith( + baseOffset: end + text.length, extentOffset: end + text.length)); + } else { + _textCtrl.value = TextEditingValue( + text: text, + selection: + TextSelection.fromPosition(TextPosition(offset: text.length))); + } + } + + static void deleteText(TextEditingController _textController) { + var value = _textController.value; + var selection = value.selection; + var text = value.text; + + String newText = ''; + if (selection.baseOffset != selection.extentOffset) { + newText = selection.textBefore(text) + selection.textAfter(text); + _textController.value = TextEditingValue( + text: newText, + selection: selection.copyWith( + baseOffset: selection.baseOffset, + extentOffset: selection.baseOffset)); + } else { + int offsetLength = 1; + String text = _textController.text; + if (text.substring(text.length - 1, text.length) == ']') { + ///删除表情 + int end = _textController.text.lastIndexOf('['); + offsetLength = text.length - end; + } + newText = text.substring(0, selection.baseOffset - offsetLength) + + selection.textAfter(text); + _textController.value = TextEditingValue( + text: newText, + selection: selection.copyWith( + baseOffset: selection.baseOffset - offsetLength, + extentOffset: selection.baseOffset - offsetLength)); + } + } +} diff --git a/lib/chat/keyboard_icon.dart b/lib/chat/keyboard_icon.dart new file mode 100644 index 0000000..ceecfde --- /dev/null +++ b/lib/chat/keyboard_icon.dart @@ -0,0 +1,30 @@ +import 'package:chat/data/constants.dart'; +import 'package:flutter/material.dart'; + +class KeyboardIcon extends StatelessWidget { + final int iconCode; + final VoidCallback onTap; + final bool isSelect; + final int selectIconCode; + final double size; + KeyboardIcon( + {this.iconCode, this.onTap, this.isSelect = false, this.selectIconCode,this.size = 28}); + + @override + Widget build(BuildContext context) { + var color = isSelect ? Color(0xFF0A80F3) : Color(0xFF797A7C); + var code; + if (selectIconCode == null) { + code = iconCode; + } else { + code = isSelect ? selectIconCode : iconCode; + } + return InkWell( + child: Icon( + IconData(code, fontFamily: Constants.IconFontFamily), + color: color, + size: size, + ), + onTap: onTap); + } +} \ No newline at end of file diff --git a/lib/chat/msg_state_widge.dart b/lib/chat/msg_state_widge.dart new file mode 100644 index 0000000..736d1c5 --- /dev/null +++ b/lib/chat/msg_state_widge.dart @@ -0,0 +1,91 @@ +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class MsgStateWidget extends StatefulWidget { + final MsgModel msg; + + MsgStateWidget(this.msg); + @override + _MsgStateWidgetState createState() => _MsgStateWidgetState(); +} + +class _MsgStateWidgetState extends State { + int sendState = MsgState.None; + + @override + void initState() { + super.initState(); + + sendState = widget.msg.state; + MessageMgr().on('Update Chat Message State', updateSendState); + } + + @override + void dispose() { + MessageMgr().off('Update Chat Message State', updateSendState); + super.dispose(); + } + + updateSendState(msg) { + if (widget.msg.time == msg['time'] && + widget.msg.sessionId == msg['sessionId']) { + widget.msg.state = msg['state']; + if (mounted) { + setState(() { + sendState = widget.msg.state; + }); + } + } + } + + @override + Widget build(BuildContext context) { + if (sendState == MsgState.UploadFailed) { + return Container( + child: IconButton( + iconSize: 22, + icon: Icon( + Icons.error_outline, + color: Colors.red, + ), + onPressed: () { + setState(() { + sendState = MsgState.Uploading; + }); + + MessageMgr().emit('ReUpload Msg', widget.msg); + }, + ), + ); + } + if (sendState == MsgState.SendingFailed) { + return Container( + child: IconButton( + iconSize: 22, + icon: Icon( + Icons.error_outline, + color: Colors.red, + ), + onPressed: () { + print('重新发送'); + setState(() { + sendState = MsgState.Sending; + }); + MsgHandler.sendChatMsg(widget.msg); + }, + ), + ); + } else if (sendState == MsgState.SendingSuccess) { + return Container(width: 0, height: 0); + } else { + return Align( + alignment: Alignment.center, + child: Padding( + padding: EdgeInsets.only(top: 5), + child: CupertinoActivityIndicator())); + } + } +} diff --git a/lib/chat/my_extended_text_selection_controls.dart b/lib/chat/my_extended_text_selection_controls.dart new file mode 100644 index 0000000..daadeb3 --- /dev/null +++ b/lib/chat/my_extended_text_selection_controls.dart @@ -0,0 +1,239 @@ +import 'package:chat/generated/i18n.dart'; +import 'package:extended_text/extended_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; + +// Minimal padding from all edges of the selection toolbar to all edges of the +// viewport. + +const double _kToolbarScreenPadding = 8.0; +const double _kToolbarHeight = 44.0; + +/// +/// create by zmtzawqlp on 2019/8/3 +/// + +class MyExtendedMaterialTextSelectionControls + extends ExtendedMaterialTextSelectionControls { + + TextSelectionDelegate delegate; + + @override + Widget buildToolbar( + BuildContext context, + Rect globalEditableRegion, + double textLineHeight, + Offset position, + List endpoints, + TextSelectionDelegate delegate, + ) { + assert(debugCheckHasMediaQuery(context)); + assert(debugCheckHasMaterialLocalizations(context)); + this.delegate = delegate; + // The toolbar should appear below the TextField + // when there is not enough space above the TextField to show it. + final TextSelectionPoint startTextSelectionPoint = endpoints[0]; + final TextSelectionPoint endTextSelectionPoint = + (endpoints.length > 1) ? endpoints[1] : null; + final double x = (endTextSelectionPoint == null) + ? startTextSelectionPoint.point.dx + : (startTextSelectionPoint.point.dx + endTextSelectionPoint.point.dx) / + 2.0; + final double availableHeight = globalEditableRegion.top - + MediaQuery.of(context).padding.top - + _kToolbarScreenPadding; + final double y = (availableHeight < _kToolbarHeight) + ? startTextSelectionPoint.point.dy + + globalEditableRegion.height + + _kToolbarHeight + + _kToolbarScreenPadding + : startTextSelectionPoint.point.dy - textLineHeight * 2.0; + final Offset preciseMidpoint = Offset(x, y); + + return ConstrainedBox( + constraints: BoxConstraints.tight(globalEditableRegion.size), + child: CustomSingleChildLayout( + delegate: ExtendedMaterialTextSelectionToolbarLayout( + MediaQuery.of(context).size, + globalEditableRegion, + preciseMidpoint, + ), + child: _TextSelectionToolbar( + handleCut: canCut(delegate) ? () => handleCut(delegate) : null, + handleCopy: canCopy(delegate) ? () => handleCopy(delegate) : null, + handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null, + handleSelectAll: + canSelectAll(delegate) ? () => handleSelectAll(delegate) : null, + // handleLike: () { + // MessageMgr().emit('Delete Select Message', msg); + // }, + // handleRef: canSelectAll(delegate) + // ? null + // : () { + // MessageMgr().emit('Reply Select Message', msg); + // }, + delegate: delegate, + ), + ), + ); + } + + + test(){ + handleSelectAll(delegate); + } + + @override + void goTest() { + Future.delayed(Duration(milliseconds: 350),(){ + handleSelectAll(delegate); + }); + } + +// @override +// Widget buildHandle( +// BuildContext context, TextSelectionHandleType type, double textHeight) { +// final Widget handle = SizedBox( +// width: _kHandleSize, +// height: _kHandleSize, +// child: Image.asset("assets/40.png"), +// ); +// +// // [handle] is a circle, with a rectangle in the top left quadrant of that +// // circle (an onion pointing to 10:30). We rotate [handle] to point +// // straight up or up-right depending on the handle type. +// switch (type) { +// case TextSelectionHandleType.left: // points up-right +// return Transform.rotate( +// angle: math.pi / 4.0, +// child: handle, +// ); +// case TextSelectionHandleType.right: // points up-left +// return Transform.rotate( +// angle: -math.pi / 4.0, +// child: handle, +// ); +// case TextSelectionHandleType.collapsed: // points up +// return handle; +// } +// assert(type != null); +// return null; +// } +} + +/// Manages a copy/paste text selection toolbar. +class _TextSelectionToolbar extends StatelessWidget { + const _TextSelectionToolbar( + {Key key, + this.handleCopy, + this.handleSelectAll, + this.handleCut, + this.handlePaste, + // this.handleRef, + // this.handleLike, + this.delegate}) + : super(key: key); + + final VoidCallback handleCut; + final VoidCallback handleCopy; + final VoidCallback handlePaste; + final VoidCallback handleSelectAll; + // final VoidCallback handleLike; + // final VoidCallback handleRef; + final TextSelectionDelegate delegate; + + + + @override + Widget build(BuildContext context) { + + final List items = []; + + if (handleCopy != null) + items.add(GestureDetector( + onTap: handleCopy, + child: Container( + padding: EdgeInsets.fromLTRB(12, 9, 12, 9), + child: Text( + I18n.of(context).copy, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white, fontSize: 12), + ), + ), + )); + + if (handleSelectAll != null) + items.add(GestureDetector( + onTap: handleSelectAll, + child: Container( + padding: EdgeInsets.fromLTRB(12, 9, 12, 9), + child: Text( + I18n.of(context).select_all, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white, fontSize: 12), + ), + ), + )); + + // if (handleRef != null) { + // items.add(GestureDetector( + // onTap: () { + // delegate.hideToolbar(); + // handleRef(); + // }, + // child: Container( + // padding: EdgeInsets.fromLTRB(12, 9, 12, 9), + // child: Text( + // '回复', + // textScaleFactor: 1.0, + // style: TextStyle(color: Colors.white, fontSize: 12), + // ), + // ), + // )); + //} + +// if (handleCut != null) +// items.add(FlatButton( +// child: Text(localizations.cutButtonLabel), onPressed: handleCut)); +// if (handleCopy != null) +// items.add(FlatButton( +// child: Text(localizations.copyButtonLabel), onPressed: handleCopy)); +// if (handlePaste != null) +// items.add(FlatButton( +// child: Text(localizations.pasteButtonLabel), +// onPressed: handlePaste, +// )); +// if (handleSelectAll != null) +// items.add(FlatButton( +// child: Text(localizations.selectAllButtonLabel), +// onPressed: handleSelectAll)); + + // if (handleLike != null) + // items.add(GestureDetector( + // onTap: handleLike, + // child: Container( + // padding: EdgeInsets.fromLTRB(12, 9, 12, 9), + // child: Text( + // I18n.of(context).delete, + // textScaleFactor: 1.0, + // style: TextStyle(color: Colors.white, fontSize: 12), + // ), + // ), + // )); + + // If there is no option available, build an empty widget. + if (items.isEmpty) { + return Container(width: 0.0, height: 0.0); + } + + return Material( + elevation: 1.0, + child: Container( + child: Wrap(children: items), + decoration: BoxDecoration( + color: Colors.black, + borderRadius: BorderRadius.all(Radius.circular(5.0))), + ), + ); + } +} diff --git a/lib/chat/my_special_text_span_builder.dart b/lib/chat/my_special_text_span_builder.dart new file mode 100644 index 0000000..bf31b37 --- /dev/null +++ b/lib/chat/my_special_text_span_builder.dart @@ -0,0 +1,52 @@ +import 'package:chat/chat/dollar_text.dart'; +import 'package:extended_text_library/extended_text_library.dart'; +import 'package:flutter/material.dart'; + +import 'emoji_gif_text.dart'; +import 'emoji_text.dart'; + +class MySpecialTextSpanBuilder extends SpecialTextSpanBuilder { + /// whether show background for @somebody + final bool showAtBackground; + final bool isShowGif; + final double emojiSize; + MySpecialTextSpanBuilder({this.showAtBackground: false,this.isShowGif=true,this.emojiSize=20.0}); + + @override + TextSpan build(String data, {TextStyle textStyle, onTap}) { + var textSpan = super.build(data, textStyle: textStyle, onTap: onTap); + return textSpan; + } + + @override + SpecialText createSpecialText(String flag, + {TextStyle textStyle, SpecialTextGestureTapCallback onTap, int index}) { + if (flag == null || flag == "") return null; + + ///index is end index of start flag, so text start index should be index-(flag.length-1) +// if (isStart(flag, AtText.flag)) { +// return AtText( +// textStyle, +// onTap, +// start: index - (AtText.flag.length - 1), +// showAtBackground: showAtBackground, +// ); +// } else if (isStart(flag, EmojiText.flag)) { +// return EmojiText(textStyle, start: index - (EmojiText.flag.length - 1)); +// } else if (isStart(flag, DollarText.flag)) { +// return DollarText(textStyle, onTap, +// start: index - (DollarText.flag.length - 1)); +// } + if (isStart(flag, EmojiText.flag)) { + return EmojiText(textStyle, start: index - (EmojiText.flag.length - 1),emojiSize: emojiSize); + } + else if (isStart(flag, EmojiGifText.flag)) { + print('EmojiGifText ----'); + return EmojiGifText(textStyle, start: index - (EmojiGifText.flag.length - 1),isShowGif: isShowGif); + }else if (isStart(flag, DollarText.flag)) { + print('DollarText ----'); + return DollarText(textStyle,onTap,start:index - (DollarText.flag.length - 1)); + } + return null; + } +} diff --git a/lib/chat/place_item.dart b/lib/chat/place_item.dart new file mode 100644 index 0000000..442fe1b --- /dev/null +++ b/lib/chat/place_item.dart @@ -0,0 +1,173 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/map/location_result.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/upload_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:menu/menu.dart'; + +class PlaceItem extends StatelessWidget { + final bool isMe; + final List placeContent; + PlaceItem({this.isMe, this.placeContent}); + @override + Widget build(BuildContext context) { + LocationResult location = + LocationResult.fromJson(json.decode(utf8.decode(placeContent))); + + print('地图截屏大小:${location.screen.length}'); + var provider = MemoryImage(Uint8List.fromList(location.screen)); + + return ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Container( + width: Screen.width - 160, + child: Column( + children: [ + AddressTitle(address: location.address), + GestureDetector( + child: Container( + height: 100, + width: double.infinity, + child: Image(fit: BoxFit.cover, image: provider), + ), + onTap: () { + print('点击地图'); + AppNavigator.pushMapPage(context, location); + }, + ) + ], + ), + ), + ); + } +} + +class AddressTitle extends StatefulWidget { + final String address; + AddressTitle({this.address}); + @override + _AddressTitleState createState() => _AddressTitleState(); +} + +class _AddressTitleState extends State { + String transTitle; + int curLan = 0; + List transList = []; + + Map translateMap = {}; + + String translateTitle; + bool isTranslating = false; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + InkWell( + onTap: isTranslating ? null : _changeTitle, + child: Menu( + items: [ + MenuItem(I18n.of(context).copy, () { + ClipboardData clipboardData = new ClipboardData( + text: translateTitle ?? widget.address); + Clipboard.setData(clipboardData); + }), + ], + child: Container( + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 8), + width: Screen.width - 160, + color: Colors.white, + child: Text(translateTitle ?? widget.address, textScaleFactor: 1.0,)))), + Positioned( + right: 0, + bottom: 0, + child: isTranslating + ? Container( + width: 10, + height: 10, + padding: EdgeInsets.all(1.0), + child: CircularProgressIndicator( + strokeWidth: 1.0, + )) + : InkWell( + child: Icon( + IconData(0xe6a5, fontFamily: Constants.IconFontFamily), + color: Color(0xFF3FBAFD), + size: 20, + ), + onTap: _changeTitle)) + ], + ); + } + + _changeTitle() async { + curLan += 1; + curLan %= 3; + var lang; + switch (curLan) { + case 0: + //lang = 'zh-cn'; + lang = LanguageType.SimplifiedChinese; + break; + case 1: + //lang = 'en'; + lang = LanguageType.English; + break; + case 2: + //lang = 'vi'; + lang = LanguageType.Vietnamese; + break; + default: + } + + if (translateMap[lang] != null) { + translateTitle = translateMap[lang]; + isTranslating = false; + setState(() {}); + return; + } + try { + isTranslating = true; + print('开始翻译 to $lang'); + setState(() {}); + + UploadUtil() + .commitTranslateSource(1, UserData().language, lang, widget.address) + .then((title) { + print('翻译结果 to $title'); + if (title != null) { + translateTitle = title; + if (lang == LanguageType.SimplifiedChinese) { + //替换street + translateTitle = translateTitle.replaceAll( + RegExp('street', caseSensitive: false), '街道'); + translateTitle = translateTitle.replaceAll( + RegExp('Binh Tan', caseSensitive: false), '平新郡'); + translateTitle = translateTitle.replaceAll( + RegExp('Tan Tao', caseSensitive: false), '新桃村'); + } + translateMap[lang] = translateTitle; + } + + isTranslating = false; + if (mounted) { + setState(() {}); + } + }); + } catch (e) { + print('翻译错误 $e'); + } + } +} diff --git a/lib/chat/record_view.dart b/lib/chat/record_view.dart new file mode 100644 index 0000000..942e94f --- /dev/null +++ b/lib/chat/record_view.dart @@ -0,0 +1,356 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/photo/ui/dialog/not_permission_dialog.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sound_util.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_audio_recorder/flutter_audio_recorder.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:path/path.dart' as p; +import 'package:permission_handler/permission_handler.dart'; + +const int soundSizeLimit = 61; +const double RecorderRadius = 30; + +class RecordView extends StatefulWidget { + final double keyboardHeight; + final Function sendMsg; + + RecordView({this.keyboardHeight, this.sendMsg}); + @override + _RecordViewState createState() => _RecordViewState(); +} + +class _RecordViewState extends State { + Timer counter; + int totalCount = 0; + bool _isRecording = false; + Timer recordTimer; + FlutterAudioRecorder recorder; + + bool isCancelState = false; + bool _isCounting = false; + + bool hasPermission = false; //录音权限 + bool isTaped = false; + + @override + void initState() { + super.initState(); + } + + void hide() { + counter.cancel(); + counter = null; + } + + @override + void deactivate() { + super.deactivate(); + + cancelRecorder(); + } + + @override + void dispose() { + print('record view dispose'); + anchorKey = null; + counter?.cancel(); + super.dispose(); + } + + _timeCounter() { + if (!_isCounting) { + return Container( + height: 40, + ); + } + int h = totalCount ~/ 3600; + int m = (totalCount % 3600) ~/ 60; + int s = totalCount % 60; + + var hStr = h >= 10 ? h.toString() : '0' + h.toString(); + var mStr = m >= 10 ? h.toString() : '0' + m.toString(); + var sStr = s >= 10 ? s.toString() : '0' + s.toString(); + return Container( + height: 40, + alignment: Alignment.center, + child: Text('$hStr:$mStr:$sStr', + textScaleFactor: 1.0, + style: TextStyle(color: Colors.black, fontSize: 30))); + } + + _startTimer() { + totalCount = 0; + _isCounting = true; + setState(() {}); + counter?.cancel(); + counter = Timer.periodic(Duration(seconds: 1), (Timer timer) { + totalCount += 1; + setState(() {}); + }); + } + + _stopTimer() { + _isCounting = false; + if (mounted) { + setState(() {}); + } + + counter?.cancel(); + } + + askRecordPermission() async { + final PermissionStatus statusFirst = await PermissionHandler() + .checkPermissionStatus(PermissionGroup.microphone); + + print('录音权限 $statusFirst'); + + final PermissionStatus storageStatus = await PermissionHandler() + .checkPermissionStatus(PermissionGroup.storage); + + print('storage权限 $storageStatus'); + if (statusFirst == PermissionStatus.granted && + storageStatus == PermissionStatus.granted) { + hasPermission = true; + } else { + + cancelRecorder(); + if(statusFirst == PermissionStatus.unknown || (statusFirst == PermissionStatus.denied && Platform.isAndroid)){ + Map permissionRequestResult = + await PermissionHandler().requestPermissions( + [PermissionGroup.microphone, PermissionGroup.storage]); + var status = permissionRequestResult[PermissionGroup.microphone]; + var storageStatus = permissionRequestResult[PermissionGroup.storage]; + if (status == PermissionStatus.granted && + storageStatus == PermissionStatus.granted) { + hasPermission = true; + } + + }else{ + + var result = await showDialog( + context: context, + builder: (ctx) => NotPermissionDialog(I18n.of(context).video_permission), + ); + if (result == true) { + PermissionHandler().openAppSettings(); + } + } + } + } + + double tempX; + double tempY; + GlobalKey anchorKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + var tipStr; + if (_isRecording) { + if (isCancelState) { + tipStr = I18n.of(context).cancel; + } else { + tipStr = I18n.of(context).voice_tips2; + } + } else { + tipStr = I18n.of(context).voice_tips; + } + + return Container( + width: double.infinity, + height: double.infinity, + padding: EdgeInsets.only(top: 10, bottom: 20), + color: Colors.white, + alignment: Alignment.center, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _timeCounter(), + Expanded( + child: GestureDetector( + child: Container( + key: anchorKey, + width: 100, + height: 100, + child: Icon( + IconData(0xe64f, fontFamily: Constants.IconFontFamily), + color: isTaped ? Colors.white : Color(0xFF018DFE), + size: 64), + decoration: BoxDecoration( + color: isTaped ? Color(0xFF018DFE) : Colors.white, + shape: BoxShape.circle, + border: Border.all(color: Color(0xFF60919F)), + boxShadow: [ + BoxShadow( + color: Color(0xFFD0D0D0), //阴影颜色 + blurRadius: 5.0, //阴影大小 + ), + ]), + ), + onTap: () { + //只是短暂按压,取消发送 + print('onTap'); + cancelRecorder(); + }, + onTapUp: (TapUpDetails details) { + print('onTapUp'); + isTaped = false; + setState(() {}); + }, + onTapDown: (TapDownDetails details) { + print('onTapDown'); + isTaped = true; + setState(() {}); + if (!hasPermission) { + askRecordPermission(); + } + RenderBox renderBox = + anchorKey.currentContext.findRenderObject(); + var offset = renderBox.localToGlobal(Offset( + renderBox.size.width / 2, renderBox.size.height / 2)); + tempX = offset.dx; + tempY = offset.dy; + }, + onLongPressStart: (LongPressStartDetails details) { + print('onLongPressStart'); + if (hasPermission) { + if (!_isRecording) { + startRecorder(context); + } + }else + { + cancelRecorder(); + } + }, + onLongPressEnd: (LongPressEndDetails details) { + print('onLongPressEnd'); + isTaped = false; + setState(() {}); + if (checkValideArea(details.globalPosition)) { + print('在范围内'); + stopRecorder(); + } else { + print('不在范围内'); + cancelRecorder(); + } + }, + onLongPressMoveUpdate: (LongPressMoveUpdateDetails details) { + if (!checkValideArea(details.globalPosition)) { + if (!isCancelState) { + setState(() { + isCancelState = true; + }); + } + } else { + if (isCancelState) { + setState(() { + isCancelState = false; + }); + } + } + }, + )), + SizedBox(height: 10), + Container( + height: 40, + alignment: Alignment.center, + child: Text(tipStr, textScaleFactor: 1.0,), + ) + ], + )); + } + + checkValideArea(Offset position) { + double offset = RecorderRadius * Screen.scale; + + return (position.dx - tempX).abs() <= offset && + (position.dy - tempY).abs() <= offset; + } + + void startRecorder(BuildContext context) async { + if (!hasPermission) { + return; + } + + SoundUtils().stop(); + try { + var directory = await getTemporaryDirectory(); + var curTime = DateTime.now().millisecondsSinceEpoch; + var path = p.join(directory.path, 'record$curTime.wav'); + + recorder = FlutterAudioRecorder(path, + audioFormat: AudioFormat.WAV, + sampleRate: 16000); // or AudioFormat.WAV + await recorder.initialized; + + await recorder.start(); + print('######开始录音'); + _startTimer(); + //60分钟后如果还在录,自动停止 + + recordTimer = Timer(Duration(seconds: soundSizeLimit), () { + stopRecorder(); + }); + + this.setState(() { + this._isRecording = true; + }); + } catch (err) { + print('startRecorder error: $err'); + } + } + + void cancelRecorder() async { + recordTimer?.cancel(); + isTaped = false; + await recorder?.stop(); + _isRecording = false; + _stopTimer(); + } + + void stopRecorder() async { + if (!hasPermission || !_isRecording) { + return; + } + + try { + var recording = await recorder.stop(); + + this._isRecording = false; + + var filePath = recording.path; + var time = recording.duration.inMilliseconds; + print("Stop recording: $filePath time : $time"); + + recordTimer?.cancel(); + _stopTimer(); + + _sendSound(filePath, time); + + this.setState(() {}); + } catch (err) { + + print('stopRecorder error: $err'); + } + } + + _sendSound(soundPath, int duration) async { + var fileData = File(soundPath).readAsBytesSync(); + + print('fileData size ${fileData.length}'); + if (duration < 1000) { + //小于1秒 + showToast(I18n.of(context).time_little); + return; + } else { + + print('发送音频文件${DateTime.now()}'); + widget.sendMsg(soundPath,duration); + } + } +} diff --git a/lib/chat/redbag_widget.dart b/lib/chat/redbag_widget.dart new file mode 100644 index 0000000..58efbba --- /dev/null +++ b/lib/chat/redbag_widget.dart @@ -0,0 +1,148 @@ +import 'dart:convert'; + +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/proto/chat.pbserver.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; + +class RedBagItem extends StatefulWidget { + final MsgModel msgModel; + + final int sendId; + + RedBagItem(Key key, this.sendId, this.msgModel) : super(key: key); + + @override + _RedBagItemState createState() => _RedBagItemState(); +} + +class _RedBagItemState extends State { + RedWallet wallet; + List translateStr; + + @override + void initState() { + super.initState(); + + wallet = RedWallet.fromBuffer(widget.msgModel.msgContent); + translateStr = widget.msgModel.translateContent; + + MessageMgr().on('Update RedWalletState', updateRedWalletState); + } + + @override + void dispose() { + MessageMgr().off('Update RedWalletState', updateRedWalletState); + super.dispose(); + } + + updateRedWalletState(walletInfo) { + if (walletInfo.orderId == wallet.orderId) { + wallet.state = walletInfo.state; + if (mounted) { + setState(() {}); + } + } + } + + @override + Widget build(BuildContext context) { + var msg; + var bgColor = Color(0xFFFF9936); + if (wallet.state == RedWalletState.Expire) { + msg = I18n.of(context).over_time; + bgColor = Color(0xFFFF9936).withOpacity(0.5); + } else if (wallet.state == RedWalletState.Received) { + msg = I18n.of(context).has_get; + bgColor = Color(0xFFFF9936).withOpacity(0.5); + } + + var titleStr; + if (translateStr != null && translateStr.length > 0) { + print('红包有翻译内容'); + titleStr = utf8.decode(translateStr); + } else { + titleStr = wallet.title; + } + + print('红包内容:$titleStr'); + var title = SizedBox( + width: Screen.width - 220, + child: Text( + titleStr, + textScaleFactor: 1.0, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 16, color: Colors.white), + )); + + var borderRadius; + double radius = 7.5; + borderRadius = BorderRadius.all(Radius.circular(radius)); + + return GestureDetector( + child: ClipRRect( + borderRadius: borderRadius, + child: Container( + decoration: BoxDecoration(boxShadow: [ + BoxShadow( + color: const Color(0x29B3B4B7), + offset: Offset(0, 5), + blurRadius: 5.5), + ]), + constraints: BoxConstraints(maxWidth: Screen.width - 160), + child: Column( + children: [ + Container( + height: 50, + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 8), + color: bgColor, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.all(2.5), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white.withOpacity(0.22)), + child: Image.asset(R.assetsImagesCoin, scale: 2), + ), + SizedBox(width: 5), + msg != null + ? Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + title, + fixedText(msg, + fontSize: 11, color: Colors.white70) + ], + ) + : title + ], + ), + ), + Container( + height: 20, + width: double.infinity, + color: Colors.white, + alignment: Alignment.centerLeft, + padding: EdgeInsets.only(left: 20), + child: fixedText(I18n.of(context).red_money, + fontSize: 10, color: Constants.GreyTextColor), + ) + ], + ), + )), + onTap: () { + print('点击红包'); + AppNavigator.pushCoinBagInfoPage(context, widget.msgModel, titleStr); + }, + ); + } +} diff --git a/lib/chat/translate_state.dart b/lib/chat/translate_state.dart new file mode 100644 index 0000000..cad1afd --- /dev/null +++ b/lib/chat/translate_state.dart @@ -0,0 +1,130 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:chat/proto/all.pbserver.dart'; + +// class TranslateState { +// static const int NoPerson = 0; //没有翻译人员在线 +// static const int SameLan = 1; //同一语言 + +// static const int Unopen = 2; //没有开启人工翻译 +// static const int Opend = 3; //已经开启人工翻译 +// } + +class TranslateSateWidget extends StatefulWidget { + final int friendId; + TranslateSateWidget({this.friendId}); + @override + _TranslateSateWidgetState createState() => _TranslateSateWidgetState(); +} + +class _TranslateSateWidgetState extends State { + //翻译相关 + + TranslateState translateStatus = TranslateState.SameLan; + + @override + void initState() { + super.initState(); + + getTranslateState(); + + MessageMgr().on("Update Translate State", updateTranslateState); + } + + @override + void dispose() { + MessageMgr().off("Update Translate State", updateTranslateState); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + Color transColor = Colors.grey; + if (translateStatus == TranslateState.Opend) { + transColor = Constants.ConfrimButtonColor; + } else if (translateStatus == TranslateState.Unopen) { + transColor = Constants.BlackTextColor; + } + + bool switchTrans = translateStatus == TranslateState.Unopen || + translateStatus == TranslateState.Opend; + if (!switchTrans) { + return Container(); + } + return Center( + child: InkWell( + child: Container( + decoration: BoxDecoration( + border: Border.all(color: transColor), + borderRadius: BorderRadius.circular(3), + ), + padding: EdgeInsets.symmetric(horizontal: 7, vertical: 2), + child: fixedText(I18n.of(context).translate, + fontSize: 11, color: transColor)), + onTap: () async { + if (UserData().isSuperVip) { + print('开启/关闭人工翻译'); + switchTranslateState(); + } else { + showToast(I18n.of(context).need_svip); + } + })); + } + + //更改人工翻译状态 + switchTranslateState() async { + TranslateState newState; + if (translateStatus == TranslateState.Opend) { + newState = TranslateState.Unopen; + } else { + newState = TranslateState.Opend; + } + bool res = await HttpUtil().updateTranslateState( + widget.friendId, newState == TranslateState.Opend); + if (res) { + translateStatus = newState; + if (mounted) { + setState(() {}); + } + MsgHandler.swtichTranslateState(newState); + } + } + + updateTranslateState(transArgs) { + print('切换人工翻译'); + + if (transArgs.hTransl == TranslateState.Opend && + translateStatus != transArgs.hTransl) { + showToast(I18n.of(context).translate_on); + } else if (transArgs.hTransl == TranslateState.Unopen) { + //showToast(I18n.of(context).translate_off); + } + translateStatus = transArgs.hTransl; + if (mounted) { + setState(() {}); + } + } + + //获取人工翻译的状态 + Future getTranslateState() async { + print('~~~~~~~~~~~获取聊天翻译状态~~~~~~~~~~~~~~'); + Map tranObj = await HttpUtil().getTranslateState(widget.friendId); + if (tranObj != null) { + int status = tranObj['status']; + + translateStatus = TranslateState.valueOf(status); + //同步双方翻译状态 + MsgHandler.swtichTranslateState(translateStatus); + if (mounted) { + setState(() {}); + } + } + } +} diff --git a/lib/chat/upload_item.dart b/lib/chat/upload_item.dart new file mode 100644 index 0000000..8f5cc12 --- /dev/null +++ b/lib/chat/upload_item.dart @@ -0,0 +1,129 @@ +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sql_util.dart'; +import 'package:chat/utils/upload_util.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:percent_indicator/percent_indicator.dart'; + +class UploadImgItem extends StatefulWidget { + final MsgModel msg; + final Widget child; + final bool isShowProgress; + final CancelToken cancelToken; + + UploadImgItem( + {this.msg, this.child, this.isShowProgress = true, this.cancelToken}); + + @override + _UploadItemState createState() => _UploadItemState(); +} + +class _UploadItemState extends State { + double percent = 0; + + @override + void initState() { + super.initState(); + MsgModel msg = widget.msg; + + if (msg.localFile != null && msg.state == MsgState.None) { + //需要上传 + uploadImg(); + } + + MessageMgr().on('ReUpload Msg', reUpload); + } + + @override + void dispose() { + MessageMgr().off('ReUpload Msg', reUpload); + + super.dispose(); + } + + reUpload(args) { + if (args == widget.msg) { + print('重新上传'); + uploadImg(); + } + } + + uploadImg() async { + if (widget.msg.state == MsgState.Uploading || + widget.msg.state == MsgState.Uploaded) { + return; + } + + widget.msg.state = MsgState.Uploading; + await UploadUtil().uploadFile(widget.msg, cancelToken: widget.cancelToken); + + if (mounted) { + this.setState(() {}); + } + + SqlUtil().updateMsgState( + widget.msg.sessionId, widget.msg.time, widget.msg.state); + } + + uploadWidget() { + if (widget.msg.state == MsgState.Uploading && widget.isShowProgress) { + return StreamBuilder( + stream: UploadUtil().getStream(widget.msg.extraFile).stream, + initialData: UploadUtil().streamLastPercentMap[widget.msg.extraFile], + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.data != null) { + if (snapshot.data >= 1) { + return SizedBox(width: 0, height: 0); + } + + return CircularPercentIndicator( + radius: 30.0, + lineWidth: 2.0, + percent: snapshot.data, + center: Padding( + padding: EdgeInsets.all(2), + child: fixedText( + "${(snapshot.data * 100).toStringAsFixed(0)}%", + fontSize: 9, + color: Colors.green)), + progressColor: Colors.green, + ); + } else { + return SizedBox(width: 0, height: 0); + } + }, + ); + } else if (widget.msg.state == MsgState.UploadFailed) { + //声音重传按钮叠加比较丑,和发送失败一起处理 + if (widget.msg.msgType == ChatType.ShortVoiceChatType.value) { + return SizedBox(width: 0, height: 0); + } + return InkWell( + onTap: uploadImg, + child: Container( + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.grey.withAlpha(150), + borderRadius: BorderRadius.circular(8)), + child: Icon(Icons.rotate_right, color: Colors.white70), + ), + ); + } else if (widget.msg.msgType == ChatType.ShortVideoChatType.value && + widget.msg.state >= MsgState.Uploaded) { + return Icon(Icons.play_circle_outline, color: Colors.white); + } else { + return SizedBox(width: 0, height: 0); + } + } + + @override + Widget build(BuildContext context) { + return Stack( + alignment: Alignment.center, + children: [widget.child, uploadWidget()], + ); + } +} diff --git a/lib/chat/util_keyboard.dart b/lib/chat/util_keyboard.dart new file mode 100644 index 0000000..81dc032 --- /dev/null +++ b/lib/chat/util_keyboard.dart @@ -0,0 +1,420 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:chat/chat/gift_select_widget.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/VipPage.dart'; +import 'package:chat/map/google_map_location_picker.dart'; +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/ChargeMoney.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/blacklist_mgr.dart'; +import 'package:chat/utils/image_util.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_image_compress/flutter_image_compress.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:provider/provider.dart'; +import 'package:video_thumbnail/video_thumbnail.dart'; +import 'package:file_picker/file_picker.dart'; + +import '../r.dart'; + + +class UtilKeyboard extends StatelessWidget { + final double keyboardHeight; + final Function sendMsg; + final bool isGroup; + UtilKeyboard({this.keyboardHeight, this.sendMsg, this.isGroup}); + + bool isAuthority = false; + + @override + Widget build(BuildContext context) { + bool isShowRedPacket = UserData().redPacketSW > 0; + + List iconList = []; + iconList.add( + _buildOtherSelect(R.assetsImagesChatItem1, I18n.of(context).camera, () { + print('开始选择拍照'); + _sendPicture(context); + })); + + iconList.add( + _buildOtherSelect(R.assetsImagesChatItem2, I18n.of(context).video, () { + print('开始选择视频'); + _sendVideo(context); + })); + + if (!isGroup) { + iconList.add( + _buildOtherSelect(R.assetsImagesChatItem3, I18n.of(context).chat, () { + _audioChat(context); + })); + } + + iconList.add( + _buildOtherSelect(R.assetsImagesChatItem4, I18n.of(context).locate, () { + _openMap(context); + })); + + if (!isGroup) { + iconList.add(Offstage( + offstage: !isShowRedPacket, + child: _buildOtherSelect( + R.assetsImagesChatItem5, I18n.of(context).red_money, () { + AppNavigator.pushCoinBagPage(context); + }))); + + iconList.add(_buildOtherSelect( + R.assetsImagesChatItem6, I18n.of(context).giving_gift, () { + _showGiftSheet(context); + })); + } + + iconList.add(_buildOtherSelect(R.assetsImagesChatItem7, '文件', () async { + _sendFile(context); + })); + + return Container( + width: Screen.width, + color: Colors.white, + height: keyboardHeight, + padding: EdgeInsets.only(top: 20, bottom: 10, left: 20), + alignment: Alignment.topLeft, + child: Wrap(spacing: 10.0, runSpacing: 20.0, children: iconList)); + } + + _showGiftSheet(BuildContext context) { + int friendId = 0; + if (!isGroup) { + friendId = Provider.of(context); + } + + showModalBottomSheet( + context: context, + elevation: 2.0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), topRight: Radius.circular(20))), + backgroundColor: Colors.transparent, + builder: (BuildContext context) { + return StatefulBuilder( + builder: (BuildContext context, setBottomSheetState) { + return GiftSelectWidget(friendId, sendMsg); + }, + ); + }); + } + + _openMap(BuildContext context) async { + if (await CustomUI.showPermissionSetting( + context, PermissionGroup.location, I18n.of(context).open_location)) { + var result = await LocationPicker.pickLocation( + context, 'AIzaSyAb9JNtW0BEZ_qLeDg87ZhvxSmZply-7hU', + initialCenter: LatLng(UserData().latitude, UserData().longitude)); + + if (result == null || + result.address == null || + result.address.length == 0) { + return; + } + + var reslutStr = jsonEncode(result); + + int friendId = 0; + if (!isGroup) { + friendId = Provider.of(context); + } + var msg = MsgHandler.createSendMsg( + ChatType.PlaceChatType, utf8.encode(reslutStr), + friendId: friendId, + channelType: + isGroup ? ChatChannelType.Group : ChatChannelType.Session); + + sendMsg(msg); + } + } + + _audioChat(BuildContext context) async { + if (await CustomUI.showPermissionSetting(context, + PermissionGroup.microphone, I18n.of(context).video_permission)) { + int friendId = Provider.of(context); + UserInfo info = await HttpUtil().getFriendInfo(friendId, true); + + if (info == null) { + print('获取用户信息失败'); + return; + } + + if (info.chatStatus == 0) { + showToast(I18n.of(context).cantt_voice); + return; + } + + if (BlacklistMgr.isBlaklistMe(info.userId)) { + showToast(I18n.of(context).you_are_blaklisted); + return; + } + + if (BlacklistMgr.isInMyblaklist(info.userId)) { + showToast(I18n.of(context).reject_message); + return; + } + + //对方关闭陌生人消息,则提示 + if (!info.isCanStrangerNews) { + showToast(I18n.of(context).stranger_close_tips); + return; + } + + if (info.isAuthority || + (!UserData().isMan() && UserData().basicInfo.isAttestation) || + info.distince < 200) { + isAuthority = true; + } + becomeVip() { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return VipPage(); + }, + ), + ); + } + + payCallback() { + if (Provider.of(context).money < + UserData().accountPrice) { + Navigator.of(context).pop(); + CustomUI.buildOneConfirm( + context, + I18n.of(context).balance_insufficien, + I18n.of(context).recharge, () { + Navigator.of(context).pop(); + ChargeMoney.showChargeSheet(context, () {}); + }); + return; + } + Navigator.of(context).pop(); + HttpUtil().buyChatAccount(UserData().accountPrice, info.userId, context, + () { + isAuthority = true; + }); + } + + freeTime() { + HttpUtil().userFreeTime(context, info.userId, 2, () { + UserData().basicInfo.usedNum++; + Navigator.of(context).pop(); + isAuthority = true; + }); + } + + if (!isAuthority) { + if (UserData().isVip) { + UserData().basicInfo.freeNum < UserData().basicInfo.usedNum + ? CustomUI.buildOneConfirm( + context, + I18n.of(context).unlock_information, + I18n.of(context) + .pay_unlock + .replaceFirst('/s1', UserData().accountPrice.toString()), + payCallback) + : CustomUI.buildOneConfirm( + context, + I18n.of(context).unlock_information, + I18n.of(context).unlock_choose, + freeTime, + ); + } else { + CustomUI.buildTowConfirm( + context, + I18n.of(context).unlock_information, + I18n.of(context).become_member, + becomeVip, + I18n.of(context) + .pay_unlock + .replaceFirst('/s1', UserData().accountPrice.toString()), + payCallback); + } + return; + } + AppNavigator.pushAudioChatPage(context, info); + } + } + + void _sendPicture(BuildContext context) async { + if (await CustomUI.showPermissionSetting( + context, PermissionGroup.camera, I18n.of(context).camera_permission)) { + File imgFile = await ImagePicker.pickImage(source: ImageSource.camera); + + if (imgFile == null) { + return; + } + var imgSize = await imgFile.length(); + + print('图片大小:${imgSize / 1024}KB'); + var sendImg; + + bool isNeedUpload = false; + if (imgSize > ImgSizeLimit) { + print('图片大于 $ImgSizeLimit,压缩'); + //发送压缩图 + sendImg = await WidgetUtil.getCompressImg(imgFile.absolute.path); + isNeedUpload = true; + } else { + sendImg = imgFile.readAsBytesSync().toList(); + } + + var rect = await WidgetUtil.getImageWH( + image: Image.memory(Uint8List.fromList(sendImg))); + + int aspectRatio = rect.width * 100 ~/ rect.height; + + int friendId = 0; + if (!isGroup) { + friendId = Provider.of(context); + } + var msg = MsgHandler.createSendMsg(ChatType.ImageChatType, sendImg, + extra: aspectRatio, + friendId: friendId, + localFile: isNeedUpload ? imgFile.absolute.path : null, + channelType: + isGroup ? ChatChannelType.Group : ChatChannelType.Session); + + sendMsg(msg); + } + } + + void _sendFile(BuildContext context) async { + File file = await FilePicker.getFile(); + int fileSize = file.lengthSync(); + print('选择的文件 ${file.path} 大小 $fileSize'); + + if (fileSize > 33 * 1024 * 1024) { + showToast('文件大于33M'); + return; + } + + int friendId = 0; + if (!isGroup) { + friendId = Provider.of(context); + } + + var fileName = file.path.split('/').last; + print('fileName $fileName'); + + var ext = ''; + var extList = fileName.split('.'); + if (extList.length > 1) { + ext = extList.last; + } + print('ext $ext'); + + var fileMsg = FileChat.create(); + fileMsg.type = ext; + fileMsg.size = fileSize; + fileMsg.name = fileName; + + var msg = MsgHandler.createSendMsg( + ChatType.FileChatType, fileMsg.writeToBuffer(), + friendId: friendId, + localFile: file.path, + channelType: isGroup ? ChatChannelType.Group : ChatChannelType.Session); + + sendMsg(msg); + } + + void _sendVideo(BuildContext context) async { + if (await CustomUI.showPhotoPermissionSetting(context)) { + File video = await ImagePicker.pickVideo(source: ImageSource.gallery); + + if (video == null) { + return; + } + var videoSize = await video.length(); + print('视频大小:$videoSize'); + + if (videoSize > 33 * 1024 * 1024) { + showToast(I18n.of(LoadingManage.context).video_more_big); + return; + } + + final thumbnail = await getVideoThumbnail(video); + + var rect = await WidgetUtil.getImageWH( + image: Image.memory(Uint8List.fromList(thumbnail))); + + int aspectRatio = rect.width * 100 ~/ rect.height; + + int friendId = 0; + if (!isGroup) { + friendId = Provider.of(context); + } + var msg = MsgHandler.createSendMsg(ChatType.ShortVideoChatType, thumbnail, + extra: aspectRatio, + friendId: friendId, + localFile: video.path, + channelType: + isGroup ? ChatChannelType.Group : ChatChannelType.Session); + + sendMsg(msg); + } + } + + getVideoThumbnail(File video) async { + List thumbnail = await VideoThumbnail.thumbnailData( + imageFormat: ImageFormat.JPEG, + video: video.path, + quality: 20, + ); + + if (thumbnail.length > ImgSizeLimit) { + print('图片较大 ${thumbnail.length}'); + thumbnail = + await FlutterImageCompress.compressWithList(thumbnail, quality: 10); + + print('压缩后 ${thumbnail.length}'); + } + + return thumbnail; + } +} + +Widget _buildOtherSelect(String imgPath, String title, VoidCallback onTap) { + var imgWidth = Screen.width / 4 - 20; + return InkWell( + child: Container( + width: imgWidth, + child: Column( + children: [ + SizedBox( + child: Image.asset(imgPath, fit: BoxFit.contain), + width: 40, + height: 40, + ), + SizedBox(height: 5), + Text(title, + maxLines: 1, + overflow: TextOverflow.ellipsis, + textScaleFactor: 1.0, + style: TextStyle(color: Color(0xFF090909), fontSize: 12)) + ], + ), + ), + onTap: onTap, + ); +} diff --git a/lib/chat/video_view.dart b/lib/chat/video_view.dart new file mode 100644 index 0000000..b1ec387 --- /dev/null +++ b/lib/chat/video_view.dart @@ -0,0 +1,45 @@ +import 'package:chat/utils/controller_widget_builder.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_ijkplayer/flutter_ijkplayer.dart'; + +class VideoPage extends StatefulWidget { + final String videoPath; + VideoPage({this.videoPath}); + @override + _VideoPageState createState() => _VideoPageState(); +} + +class _VideoPageState extends State { + + IjkMediaController controller = IjkMediaController(); + bool hideMenu = true; + + @override + void initState() { + super.initState(); + + WidgetsBinding.instance.addPostFrameCallback((_) { + controller.setNetworkDataSource(widget.videoPath, autoPlay: true); + }); + } + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + Widget build(BuildContext context) { + return Container( + // height: 400, // 这里随意 + child: IjkPlayer( + controllerWidgetBuilder: (ctl) { + return MyDefaultIJKControllerWidget( + ///按钮修改 + controller: ctl, + ); + }, + mediaController: controller, + )); + } +} diff --git a/lib/data/UserData.dart b/lib/data/UserData.dart new file mode 100644 index 0000000..9980c40 --- /dev/null +++ b/lib/data/UserData.dart @@ -0,0 +1,237 @@ +import 'dart:convert'; + +import 'package:amap_location/amap_location.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:crclib/crclib.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../models/UserInfo.dart'; + +class UserData { + //私有构造函数 + UserData._internal(); + + //保存单例 + static UserData _singleton = new UserData._internal(); + + //工厂构造函数 + factory UserData() => _singleton; + + int language = 0; + int deviceLanguage = 0; + double latitude = 10.7517368433358; + double longitude = 106.600798525456; + UserInfo basicInfo = new UserInfo(); + int totalMoney = 0; //用户总金额 + String bindCardId = ''; + bool isCanProgram = true; //用户能否发约会节目 + int picNum = 0; //用户相册的数量 + int incomeMoney = 0; //用户收入金额 + int frozenMoney = 0; //用户冻结金额 + bool isFirstTip = false; //第一次进来提示完善资料 + int mobile = 0; //是否绑定手机号 + int freeNum = 0; //免费次数 + int usedNum = 0; //使用的次数 + bool haveReview = false; //有照片在审核 + String memberEndTime = ''; //会员到期时间 + bool hasLocationPermission = false; //是否有定位权限 + bool isBannerStatus = false; //是否支付状态 + int agentId = 0; //代理id + int redPacketSW = 0; //红包开关 + int giftSwitch = 0; //打赏礼物开关 + int bannerZF = 0; //苹果内购开关 + int sign = 0; //签到开关 + int groupQRCode = 0; //群二维码开关 + int addFdDistanceSwitch = 0; //二维码加好友距离判断开关 + int inviteCodePrice = 0; //绑定邀请码奖励 + int accountPrice = 0; //解锁账号金额 + int redPhotoPrice = 0; //红包照片金额 + int addProgramPrice = 120; //发布节目金额 + double keyboardHeight = 0; //缓存键盘高度 + bool privatyMsgPushSwitch = true; //私人消息推送开关 + bool needRequestPushPermission = false; //是否需要推送权限 + bool newDateSwitch = false; //有新约会提醒开关 + bool applyCheckSwitch = false; //查看资料提醒开关 + bool acceptCheckSwitch = false; //通过查看资料提醒开关 + bool checkPhotoSwitch = false; //查看红包照片提醒开关 + bool codeSucessSwitch = false; //邀请码申请成功提醒开关 + bool stationOpenSwitch = true; //开启电台开关 + bool myProgramOpenSwitch = true; //我的节目开关 + bool nearbyOpenSwitch = true; //附近的人开关 + List contactList = []; + bool isInChina = false; + int homemainIndex = 0; + String currentCity = ''; + + Map toJson() { + Map json = new Map(); + json['language'] = language; + json['deviceLanguage'] = deviceLanguage; + json['latitude'] = latitude; + json['longitude'] = longitude; + json['basicInfo'] = jsonEncode(basicInfo).toString(); + json['totalMoney'] = totalMoney; + json['bindCardId'] = bindCardId; + json['isCanProgram'] = isCanProgram; + json['picNum'] = picNum; + json['incomeMoney'] = incomeMoney; + json['frozenMoney'] = frozenMoney; + json['isFirstTip'] = isFirstTip; + json['mobile'] = mobile; + json['freeNum'] = freeNum; + json['usedNum'] = usedNum; + json['haveReview'] = haveReview; + json['memberEndTime'] = memberEndTime; + json['isBannerStatus'] = isBannerStatus; + json['agentId'] = agentId; + json['redPacketSW'] = redPacketSW; + json['giftSwitch'] = giftSwitch; + json['bannerZF'] = bannerZF; + json['sign'] = sign; + json['groupQRCode'] = groupQRCode; + json['addFdDistanceSwitch'] = addFdDistanceSwitch; + json['inviteCodePrice'] = inviteCodePrice; + json['accountPrice'] = accountPrice; + json['redPhotoPrice'] = redPhotoPrice; + json['addProgramPrice'] = addProgramPrice; + json['keyboardHeight'] = keyboardHeight; + json['privatyMsgPushSwitch'] = privatyMsgPushSwitch; + json['needRequestPushPermission'] = needRequestPushPermission; + json['newDateSwitch'] = newDateSwitch; + json['applyCheckSwitch'] = applyCheckSwitch; + json['acceptCheckSwitch'] = acceptCheckSwitch; + json['checkPhotoSwitch'] = checkPhotoSwitch; + json['codeSucessSwitch'] = codeSucessSwitch; + json['stationOpenSwitch'] = stationOpenSwitch; + json['myProgramOpenSwitch'] = myProgramOpenSwitch; + json['nearbyOpenSwitch'] = nearbyOpenSwitch; + json['isInChina'] = isInChina; + return json; + } + + fromLocalJson(Map data) { + language = data['language']; + deviceLanguage = data['deviceLanguage']; + latitude = data['latitude']; + longitude = data['longitude']; + basicInfo = UserInfo.fromLocalJson(json.decode(data['basicInfo'])); + totalMoney = data['totalMoney']; + bindCardId = data['bindCardId']; + isCanProgram = data['isCanProgram']; + picNum = data['picNum']; + incomeMoney = data['incomeMoney']; + frozenMoney = data['frozenMoney']; + isFirstTip = data['isFirstTip']; + mobile = data['mobile']; + freeNum = data['freeNum']; + usedNum = data['usedNum']; + haveReview = data['haveReview']; + memberEndTime = data['memberEndTime']; + isBannerStatus = data['isBannerStatus']; + agentId = data['agentId']; + redPacketSW = data['redPacketSW']; + giftSwitch = data['giftSwitch']; + bannerZF = data['bannerZF']; + sign = data['sign']; + groupQRCode = data['groupQRCode']; + addFdDistanceSwitch = data['addFdDistanceSwitch']; + inviteCodePrice = data['inviteCodePrice']; + accountPrice = data['accountPrice']; + redPhotoPrice = data['redPhotoPrice']; + addProgramPrice = data['addProgramPrice']; + keyboardHeight = data['keyboardHeight']; + privatyMsgPushSwitch = data['privatyMsgPushSwitch']; + needRequestPushPermission = data['needRequestPushPermission']; + newDateSwitch = data['newDateSwitch']; + applyCheckSwitch = data['applyCheckSwitch']; + acceptCheckSwitch = data['acceptCheckSwitch']; + checkPhotoSwitch = data['checkPhotoSwitch']; + codeSucessSwitch = data['codeSucessSwitch']; + stationOpenSwitch = data['stationOpenSwitch']; + myProgramOpenSwitch = data['myProgramOpenSwitch']; + nearbyOpenSwitch = data['nearbyOpenSwitch']; + isInChina = data['isInChina']; + } + + bool isMan() { + return UserData().basicInfo.sex == 1; + } + + setKeyboardHeight(double newHeight) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + var oldHeight = prefs.getDouble(Constants.KeyboardHeight); + if (oldHeight != newHeight) { + prefs.setDouble(Constants.KeyboardHeight, newHeight); + } + } + + getValidHCoin() { + return incomeMoney - frozenMoney; + } + + bool get isSuperVip { + return basicInfo.isMember == 2; + } + + bool get isVip { + return basicInfo.isMember > 0; + } + + int getSessionId(int friendId) { + var myId = basicInfo.userId; + var idStr = myId > friendId + ? friendId.toString() + myId.toString() + : myId.toString() + friendId.toString(); + + return Crc32Zlib().convert(utf8.encode(idStr)); + } + + reset() { + basicInfo = new UserInfo(); + bindCardId = ''; + isCanProgram = true; //用户能否发约会节目 + picNum = 0; //用户相册的数量 + incomeMoney = 0; //用户收入金额 + frozenMoney = 0; + + isFirstTip = false; //第一次进来提示完善资料 + mobile = 0; //是否绑定手机号 + freeNum = 0; //免费次数 + usedNum = 0; //使用的次数 + haveReview = false; //有照片在审核 + memberEndTime = ''; + agentId = 0; + isBannerStatus = false; + homemainIndex = 0; + } + + getCurrentPosition({callback}) async { + //使用高德定位 + var loc = await AMapLocationClient.getLocation(false); + + if (loc != null && loc.latitude != null && loc.longitude != null) { + UserData().latitude = loc.latitude; + UserData().longitude = loc.longitude; + + SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.setDouble(Constants.Latitude, UserData().latitude); + await prefs.setDouble(Constants.Longitude, UserData().longitude); + HttpUtil().getAddress(loc.longitude, loc.latitude); + //HttpUtil().getAddress(106.600798525456, 10.7517368433358); + //HttpUtil().getAddress(113.8669580078125, 22.568465711805555); + if (callback != null) callback(loc); + } + } + + getCurrentCityKey() { + if (UserData().basicInfo.meetPlace == null || + UserData().basicInfo.meetPlace == "") return 'HoChiMinhCIty'; + var list = UserData().basicInfo.meetPlace.split('-'); + if (list.length == 2) { + return list[1]; + } else { + return 'HoChiMinhCIty'; + } + } +} diff --git a/lib/data/WebData.dart b/lib/data/WebData.dart new file mode 100644 index 0000000..9fdd110 --- /dev/null +++ b/lib/data/WebData.dart @@ -0,0 +1,6193 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:flutter/widgets.dart'; + +import '../data/UserData.dart'; +import '../utils/TokenMgr.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:dio/dio.dart'; + +enum PhotoType { + free, + destroy, + money, + destroyMoney, +} + +Map phone = { + "+86": "86", + "+84": "84", +}; + +var constData = [ + { + 'program': [ + {"Key": "Motion", "Value": "Motion", "PageKey": 0, "List": []}, + {"Key": "Party", "Value": "Party", "PageKey": 0, "List": []}, + {"Key": "Foodie", "Value": "Foodie", "PageKey": 0, "List": []}, + {"Key": "Movie", "Value": "WatchMovie", "PageKey": 0, "List": []}, + {"Key": "Game", "Value": "Game", "PageKey": 0, "List": []}, + {"Key": "Travel", "Value": "CompanionTravel", "PageKey": 0, "List": []}, + {"Key": "Chat", "Value": "LianmaiChats", "PageKey": 0, "List": []}, + {"Key": "Other", "Value": "Other", "PageKey": 0, "List": []} + ], + 'lovePeople': [ + {"Key": "Face", "Value": "LookFace", "PageKey": 0, "List": []}, + {"Key": "Interesting", "Value": "Interesting", "PageKey": 0, "List": []}, + {"Key": "LocalTyrant", "Value": "LocalTyrant", "PageKey": 0, "List": []}, + {"Key": "Love", "Value": "LoveMe", "PageKey": 0, "List": []}, + {"Key": "Feel", "Value": "LookFeeling", "PageKey": 0, "List": []}, + {"Key": "Indifferent", "Value": "Indifferent", "PageKey": 0, "List": []} + ], + 'job': [ + { + "Key": "Information", + "Value": "InformationTechnology", + "PageKey": 0, + "List": [ + { + "Key": "Internet", + "Value": "Internet", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "IT", + "Value": "IT", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Operate", + "Value": "TelecomOperation", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "NetworkGame", + "Value": "NetworkGame", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Communication", + "Value": "Communication", + "PageKey": 0, + "ParentKey": "Information" + } + ] + }, + { + "Key": "Financial", + "Value": "FinancialInsurance", + "PageKey": 0, + "List": [ + { + "Key": "Investment", + "Value": "Investment", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "StockFund", + "Value": "StockFund", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Insurance", + "Value": "Insurance", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Bank", + "Value": "Bank", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "TrustGuarantee", + "Value": "TrustGuarantee", + "PageKey": 0, + "ParentKey": "Financial" + } + ] + }, + { + "Key": "CommercialServices", + "Value": "CommercialServices", + "PageKey": 0, + "List": [ + { + "Key": "Consultation", + "Value": "Consultation", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Individual", + "Value": "IndividualManagement", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Cosmetology", + "Value": "BeautyAndHairdressing", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Decoration", + "Value": "Decoration", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Detective", + "Value": "Detective", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "EstateManagement", + "Value": "EstateManagement", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "RealEstate", + "Value": "RealEstate", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Car", + "Value": "Car", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Trade", + "Value": "Trade", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "LeisureTime", + "Value": "Recreation", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "HotelCatering", + "Value": "HotelCatering", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Travel", + "Value": "Travel", + "PageKey": 0, + "ParentKey": "CommercialServices" + } + ] + }, + { + "Key": "Make", + "Value": "EngineeringManufacturing", + "PageKey": 0, + "List": [ + { + "Key": "Architecture", + "Value": "Architecture", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "CivilEngineering", + "Value": "CivilEngineering", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Mechanics", + "Value": "MachineryManufacturing", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Energy", + "Value": "\r\nEnergy", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Clothing", + "Value": "Clothing", + "PageKey": 0, + "ParentKey": "Make" + }, + {"Key": "Food", "Value": "Food", "PageKey": 0, "ParentKey": "Make"}, + { + "Key": "Biomedicine", + "Value": "BiomedicalScience", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Electronics", + "Value": "Electronics", + "PageKey": 0, + "ParentKey": "Make" + } + ] + }, + { + "Key": "Transportation", + "Value": "Traffic", + "PageKey": 0, + "List": [ + { + "Key": "Aviation", + "Value": "Aviation", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Railway", + "Value": "Railway", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Logistics", + "Value": "LogisticsTransportation", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Traffic", + "Value": "MassTransit", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "ShippingShips", + "Value": "ShippingShips", + "PageKey": 0, + "ParentKey": "Transportation" + } + ] + }, + { + "Key": "CulturalMedia", + "Value": "CulturalMedia", + "PageKey": 0, + "List": [ + { + "Key": "MediaPublishing", + "Value": "MediaPublishing", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Photography", + "Value": "Photography", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Exhibition", + "Value": "PublicRelationsExhibition", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Comic", + "Value": "Comic", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Originality", + "Value": "AdvertisingCreativity", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Spread", + "Value": "CulturalCommunication", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Design", + "Value": "Design", + "PageKey": 0, + "ParentKey": "CulturalMedia" + } + ] + }, + { + "Key": "EntertainmentSports", + "Value": "EntertainmentSports", + "PageKey": 0, + "List": [ + { + "Key": "Model", + "Value": "Model", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Music", + "Value": "Music", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "SportsSports", + "Value": "SportsSports", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Movies", + "Value": "Movies", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + } + ] + }, + { + "Key": "PublicUtilities", + "Value": "PublicUtilities", + "PageKey": 0, + "List": [ + { + "Key": "PublicWelfare", + "Value": "PublicWelfare", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Speak", + "Value": "Research", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "GovernmentOrgans", + "Value": "GovernmentOrgans", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Education", + "Value": "Education", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Law", + "Value": "Law", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "MedicalCare", + "Value": "MedicalCare", + "PageKey": 0, + "ParentKey": "PublicUtilities" + } + ] + }, + { + "Key": "Student", + "Value": "Student", + "PageKey": 0, + "List": [ + { + "Key": "PuPils", + "Value": "Student", + "PageKey": 0, + "ParentKey": "Student" + } + ] + }, + { + "Key": "Nothing", + "Value": "Nothing", + "PageKey": 0, + "List": [ + { + "Key": "NotHave", + "Value": "Nothing", + "PageKey": 0, + "ParentKey": "Nothing" + } + ] + } + ], + 'city': [ + { + "Key": "VietNam", + "Value": "VietNam", + "PageKey": 0, + "List": [ + { + "Key": "AnGiang", + "Value": "AnGiang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacGiang", + "Value": "BacGiang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacCan", + "Value": "BacCan", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacLieu", + "Value": "BacLieu", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BeiNing", + "Value": "BeiNing", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BaRiaVungTau", + "Value": "BaRiaVungTau", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BenTre", + "Value": "BenTre", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BinhDinh", + "Value": "BinhDinh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingYang", + "Value": "PingYang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingFu", + "Value": "PingFu", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaMau", + "Value": "CaMau", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaoBang", + "Value": "CaoBang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DeLe", + "Value": "DeLe", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DeNong", + "Value": "DeNong", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DienBien", + "Value": "DienBien", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongNai", + "Value": "DongNai", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongThap", + "Value": "DongThap", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "GiaLai", + "Value": "GiaLai", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaGiang", + "Value": "HaGiang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaiDuang", + "Value": "HaiDuang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Henan", + "Value": "Henan", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaTinh", + "Value": "HaTinh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HoaBinh", + "Value": "HoaBinh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HouJiang", + "Value": "HouJiang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Xingan", + "Value": "Xingan", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KhanhHo", + "Value": "KhanhHo", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "JianJiang", + "Value": "JianJiang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KonTum", + "Value": "KonTum", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaiChua", + "Value": "LaiChua", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LamDong", + "Value": "LamDong", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LangSon", + "Value": "LangSon", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaoCai", + "Value": "LaoCai", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LongAn", + "Value": "LongAn", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NamDinh", + "Value": "NamDinh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NgheAn", + "Value": "NgheAn", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "FuShou", + "Value": "FuShou", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PhuYen", + "Value": "PhuYen", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangBinh", + "Value": "QuangBinh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNam", + "Value": "QuangNam", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNgai", + "Value": "QuangNgai", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNinh", + "Value": "QuangNinh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangTri", + "Value": "QuangTri", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "SocTrang", + "Value": "SocTrang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "SonLa", + "Value": "SonLa", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TayNinh", + "Value": "TayNinh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiBinh", + "Value": "ThaiBinh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiNguyen", + "Value": "ThaiNguyen", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThanhHoa", + "Value": "ThanhHoa", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThuaThienHue", + "Value": "ThuaThienHue", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TraVinh", + "Value": "TraVinh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TuyenQuang", + "Value": "TuyenQuang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhLon", + "Value": "VinhLon", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhPhu", + "Value": "VinhPhu", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "YenBai", + "Value": "YenBai", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaoTho", + "Value": "CaoTho", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DaNang", + "Value": "DaNang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Haiphong", + "Value": "Haiphong", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Hanoi", + "Value": "Hanoi", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HoChiMinhCIty", + "Value": "HoChiMinhCIty", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingShun", + "Value": "NingShun", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NinhThuan", + "Value": "NinhThuan", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingPing", + "Value": "NingPing", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Qianjiang", + "Value": "Qianjiang", + "PageKey": 0, + "ParentKey": "VietNam" + } + ] + }, + { + "Key": "China", + "Value": "China", + "PageKey": 0, + "List": [ + { + "Key": "ChinaRepeat", + "Value": "China", + "PageKey": 0, + "ParentKey": "China" + } + ] + }, + { + "Key": "UnitedStates", + "Value": "UnitedStates", + "PageKey": 0, + "List": [] + }, + {"Key": "Russia", "Value": "Russia", "PageKey": 0, "List": []}, + {"Key": "Germany", "Value": "Germany", "PageKey": 0, "List": []}, + { + "Key": "UnitedKingdom", + "Value": "UnitedKingdom", + "PageKey": 0, + "List": [] + }, + {"Key": "France", "Value": "France", "PageKey": 0, "List": []}, + {"Key": "Australia", "Value": "Australia", "PageKey": 0, "List": []}, + {"Key": "Japan", "Value": "Japan", "PageKey": 0, "List": []}, + {"Key": "Korea", "Value": "Korea", "PageKey": 0, "List": []}, + {"Key": "Laos", "Value": "Laos", "PageKey": 0, "List": []}, + {"Key": "Cambodia", "Value": "Cambodia", "PageKey": 0, "List": []}, + {"Key": "Myanmar", "Value": "Myanmar", "PageKey": 0, "List": []}, + {"Key": "Thailand", "Value": "Thailand", "PageKey": 0, "List": []}, + {"Key": "Malaysia", "Value": "Malaysia", "PageKey": 0, "List": []}, + {"Key": "Singapore", "Value": "Singapore", "PageKey": 0, "List": []}, + { + "Key": "OtherCountries", + "Value": "OtherCountries", + "PageKey": 0, + "List": [] + } + ] + }, + { + 'program': [ + {"Key": "Motion", "Value": "Luyện tập Y", "PageKey": 0, "List": []}, + {"Key": "Party", "Value": "Tiệc mèo đêm", "PageKey": 0, "List": []}, + {"Key": "Foodie", "Value": "Tôi ăn", "PageKey": 0, "List": []}, + {"Key": "Movie", "Value": "Xem phim", "PageKey": 0, "List": []}, + {"Key": "Game", "Value": "Chơi một trò chơi", "PageKey": 0, "List": []}, + {"Key": "Travel", "Value": "Đi với bạn", "PageKey": 0, "List": []}, + {"Key": "Chat", "Value": "Lianmai trò chuyện", "PageKey": 0, "List": []}, + {"Key": "Other", "Value": "Khác", "PageKey": 0, "List": []} + ], + 'lovePeople': [ + {"Key": "Face", "Value": "Nhìn mặt đi", "PageKey": 0, "List": []}, + {"Key": "Interesting", "Value": "thú vị", "PageKey": 0, "List": []}, + {"Key": "LocalTyrant", "Value": "Lão Sa Đà", "PageKey": 0, "List": []}, + {"Key": "Love", "Value": "Hãy yêu em", "PageKey": 0, "List": []}, + { + "Key": "Feel", + "Value": "Hãy nhìn vào cảm giác", + "PageKey": 0, + "List": [] + }, + {"Key": "Indifferent", "Value": "Khác", "PageKey": 0, "List": []} + ], + 'job': [ + { + "Key": "Information", + "Value": "Công nghệ thông tin", + "PageKey": 0, + "List": [ + { + "Key": "Internet", + "Value": "Internet", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "IT", + "Value": "IT", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Operate", + "Value": "Hoạt động điện thoại", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "NetworkGame", + "Value": "Trò chơi mạng", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Communication", + "Value": "Truyền thông", + "PageKey": 0, + "ParentKey": "Information" + } + ] + }, + { + "Key": "Financial", + "Value": "Công ty bảo hiểm", + "PageKey": 0, + "List": [ + { + "Key": "Investment", + "Value": "Đầu", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "StockFund", + "Value": "Quỹ cổ phiếu", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Insurance", + "Value": "Bảo hiểm", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Bank", + "Value": "Mở", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "TrustGuarantee", + "Value": "Bảo đảm tín dụng", + "PageKey": 0, + "ParentKey": "Financial" + } + ] + }, + { + "Key": "CommercialServices", + "Value": "Dịch vụ kinh doanh", + "PageKey": 0, + "List": [ + { + "Key": "Consultation", + "Value": "Tư vấn", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Individual", + "Value": "Tự làm chủ", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Cosmetology", + "Value": "Thẩm mỹ viện", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Decoration", + "Value": "Cải tạo và trang trí", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Detective", + "Value": "Thám tử.", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "EstateManagement", + "Value": "Quản lý đất", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "RealEstate", + "Value": "Bất động sản", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Car", + "Value": "xe hơi", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Trade", + "Value": "buôn bán", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "LeisureTime", + "Value": "Giải lao", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "HotelCatering", + "Value": "Khách sạn Name", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Travel", + "Value": "chuyến du lịch", + "PageKey": 0, + "ParentKey": "CommercialServices" + } + ] + }, + { + "Key": "Make", + "Value": "Kỹ sư sản xuất", + "PageKey": 0, + "List": [ + { + "Key": "Architecture", + "Value": "Kiến", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "CivilEngineering", + "Value": "Công cụ", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Mechanics", + "Value": "Xưởng sản xuất", + "PageKey": 0, + "ParentKey": "Make" + }, + {"Key": "Energy", "Value": "năng", "PageKey": 0, "ParentKey": "Make"}, + { + "Key": "Clothing", + "Value": "vải", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Food", + "Value": "thức ăn", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Biomedicine", + "Value": "Khoa học sinh", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Electronics", + "Value": "Điện", + "PageKey": 0, + "ParentKey": "Make" + } + ] + }, + { + "Key": "Transportation", + "Value": "Giao thông vận tải", + "PageKey": 0, + "List": [ + { + "Key": "Aviation", + "Value": "hàng không", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Railway", + "Value": "Tuyến", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Logistics", + "Value": "Chuyển hóa", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Traffic", + "Value": "Vận chuyển cộng", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "ShippingShips", + "Value": "Tàu vận tải", + "PageKey": 0, + "ParentKey": "Transportation" + } + ] + }, + { + "Key": "CulturalMedia", + "Value": "Truyền thông văn hóa", + "PageKey": 0, + "List": [ + { + "Key": "MediaPublishing", + "Value": "Nhà xuất bản phương tiện", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Photography", + "Value": "Ảnh", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Exhibition", + "Value": "Hội chợ Quan hệ", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Comic", + "Value": "Truyện", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Originality", + "Value": "Tạo hóa quảng cáo", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Spread", + "Value": "Truyền thuyết văn hóa", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Design", + "Value": "thiết kế", + "PageKey": 0, + "ParentKey": "CulturalMedia" + } + ] + }, + { + "Key": "EntertainmentSports", + "Value": "Thể thao", + "PageKey": 0, + "List": [ + { + "Key": "Model", + "Value": "Mẫu", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Music", + "Value": "Âm", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "SportsSports", + "Value": "Thể thao", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Movies", + "Value": "Phim", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + } + ] + }, + { + "Key": "PublicUtilities", + "Value": "Công ty", + "PageKey": 0, + "List": [ + { + "Key": "PublicWelfare", + "Value": "Phúc lợi xã hội", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Speak", + "Value": "Nghiên cứu khoa học", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "GovernmentOrgans", + "Value": "Nội tạng chính phủ", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Education", + "Value": "giáo dục", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Law", + "Value": "Luật", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "MedicalCare", + "Value": "Y tế", + "PageKey": 0, + "ParentKey": "PublicUtilities" + } + ] + }, + { + "Key": "Student", + "Value": "Học sinh", + "PageKey": 0, + "List": [ + { + "Key": "PuPils", + "Value": "Học sinh", + "PageKey": 0, + "ParentKey": "Student" + } + ] + }, + { + "Key": "Nothing", + "Value": "không", + "PageKey": 0, + "List": [ + { + "Key": "NotHave", + "Value": "không", + "PageKey": 0, + "ParentKey": "Nothing" + } + ] + } + ], + 'city': [ + { + "Key": "VietNam", + "Value": "Việt Nam", + "PageKey": 0, + "List": [ + { + "Key": "AnGiang", + "Value": "An Giang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacGiang", + "Value": "Bắc Giang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacCan", + "Value": "Bắc Cạn", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacLieu", + "Value": "Bạc Liêu", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BeiNing", + "Value": "Bắc Ninh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BaRiaVungTau", + "Value": "Bà Rịa- Vũng Tàu", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BenTre", + "Value": "Bến Tre", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BinhDinh", + "Value": "Bình Định", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingYang", + "Value": "Bình Dương", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingFu", + "Value": "Bình Phước", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaMau", + "Value": "Cà Mau", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaoBang", + "Value": "Cao Bằng", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DeLe", + "Value": "Đà Lạt", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DeNong", + "Value": "Đắc Nông", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DienBien", + "Value": "Điện Biên", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongNai", + "Value": "Đồng Nai", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongThap", + "Value": "Đồng Tháp", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "GiaLai", + "Value": "Gia Lai", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaGiang", + "Value": "Hà Giang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaiDuang", + "Value": "Hải Dương", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Henan", + "Value": "Hà Nam", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaTinh", + "Value": "Hà Tĩnh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HoaBinh", + "Value": "Hòa Bình", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HouJiang", + "Value": "Hậu Giang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Xingan", + "Value": "Hưng Yên", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KhanhHo", + "Value": "Khánh Hòa", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "JianJiang", + "Value": "Kiên Giang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KonTum", + "Value": "Kon Tum", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaiChua", + "Value": "Lai Châu", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LamDong", + "Value": "Lâm Đồng", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LangSon", + "Value": "Lạng Sơn", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaoCai", + "Value": "Lào Cai", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LongAn", + "Value": "Long An", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NamDinh", + "Value": "Nam Định", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NgheAn", + "Value": "Nghệ An", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "FuShou", + "Value": "Phú Thọ", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PhuYen", + "Value": "Phú Yên", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangBinh", + "Value": "Quảng Bình", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNam", + "Value": "Quảng Nam", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNgai", + "Value": "Quảng Ngãi", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNinh", + "Value": "Quảng Ninh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangTri", + "Value": "Quảng Trị", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "SocTrang", + "Value": "Sóc Trăng", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "SonLa", + "Value": "Sơn La", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TayNinh", + "Value": "Tây Ninh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiBinh", + "Value": "Thái Bình", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiNguyen", + "Value": "Thái Nguyên", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThanhHoa", + "Value": "Thanh Hóa", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThuaThienHue", + "Value": "Thừa Thiên- Huế", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TraVinh", + "Value": "Trà Vinh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TuyenQuang", + "Value": "Tuyên Quang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhLon", + "Value": "Vĩnh Long", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhPhu", + "Value": "Vĩnh Phúc", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "YenBai", + "Value": "Yên Bái", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaoTho", + "Value": "Cần Thơ", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DaNang", + "Value": "Đà Nẵng", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Haiphong", + "Value": "Hải Phòng", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Hanoi", + "Value": "Hà Nội", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HoChiMinhCIty", + "Value": "Hồ Chí Minh", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NinhThuan", + "Value": "Bình Thuận", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingShun", + "Value": "Ninh Thuận", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingPing", + "Value": "Ninh Bình", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Qianjiang", + "Value": "Tiền Giang", + "PageKey": 0, + "ParentKey": "VietNam" + } + ] + }, + { + "Key": "China", + "Value": "Trung quốc", + "PageKey": 0, + "List": [ + { + "Key": "ChinaRepeat", + "Value": "Trung quốc", + "PageKey": 0, + "ParentKey": "China" + }, + ] + }, + {"Key": "UnitedStates", "Value": "Hoa Kỳ", "PageKey": 0, "List": []}, + {"Key": "Russia", "Value": "Nga", "PageKey": 0, "List": []}, + {"Key": "Germany", "Value": "Đức", "PageKey": 0, "List": []}, + {"Key": "UnitedKingdom", "Value": "Anh", "PageKey": 0, "List": []}, + {"Key": "France", "Value": "Pháp", "PageKey": 0, "List": []}, + {"Key": "Australia", "Value": "Úc", "PageKey": 0, "List": []}, + {"Key": "Japan", "Value": "Nhật Bản", "PageKey": 0, "List": []}, + {"Key": "Korea", "Value": "Hàn Quốc", "PageKey": 0, "List": []}, + {"Key": "Laos", "Value": "Lào", "PageKey": 0, "List": []}, + {"Key": "Cambodia", "Value": "Campuchia", "PageKey": 0, "List": []}, + {"Key": "Myanmar", "Value": "Myanmar", "PageKey": 0, "List": []}, + {"Key": "Thailand", "Value": "Thái Lan", "PageKey": 0, "List": []}, + {"Key": "Malaysia", "Value": "Malaysia", "PageKey": 0, "List": []}, + {"Key": "Singapore", "Value": "Singapore", "PageKey": 0, "List": []}, + { + "Key": "OtherCountries", + "Value": "Các nước khác", + "PageKey": 0, + "List": [] + } + ] + }, + { + 'program': [ + {"Key": "Motion", "Value": "健康運動", "PageKey": 0, "List": []}, + {"Key": "Party", "Value": "夜蒲聚會", "PageKey": 0, "List": []}, + {"Key": "Foodie", "Value": "我是吃貨", "PageKey": 0, "List": []}, + {"Key": "Movie", "Value": "看電影", "PageKey": 0, "List": []}, + {"Key": "Game", "Value": "玩遊戲", "PageKey": 0, "List": []}, + {"Key": "Travel", "Value": "結伴旅行", "PageKey": 0, "List": []}, + {"Key": "Chat", "Value": "連麥聊天", "PageKey": 0, "List": []}, + {"Key": "Other", "Value": "其他", "PageKey": 0, "List": []} + ], + 'lovePeople': [ + {"Key": "Face", "Value": "看臉", "PageKey": 0, "List": []}, + {"Key": "Interesting", "Value": "有趣", "PageKey": 0, "List": []}, + {"Key": "LocalTyrant", "Value": "土豪", "PageKey": 0, "List": []}, + {"Key": "Love", "Value": "關愛我", "PageKey": 0, "List": []}, + {"Key": "Feel", "Value": "看感覺", "PageKey": 0, "List": []}, + {"Key": "Indifferent", "Value": "無所謂", "PageKey": 0, "List": []} + ], + 'job': [ + { + "Key": "Information", + "Value": "資訊技術", + "PageKey": 0, + "List": [ + { + "Key": "Internet", + "Value": "互聯網", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "IT", + "Value": "IT", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Operate", + "Value": "電信運營", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "NetworkGame", + "Value": "網路遊戲", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Communication", + "Value": "通訊", + "PageKey": 0, + "ParentKey": "Information" + } + ] + }, + { + "Key": "Financial", + "Value": "金融保險", + "PageKey": 0, + "List": [ + { + "Key": "Investment", + "Value": "投資", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "StockFund", + "Value": "股票基金", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Insurance", + "Value": "保險", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Bank", + "Value": "銀行", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "TrustGuarantee", + "Value": "信託擔保", + "PageKey": 0, + "ParentKey": "Financial" + } + ] + }, + { + "Key": "CommercialServices", + "Value": "商業服務", + "PageKey": 0, + "List": [ + { + "Key": "Consultation", + "Value": "諮詢", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Individual", + "Value": "個體經營", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Cosmetology", + "Value": "美容美髮", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Decoration", + "Value": "裝修裝潢", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Detective", + "Value": "偵探", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "EstateManagement", + "Value": "物業管理", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "RealEstate", + "Value": "房地產", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Car", + "Value": "汽車", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Trade", + "Value": "貿易", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "LeisureTime", + "Value": "休閒娛樂", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "HotelCatering", + "Value": "酒店餐飲", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Travel", + "Value": "旅遊", + "PageKey": 0, + "ParentKey": "CommercialServices" + } + ] + }, + { + "Key": "Make", + "Value": "工程製造", + "PageKey": 0, + "List": [ + { + "Key": "Architecture", + "Value": "建築", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "CivilEngineering", + "Value": "土木工程", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Mechanics", + "Value": "機械製造", + "PageKey": 0, + "ParentKey": "Make" + }, + {"Key": "Energy", "Value": "能源", "PageKey": 0, "ParentKey": "Make"}, + {"Key": "Clothing", "Value": "服裝", "PageKey": 0, "ParentKey": "Make"}, + {"Key": "Food", "Value": "食品", "PageKey": 0, "ParentKey": "Make"}, + { + "Key": "Biomedicine", + "Value": "生物醫學", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Electronics", + "Value": "電子", + "PageKey": 0, + "ParentKey": "Make" + } + ] + }, + { + "Key": "Transportation", + "Value": "交通運輸", + "PageKey": 0, + "List": [ + { + "Key": "Aviation", + "Value": "航空", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Railway", + "Value": "鐵路", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Logistics", + "Value": "物流運輸", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Traffic", + "Value": "公共交通", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "ShippingShips", + "Value": "航運船舶", + "PageKey": 0, + "ParentKey": "Transportation" + } + ] + }, + { + "Key": "CulturalMedia", + "Value": "文化傳媒", + "PageKey": 0, + "List": [ + { + "Key": "MediaPublishing", + "Value": "媒體出版", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Photography", + "Value": "攝影", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Exhibition", + "Value": "公關會展", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Comic", + "Value": "動漫", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Originality", + "Value": "廣告創意", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Spread", + "Value": "文化傳播", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Design", + "Value": "設計", + "PageKey": 0, + "ParentKey": "CulturalMedia" + } + ] + }, + { + "Key": "EntertainmentSports", + "Value": "娛樂體育", + "PageKey": 0, + "List": [ + { + "Key": "Model", + "Value": "糢特", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Music", + "Value": "音樂", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "SportsSports", + "Value": "運動體育", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Movies", + "Value": "影視", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + } + ] + }, + { + "Key": "PublicUtilities", + "Value": "公共事業", + "PageKey": 0, + "List": [ + { + "Key": "PublicWelfare", + "Value": "公益", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Speak", + "Value": "科研", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "GovernmentOrgans", + "Value": "政府機構", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Education", + "Value": "教育", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Law", + "Value": "法律", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "MedicalCare", + "Value": "醫療", + "PageKey": 0, + "ParentKey": "PublicUtilities" + } + ] + }, + { + "Key": "Student", + "Value": "學生", + "PageKey": 0, + "List": [ + {"Key": "PuPils", "Value": "學生", "PageKey": 0, "ParentKey": "Student"} + ] + }, + { + "Key": "Nothing", + "Value": "無", + "PageKey": 0, + "List": [ + {"Key": "NotHave", "Value": "無", "PageKey": 0, "ParentKey": "Nothing"} + ] + } + ], + 'city': [ + { + "Key": "VietNam", + "Value": "越南", + "PageKey": 0, + "List": [ + { + "Key": "AnGiang", + "Value": "安江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacGiang", + "Value": "北江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacCan", + "Value": "北件", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacLieu", + "Value": "薄遼", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BeiNing", + "Value": "北寧", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BaRiaVungTau", + "Value": "巴地頭頓", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BenTre", + "Value": "檳椥", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BinhDinh", + "Value": "平定", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingYang", + "Value": "平陽", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingFu", + "Value": "平福", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NinhThuan", + "Value": "平順", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "CaMau", "Value": "金甌", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "CaoBang", + "Value": "高平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "DeLe", "Value": "得樂", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "DeNong", + "Value": "得農", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DienBien", + "Value": "奠邊", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongNai", + "Value": "同奈", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongThap", + "Value": "同塔", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "GiaLai", + "Value": "嘉萊", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaGiang", + "Value": "河江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaiDuang", + "Value": "海陽", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "Henan", "Value": "河南", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "HaTinh", + "Value": "河靜", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HoaBinh", + "Value": "和平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HouJiang", + "Value": "後江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Xingan", + "Value": "興安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KhanhHo", + "Value": "慶和", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "JianJiang", + "Value": "堅江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KonTum", + "Value": "昆嵩", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaiChua", + "Value": "萊州", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LamDong", + "Value": "林同", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LangSon", + "Value": "諒山", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaoCai", + "Value": "老街", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LongAn", + "Value": "隆安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NamDinh", + "Value": "南定", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NgheAn", + "Value": "乂安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingShun", + "Value": "寧順", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "FuShou", + "Value": "富壽", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PhuYen", + "Value": "富安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangBinh", + "Value": "廣平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNam", + "Value": "廣南", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNgai", + "Value": "廣義", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNinh", + "Value": "廣寧", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangTri", + "Value": "廣治", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "SocTrang", + "Value": "朔莊", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "SonLa", "Value": "山羅", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "TayNinh", + "Value": "西寧", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiBinh", + "Value": "太平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiNguyen", + "Value": "太原", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThanhHoa", + "Value": "清化", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThuaThienHue", + "Value": "承天順化", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TraVinh", + "Value": "茶榮", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TuyenQuang", + "Value": "宣光", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhLon", + "Value": "永隆", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhPhu", + "Value": "永富", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "YenBai", + "Value": "安沛", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaoTho", + "Value": "芹苴", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DaNang", + "Value": "峴港", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Haiphong", + "Value": "海防", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "Hanoi", "Value": "河内", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "HoChiMinhCIty", + "Value": "胡志明市", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingPing", + "Value": "甯平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Qianjiang", + "Value": "前江", + "PageKey": 0, + "ParentKey": "VietNam" + } + ] + }, + { + "Key": "China", + "Value": "中國", + "PageKey": 0, + "List": [ + { + "Key": "ChinaRepeat", + "Value": "中國", + "PageKey": 0, + "ParentKey": "China" + }, + ] + }, + {"Key": "UnitedStates", "Value": "美國", "PageKey": 0, "List": []}, + {"Key": "Russia", "Value": "俄羅斯", "PageKey": 0, "List": []}, + {"Key": "Germany", "Value": "德國", "PageKey": 0, "List": []}, + {"Key": "UnitedKingdom", "Value": "英國", "PageKey": 0, "List": []}, + {"Key": "France", "Value": "法國", "PageKey": 0, "List": []}, + {"Key": "Australia", "Value": "澳大利亞", "PageKey": 0, "List": []}, + {"Key": "Japan", "Value": "日本", "PageKey": 0, "List": []}, + {"Key": "Korea", "Value": "韓國", "PageKey": 0, "List": []}, + {"Key": "Laos", "Value": "老撾", "PageKey": 0, "List": []}, + {"Key": "Cambodia", "Value": "柬埔寨", "PageKey": 0, "List": []}, + {"Key": "Myanmar", "Value": "緬甸", "PageKey": 0, "List": []}, + {"Key": "Thailand", "Value": "泰國", "PageKey": 0, "List": []}, + {"Key": "Malaysia", "Value": "馬來西亞", "PageKey": 0, "List": []}, + {"Key": "Singapore", "Value": "新加坡", "PageKey": 0, "List": []}, + {"Key": "OtherCountries", "Value": "其他國家", "PageKey": 0, "List": []} + ], + }, + { + 'program': [ + {"Key": "Motion", "Value": "健康运动", "PageKey": 0, "List": []}, + {"Key": "Party", "Value": "夜蒲聚会", "PageKey": 0, "List": []}, + {"Key": "Foodie", "Value": "我是吃货", "PageKey": 0, "List": []}, + {"Key": "Movie", "Value": "看电影", "PageKey": 0, "List": []}, + {"Key": "Game", "Value": "玩游戏", "PageKey": 0, "List": []}, + {"Key": "Travel", "Value": "结伴旅行", "PageKey": 0, "List": []}, + {"Key": "Chat", "Value": "连麦聊天", "PageKey": 0, "List": []}, + {"Key": "Other", "Value": "其他", "PageKey": 0, "List": []} + ], + 'lovePeople': [ + {"Key": "Face", "Value": "看脸", "PageKey": 0, "List": []}, + {"Key": "Interesting", "Value": "有趣", "PageKey": 0, "List": []}, + {"Key": "LocalTyrant", "Value": "土豪", "PageKey": 0, "List": []}, + {"Key": "Love", "Value": "关爱我", "PageKey": 0, "List": []}, + {"Key": "Feel", "Value": "看感觉", "PageKey": 0, "List": []}, + {"Key": "Indifferent", "Value": "无所谓", "PageKey": 0, "List": []} + ], + 'job': [ + { + "Key": "Information", + "Value": "信息技术", + "PageKey": 0, + "List": [ + { + "Key": "Information", + "Value": "通讯", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Internet", + "Value": "互联网", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "IT", + "Value": "IT", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Operate", + "Value": "电信运营", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "NetworkGame", + "Value": "网络游戏", + "PageKey": 0, + "ParentKey": "Information" + } + ] + }, + { + "Key": "Financial", + "Value": "金融保险", + "PageKey": 0, + "List": [ + { + "Key": "Investment", + "Value": "投资", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "StockFund", + "Value": "股票基金", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Insurance", + "Value": "保险", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Bank", + "Value": "银行", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "TrustGuarantee", + "Value": "信托担保", + "PageKey": 0, + "ParentKey": "Financial" + } + ] + }, + { + "Key": "CommercialServices", + "Value": "商业服务", + "PageKey": 0, + "List": [ + { + "Key": "Consultation", + "Value": "咨询", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Individual", + "Value": "个体经营", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Cosmetology", + "Value": "美容美发", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Decoration", + "Value": "装修装潢", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Detective", + "Value": "侦探", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "EstateManagement", + "Value": "物业管理", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "RealEstate", + "Value": "房地产", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Car", + "Value": "汽车", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Trade", + "Value": "贸易", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "LeisureTime", + "Value": "休闲娱乐", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "HotelCatering", + "Value": "酒店餐饮", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Travel", + "Value": "旅游", + "PageKey": 0, + "ParentKey": "CommercialServices" + } + ] + }, + { + "Key": "Make", + "Value": "工程制造", + "PageKey": 0, + "List": [ + { + "Key": "Architecture", + "Value": "建筑", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "CivilEngineering", + "Value": "土木工程", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Mechanics", + "Value": "机械制造", + "PageKey": 0, + "ParentKey": "Make" + }, + {"Key": "Energy", "Value": "能源", "PageKey": 0, "ParentKey": "Make"}, + {"Key": "Clothing", "Value": "服装", "PageKey": 0, "ParentKey": "Make"}, + {"Key": "Food", "Value": "食品", "PageKey": 0, "ParentKey": "Make"}, + { + "Key": "Biomedicine", + "Value": "生物医学", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Electronics", + "Value": "电子", + "PageKey": 0, + "ParentKey": "Make" + } + ] + }, + { + "Key": "Transportation", + "Value": "交通运输", + "PageKey": 0, + "List": [ + { + "Key": "Aviation", + "Value": "航空", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Railway", + "Value": "铁路", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Logistics", + "Value": "物流运输", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Traffic", + "Value": "公共交通", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "ShippingShips", + "Value": "航运船舶", + "PageKey": 0, + "ParentKey": "Transportation" + } + ] + }, + { + "Key": "CulturalMedia", + "Value": "文化传媒", + "PageKey": 0, + "List": [ + { + "Key": "MediaPublishing", + "Value": "媒体出版", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Photography", + "Value": "摄影", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Exhibition", + "Value": "公关会展", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Comic", + "Value": "动漫", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Originality", + "Value": "广告创意", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Spread", + "Value": "文化传播", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Design", + "Value": "设计", + "PageKey": 0, + "ParentKey": "CulturalMedia" + } + ] + }, + { + "Key": "EntertainmentSports", + "Value": "娱乐体育", + "PageKey": 0, + "List": [ + { + "Key": "Model", + "Value": "模特", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Music", + "Value": "音乐", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "SportsSports", + "Value": "运动体育", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Movies", + "Value": "影视", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + } + ] + }, + { + "Key": "PublicUtilities", + "Value": "公共事业", + "PageKey": 0, + "List": [ + { + "Key": "PublicWelfare", + "Value": "公益", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Speak", + "Value": "科研", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "GovernmentOrgans", + "Value": "政府机构", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Education", + "Value": "教育", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Law", + "Value": "法律", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "MedicalCare", + "Value": "医疗", + "PageKey": 0, + "ParentKey": "PublicUtilities" + } + ] + }, + { + "Key": "Student", + "Value": "学生", + "PageKey": 0, + "List": [ + {"Key": "PuPils", "Value": "学生", "PageKey": 0, "ParentKey": "Student"} + ] + }, + { + "Key": "Nothing", + "Value": "无", + "PageKey": 0, + "List": [ + {"Key": "NotHave", "Value": "无", "PageKey": 0, "ParentKey": "Nothing"} + ] + } + ], + 'city': [ + { + "Key": "VietNam", + "Value": "越南", + "PageKey": 0, + "List": [ + { + "Key": "AnGiang", + "Value": "安江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacGiang", + "Value": "北江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacCan", + "Value": "北件", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacLieu", + "Value": "薄辽", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BeiNing", + "Value": "北宁", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BaRiaVungTau", + "Value": "巴地头顿", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BenTre", + "Value": "槟椥", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BinhDinh", + "Value": "平定", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingYang", + "Value": "平阳", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingFu", + "Value": "平福", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NinhThuan", + "Value": "平顺", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "CaMau", "Value": "金瓯", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "CaoBang", + "Value": "高平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "DeLe", "Value": "得乐", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "DeNong", + "Value": "得农", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DienBien", + "Value": "奠边", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongNai", + "Value": "同奈", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongThap", + "Value": "同塔", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "GiaLai", + "Value": "嘉莱", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaGiang", + "Value": "河江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaiDuang", + "Value": "海阳", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "Henan", "Value": "河南", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "HaTinh", + "Value": "河静", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HoaBinh", + "Value": "和平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HouJiang", + "Value": "后江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Xingan", + "Value": "兴安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KhanhHo", + "Value": "庆和", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "JianJiang", + "Value": "坚江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KonTum", + "Value": "昆嵩", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaiChua", + "Value": "莱州", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LamDong", + "Value": "林同", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LangSon", + "Value": "谅山", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaoCai", + "Value": "老街", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LongAn", + "Value": "隆安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NamDinh", + "Value": "南定", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NgheAn", + "Value": "乂安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingShun", + "Value": "宁顺", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "FuShou", + "Value": "富寿", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PhuYen", + "Value": "富安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangBinh", + "Value": "广平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNam", + "Value": "广南", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNgai", + "Value": "广义", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNinh", + "Value": "广宁", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangTri", + "Value": "广治", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "SocTrang", + "Value": "朔庄", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "SonLa", "Value": "山罗", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "TayNinh", + "Value": "西宁", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiBinh", + "Value": "太平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiNguyen", + "Value": "太原", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThanhHoa", + "Value": "清化", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThuaThienHue", + "Value": "承天顺化", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TraVinh", + "Value": "茶荣", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TuyenQuang", + "Value": "宣光", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhLon", + "Value": "永隆", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhPhu", + "Value": "永富", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "YenBai", + "Value": "安沛", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaoTho", + "Value": "芹苴", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DaNang", + "Value": "岘港", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Haiphong", + "Value": "海防", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "Hanoi", "Value": "河内", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "HoChiMinhCIty", + "Value": "胡志明市", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Qianjiang", + "Value": "前江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingPing", + "Value": "宁平", + "PageKey": 0, + "ParentKey": "VietNam" + } + ] + }, + { + "Key": "China", + "Value": "中国", + "PageKey": 0, + "List": [ + { + "Key": "ChinaRepeat", + "Value": "中国", + "PageKey": 0, + "ParentKey": "China" + } + ] + }, + {"Key": "UnitedStates", "Value": "美国", "PageKey": 0, "List": []}, + {"Key": "Russia", "Value": "俄罗斯", "PageKey": 0, "List": []}, + {"Key": "Germany", "Value": "德国", "PageKey": 0, "List": []}, + {"Key": "UnitedKingdom", "Value": "英国", "PageKey": 0, "List": []}, + {"Key": "France", "Value": "法国", "PageKey": 0, "List": []}, + {"Key": "Australia", "Value": "澳大利亚", "PageKey": 0, "List": []}, + {"Key": "Japan", "Value": "日本", "PageKey": 0, "List": []}, + {"Key": "Korea", "Value": "韩国", "PageKey": 0, "List": []}, + {"Key": "Laos", "Value": "老挝", "PageKey": 0, "List": []}, + {"Key": "Cambodia", "Value": "柬甫寨", "PageKey": 0, "List": []}, + {"Key": "Myanmar", "Value": "缅甸", "PageKey": 0, "List": []}, + {"Key": "Thailand", "Value": "泰国", "PageKey": 0, "List": []}, + {"Key": "Malaysia", "Value": "马来西亚", "PageKey": 0, "List": []}, + {"Key": "Singapore", "Value": "新加坡", "PageKey": 0, "List": []}, + {"Key": "OtherCountries", "Value": "其他国家", "PageKey": 0, "List": []} + ] + }, + { + 'program': [ + {"Key": "Motion", "Value": "건강 운동", "PageKey": 0, "List": []}, + {"Key": "Party", "Value": "나이트 푸 파티", "PageKey": 0, "List": []}, + {"Key": "Foodie", "Value": "나는 먹고있다", "PageKey": 0, "List": []}, + {"Key": "Movie", "Value": "영화보기", "PageKey": 0, "List": []}, + {"Key": "Game", "Value": "게임하기", "PageKey": 0, "List": []}, + {"Key": "Travel", "Value": "함께 여행", "PageKey": 0, "List": []}, + {"Key": "Chat", "Value": "리안 마이 채팅", "PageKey": 0, "List": []}, + {"Key": "Other", "Value": "기타", "PageKey": 0, "List": []} + ], + 'lovePeople': [ + {"Key": "Face", "Value": "얼굴을 봐", "PageKey": 0, "List": []}, + {"Key": "Interesting", "Value": "재미있는", "PageKey": 0, "List": []}, + {"Key": "LocalTyrant", "Value": "폭군", "PageKey": 0, "List": []}, + {"Key": "Love", "Value": "나를 돌 봐줘", "PageKey": 0, "List": []}, + {"Key": "Feel", "Value": "느낌을 참조하십시오", "PageKey": 0, "List": []}, + {"Key": "Indifferent", "Value": "상관 없습니다", "PageKey": 0, "List": []} + ], + 'job': [ + { + "Key": "Information", + "Value": "정보 기술", + "PageKey": 0, + "List": [ + { + "Key": "Information", + "Value": "통신", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Internet", + "Value": "인터넷", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "IT", + "Value": "IT", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Operate", + "Value": "통신 운영", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "NetworkGame", + "Value": "온라인 게임", + "PageKey": 0, + "ParentKey": "Information" + } + ] + }, + { + "Key": "Financial", + "Value": "금융 보험", + "PageKey": 0, + "List": [ + { + "Key": "Investment", + "Value": "투자", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "StockFund", + "Value": "주식 기금", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Insurance", + "Value": "보험", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Bank", + "Value": "은행", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "TrustGuarantee", + "Value": "신뢰 보장", + "PageKey": 0, + "ParentKey": "Financial" + } + ] + }, + { + "Key": "CommercialServices", + "Value": "비즈니스 서비스", + "PageKey": 0, + "List": [ + { + "Key": "Consultation", + "Value": "컨설팅", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Individual", + "Value": "자영업자", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Cosmetology", + "Value": "미용실", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Decoration", + "Value": "데코레이션", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Detective", + "Value": "형사", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "EstateManagement", + "Value": "재산 관리", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "RealEstate", + "Value": "부동산", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Car", + "Value": "자동차", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Trade", + "Value": "무역", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "LeisureTime", + "Value": "레저", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "HotelCatering", + "Value": "호텔 케이터링", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Travel", + "Value": "여행", + "PageKey": 0, + "ParentKey": "CommercialServices" + } + ] + }, + { + "Key": "Make", + "Value": "엔지니어링 제조", + "PageKey": 0, + "List": [ + { + "Key": "Architecture", + "Value": "빌딩", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "CivilEngineering", + "Value": "토목 공학", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Mechanics", + "Value": "기계 제조", + "PageKey": 0, + "ParentKey": "Make" + }, + {"Key": "Energy", "Value": "에너지", "PageKey": 0, "ParentKey": "Make"}, + {"Key": "Clothing", "Value": "의류", "PageKey": 0, "ParentKey": "Make"}, + {"Key": "Food", "Value": "음식", "PageKey": 0, "ParentKey": "Make"}, + { + "Key": "Biomedicine", + "Value": "생의학", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Electronics", + "Value": "전자 제품", + "PageKey": 0, + "ParentKey": "Make" + } + ] + }, + { + "Key": "Transportation", + "Value": "교통 수단", + "PageKey": 0, + "List": [ + { + "Key": "Aviation", + "Value": "항공", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Railway", + "Value": "철도", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Logistics", + "Value": "물류 운송", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Traffic", + "Value": "대중 교통", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "ShippingShips", + "Value": "배송 선", + "PageKey": 0, + "ParentKey": "Transportation" + } + ] + }, + { + "Key": "CulturalMedia", + "Value": "문화 미디어", + "PageKey": 0, + "List": [ + { + "Key": "MediaPublishing", + "Value": "미디어 출판", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Photography", + "Value": "사진", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Exhibition", + "Value": "홍보 전시회", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Comic", + "Value": "아니메", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Originality", + "Value": "광고 아이디어", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Spread", + "Value": "문화 커뮤니케이션", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Design", + "Value": "디자인", + "PageKey": 0, + "ParentKey": "CulturalMedia" + } + ] + }, + { + "Key": "EntertainmentSports", + "Value": "엔터테인먼트 스포츠", + "PageKey": 0, + "List": [ + { + "Key": "Model", + "Value": "모형", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Music", + "Value": "음악", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "SportsSports", + "Value": "스포츠 스포츠", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Movies", + "Value": "영화", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + } + ] + }, + { + "Key": "PublicUtilities", + "Value": "공공 시설", + "PageKey": 0, + "List": [ + { + "Key": "PublicWelfare", + "Value": "공공 복지", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Speak", + "Value": "리서치", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "GovernmentOrgans", + "Value": "정부 기관", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Education", + "Value": "교육", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Law", + "Value": "법", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "MedicalCare", + "Value": "의료", + "PageKey": 0, + "ParentKey": "PublicUtilities" + } + ] + }, + { + "Key": "Student", + "Value": "학생", + "PageKey": 0, + "List": [ + {"Key": "PuPils", "Value": "학생", "PageKey": 0, "ParentKey": "Student"} + ] + }, + { + "Key": "Nothing", + "Value": "없음", + "PageKey": 0, + "List": [ + { + "Key": "NotHave", + "Value": "없음", + "PageKey": 0, + "ParentKey": "Nothing" + } + ] + } + ], + 'city': [ + { + "Key": "VietNam", + "Value": "베트남", + "PageKey": 0, + "List": [ + { + "Key": "AnGiang", + "Value": "안강", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacGiang", + "Value": "북강", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacCan", + "Value": "북부", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacLieu", + "Value": "얇다", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BeiNing", + "Value": "북녕", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BaRiaVungTau", + "Value": "무턱대고", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BenTre", + "Value": "베트남의 지명", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BinhDinh", + "Value": "평정하다", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingYang", + "Value": "평양", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingFu", + "Value": "평복", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NinhThuan", + "Value": "순조롭다", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaMau", + "Value": "저장 성", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaoBang", + "Value": "고평", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "DeLe", "Value": "즐기다", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "DeNong", + "Value": "농사를 짓다", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DienBien", + "Value": "가장자리를 닦다", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongNai", + "Value": "어떻게", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongThap", + "Value": "동탑", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "GiaLai", + "Value": "가래", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaGiang", + "Value": "강", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaiDuang", + "Value": "해양", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "Henan", "Value": "하남", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "HaTinh", + "Value": "강정", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HoaBinh", + "Value": "평화", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HouJiang", + "Value": "후강", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Xingan", + "Value": "흥안", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KhanhHo", + "Value": "경합", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "JianJiang", + "Value": "젠 장", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KonTum", + "Value": "부피", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaiChua", + "Value": "레주", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LamDong", + "Value": "숲", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LangSon", + "Value": "양산", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaoCai", + "Value": "옛거리", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LongAn", + "Value": "융안", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NamDinh", + "Value": "남정", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NgheAn", + "Value": "안정되다", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingShun", + "Value": "순종하다", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "FuShou", + "Value": "장수", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PhuYen", + "Value": "부안", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangBinh", + "Value": "광평", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNam", + "Value": "광남", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNgai", + "Value": "광의", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNinh", + "Value": "광녕", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangTri", + "Value": "널리 치료하다", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "SocTrang", + "Value": "삭장", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "SonLa", "Value": "산라", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "TayNinh", + "Value": "서녕", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiBinh", + "Value": "태평", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiNguyen", + "Value": "태원", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThanhHoa", + "Value": "청산하다", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThuaThienHue", + "Value": "승천순화", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TraVinh", + "Value": "차의 영광", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TuyenQuang", + "Value": "선광", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhLon", + "Value": "영영", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhPhu", + "Value": "영부", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "YenBai", + "Value": "편안하다", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaoTho", + "Value": "미나리", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DaNang", + "Value": "다낭", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Haiphong", + "Value": "해방", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "Hanoi", "Value": "하내", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "HoChiMinhCIty", + "Value": "호치명시", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingPing", + "Value": "평온하다", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Qianjiang", + "Value": "전강", + "PageKey": 0, + "ParentKey": "VietNam" + } + ] + }, + { + "Key": "China", + "Value": "중국", + "PageKey": 0, + "List": [ + { + "Key": "ChinaRepeat", + "Value": "중국", + "PageKey": 0, + "ParentKey": "China" + } + ] + }, + {"Key": "Russia", "Value": "러시아", "PageKey": 0, "List": []}, + {"Key": "Germany", "Value": "독일", "PageKey": 0, "List": []}, + {"Key": "UnitedKingdom", "Value": "영국", "PageKey": 0, "List": []}, + {"Key": "France", "Value": "프랑스", "PageKey": 0, "List": []}, + {"Key": "Australia", "Value": "오스트레일리아", "PageKey": 0, "List": []}, + {"Key": "Japan", "Value": "일본", "PageKey": 0, "List": []}, + {"Key": "Korea", "Value": "한국", "PageKey": 0, "List": []}, + {"Key": "Laos", "Value": "라오스", "PageKey": 0, "List": []}, + {"Key": "Cambodia", "Value": "청첩장", "PageKey": 0, "List": []}, + {"Key": "Myanmar", "Value": "미얀마", "PageKey": 0, "List": []}, + {"Key": "Thailand", "Value": "태국", "PageKey": 0, "List": []}, + {"Key": "Malaysia", "Value": "말레이시아", "PageKey": 0, "List": []}, + {"Key": "Singapore", "Value": "싱가포르", "PageKey": 0, "List": []}, + {"Key": "OtherCountries", "Value": "다른 나라", "PageKey": 0, "List": []}, + {"Key": "UnitedStates", "Value": "미국", "PageKey": 0, "List": []}, + {"Key": "HongKong", "Value": "홍콩, 중국", "PageKey": 0, "List": []}, + {"Key": "Taiwan", "Value": "대만, 중국", "PageKey": 0, "List": []} + ] + }, + { + 'program': [ + {"Key": "Motion", "Value": "健康运动", "PageKey": 0, "List": []}, + {"Key": "Party", "Value": "夜蒲聚会", "PageKey": 0, "List": []}, + {"Key": "Foodie", "Value": "我是吃货", "PageKey": 0, "List": []}, + {"Key": "Movie", "Value": "看电影", "PageKey": 0, "List": []}, + {"Key": "Game", "Value": "玩游戏", "PageKey": 0, "List": []}, + {"Key": "Travel", "Value": "结伴旅行", "PageKey": 0, "List": []}, + {"Key": "Chat", "Value": "连麦聊天", "PageKey": 0, "List": []}, + {"Key": "Other", "Value": "其他", "PageKey": 0, "List": []} + ], + 'lovePeople': [ + {"Key": "Face", "Value": "看脸", "PageKey": 0, "List": []}, + {"Key": "Interesting", "Value": "有趣", "PageKey": 0, "List": []}, + {"Key": "LocalTyrant", "Value": "土豪", "PageKey": 0, "List": []}, + {"Key": "Love", "Value": "关爱我", "PageKey": 0, "List": []}, + {"Key": "Feel", "Value": "看感觉", "PageKey": 0, "List": []}, + {"Key": "Indifferent", "Value": "无所谓", "PageKey": 0, "List": []} + ], + 'job': [ + { + "Key": "Information", + "Value": "信息技术", + "PageKey": 0, + "List": [ + { + "Key": "Information", + "Value": "通讯", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Internet", + "Value": "互联网", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "IT", + "Value": "IT", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Operate", + "Value": "电信运营", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "NetworkGame", + "Value": "网络游戏", + "PageKey": 0, + "ParentKey": "Information" + } + ] + }, + { + "Key": "Financial", + "Value": "金融保险", + "PageKey": 0, + "List": [ + { + "Key": "Investment", + "Value": "投资", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "StockFund", + "Value": "股票基金", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Insurance", + "Value": "保险", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Bank", + "Value": "银行", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "TrustGuarantee", + "Value": "信托担保", + "PageKey": 0, + "ParentKey": "Financial" + } + ] + }, + { + "Key": "CommercialServices", + "Value": "商业服务", + "PageKey": 0, + "List": [ + { + "Key": "Consultation", + "Value": "咨询", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Individual", + "Value": "个体经营", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Cosmetology", + "Value": "美容美发", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Decoration", + "Value": "装修装潢", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Detective", + "Value": "侦探", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "EstateManagement", + "Value": "物业管理", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "RealEstate", + "Value": "房地产", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Car", + "Value": "汽车", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Trade", + "Value": "贸易", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "LeisureTime", + "Value": "休闲娱乐", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "HotelCatering", + "Value": "酒店餐饮", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Travel", + "Value": "旅游", + "PageKey": 0, + "ParentKey": "CommercialServices" + } + ] + }, + { + "Key": "Make", + "Value": "工程制造", + "PageKey": 0, + "List": [ + { + "Key": "Architecture", + "Value": "建筑", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "CivilEngineering", + "Value": "土木工程", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Mechanics", + "Value": "机械制造", + "PageKey": 0, + "ParentKey": "Make" + }, + {"Key": "Energy", "Value": "能源", "PageKey": 0, "ParentKey": "Make"}, + {"Key": "Clothing", "Value": "服装", "PageKey": 0, "ParentKey": "Make"}, + {"Key": "Food", "Value": "食品", "PageKey": 0, "ParentKey": "Make"}, + { + "Key": "Biomedicine", + "Value": "生物医学", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Electronics", + "Value": "电子", + "PageKey": 0, + "ParentKey": "Make" + } + ] + }, + { + "Key": "Transportation", + "Value": "交通运输", + "PageKey": 0, + "List": [ + { + "Key": "Aviation", + "Value": "航空", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Railway", + "Value": "铁路", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Logistics", + "Value": "物流运输", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Traffic", + "Value": "公共交通", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "ShippingShips", + "Value": "航运船舶", + "PageKey": 0, + "ParentKey": "Transportation" + } + ] + }, + { + "Key": "CulturalMedia", + "Value": "文化传媒", + "PageKey": 0, + "List": [ + { + "Key": "MediaPublishing", + "Value": "媒体出版", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Photography", + "Value": "摄影", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Exhibition", + "Value": "公关会展", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Comic", + "Value": "动漫", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Originality", + "Value": "广告创意", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Spread", + "Value": "文化传播", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Design", + "Value": "设计", + "PageKey": 0, + "ParentKey": "CulturalMedia" + } + ] + }, + { + "Key": "EntertainmentSports", + "Value": "娱乐体育", + "PageKey": 0, + "List": [ + { + "Key": "Model", + "Value": "模特", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Music", + "Value": "音乐", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "SportsSports", + "Value": "运动体育", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Movies", + "Value": "影视", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + } + ] + }, + { + "Key": "PublicUtilities", + "Value": "公共事业", + "PageKey": 0, + "List": [ + { + "Key": "PublicWelfare", + "Value": "公益", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Speak", + "Value": "科研", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "GovernmentOrgans", + "Value": "政府机构", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Education", + "Value": "教育", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Law", + "Value": "法律", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "MedicalCare", + "Value": "医疗", + "PageKey": 0, + "ParentKey": "PublicUtilities" + } + ] + }, + { + "Key": "Student", + "Value": "学生", + "PageKey": 0, + "List": [ + {"Key": "PuPils", "Value": "学生", "PageKey": 0, "ParentKey": "Student"} + ] + }, + { + "Key": "Nothing", + "Value": "无", + "PageKey": 0, + "List": [ + {"Key": "NotHave", "Value": "无", "PageKey": 0, "ParentKey": "Nothing"} + ] + } + ], + 'city': [ + { + "Key": "VietNam", + "Value": "越南", + "PageKey": 0, + "List": [ + { + "Key": "AnGiang", + "Value": "安江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacGiang", + "Value": "北江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacCan", + "Value": "北件", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacLieu", + "Value": "薄辽", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BeiNing", + "Value": "北宁", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BaRiaVungTau", + "Value": "巴地头顿", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BenTre", + "Value": "槟椥", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BinhDinh", + "Value": "平定", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingYang", + "Value": "平阳", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingFu", + "Value": "平福", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NinhThuan", + "Value": "平顺", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "CaMau", "Value": "金瓯", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "CaoBang", + "Value": "高平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "DeLe", "Value": "得乐", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "DeNong", + "Value": "得农", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DienBien", + "Value": "奠边", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongNai", + "Value": "同奈", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongThap", + "Value": "同塔", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "GiaLai", + "Value": "嘉莱", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaGiang", + "Value": "河江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaiDuang", + "Value": "海阳", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "Henan", "Value": "河南", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "HaTinh", + "Value": "河静", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HoaBinh", + "Value": "和平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HouJiang", + "Value": "后江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Xingan", + "Value": "兴安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KhanhHo", + "Value": "庆和", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "JianJiang", + "Value": "坚江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KonTum", + "Value": "昆嵩", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaiChua", + "Value": "莱州", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LamDong", + "Value": "林同", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LangSon", + "Value": "谅山", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaoCai", + "Value": "老街", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LongAn", + "Value": "隆安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NamDinh", + "Value": "南定", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NgheAn", + "Value": "乂安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingShun", + "Value": "宁顺", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "FuShou", + "Value": "富寿", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PhuYen", + "Value": "富安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangBinh", + "Value": "广平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNam", + "Value": "广南", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNgai", + "Value": "广义", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNinh", + "Value": "广宁", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangTri", + "Value": "广治", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "SocTrang", + "Value": "朔庄", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "SonLa", "Value": "山罗", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "TayNinh", + "Value": "西宁", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiBinh", + "Value": "太平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiNguyen", + "Value": "太原", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThanhHoa", + "Value": "清化", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThuaThienHue", + "Value": "承天顺化", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TraVinh", + "Value": "茶荣", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TuyenQuang", + "Value": "宣光", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhLon", + "Value": "永隆", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhPhu", + "Value": "永富", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "YenBai", + "Value": "安沛", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaoTho", + "Value": "芹苴", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DaNang", + "Value": "岘港", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Haiphong", + "Value": "海防", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "Hanoi", "Value": "河内", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "HoChiMinhCIty", + "Value": "胡志明市", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Qianjiang", + "Value": "前江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingPing", + "Value": "宁平", + "PageKey": 0, + "ParentKey": "VietNam" + } + ] + }, + { + "Key": "China", + "Value": "中国", + "PageKey": 0, + "List": [ + { + "Key": "ChinaRepeat", + "Value": "中国", + "PageKey": 0, + "ParentKey": "China" + } + ] + }, + {"Key": "UnitedStates", "Value": "美国", "PageKey": 0, "List": []}, + {"Key": "Russia", "Value": "俄罗斯", "PageKey": 0, "List": []}, + {"Key": "Germany", "Value": "德国", "PageKey": 0, "List": []}, + {"Key": "UnitedKingdom", "Value": "英国", "PageKey": 0, "List": []}, + {"Key": "France", "Value": "法国", "PageKey": 0, "List": []}, + {"Key": "Australia", "Value": "澳大利亚", "PageKey": 0, "List": []}, + {"Key": "Japan", "Value": "日本", "PageKey": 0, "List": []}, + {"Key": "Korea", "Value": "韩国", "PageKey": 0, "List": []}, + {"Key": "Laos", "Value": "老挝", "PageKey": 0, "List": []}, + {"Key": "Cambodia", "Value": "柬甫寨", "PageKey": 0, "List": []}, + {"Key": "Myanmar", "Value": "缅甸", "PageKey": 0, "List": []}, + {"Key": "Thailand", "Value": "泰国", "PageKey": 0, "List": []}, + {"Key": "Malaysia", "Value": "马来西亚", "PageKey": 0, "List": []}, + {"Key": "Singapore", "Value": "新加坡", "PageKey": 0, "List": []}, + {"Key": "OtherCountries", "Value": "其他国家", "PageKey": 0, "List": []} + ] + }, + { + 'program': [ + {"Key": "Motion", "Value": "健康運動", "PageKey": 0, "List": []}, + {"Key": "Party", "Value": "ナイトプーパーティー", "PageKey": 0, "List": []}, + {"Key": "Foodie", "Value": "私は食べています", "PageKey": 0, "List": []}, + {"Key": "Movie", "Value": "映画を見る", "PageKey": 0, "List": []}, + {"Key": "Game", "Value": "ゲームをする", "PageKey": 0, "List": []}, + {"Key": "Travel", "Value": "一緒に旅行する", "PageKey": 0, "List": []}, + {"Key": "Chat", "Value": "リアンマイチャット", "PageKey": 0, "List": []}, + {"Key": "Other", "Value": "その他", "PageKey": 0, "List": []} + ], + 'lovePeople': [ + {"Key": "Face", "Value": "顔を見て", "PageKey": 0, "List": []}, + {"Key": "Interesting", "Value": "おもしろい", "PageKey": 0, "List": []}, + {"Key": "LocalTyrant", "Value": "暴君", "PageKey": 0, "List": []}, + {"Key": "Love", "Value": "私の世話", "PageKey": 0, "List": []}, + {"Key": "Feel", "Value": "気持ちを見る", "PageKey": 0, "List": []}, + {"Key": "Indifferent", "Value": "関係ない", "PageKey": 0, "List": []} + ], + 'job': [ + { + "Key": "Information", + "Value": "情報技術", + "PageKey": 0, + "List": [ + { + "Key": "Information", + "Value": "コミュニケーション", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Internet", + "Value": "インターネット", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "IT", + "Value": "IT", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "Operate", + "Value": "電気通信事業", + "PageKey": 0, + "ParentKey": "Information" + }, + { + "Key": "NetworkGame", + "Value": "オンラインゲーム", + "PageKey": 0, + "ParentKey": "Information" + } + ] + }, + { + "Key": "Financial", + "Value": "金融保険", + "PageKey": 0, + "List": [ + { + "Key": "Investment", + "Value": "投資", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "StockFund", + "Value": "株式ファンド", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Insurance", + "Value": "保険", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "Bank", + "Value": "銀行", + "PageKey": 0, + "ParentKey": "Financial" + }, + { + "Key": "TrustGuarantee", + "Value": "信頼保証", + "PageKey": 0, + "ParentKey": "Financial" + } + ] + }, + { + "Key": "CommercialServices", + "Value": "ビジネスサービス", + "PageKey": 0, + "List": [ + { + "Key": "Consultation", + "Value": "コンサルティング", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Individual", + "Value": "自営業者", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Cosmetology", + "Value": "美容室", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Decoration", + "Value": "デコレーション", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Detective", + "Value": "探偵", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "EstateManagement", + "Value": "財産管理", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "RealEstate", + "Value": "不動産", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Car", + "Value": "車", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Trade", + "Value": "貿易", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "LeisureTime", + "Value": "余暇", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "HotelCatering", + "Value": "ホテルケータリング", + "PageKey": 0, + "ParentKey": "CommercialServices" + }, + { + "Key": "Travel", + "Value": "旅行", + "PageKey": 0, + "ParentKey": "CommercialServices" + } + ] + }, + { + "Key": "Make", + "Value": "エンジニアリング製造", + "PageKey": 0, + "List": [ + { + "Key": "Architecture", + "Value": "建物", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "CivilEngineering", + "Value": "土木", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Mechanics", + "Value": "機械製造", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Energy", + "Value": "エネルギー", + "PageKey": 0, + "ParentKey": "Make" + }, + {"Key": "Clothing", "Value": "服装", "PageKey": 0, "ParentKey": "Make"}, + {"Key": "Food", "Value": "食べ物", "PageKey": 0, "ParentKey": "Make"}, + { + "Key": "Biomedicine", + "Value": "生物医学", + "PageKey": 0, + "ParentKey": "Make" + }, + { + "Key": "Electronics", + "Value": "エレクトロニクス", + "PageKey": 0, + "ParentKey": "Make" + } + ] + }, + { + "Key": "Transportation", + "Value": "交通機関", + "PageKey": 0, + "List": [ + { + "Key": "Aviation", + "Value": "航空", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Railway", + "Value": "鉄道", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Logistics", + "Value": "物流輸送", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "Traffic", + "Value": "公共交通機関", + "PageKey": 0, + "ParentKey": "Transportation" + }, + { + "Key": "ShippingShips", + "Value": "発送船", + "PageKey": 0, + "ParentKey": "Transportation" + } + ] + }, + { + "Key": "CulturalMedia", + "Value": "文化メディア", + "PageKey": 0, + "List": [ + { + "Key": "MediaPublishing", + "Value": "メディア出版", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Photography", + "Value": "写真撮影", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Exhibition", + "Value": "PR展", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Comic", + "Value": "アニメ", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Originality", + "Value": "広告のアイデア", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Spread", + "Value": "文化的コミュニケーション", + "PageKey": 0, + "ParentKey": "CulturalMedia" + }, + { + "Key": "Design", + "Value": "設計", + "PageKey": 0, + "ParentKey": "CulturalMedia" + } + ] + }, + { + "Key": "EntertainmentSports", + "Value": "エンターテインメントスポーツ", + "PageKey": 0, + "List": [ + { + "Key": "Model", + "Value": "モデル", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Music", + "Value": "ミュージック", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "SportsSports", + "Value": "スポーツスポーツ", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + }, + { + "Key": "Movies", + "Value": "ムービー", + "PageKey": 0, + "ParentKey": "EntertainmentSports" + } + ] + }, + { + "Key": "PublicUtilities", + "Value": "公益事業", + "PageKey": 0, + "List": [ + { + "Key": "PublicWelfare", + "Value": "公益", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Speak", + "Value": "リサーチ", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "GovernmentOrgans", + "Value": "政府機関", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Education", + "Value": "教育", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "Law", + "Value": "法律", + "PageKey": 0, + "ParentKey": "PublicUtilities" + }, + { + "Key": "MedicalCare", + "Value": "メディカル", + "PageKey": 0, + "ParentKey": "PublicUtilities" + } + ] + }, + { + "Key": "Student", + "Value": "学生", + "PageKey": 0, + "List": [ + {"Key": "PuPils", "Value": "学生", "PageKey": 0, "ParentKey": "Student"} + ] + }, + { + "Key": "Nothing", + "Value": "なし", + "PageKey": 0, + "List": [ + { + "Key": "NotHave", + "Value": "なし", + "PageKey": 0, + "ParentKey": "Nothing" + } + ] + } + ], + 'city': [ + { + "Key": "VietNam", + "Value": "ベトナム", + "PageKey": 0, + "List": [ + { + "Key": "AnGiang", + "Value": "安江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacGiang", + "Value": "北江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacCan", + "Value": "ノースウェア", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BacLieu", + "Value": "ボリアオ", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BeiNing", + "Value": "ビーニング", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BaRiaVungTau", + "Value": "バディ・ブンタウ", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BenTre", + "Value": "キンマ", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "BinhDinh", + "Value": "落ち着いた", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingYang", + "Value": "ビンズオン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PingFu", + "Value": "平福", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NinhThuan", + "Value": "平顺", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaMau", + "Value": "ジン・ヤン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaoBang", + "Value": "ゲーピング", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "DeLe", "Value": "デレ", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "DeNong", + "Value": "デノン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DienBien", + "Value": "モビアン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongNai", + "Value": "ドンナイ", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DongThap", + "Value": "ドンタ", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "GiaLai", + "Value": "ジャライ", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaGiang", + "Value": "川", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HaiDuang", + "Value": "海陽", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "Henan", "Value": "河南", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "HaTinh", + "Value": "彼はジン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HoaBinh", + "Value": "平和", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HouJiang", + "Value": "後江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Xingan", + "Value": "兴安", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KhanhHo", + "Value": "和を祝う", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "JianJiang", + "Value": "堅江", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "KonTum", + "Value": "くんソング", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaiChua", + "Value": "i州", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LamDong", + "Value": "林通", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LangSon", + "Value": "Lang山", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LaoCai", + "Value": "古い通り", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "LongAn", + "Value": "リュウガン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NamDinh", + "Value": "南定", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NgheAn", + "Value": "ルアン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingShun", + "Value": "寧順", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "FuShou", + "Value": "ふしょう", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "PhuYen", + "Value": "フアン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangBinh", + "Value": "広平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNam", + "Value": "広南", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNgai", + "Value": "广义", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangNinh", + "Value": "広寧", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "QuangTri", + "Value": "広志", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "SocTrang", + "Value": "ソチュアン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + {"Key": "SonLa", "Value": "山", "PageKey": 0, "ParentKey": "VietNam"}, + { + "Key": "TayNinh", + "Value": "西寧", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiBinh", + "Value": "タイピン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThaiNguyen", + "Value": "太原", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThanhHoa", + "Value": "清華", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "ThuaThienHue", + "Value": "チェンティアンフエ", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TraVinh", + "Value": "チャロン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "TuyenQuang", + "Value": "Xuanguang", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhLon", + "Value": "永隆", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "VinhPhu", + "Value": "永福", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "YenBai", + "Value": "アンペ", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "CaoTho", + "Value": "カントー", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "DaNang", + "Value": "ダナン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Haiphong", + "Value": "ハイフォン", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Hanoi", + "Value": "ハノイ", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "HoChiMinhCIty", + "Value": "ホーチミン市", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "NingPing", + "Value": "寧平", + "PageKey": 0, + "ParentKey": "VietNam" + }, + { + "Key": "Qianjiang", + "Value": "前江", + "PageKey": 0, + "ParentKey": "VietNam" + } + ] + }, + { + "Key": "China", + "Value": "中国", + "PageKey": 0, + "List": [ + { + "Key": "ChinaRepeat", + "Value": "中国", + "PageKey": 0, + "ParentKey": "China" + } + ] + }, + {"Key": "Russia", "Value": "ロシア", "PageKey": 0, "List": []}, + {"Key": "Germany", "Value": "ドイツ", "PageKey": 0, "List": []}, + {"Key": "UnitedKingdom", "Value": "イギリス", "PageKey": 0, "List": []}, + {"Key": "France", "Value": "フランス", "PageKey": 0, "List": []}, + {"Key": "Australia", "Value": "オーストラリア", "PageKey": 0, "List": []}, + {"Key": "Japan", "Value": "日本", "PageKey": 0, "List": []}, + {"Key": "Korea", "Value": "韓国", "PageKey": 0, "List": []}, + {"Key": "Laos", "Value": "ラオス", "PageKey": 0, "List": []}, + {"Key": "Cambodia", "Value": "カンボジアの村", "PageKey": 0, "List": []}, + {"Key": "Myanmar", "Value": "ミャンマー", "PageKey": 0, "List": []}, + {"Key": "Thailand", "Value": "タイ", "PageKey": 0, "List": []}, + {"Key": "Malaysia", "Value": "マレーシア", "PageKey": 0, "List": []}, + {"Key": "Singapore", "Value": "シンガポール", "PageKey": 0, "List": []}, + {"Key": "OtherCountries", "Value": "その他の国", "PageKey": 0, "List": []}, + {"Key": "UnitedStates", "Value": "アメリカ", "PageKey": 0, "List": []}, + {"Key": "HongKong", "Value": "香港、中国", "PageKey": 0, "List": []}, + {"Key": "Taiwan", "Value": "台湾、中国", "PageKey": 0, "List": []}, + {"Key": "Macao", "Value": "マカオ、中国", "PageKey": 0, "List": []} + ] + } +]; + +class WebData { + //私有构造函数 + WebData._internal(); + + Locale locale = Locale("en", "US"); + //保存单例 + static WebData _singleton = new WebData._internal(); + + //工厂构造函数 + factory WebData() => _singleton; + //职业 + Map professionCate = {}; + Map professionList = {}; + + //约会节目 + Map dateItemMap = {}; + + //期待对象 + Map loverPeopleMap = {}; + + //约会范围 + Map provinces = {}; + Map cities = {}; + + //身高数据 + Map heightData = { + "0": "不显示", + }; + Map heightListData = { + '0': { + "100000": {"name": 'test'} + }, + }; + + //银行数据 + Map bankData = {}; + Map bankListData = {}; + + //体重数据 + Map weightData = { + "0": "不显示", + }; + + Map weightListData = { + '0': { + "100000": {"name": 'test'} + }, + }; + + Map res = {}; + //获取时间范围 + Map getDateTime(BuildContext context) { + res[1] = I18n.of(context).morning; + res[2] = I18n.of(context).noon; + res[3] = I18n.of(context).afternoon; + res[4] = I18n.of(context).night; + res[5] = I18n.of(context).overnight; + res[6] = I18n.of(context).all_day; + return res; + } + + String getDateString(BuildContext context, int type) { + String res; + switch (type) { + case 1: + res = I18n.of(context).morning; + break; + case 2: + res = I18n.of(context).noon; + break; + case 3: + res = I18n.of(context).afternoon; + break; + case 4: + res = I18n.of(context).night; + break; + case 5: + res = I18n.of(context).overnight; + break; + case 6: + res = I18n.of(context).all_day; + break; + default: + } + return res; + } + + //检测是否超时 + bool testTimeOver(int type, String time) { + //如果是一整天直接返回 + //上午 [0 ,11) + //中午 [11, 13) + //下午 [13,17) + //晚上 [17,20) + //通宵 [20,24) + var list = time.split('-'); + int year = int.parse(list[0]); + int month = int.parse(list[1]); + int day = int.parse(list[2]); + var now = DateTime.now(); + switch (type) { + case 1: + return now.isAfter(DateTime(year, month, day, 11)); + case 2: + return now.isAfter(DateTime(year, month, day, 13)); + case 3: + return now.isAfter(DateTime(year, month, day, 17)); + case 4: + return now.isAfter(DateTime(year, month, day, 20)); + case 5: + return now.isAfter(DateTime(year, month, day, 24)); + break; + case 6: + return false; + default: + return true; + } + } + + deleteDemain(String url) { + for (int i = 0; i < 3; i++) { + int index = url.indexOf('/'); + url = url.substring(index + 1); + } + return url; + } + + getDistanceString(double distance) { + return (distance > 1000 + ? ('${(distance ~/ 1000).toInt()}km') + : '${distance.toInt()}m'); + } + + changeLoaction(int code) { + var location; + String str; + switch (code) { + case LanguageType.English: + location = Locale("en", "US"); + str = 'Hidden'; + break; + case LanguageType.Vietnamese: + location = Locale("vi", "VN"); + str = 'Không hiển thị'; + break; + case LanguageType.TraditionalChinese: + location = Locale("zh", "HK"); + str = '不顯示'; + break; + case LanguageType.SimplifiedChinese: + location = Locale("zh", "CN"); + str = '不显示'; + break; + case LanguageType.Korean: + location = Locale("ko", "KR"); + str = '표시하지 않음'; + break; + case LanguageType.Japanese: + location = Locale("ja", "JP"); + str = '表示しない'; + break; + default: + location = Locale("en", "US"); + str = 'Hidden'; + break; + } + locale = location; + heightData['0'] = str; + weightData['0'] = str; + I18n.onLocaleChanged(locale); + } + + //获取评价值 + getEvaluation(BuildContext context, String str) { + if (str == '') { + return ''; + } + var res = ''; + List list = str.split('|'); + list.forEach((f) { + var temp = ''; + switch (f) { + case 'Friendly': + temp = I18n.of(context).friendly; + break; + case 'Interesting': + temp = I18n.of(context).interesting; + break; + case 'Refreshing': + temp = I18n.of(context).readily; + break; + case 'Patience': + temp = I18n.of(context).patient; + break; + case 'Hello': + temp = I18n.of(context).lie; + break; + case 'Unfriendly': + temp = I18n.of(context).unfriendly; + break; + default: + } + res += res == '' ? temp : ('/' + temp); + }); + return res; + } + + //获取节目名字 + getProgramName(BuildContext context, int type) { + String res = ''; + switch (type) { + case 0: + res = I18n.of(context).healthy_exercise; + break; + case 1: + res = I18n.of(context).night_party; + break; + case 2: + res = I18n.of(context).gourmet_party; + break; + case 3: + res = I18n.of(context).watch_movie; + break; + case 4: + res = I18n.of(context).play_games; + break; + case 5: + res = I18n.of(context).travel_together; + break; + case 6: + res = I18n.of(context).voice_chat; + break; + case 7: + res = I18n.of(context).other; + break; + } + return res; + } + + //获取星座 + getConstellation(BuildContext context, type) { + if (type == null || type == '') return ""; + if (type is String) type = int.parse(type); + + String res = ''; + switch (type) { + case 1: + res = I18n.of(context).aquarius; + break; + case 2: + res = I18n.of(context).pisces; + break; + case 3: + res = I18n.of(context).aries; + break; + case 4: + res = I18n.of(context).taurus; + break; + case 5: + res = I18n.of(context).gemini; + break; + case 6: + res = I18n.of(context).cancer; + break; + case 7: + res = I18n.of(context).leo; + break; + case 8: + res = I18n.of(context).virgo; + break; + case 9: + res = I18n.of(context).libra; + break; + case 10: + res = I18n.of(context).scorpio; + break; + case 11: + res = I18n.of(context).sagittarius; + break; + case 12: + res = I18n.of(context).capricorn; + break; + default: + } + return res; + } + + //获取职业名称 + getProffesionName(String str) { + if (str == '' || str == null) return ''; + var result = ''; + try { + var list = str.split('-'); + result = professionList[list[0]][list[1]]; + } catch (e) {} + return result; + } + + getProgram(String str) { + if (str == '' || str == null) return str; + var list = str.split(','); + String result = ''; + list.forEach((item) { + result += result == '' ? dateItemMap[item] : '/${dateItemMap[item]}'; + }); + return result; + } + + //获取期待对象 + getLovePeople(String str) { + if (str == '' || str == null) return str; + var list = str.split(','); + String result = ''; + list.forEach((item) { + result += + result == '' ? loverPeopleMap[item] : '/${loverPeopleMap[item]}'; + }); + return result; + } + + formatTimeString(int second) { + if (second < 10) { + return '00:0$second'; + } + if (second < 60) { + return '00:$second'; + } + } + + getCity(String city) { + if (city == '' || city == null) city = "HoChiMinhCIty"; + return getDateRange("VietNam-" + city); + } + + getCountry(String country) { + if (country == '' || country == null) country = "VietNam"; + return provinces[country]; + } + + getDateRange(String str) { + if (str == '' || str == null) return ''; + var list = str.split(','); + String result = ''; +// print('cities length ${cities.length}'); +// print('cities all ${cities}'); +// print('cities length ${cities['China']}'); + list.forEach((item) { + var city = item.split('-'); + Map map = cities[city[0]]; + + ///ios点击上传相册回来后 中国的数据会丢失 + if (!map.containsKey(city[1])) { + result = '中国'; + return; + } + result += result == '' + ? cities[city[0]][city[1]] + : '/${cities[city[0]][city[1]]}'; + }); + return result; + } + + bool isThreeDayAgo(String loginStr) { + var temp = DateTime.parse(loginStr); + var logindate = DateTime.utc(temp.year, temp.month, temp.day, temp.hour, + temp.minute, temp.second, temp.millisecond, temp.microsecond); + var now = DateTime.now().toUtc().add(Duration(hours: 8)); + + var diff = now.difference(logindate); + + return diff.inDays > 3; + } + + String getLoginTime(BuildContext context, String loginStr) { + if (loginStr == null || loginStr == '') return ''; + var temp = DateTime.parse(loginStr); + var logindate = DateTime.utc(temp.year, temp.month, temp.day, temp.hour, + temp.minute, temp.second, temp.millisecond, temp.microsecond); + var now = DateTime.now().toUtc().add(Duration(hours: 8)); + + var diff = now.difference(logindate); + //刚刚 + if (diff.inMinutes == 0) { + return I18n.of(context).just; + } + //xx分钟前 + if (diff.inHours == 0) { + return I18n.of(context) + .minute_ago + .replaceFirst('/s1', diff.inMinutes.toString()); + } + //xx小时前 + if (diff.inDays == 0) { + return I18n.of(context) + .hour_ago + .replaceFirst('/s1', diff.inHours.toString()); + } + //xx天前 + return I18n.of(context).day_ago.replaceFirst('/s1', diff.inDays.toString()); + } + + String subUserName(String name, {int size = 8}) { + return name.length > size ? name.substring(0, size) + '...' : name; + } + + initLocalData() { + var data = constData[UserData().language]; + initCity(data['city']); + initProgram(data['program']); + initLovePeople(data['lovePeople']); + initJob(data['job']); + } + + initCity(list) { + list.forEach((item) { + provinces[item['Key']] = item['Value']; + Map map = {}; + item['List'].forEach((data) { + map[data['Key']] = data['Value']; + }); + cities[item['Key']] = map; + }); + } + + initProgram(list) { + list.forEach((item) { + dateItemMap[item['Key']] = item['Value']; + }); + } + + initLovePeople(list) { + list.forEach((item) { + loverPeopleMap[item['Key']] = item['Value']; + }); + } + + initJob(list) { + list.forEach((item) { + professionCate[item['Key']] = item['Value']; + Map map = {}; + item['List'].forEach((data) { + map[data['Key']] = data['Value']; + }); + professionList[item['Key']] = map; + }); + } + + getAllData() { + changeLoaction(UserData().language); + initLocalData(); + //获取约会范围 + _getSelectData(4, (List list) { + initCity(list); + }); + + //获取约会节目 + _getSelectData(1, (List list) { + initProgram(list); + }); + + //获取期待对象 + _getSelectData(2, (List list) { + initLovePeople(list); + }); + + //获取职业 + _getSelectData(3, (List list) { + initJob(list); + }); + + _getBankInfo(); + + _getSystemSetting(); + + //初始化身高数据 + for (int i = 140; i <= 230; i++) { + heightData[i.toString()] = '${i}CM'; + heightListData[i.toString()] = { + "100000": {"name": 'test'} + }; + } + + //初始化体重数据 + for (int i = 30; i <= 120; i++) { + weightData[i.toString()] = '${i}KG'; + weightListData[i.toString()] = { + "100000": {"name": 'test'} + }; + } + } + + _getBankInfo() async { + Map data = { + "language": UserData().language, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('wallet/bank/info', data: data); + if (res == null) { + return; + } + Map resData = res.data; + if (resData['code'] == 0 && resData['data'] != null) { + //初始化银行数据 + for (int i = 0; i < resData['data'].length; i++) { + var rdata = resData['data'][i]; + bankData['${rdata['BId']}'] = '${rdata['BankName']}'; + bankListData['${rdata['BId']}'] = { + "100000": {"name": 'test'} + }; + } + } + } + + _getSystemSetting() async { + Map data = { + "language": UserData().language, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('system/parameter/config', data: data); + if (res == null) { + return; + } + Map resData = res.data; + print(resData); + if (resData['code'] == 0 && resData['data'] != null) { + UserData().inviteCodePrice = resData['data']['InviteCode']; + UserData().accountPrice = resData['data']['AccountPrice']; + UserData().redPhotoPrice = resData['data']['RedPhotoPrice']; + UserData().addProgramPrice = resData['data']['PublishPrice']; + } + } + + _getSelectData(type, callback) async { + var data = { + "language": UserData().language, + "type": type, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('type/getlanguagelist', data: data); + if (res == null) { + return; + } + Map resData = res.data; + if (resData['code'] == 0) { + callback(resData['data']); + } + } +} diff --git a/lib/data/chat_data_mgr.dart b/lib/data/chat_data_mgr.dart new file mode 100644 index 0000000..509a570 --- /dev/null +++ b/lib/data/chat_data_mgr.dart @@ -0,0 +1,395 @@ +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/last_msg_provider.dart'; +import 'package:chat/models/unread_count_provider.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/sql_util.dart'; + +class ChatDataMgr { + static ChatDataMgr _instance; + + static ChatDataMgr _getInstance() { + if (_instance == null) { + _instance = ChatDataMgr._(); + } + return _instance; + } + + bool _isInit = false; + + factory ChatDataMgr() => _getInstance(); + + ChatDataMgr._(); + + //私聊最新消息 + LastMsgProvider lastMsgProvider; + + UnreadCountProvider unreadCountProvider; //私人未读消息 + UnreadCountProvider groupUnreadProvider; //群聊未读消息 + + //私聊记录 + Map> msgRecordMap; + //群聊记录 + Map> groupRecordMap; + + //获取本地聊天数据 + initMsg() async { + if (!_isInit) { + _isInit = true; + + print('初始化本地聊天记录'); + lastMsgProvider = LastMsgProvider(); + + unreadCountProvider = UnreadCountProvider(); + groupUnreadProvider = UnreadCountProvider(); + + initLocalMsg(); + } + } + + initLocalMsg() async { + msgRecordMap = await SqlUtil.getAllRecord(isGroup: false); + groupRecordMap = await SqlUtil.getAllRecord(isGroup: true); + print('查询本地未读消息'); + + initUnreadCount(); + initGroupUnreadCount(); + + getLastRecord(); + } + + + //初始化私聊未读消息 + initUnreadCount() async { + var unreadCountMap = await SqlUtil.getUnreadCount(false); + + unreadCountMap.forEach((k, v) { + unreadCountProvider.updateUnreadCount(k, v); + }); + } + + //初始化群聊未读消息 + initGroupUnreadCount() async { + var unreadCountMap = await SqlUtil.getUnreadCount(true); + + unreadCountMap.forEach((k, v) { + groupUnreadProvider.updateUnreadCount(k, v); + }); + } + + logout() { + GroupInfoMgr().clear(); + unreadCountProvider.clear(); + groupUnreadProvider.clear(); + lastMsgProvider.clear(); + msgRecordMap.clear(); + groupRecordMap.clear(); + + _isInit = false; + } + + //获取私聊记录 + List getRecord() { + var record = msgRecordMap[MsgHandler.curActiveSession]; + if (record == null) { + record = []; + msgRecordMap[MsgHandler.curActiveSession] = record; + } + return record; + } + + //获取群聊记录 + List getGroupRecord() { + var record = groupRecordMap[MsgHandler.curActiveSession]; + if (record == null) { + record = []; + groupRecordMap[MsgHandler.curActiveSession] = record; + } + return record; + } + + //获取企业号聊天记录 + List getCompanyRecord() { + var record = msgRecordMap[MsgHandler.curActiveSession]; + if (record == null) { + record = []; + msgRecordMap[MsgHandler.curActiveSession] = record; + } + return record; + } + + updateLastMsgWithTranslateMsg(PushChat chat) async { + if (chat.channelType == ChatChannelType.Group) { + var groupInfo = await GroupInfoMgr().getGroupInfo(chat.targetId); + if (groupInfo != null) { + groupInfo.updateLastMsgWithTransMsg(chat); + } + } else { + lastMsgProvider.updateWithTranslateMsg(chat); + } + } + + //标记消息已读 + signRead(int sessionId, {bool isGroup = false}) { + print('消除未读标记:$sessionId 群$isGroup'); + + SqlUtil().updateReadState(sessionId, isGroup: isGroup); + + //获取消息列表 + List recordList; + if (isGroup) { + recordList = getGroupRecord(); + } else { + recordList = getRecord(); + } + for (var i = 0; i < recordList.length; i++) { + var record = recordList[i]; + if (record.readState == 1) { + record.readState = 0; + } + } + + if (isGroup) { + print('群消息'); + groupUnreadProvider.signRead(sessionId); + MessageMgr().emit('Update Unread Msg Count'); + //to do + } else { + unreadCountProvider.signRead(sessionId); + MessageMgr().emit('Update Unread Msg Count'); + } + } + + getLastMsg(int sessionId, isGroup) { + if (isGroup) { + var record = groupRecordMap[sessionId]; + if (record != null && record.length > 0) { + return record.first; + } + } else { + var record = msgRecordMap[sessionId]; + if (record != null && record.length > 0) { + return record.first; + } + } + + return null; + } + + //获得最新一条聊天记录, 先读取历史消息 + getLastRecord() { + List recordList = []; + + if (msgRecordMap == null) { + msgRecordMap = {}; + } + msgRecordMap.values.forEach((record) { + recordList.add(record.first); + }); + + for (var i = 0; i < recordList.length; i++) { + MsgModel msgModel = recordList[i]; + lastMsgProvider.addMsg(msgModel); + } + + lastMsgProvider.sortLastMsg(); + } + + //更新红包消息状态 + void updateRedWalletMsg( + int sessionId, String walletId, RedWalletState state) { + //获取消息列表 + List recordList = getRecord(); + for (var i = 0; i < recordList.length; i++) { + var record = recordList[i]; + + if (record.msgType == ChatType.RedWalletChatType.value) { + //系统红包通知消息 + RedWallet wallet = RedWallet.fromBuffer(record.msgContent); + if (wallet.orderId == walletId) { + wallet.state = state; + } + record.msgContent = wallet.writeToBuffer(); + + MessageMgr().emit('Update RedWalletState', wallet); + + SqlUtil().updateWalletState(record); + + break; + } + } + } + + //处理未读消息 + updateRecordWithUnreadMsg(List noticeList) async { + var unreadCount = noticeList.length; + + print('更新未读消息$unreadCount'); + + for (var i = 0; i < unreadCount; i++) { + var unread = noticeList[i]; + + if (unread.channelType == ChatChannelType.Group) { + print('群聊未读消息'); + var groupInfo = await GroupInfoMgr().getGroupInfo(unread.targetId); + if (groupInfo != null) { + groupInfo.updateLastMsgWithUnread(unread); + } + if (unread.targetId != MsgHandler.curActiveSession) { + groupUnreadProvider.updateUnreadCount( + unread.targetId, unread.unreadMsgNum); + } else { + MsgHandler.getUnreadMsgDetail(true); + } + } else { + print('私聊未读消息'); + lastMsgProvider.addUnreadMsg(unread); + if (unread.targetId != MsgHandler.curActiveSession) { + unreadCountProvider.updateUnreadCount( + unread.targetId, unread.unreadMsgNum); + } else { + MsgHandler.getUnreadMsgDetail(false); + } + } + } + } + + //保存反馈助手聊天信息 + saveCompanyMsg(MsgModel msg) { + var record = msgRecordMap[msg.sessionId]; + if (record == null) { + record = []; + msgRecordMap[msg.sessionId] = record; + } + var result = getMsgBy(msg.sessionId, msg.time, false); + if (result == null) { + insertToDB(msg, record); + } + } + + //保存本地聊天数据 + saveMsg(MsgModel msg) { + if (msg.channelType == ChatChannelType.Group.value) { + var record = groupRecordMap[msg.sessionId]; + + if (record == null) { + record = []; + groupRecordMap[msg.sessionId] = record; + } + var result = getMsgBy(msg.sessionId, msg.time, true); + if (result != null) { + // print('消息存在!!!!'); + } else { + insertToDB(msg, record); + } + } else { + var record = msgRecordMap[msg.sessionId]; + + if (record == null) { + record = []; + msgRecordMap[msg.sessionId] = record; + } + var result = getMsgBy(msg.sessionId, msg.time, false); + if (result != null) { + // print('消息存在!!!!'); + } else { + insertToDB(msg, record); + } + } + } + + updateMsgState(int sessionId, int time, int channelType, int state) { + SqlUtil().updateMsgState(sessionId, time, state, + isGroup: channelType == ChatChannelType.Group.value); + + MessageMgr().emit('Update Chat Message State', + {'sessionId': sessionId, 'time': time, 'state': state}); + } + + insertToDB(MsgModel msg, List record) { + if (msg.sessionId == null) { + print('数据为空,无法插入'); + } else { + record.insert(0, msg); + + SqlUtil.insert(msg); + + updateLastRecordWithMsg(msg); + } + } + + MsgModel getMsgBy(int sessionId, int timestamp, bool isGroup) { + var record; + if (isGroup) { + record = groupRecordMap[sessionId]; + } else { + record = msgRecordMap[sessionId]; + } + + if (record != null) { + for (var i = 0; i < record.length; i++) { + MsgModel msg = record[i]; + if (msg.time == timestamp) { + return msg; + } + } + } + + return null; + } + + //删除本地聊天消息 + deleteMsg(int sessionId, bool isGroup) { + SqlUtil().delteRecord(sessionId, isGroup: isGroup); + + if (isGroup) { + var record = groupRecordMap[sessionId]; + + if (record != null) { + record.clear(); + } + groupUnreadProvider.signRead(sessionId); + } else { + var record = msgRecordMap[sessionId]; + if (record != null) { + record.clear(); + } + unreadCountProvider.signRead(sessionId); + } + } + + //删除所有聊天消息 + deleteAllRecord() { + //未读数据 + groupUnreadProvider.clear(); + unreadCountProvider.clear(); + + //聊天记录 + msgRecordMap.clear(); + groupRecordMap.clear(); + + //数据库 + SqlUtil.chatDataTableModel.clear(); + } + + //更新最后一条记录 + updateLastRecordWithMsg(MsgModel msgModel) async { + if (msgModel == null) { + print('消息为空,无法更新'); + } + if (msgModel.channelType == ChatChannelType.Group.value) { + var groupInfo = await GroupInfoMgr().getGroupInfo(msgModel.sessionId); + groupInfo.updateLastMsg(msgModel); + if (msgModel.readState == 1) { + groupUnreadProvider.updateUnreadCount(msgModel.sessionId, 1); + } + } else { + lastMsgProvider.updateLastMsg(msgModel); + if (msgModel.readState == 1) { + unreadCountProvider.updateUnreadCount(msgModel.sessionId, 1); + } + } + } +} diff --git a/lib/data/constants.dart b/lib/data/constants.dart new file mode 100644 index 0000000..3f67ccd --- /dev/null +++ b/lib/data/constants.dart @@ -0,0 +1,375 @@ +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/date_utils.dart'; +import 'package:flutter/material.dart'; + +class AppColors { + static const BackgroundColor = Color(0xFFeeeeee); + static const RefreshBgColor = Color(0xFFF4F4F4); + static const AppBarColor = 0xff303030; + static const TabIconNormal = 0xff999999; + static const TabIconActive = 0xff46c11b; + static const AppBarPopupMenuColor = 0xffffffff; + static const TitleColor = Color(0xff353535); + static const ConversationItemBgColor = 0xffffffff; + static const DescTextColor = 0xff9e9e9e; + static const DividerColor = Color(0xffd9d9d9); + static const NewAppbarBgColor = Colors.white; + static const NewAppbarTextColor = Colors.black; + static const ChatItemBgColor = Color(0xffF75F92); + static const NotifyDotBgColor = 0xffff3e3e; + static const NotifyDotText = 0xffffffff; + static const ConversationMuteIconColor = 0xffd8d8d8; + static const DeviceInfoItemBgColor = 0xfff5f5f5; + static const DeviceInfoItemTextColor = 0xff606062; + static const DeviceInfoItemIconColor = 0xff606062; + static const ContactGroupTitleBgColor = 0xffebebeb; + static const ContactGroupTitleColor = 0xff888888; + static const IndexLetterBoxBgColor = Colors.black45; +} + +class AppStyles { + static const TitleStyle = TextStyle( + fontSize: 14.0, + color: AppColors.TitleColor, + ); + + static const DescStyle = TextStyle( + fontSize: 12.0, + color: Constants.GreyTextColor, + ); + static const UnreadMsgCountDotStyle = TextStyle( + fontSize: 11.0, + color: Color(AppColors.NotifyDotText), + ); + + static const DeviceInfoItemTextStyle = TextStyle( + fontSize: 13.0, + color: Color(AppColors.DeviceInfoItemTextColor), + ); + static const GroupTitleItemTextStyle = + TextStyle(color: Color(AppColors.ContactGroupTitleColor), fontSize: 14.0); + + static const IndexLetterBoxTextStyle = TextStyle( + fontSize: 64.0, + color: Colors.white, + ); +} + +class ComId { + static const int Heart = 0; + static const int Login = 1; + static const int Chat = 2; + static const int PushMsg = 100; +} + +enum ChatState { + connecting, //连接中 + connected, //连接成功 + connectFailed, //连接失败 + logining, //登录中 + logined, //登录成功 + loginFailed //登录失败 +} + +//语言类别 +class LanguageType { + static const int English = 0; //英语 + static const int Vietnamese = 1; //越南语 + static const int TraditionalChinese = 2; //繁体中文 + static const int SimplifiedChinese = 3; //简体中文 + static const int Korean = 4; //韩语 + static const int Japanese = 5; //日语 +} + +//群管理界面类别 +class GroupOperatingPageType { + static const int AddMember = 0; //增加新的成员 + static const int DeleteMember = 1; //删除新的成员 + static const int SelectGroupOwner = 2; //选择群主 + static const int CreateGroup = 3; //创建群组 +} + +//消息发送界面类别 +class SendMessagePageType { + static const int AddFriends = 0; //添加朋友 + static const int ChangeGroupName = 1; //修改群名字 + static const int ChangeGroupNickName = 2; //修改群昵称 +} + +//全局搜索类别 +class GlobalSearchPageType { + static const int SearchMyFriends = 0; //查找我的好友成员 + static const int SearchGroup = 1; //查找群 + static const int SearchNewFriends = 2; //查找新的好友 +} + +const String googleMapApiKey = 'AIzaSyAb9JNtW0BEZ_qLeDg87ZhvxSmZply-7hU'; + +class Constants { + ///ture 应用商店版本 false线下渠道 + static const bool isStoreVersion = false; + + ///在pubspec.yaml中修改版本号 + static String versionName = '1.0.0'; + + static bool isSandbox = false; + + static String packageName = 'com.cyhd.henhoandroid'; + + static const IconFontFamily = "iconFont"; + static const ConversationAvatarSize = 48.0; + static const DividerWidth = 0.5; + static const UnReadMsgNotifyDotSize = 22.0; + static const ConversationMuteIcon = 18.0; + static const ContactAvatarSize = 36.0; + static const IndexBarWidth = 24.0; + static const IndexLetterBoxSize = 114.0; + static const IndexLetterBoxRadius = 4.0; + static const FullWidthIconButtonIconSize = 24.0; + static const ProfileHeaderIconSize = 60.0; + + static const AppId = 'wx02328a8853f058ad'; + static const Secret = '9d401b6a8bfe7b2fe63b3bf5c040b2f2'; + + static const CloseLoaindTime = 250; + + static const VipColor = const Color(0xFFFA9F00); + //背景色 + static const LightGreyBackgroundColor = const Color(0xfffafafa); + static const GreyBackgroundColor = const Color(0xFFF0F0F0); + static const PurpleBackgroundColor = const Color(0xFFEC4163); + static const LightBlueBackgroundColor = const Color(0xFFEDF6FE); + + //字体颜色 + static const GreyTextColor = const Color(0xFF848486); + static const BlackTextColor = const Color(0xFF1B201F); + static const RedTextColor = const Color(0xFFFD959F); + static const YellowTextColor = const Color(0xFFCDBD75); + static const BlueTextColor = const Color(0xFF008AFF); + static const LightBlueTextColor = const Color(0xFF88A3BC); + static const LightGreyTextColor = const Color(0xFFB0B0B0); + static const OpacityBlueTextColor = const Color(0xFFB7DEFF); + static const PinkTextColor = const Color(0xFFEB71BD); + + //图标颜色 + static const BlueIconColor = const Color(0xFF86B3D9); + static const LightBlueIconColor = const Color(0xFFB6DDFF); + + static const MainTitleStyle = TextStyle( + fontSize: 20.0, + color: Constants.BlackTextColor, + fontWeight: FontWeight.w500); + + //分割线颜色 + static const DividerLineColor = const Color(0xFFE8E8E8); + static const GreyBorderSide = + BorderSide(color: const Color(0xFFF3F3F3), width: 1); + + //按钮颜色 + static const ConfrimButtonColor = const Color(0xFF3875E9); + static const CancleButtonColor = Colors.grey; + static const LightBlueButtonColor = const Color(0xFF6EBCFF); + + //按钮 + static const ConfirmBUttonBoxDecoration = BoxDecoration( + color: Constants.ConfrimButtonColor, + borderRadius: BorderRadius.all(Radius.circular(LittleButtonRadius))); + + static const BottomIconGreyColor = const Color(0xffa0a0a0); + + static const LittleButtonRadius = 5.0; + static const BigButtonRadius = 8.0; + + //tabbar样式 + static const SelectTabBarTextStyle = TextStyle(fontSize: 14); + static const UnselectTabBarTextStyle = TextStyle(fontSize: 14); + + static const AppBarActionTextStyle = + TextStyle(color: BlueTextColor, fontSize: 14.9); + + static const double ShaderButtonHeight = 49.15; + static const double ShaderButtonFontSize = 18; + + static const TextFieldIconSize = 20.0; + + //图片 + static const DefaultHeadImgUrl = 'assets/images/default_nor_avatar.png'; + + //类别颜色 + static const Category1Color = const Color(0xFF3D9BE2); + static const Category2Color = const Color(0xFF934DDA); + static const Category3Color = const Color(0xFF5B6AEB); + static const Category4Color = const Color(0xFFE66C84); + static const Category5Color = const Color(0xFFD4915E); + static const Category6Color = const Color(0xFF3AB364); + static const Category7Color = const Color(0xFF59B1FA); + static const Category8Color = const Color(0xFF676666); + + //系统消息渐变 + static const RadioGradient = LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFF58B7F5), + const Color(0xFF1874C9), + ]); + + static const MoneyGradient = LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFF6171F1), + const Color(0xFF3441C1), + ]); + static const ApplyGradient = LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFFED7990), + const Color(0xFFC22444), + ]); + static const EvaGradient = LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFF1BC79F), + const Color(0xFF078D75), + ]); + static const ParkGradient = LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFFFBC535), + const Color(0xFFE67430), + ]); + + //本地存储key + static const KeyboardHeight = 'KeyboardHeight'; + static const AutoLoginKey = 'autoLoginKey'; + static const Language = 'language'; + static const LocalUserId = 'localUserId'; + + static const ApplyCount = 'applyCount'; + static const EvaluateCount = 'evaluateCount'; + static const ParkCount = 'parkCount'; + static const CastCount = 'castCount'; + static const WalletCount = 'walletCount'; + + static const IOS_IAP_Receipt = 'iosIAPReceipt'; + static const SOUND_PLAY_MODE = 'isSoundReceiver'; //false外放-ture声筒 + + static const ContactNum = 'ConstantNum'; //本地存储通讯录数量 + + static const NewFriendsList = 'NewFriendsList'; //本地缓存的新朋友列表 + + static const Splash_OPENED = 'splashOpened_13'; //是否加载过引导页 + static const LocalUsrInfo = 'LocalUsrInfo'; //本地用户数据 + + //定位获取太慢,缓存经纬度 + static const Latitude = 'Latitude'; + static const Longitude = 'Longitude'; + + /// currentGoodsId+'@'+receipt+'@'+purchaseToken + + static final vipIcon = Image.asset( + 'assets/images/VIP.png', + height: 11.5, + ); + + static final svipIcon = Padding( + padding: EdgeInsets.only(bottom: 5.5), + child: Image.asset( + 'assets/images/svip.png', + height: 14, + ), + ); + + static const ConversationAvatarDefaultIocn = Icon( + IconData( + 0xe642, + fontFamily: IconFontFamily, + ), + size: ConversationAvatarSize, + ); + + static const ContactAvatarDefaultIocn = Icon( + IconData( + 0xe642, + fontFamily: IconFontFamily, + ), + size: ContactAvatarSize, + ); + + static const ProfileAvatarDefaultIocn = Icon( + IconData( + 0xe642, + fontFamily: IconFontFamily, + ), + size: ProfileHeaderIconSize, + ); + + static const Agore_appId = '7564ab9804b6455ba337ff39aad2779b'; + + //一些公共函数 + static getShowTime(int msgTime, BuildContext context) { + var showTime; + + DateTime now = DateTime.now(); + DateTime time = DateTime.fromMillisecondsSinceEpoch(msgTime); + + if (now.year != time.year) { + showTime = DateUtils().getFormartData(timeSamp: msgTime, format: 'yyyy'); + } else { + if (now.month != time.month) { + showTime = + DateUtils().getFormartData(timeSamp: msgTime, format: 'MM/dd'); + } else { + int days = now.day - time.day; + if (days != 0) { + showTime = + I18n.of(context).day_ago.replaceFirst('/s1', days.toString()); + } else { + showTime = + DateUtils().getFormartData(timeSamp: msgTime, format: 'HH:mm'); + } + } + } + + return showTime; + } +} + +const INDEX_BAR_WORDS = [ + "↑", + "#", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + " " +]; + +const double MARGIN_VERTICAL = 10.0; +const double GROUP_TITLE_HEIGHT = 24.0; diff --git a/lib/data/conversation.dart b/lib/data/conversation.dart new file mode 100644 index 0000000..e6034a7 --- /dev/null +++ b/lib/data/conversation.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import './constants.dart'; + +enum Device { MAC, WIN } + +class Conversation { + final String avatar; + final String title; + final Color titleColor; + final String desc; + final String updateAt; + final int unreadMsgCount; + final bool dispalyDot; + + const Conversation( + {@required this.avatar, + @required this.title, + this.titleColor: AppColors.TitleColor, + this.desc, + @required this.updateAt, + this.unreadMsgCount: 0, + this.dispalyDot: false}) + : assert(avatar != null), + assert(title != null), + assert(updateAt != null); + + bool isAvatarFromNet() { + if (this.avatar.indexOf('http') == 0 || this.avatar.indexOf('https') == 0) { + return true; + } + return false; + } +} + +class ConversationPageData { + final Device device; + final List conversations; + + const ConversationPageData({ + this.device, + this.conversations, + }); + +} diff --git a/lib/data/gift_data_mgr.dart b/lib/data/gift_data_mgr.dart new file mode 100644 index 0000000..424ee4f --- /dev/null +++ b/lib/data/gift_data_mgr.dart @@ -0,0 +1,55 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/models/gift_item_model.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:dio/dio.dart'; + +class GiftMgr { + static GiftMgr _instance; + static GiftMgr _getInstance() { + if (_instance == null) { + _instance = GiftMgr._(); + } + return _instance; + } + + factory GiftMgr() => _getInstance(); + GiftMgr._(); + + static Map giftMap = {}; + + Future> getGiftList() async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('prop/get/list', data: data); + + if (res == null) { + return null; + } + + Map resData = res.data; + if (resData['code'] == 0) { + //领取成功 + List giftList = resData['data'].map((v) { + var model = GiftItemModel.fromJson(v); + updateGiftMap(model); + return model; + }).toList(); + + return giftList; + } + + return null; + } + + updateGiftMap(GiftItemModel itemModel) { + giftMap[itemModel.id] = itemModel.name; + } + + getGiftName(int id) { + return giftMap[id] ?? ''; + } +} diff --git a/lib/data/group_data_mgr.dart b/lib/data/group_data_mgr.dart new file mode 100644 index 0000000..052abfe --- /dev/null +++ b/lib/data/group_data_mgr.dart @@ -0,0 +1,400 @@ +import 'dart:convert'; + +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/proto/chat.pbserver.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/group_member_model.dart'; +import 'package:chat/utils/sql_util.dart'; +import 'package:chat/utils/upload_util.dart'; +import 'package:crclib/crclib.dart'; + +class GroupInfoMgr { + static GroupInfoMgr _instance; + factory GroupInfoMgr() => _getInstance(); + + GroupInfoMgr._(); + static GroupInfoMgr _getInstance() { + if (_instance == null) { + _instance = GroupInfoMgr._(); + } + return _instance; + } + + List groupInfoList = []; + + bool isLoading = false; + bool isInit = false; + + initLocalGroupList() async { + if (isInit == true) { + return; + } + isInit = true; + var res = await SqlUtil.getAllGroupInfo(); + + for (var i = 0; i < res.length; i++) { + if (isGroupInList(res[i].sessionId)) { + print('群已添加,勿重复添加'); + } else { + groupInfoList.add(res[i]); + } + } + sortGroupList(); + } + + int getGroupCheckStr(int groupId) { + for (var group in groupInfoList) { + if (group.sessionId == groupId) { + group.members.sort((a, b) => a.memberId.compareTo(b.memberId)); + var checkStr = ''; + for (var member in group.members) { + if (member.inGroup > 0) { + checkStr = + '$checkStr${member.memberId}${member.refName}${member.identity}'; + } + } + checkStr = '${group.sessionId}${group.name}${group.describe}$checkStr'; + + return Crc32Zlib().convert(utf8.encode(checkStr)); + } + } + return -1; + } + + checkGroupValid() async { + if (groupInfoList.length > 0) { + //获取群校验信息 + var groupCheckMap = await UploadUtil().getGroupCheckInfo(); + + //获取无效群 + List invalidGroupList = []; + + groupCheckMap.forEach((key, serverCode) { + int groupId = int.parse(key); + int checkStr = getGroupCheckStr(groupId); + + if (checkStr != serverCode) { + print('群校验没有通过 $groupId :$checkStr : $serverCode'); + invalidGroupList.add(groupId); + clearGroupCache(groupId); + } + }); + + if (invalidGroupList.length > 0) { + List res = + await UploadUtil().getMoreGroupInfo(invalidGroupList); + if (res == null || res.length == 0) { + return; + } + for (var i = 0; i < res.length; i++) { + GroupInfoMgr().addGroup(res[i]); + } + + MessageMgr().emit('Update Group List'); + } + } else { + int localGroupCount = await SqlUtil.getGroupCount(); + if (localGroupCount == 0) { + print('本地数据没有群数据,从服务器拉取群数据'); + var infoList = await UploadUtil().getGroupList(); + if (infoList == null || infoList.length == 0) { + return; + } + + for (var i = 0; i < infoList.length; i++) { + GroupInfoMgr().addGroup(infoList[i]); + } + + MessageMgr().emit('Update Group List'); + } + } + } + + clearGroupCache(int groupId) async { + for (var i = 0; i < groupInfoList.length; i++) { + if (groupInfoList[i].sessionId == groupId) { + groupInfoList.removeAt(i); + } + } + SqlUtil.groupInfoTableModel.deleteGroup(groupId); + SqlUtil.groupMemberTableModel.deleteMembers(groupId); + } + + sortGroupList() { + print('排序开始'); + for (var item in groupInfoList) { + print(item.name); + } + groupInfoList.sort((GroupInfoModel a, GroupInfoModel b) { + if (a.topTag > b.topTag) { + return -1; + } else if (a.topTag < b.topTag) { + return 1; + } else { + if (a.lastMsg != null && b.lastMsg != null) { + if (a.lastMsg.updateAt > b.lastMsg.updateAt) { + return -1; + } else if (a.lastMsg.updateAt < b.lastMsg.updateAt) { + return 1; + } else { + return 0; + } + } else if (a.lastMsg == null) { + return 1; + } else if (b.lastMsg == null) { + return -1; + } else { + return 0; + } + } + }); + } + + //获取群中的好友名称 + String getGroupFdName(int sessionId, int fdId) { + GroupInfoModel group; + for (var i = 0; i < groupInfoList.length; i++) { + if (groupInfoList[i].sessionId == sessionId) { + group = groupInfoList[i]; + } + } + + if (group == null) { + print('getGroupFdName 没有找到该群'); + } else { + for (var member in group.members) { + if (member.memberId == fdId) { + return member.refName; + } + } + } + + print('没有找到群好友的名字'); + + return ''; + } + + //获取群信息 + Future getGroupInfo(int sessionId, + {bool isSave = true}) async { + if (groupInfoList.length == 0) { + print('当前没有群'); + } else { + for (var i = 0; i < groupInfoList.length; i++) { + if (groupInfoList[i].sessionId == sessionId) { + return groupInfoList[i]; + } + } + } + + var info = await UploadUtil().getGroupInfo(sessionId); + if (info != null) { + if (isSave) { + addGroup(info); + } + + return info; + } + + print('群不存在 $sessionId'); + return null; + } + + bool isGroupInList(int groupId) { + for (var i = 0; i < groupInfoList.length; i++) { + if (groupInfoList[i].sessionId == groupId) { + return true; + } + } + + return false; + } + + //保存群 + void addGroup(GroupInfoModel groupInfoModel) async { + if (isGroupInList(groupInfoModel.sessionId)) { + print('群已添加,勿重复添加'); + } else { + bool isValid = false; + for (GroupMemberModel member in groupInfoModel.members) { + if (member.inGroup != 0) { + isValid = true; + } + } + + if (isValid) { + groupInfoList.add(groupInfoModel); + + var lastMsg = ChatDataMgr().getLastMsg(groupInfoModel.sessionId, true); + groupInfoModel.updateLastMsg(lastMsg); + + bool isExist = await SqlUtil.groupInfoTableModel + .isExistGroup(groupInfoModel.sessionId); + if (!isExist) { + SqlUtil.groupInfoTableModel.addGroup(groupInfoModel); + SqlUtil.groupMemberTableModel.addMembers(groupInfoModel); + + print('创群成功!!! 成员数:${groupInfoModel.members.length}'); + } + } + } + } + + //删除群 + void deleteGroup(int groupId) async { + print('退出群聊 $groupId'); + + var groupInfoModel = await getGroupInfo(groupId); + + //清空聊天数据 + ChatDataMgr().deleteMsg(groupId, true); + + if (groupInfoModel != null) { + groupInfoList.remove(groupInfoModel); + SqlUtil.groupInfoTableModel.deleteGroup(groupId); + SqlUtil.groupMemberTableModel.deleteMembers(groupId); + + MessageMgr().emit('Update Group List'); + } + } + + deleteAllGroup() async { + print('清空所有群'); + + SqlUtil.groupInfoTableModel.clearSelfData(); + SqlUtil.groupMemberTableModel.clearSelfData(); + SqlUtil.groupChatTableModel.clearSelfData(); + + groupInfoList.clear(); + } + + //添加群成员 + void addMembers(int groupId, List members) async { + print('添加群成员 ${members.length}个'); + var groupInfo = await getGroupInfo(groupId); + if (groupInfo == null) { + print('群不存在'); + return; + } + cleanAvatar(groupInfo); + + for (var i = 0; i < members.length; i++) { + var member = GroupMemberModel.fromBaseInfo(members[i]); + print('添加群成员 ${member.nickName}'); + groupInfo.addMember(member); + } + + MessageMgr().emit('Update Group Info'); + } + + //自己被移出群 + void removeSelf(int groupId) async { + var groupInfo = await getGroupInfo(groupId); + if (groupInfo == null) { + print('群不存在'); + return; + } + + var myId = UserData().basicInfo.userId; + groupInfo.removeMember(myId); + groupInfo.isInGroup = false; + + MessageMgr().emit('Update Group Info'); + } + + //移出群成员 + void removeMembers(int groupId, List members) async { + print('移出群成员 ${members.length}个'); + + var groupInfo = await getGroupInfo(groupId); + if (groupInfo == null) { + print('群不存在'); + return; + } + cleanAvatar(groupInfo); + for (var i = 0; i < members.length; i++) { + groupInfo.removeMember(members[i].id); + print('移出群成员 ${members[i].niceName}'); + } + + MessageMgr().emit('Update Group Info'); + } + + //修改群名称 + void updateGroupName(int groupId, name) async { + print('修改群名称'); + + var groupInfo = await getGroupInfo(groupId); + if (groupInfo != null) { + groupInfo.updateGroupName(name); + } + + MessageMgr().emit('Update Group Info'); + } + + //修改群公告 + void updateGroupDescription(int groupId, String notice) async { + var groupInfo = await getGroupInfo(groupId); + if (groupInfo != null) { + groupInfo.updateGroupNotice(notice); + } + + MessageMgr().emit('Update Group Info'); + } + + //修改群成员别名 + void updateMemberRefName(int groupId, int uId, String refName) async { + var groupInfo = await getGroupInfo(groupId); + if (groupInfo != null) { + groupInfo.updateMemberRefName(uId, refName); + } + + MessageMgr().emit('Update Group Info'); + } + + //修改群校验开关 + void updateAskSwitch(int groupId, bool isOpen) async { + var groupInfo = await getGroupInfo(groupId); + if (groupInfo != null) { + groupInfo.updateAskSwitch(isOpen); + } + } + + //修改成员免打扰设置 + void updateMemberMsgFree(int groupId, bool isOpen) async { + var groupInfo = await getGroupInfo(groupId); + if (groupInfo != null) { + groupInfo.updateMemberMsgFree(isOpen ? 1 : 0); + } + } + + //修改群主 + void updateGroupMaster(int groupId, int oldId, int uId) async { + var groupInfo = await getGroupInfo(groupId); + if (groupInfo != null) { + groupInfo.updateGroupHoster(oldId, uId); + } + } + + //更新头像 + void updateAvatar(int groupId, String path) async { + var groupInfo = await getGroupInfo(groupId); + if (groupInfo != null) { + groupInfo.updateAvatar(path); + } + } + + void cleanAvatar(GroupInfoModel groupInfo) { + if (groupInfo != null) { + print('@@清除群头像'); + groupInfo.cleanAvatar(); + } + } + + clear() { + groupInfoList.clear(); + isInit = false; + } +} diff --git a/lib/data/robot_chat_mgr.dart b/lib/data/robot_chat_mgr.dart new file mode 100644 index 0000000..b07ce85 --- /dev/null +++ b/lib/data/robot_chat_mgr.dart @@ -0,0 +1,37 @@ +class RobotChatModel { + var msgContent; + int extraInfo; + bool isMe; + int type;//0文本,1声音 + + RobotChatModel({this.msgContent, this.extraInfo,this.isMe,this.type=0}); + + fromJson(Map json) { + msgContent = json['msgContent']; + } +} + +class RobotChatMgr { + static RobotChatMgr _instance; + + static RobotChatMgr _getInstance() { + if (_instance == null) { + _instance = RobotChatMgr._(); + } + return _instance; + } + + factory RobotChatMgr() => _getInstance(); + + RobotChatMgr._(); + + List robotChatList = []; + + addSource(RobotChatModel msg) { + robotChatList.insert(0,msg); + } + + addTranslate(RobotChatModel msg) { + robotChatList.insert(0,msg); + } +} diff --git a/lib/generated/i18n.dart b/lib/generated/i18n.dart new file mode 100644 index 0000000..66a89a1 --- /dev/null +++ b/lib/generated/i18n.dart @@ -0,0 +1,19916 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: camel_case_types +// ignore_for_file: prefer_single_quotes +// ignore_for_file: unnecessary_brace_in_string_interps + +//WARNING: This file is automatically generated. DO NOT EDIT, all your changes would be lost. + +typedef void LocaleChangeCallback(Locale locale); + +class I18n implements WidgetsLocalizations { + const I18n(); + static Locale _locale; + static bool _shouldReload = false; + + static set locale(Locale _newLocale) { + _shouldReload = true; + I18n._locale = _newLocale; + } + + static const GeneratedLocalizationsDelegate delegate = + const GeneratedLocalizationsDelegate(); + + /// function to be invoked when changing the language + static LocaleChangeCallback onLocaleChanged; + + static I18n of(BuildContext context) => + Localizations.of(context, WidgetsLocalizations); + + @override + TextDirection get textDirection => TextDirection.ltr; + + /// "Hibok park" + String get appName => "Hibok park"; + /// "Login" + String get login => "Login"; + /// "Registration" + String get registration => "Registration"; + /// "Other login" + String get other_login => "Other login"; + /// "Account number" + String get account => "Account number"; + /// "Please enter Username" + String get enter_username => "Please enter Username"; + /// "Password" + String get password => "Password"; + /// "Enter password" + String get enter_password => "Enter password"; + /// "Forget password" + String get forget_password => "Forget password"; + /// "Reset Password" + String get reset_password => "Reset Password"; + /// "Mobile number registration" + String get number_registration => "Mobile number registration"; + /// "Please enter phone number" + String get enter_number => "Please enter phone number"; + /// "Code" + String get code => "Code"; + /// "Please enter the code" + String get enter_code => "Please enter the code"; + /// "Send the code" + String get send_code => "Send the code"; + /// "Send again" + String get send_again => "Send again"; + /// "Set password" + String get set_password => "Set password"; + /// "Password least six" + String get password_limit => "Password least six"; + /// "Set Password" + String get set_password2 => "Set Password"; + /// "Next step" + String get next_step => "Next step"; + /// "Click to enter means you have read and agreed <>" + String get agreed_agreement => "Click to enter means you have read and agreed <>"; + /// "Please enter your password" + String get enter_password2 => "Please enter your password"; + /// "Reset now" + String get reset_now => "Reset now"; + /// "Choose gender" + String get choose_gender => "Choose gender"; + /// "You are..." + String get who => "You are..."; + /// "Determine" + String get determine => "Determine"; + /// "Cannot be modified after selecting gender" + String get cannot_modified => "Cannot be modified after selecting gender"; + /// "Tip" + String get tip => "Tip"; + /// "You are about to complete registration, are you quit now?" + String get choose_quit => "You are about to complete registration, are you quit now?"; + /// "Confirm" + String get confirm => "Confirm"; + /// "Use" + String get use => "Use"; + /// "Cancel" + String get cancel => "Cancel"; + /// "Close" + String get close => "Close"; + /// "Delete" + String get delete => "Delete"; + /// "Forget it" + String get forget_it => "Forget it"; + /// "OK" + String get ok => "OK"; + /// "After registration, you will not be able to modify your gender. Are you sure?" + String get choose_quit2 => "After registration, you will not be able to modify your gender. Are you sure?"; + /// "Tip: You can't communicate with users of the same gender" + String get tip_content => "Tip: You can't communicate with users of the same gender"; + /// "Welcome" + String get welcome => "Welcome"; + /// "Please enter the invitation code" + String get enter_incode => "Please enter the invitation code"; + /// "Hibok only serves men with invitation codes" + String get must_incode => "Hibok only serves men with invitation codes"; + /// "Your invitation code" + String get your_incode => "Your invitation code"; + /// "No invitation code? You can get it in the following ways" + String get how_get => "No invitation code? You can get it in the following ways"; + /// "Method 1" + String get method1 => "Method 1"; + /// "Free application" + String get free => "Free application"; + /// "Apply now" + String get apply_now => "Apply now"; + /// "Check code" + String get check_incode => "Check code"; + /// "You need to fill in some personal information, and send you an invitation code after the review is passed." + String get so_get => "You need to fill in some personal information, and send you an invitation code after the review is passed."; + /// "Apply for an invitation code" + String get apply_incode => "Apply for an invitation code"; + /// "Location" + String get location => "Location"; + /// "The name of your city" + String get cityname => "The name of your city"; + /// "Message channel" + String get message_channel => "Message channel"; + /// "Where do you know the APP?" + String get how_know => "Where do you know the APP?"; + /// "Wechat" + String get wechat_number => "Wechat"; + /// "Your we chat" + String get your_wechat => "Your we chat"; + /// "Facebook" + String get facebook => "Facebook"; + /// "Your Facebook" + String get your_facebook => "Your Facebook"; + /// "Submit application" + String get submit_application => "Submit application"; + /// "Please enter your city" + String get enter_city => "Please enter your city"; + /// "Please tell us about your access to the app." + String get so_know => "Please tell us about your access to the app."; + /// "Please tell us your social account" + String get your_social => "Please tell us your social account"; + /// "We will process your application as soon as possible. If you pass the review, you will receive the invitation code we issued in the message center." + String get receive_incode => "We will process your application as soon as possible. If you pass the review, you will receive the invitation code we issued in the message center."; + /// "The invitation code has not been issued yet, please be patient after applying!" + String get wait_incode => "The invitation code has not been issued yet, please be patient after applying!"; + /// "Application successful!" + String get successful_application1 => "Application successful!"; + /// "Application failed!" + String get application_failed1 => "Application failed!"; + /// "Successful copy" + String get successful_copy => "Successful copy"; + /// "Method 2" + String get method2 => "Method 2"; + /// "Join member" + String get joinvip => "Join member"; + /// "Join now" + String get join_now => "Join now"; + /// "Joined" + String get joined => "Joined"; + /// "Joining members can enjoy various privileges, including registration without an invitation code" + String get join_odds => "Joining members can enjoy various privileges, including registration without an invitation code"; + /// "You have not joined the membership yet." + String get not_joinvip => "You have not joined the membership yet."; + /// "After joining the membership, you can complete the registration without the invitation code." + String get join_after => "After joining the membership, you can complete the registration without the invitation code."; + /// "Invitation code verification passed" + String get incode_passed => "Invitation code verification passed"; + /// "Welcome! Do not reveal your account to others. Once you find that the login is abnormal, the account will be automatically frozen." + String get welcome_join => "Welcome! Do not reveal your account to others. Once you find that the login is abnormal, the account will be automatically frozen."; + /// "Member Centre" + String get member_centre => "Member Centre"; + /// "Member's privilege" + String get members_privilege => "Member's privilege"; + /// "Right 1" + String get see_more => "Right 1"; + /// "View users unlimited times a day" + String get unlimited_see => "View users unlimited times a day"; + /// "Right 2" + String get see_cheaper => "Right 2"; + /// "/s1 free times per day to pay photo or social accounts" + String get free10 => "/s1 free times per day to pay photo or social accounts"; + /// "Right 3" + String get see_longer => "Right 3"; + /// "View time increased from 2s to /s1s." + String get towto6 => "View time increased from 2s to /s1s."; + /// "Right 4" + String get see_better => "Right 4"; + /// "Free release of dating broadcasts" + String get free_release => "Free release of dating broadcasts"; + /// "Choose a package" + String get choose_price => "Choose a package"; + /// "Payment method" + String get pay_method => "Payment method"; + /// "Payment amount" + String get pay_amount => "Payment amount"; + /// "Insufficient wallet balance" + String get not_enough => "Insufficient wallet balance"; + /// "Confirm payment" + String get confirm_pay => "Confirm payment"; + /// "Complete material" + String get complete_material => "Complete material"; + /// "Basic information" + String get basic_information => "Basic information"; + /// "Upload avatar" + String get upload_avatar => "Upload avatar"; + /// "Please choose" + String get choose => "Please choose"; + /// "Please fill out" + String get fill_out => "Please fill out"; + /// "Can choose multiple" + String get choose_multiple => "Can choose multiple"; + /// "Optional" + String get optional => "Optional"; + /// "Fill in at least /s1" + String get least => "Fill in at least /s1"; + /// "Introduce yourself" + String get introduce_yourself => "Introduce yourself"; + /// "Select up to /s1" + String get most => "Select up to /s1"; + /// "nickname" + String get nickname => "nickname"; + /// "Nickname can only be 1-20 characters" + String get only1_8 => "Nickname can only be 1-20 characters"; + /// "Current City" + String get Resident_city => "Current City"; + /// "Please select the current city" + String get Please_select_a_resident_city => "Please select the current city"; + /// "Can Tho" + String get City1 => "Can Tho"; + /// "Da Nang" + String get City2 => "Da Nang"; + /// "Hai phong" + String get City3 => "Hai phong"; + /// "Hanoi" + String get City4 => "Hanoi"; + /// "Ho Chi Minh" + String get City5 => "Ho Chi Minh"; + /// "An Giang" + String get City6 => "An Giang"; + /// "Bac Giang" + String get City7 => "Bac Giang"; + /// "Bac Can" + String get City8 => "Bac Can"; + /// "Bo Liao" + String get City9 => "Bo Liao"; + /// "Bac Ninh" + String get City10 => "Bac Ninh"; + /// "Ba Ria-Vung Tau" + String get City11 => "Ba Ria-Vung Tau"; + /// "Ben Tre" + String get City12 => "Ben Tre"; + /// "Binh Dinh" + String get City13 => "Binh Dinh"; + /// "Binh Duong" + String get City14 => "Binh Duong"; + /// "Binh Phuoc" + String get City15 => "Binh Phuoc"; + /// "Binh Thuan" + String get City16 => "Binh Thuan"; + /// "Ca Mau" + String get City17 => "Ca Mau"; + /// "Cao Bang" + String get City18 => "Cao Bang"; + /// "Dele" + String get City19 => "Dele"; + /// "Dac Nong" + String get City20 => "Dac Nong"; + /// "Dien Bien" + String get City21 => "Dien Bien"; + /// "Dong Nai" + String get City22 => "Dong Nai"; + /// "Dong Thap" + String get City23 => "Dong Thap"; + /// "Gia Lai" + String get City24 => "Gia Lai"; + /// "Ha Giang" + String get City25 => "Ha Giang"; + /// "Hai Duong" + String get City26 => "Hai Duong"; + /// "Ha Nam" + String get City27 => "Ha Nam"; + /// "Ha Tinh" + String get City28 => "Ha Tinh"; + /// "Hoa Binh" + String get City29 => "Hoa Binh"; + /// "Hau Giang" + String get City30 => "Hau Giang"; + /// "Hung Yen" + String get City31 => "Hung Yen"; + /// "Khanh Hoa" + String get City32 => "Khanh Hoa"; + /// "Kien Giang" + String get City33 => "Kien Giang"; + /// "Kon Tum" + String get City34 => "Kon Tum"; + /// "Lai Chau" + String get City35 => "Lai Chau"; + /// "Lam Dong" + String get City36 => "Lam Dong"; + /// "Lang Son" + String get City37 => "Lang Son"; + /// "Lao Cai" + String get City38 => "Lao Cai"; + /// "Long An" + String get City39 => "Long An"; + /// "Nghe An" + String get City40 => "Nghe An"; + /// "Ninh Binh" + String get City41 => "Ninh Binh"; + /// "Ninh Thuan" + String get City42 => "Ninh Thuan"; + /// "Phu Tho" + String get City43 => "Phu Tho"; + /// "Phu Yen" + String get City44 => "Phu Yen"; + /// "Quang Binh" + String get City45 => "Quang Binh"; + /// "Quang Nam" + String get City46 => "Quang Nam"; + /// "Quang Ngai" + String get City47 => "Quang Ngai"; + /// "Quang Ninh" + String get City48 => "Quang Ninh"; + /// "Quang Tri" + String get City49 => "Quang Tri"; + /// "Soc Trang" + String get City50 => "Soc Trang"; + /// "Son La" + String get City51 => "Son La"; + /// "Tay Ninh" + String get City52 => "Tay Ninh"; + /// "Thai Binh" + String get City53 => "Thai Binh"; + /// "Thai Nguyen" + String get City54 => "Thai Nguyen"; + /// "Thanh Hoa" + String get City55 => "Thanh Hoa"; + /// "Thua Thien-Hue" + String get City56 => "Thua Thien-Hue"; + /// "Tien Giang" + String get City57 => "Tien Giang"; + /// "Tra Vinh" + String get City58 => "Tra Vinh"; + /// "Tuyen Quang" + String get City59 => "Tuyen Quang"; + /// "Vinh Long" + String get City60 => "Vinh Long"; + /// "Vinh Phuc" + String get City61 => "Vinh Phuc"; + /// "Yen Bai" + String get City62 => "Yen Bai"; + /// "Nam Dinh" + String get City63 => "Nam Dinh"; + /// "Birthday" + String get birthday => "Birthday"; + /// "Please choose birthday" + String get choose_birthday => "Please choose birthday"; + /// "Year" + String get year => "Year"; + /// "Month" + String get month => "Month"; + /// "Day" + String get day => "Day"; + /// "Hour" + String get hour => "Hour"; + /// "Minute" + String get minute => "Minute"; + /// "Second" + String get second => "Second"; + /// "Just" + String get just => "Just"; + /// "/s1 minute ago" + String get minute_ago => "/s1 minute ago"; + /// "/s1 hour ago" + String get hour_ago => "/s1 hour ago"; + /// "/s1 day ago" + String get day_ago => "/s1 day ago"; + /// "/s1 week ago" + String get week_ago => "/s1 week ago"; + /// "/s1 month ago" + String get month_ago => "/s1 month ago"; + /// "Morning" + String get morning => "Morning"; + /// "Noon" + String get noon => "Noon"; + /// "Afternoon" + String get afternoon => "Afternoon"; + /// "Night" + String get night => "Night"; + /// "All day" + String get all_day => "All day"; + /// "Yesterday" + String get yesterday => "Yesterday"; + /// "The day before yesterday" + String get two_yesterday => "The day before yesterday"; + /// "Overnight" + String get overnight => "Overnight"; + /// "One" + String get one => "One"; + /// "Ten" + String get ten => "Ten"; + /// "Hundred" + String get hundred => "Hundred"; + /// "Thousand" + String get thousand => "Thousand"; + /// "Ten thousand" + String get ten_thousand => "Ten thousand"; + /// "Aries" + String get aries => "Aries"; + /// "Taurus" + String get taurus => "Taurus"; + /// "Gemini" + String get gemini => "Gemini"; + /// "Cancer" + String get cancer => "Cancer"; + /// "Leo" + String get leo => "Leo"; + /// "Virgo" + String get virgo => "Virgo"; + /// "Libra" + String get libra => "Libra"; + /// "Scorpio" + String get scorpio => "Scorpio"; + /// "Sagittarius" + String get sagittarius => "Sagittarius"; + /// "Capricorn" + String get capricorn => "Capricorn"; + /// "Aquarius" + String get aquarius => "Aquarius"; + /// "Pisces" + String get pisces => "Pisces"; + /// "Monday" + String get monday => "Monday"; + /// "Tuesday" + String get tuesday => "Tuesday"; + /// "Wednesday" + String get wednesday => "Wednesday"; + /// "Thursday" + String get thursday => "Thursday"; + /// "Friday" + String get friday => "Friday"; + /// "Saturday" + String get saturday => "Saturday"; + /// "Sunday" + String get sunday => "Sunday"; + /// "Job" + String get job => "Job"; + /// "Please choose a career" + String get choose_career => "Please choose a career"; + /// "Information Technology" + String get career1 => "Information Technology"; + /// "Internet" + String get career2 => "Internet"; + /// "IT" + String get career3 => "IT"; + /// "Telecommunications operation" + String get career4 => "Telecommunications operation"; + /// "Online game" + String get career5 => "Online game"; + /// "Financial insurance" + String get career6 => "Financial insurance"; + /// "Investment" + String get career7 => "Investment"; + /// "Equity fund" + String get career8 => "Equity fund"; + /// "Insurance" + String get career9 => "Insurance"; + /// "Bank" + String get career10 => "Bank"; + /// "Trust guarantee" + String get career11 => "Trust guarantee"; + /// "Business service" + String get career12 => "Business service"; + /// "Advisory" + String get career13 => "Advisory"; + /// "Self-employed" + String get career14 => "Self-employed"; + /// "Beauty salons" + String get career15 => "Beauty salons"; + /// "Tourism" + String get career16 => "Tourism"; + /// "Hotel catering" + String get career17 => "Hotel catering"; + /// "Leisure and entertainment" + String get career18 => "Leisure and entertainment"; + /// "Trading" + String get career19 => "Trading"; + /// "Driver" + String get career20 => "Driver"; + /// "Estate" + String get career21 => "Estate"; + /// "Property management" + String get career22 => "Property management"; + /// "Decoration worker" + String get career23 => "Decoration worker"; + /// "Detective" + String get career24 => "Detective"; + /// "Engineering manufacturing" + String get career25 => "Engineering manufacturing"; + /// "Builder" + String get career26 => "Builder"; + /// "Civil Engineering" + String get career27 => "Civil Engineering"; + /// "Machine made" + String get career28 => "Machine made"; + /// "Electronic" + String get career29 => "Electronic"; + /// "Biomedical Science" + String get career30 => "Biomedical Science"; + /// "Food" + String get career31 => "Food"; + /// "Clothing" + String get career32 => "Clothing"; + /// "Energy" + String get career33 => "Energy"; + /// "Transportation" + String get career34 => "Transportation"; + /// "Aviation" + String get career35 => "Aviation"; + /// "Railway" + String get career36 => "Railway"; + /// "Shipping ship" + String get career37 => "Shipping ship"; + /// "Public transit" + String get career38 => "Public transit"; + /// "Logistics transportation" + String get career39 => "Logistics transportation"; + /// "Culture Media" + String get career40 => "Culture Media"; + /// "Media publishing" + String get career41 => "Media publishing"; + /// "Design" + String get career42 => "Design"; + /// "Cultural communication" + String get career43 => "Cultural communication"; + /// "Advertising creativity" + String get career44 => "Advertising creativity"; + /// "Anime" + String get career45 => "Anime"; + /// "Public relations exhibition" + String get career46 => "Public relations exhibition"; + /// "Photography" + String get career47 => "Photography"; + /// "Entertainment sports" + String get career48 => "Entertainment sports"; + /// "Movie" + String get career49 => "Movie"; + /// "Sports sports" + String get career50 => "Sports sports"; + /// "Music" + String get career51 => "Music"; + /// "Model" + String get career52 => "Model"; + /// "Public utilities" + String get career53 => "Public utilities"; + /// "Medical" + String get career54 => "Medical"; + /// "Legal" + String get career55 => "Legal"; + /// "Education" + String get career56 => "Education"; + /// "Government agency" + String get career57 => "Government agency"; + /// "Public welfare" + String get career58 => "Public welfare"; + /// "Student" + String get career59 => "Student"; + /// "No" + String get career60 => "No"; + /// "Program" + String get program => "Program"; + /// "Please select a nationality" + String get select_program => "Please select a nationality"; + /// "Exercise" + String get healthy_exercise => "Exercise"; + /// "Party" + String get night_party => "Party"; + /// "Food" + String get gourmet_party => "Food"; + /// "Movie" + String get watch_movie => "Movie"; + /// "Games" + String get play_games => "Games"; + /// "Travel" + String get travel_together => "Travel"; + /// "Voice chat" + String get voice_chat => "Voice chat"; + /// "Other" + String get other => "Other"; + /// "Expect lover" + String get expect_lover => "Expect lover"; + /// "Please choose the expect lover" + String get choose_lover => "Please choose the expect lover"; + /// "Beautiful" + String get beautiful => "Beautiful"; + /// "Rich" + String get rich => "Rich"; + /// "Care for me" + String get care_me => "Care for me"; + /// "Look feeling" + String get look_feeling => "Look feeling"; + /// "Does not matter" + String get doesnt_matter => "Does not matter"; + /// "Please fill in at least one social networking account" + String get least_account => "Please fill in at least one social networking account"; + /// "Hide social account" + String get hide_account1 => "Hide social account"; + /// "More information" + String get more_information => "More information"; + /// "Height" + String get height => "Height"; + /// "Weight" + String get weight => "Weight"; + /// "Hidden" + String get not_show => "Hidden"; + /// "Introduction" + String get self_introduction => "Introduction"; + /// "Registration success" + String get registration_success1 => "Registration success"; + /// "Exit?" + String get exit => "Exit?"; + /// "Your personal information is not yet perfect, if you quit now, next time you enter, sign directly with a registered account" + String get exit_registration => "Your personal information is not yet perfect, if you quit now, next time you enter, sign directly with a registered account"; + /// "Men can't see other men's details" + String get cant_see => "Men can't see other men's details"; + /// "Ms. cannot see other ladies details" + String get cant_see2 => "Ms. cannot see other ladies details"; + /// "You can still see /s1 lady today." + String get see_one => "You can still see /s1 lady today."; + /// "Non-members can only view 15 women per day" + String get only_see => "Non-members can only view 15 women per day"; + /// "Continue to see" + String get continue_see => "Continue to see"; + /// "User has frozen" + String get user_frozen => "User has frozen"; + /// "Please enter a nickname / occupation to search" + String get search_user => "Please enter a nickname / occupation to search"; + /// "Nearby" + String get nearby => "Nearby"; + /// "Member" + String get member => "Member"; + /// "New" + String get new_registration => "New"; + /// "Certified" + String get authenticate => "Certified"; + /// "Online" + String get first_online => "Online"; + /// "Positioning is off, distance cannot be calculated" + String get not_positioned => "Positioning is off, distance cannot be calculated"; + /// "Unknown" + String get unknown => "Unknown"; + /// "Secrecy" + String get secrecy => "Secrecy"; + /// "Collection" + String get collection => "Collection"; + /// "Cancel collection" + String get cancel_collection => "Cancel collection"; + /// "Canceled collection" + String get canceled_collection => "Canceled collection"; + /// "Like" + String get like => "Like"; + /// "Added like" + String get added_like => "Added like"; + /// "Canceled like" + String get canceled_like => "Canceled like"; + /// "Blacklist" + String get blacklist => "Blacklist"; + /// "You will no longer see each other and each other's dynamic, Are you sure" + String get blacklist_choose => "You will no longer see each other and each other's dynamic, Are you sure"; + /// "Blacklisted" + String get blacklisted => "Blacklisted"; + /// "Add the other party to the blacklist and reject the message" + String get reject_message => "Add the other party to the blacklist and reject the message"; + /// "Remove blacklist" + String get remove_blacklist => "Remove blacklist"; + /// "Blacklist removed" + String get blacklist_removed => "Blacklist removed"; + /// "Move the other party out of the blacklist" + String get receive_message => "Move the other party out of the blacklist"; + /// "Online" + String get online => "Online"; + /// "Paid photo album" + String get paid_photo => "Paid photo album"; + /// "Apply" + String get application_view => "Apply"; + /// "Passed" + String get passed => "Passed"; + /// "Park" + String get park => "Park"; + /// "Radio" + String get radio => "Radio"; + /// "News" + String get news => "News"; + /// "Me" + String get me => "Me"; + /// "More operations" + String get more_operations => "More operations"; + /// "Anonymous report" + String get anonymous_report => "Anonymous report"; + /// "Video" + String get certified_video => "Video"; + /// "She has passed the video certification authenticity" + String get passed_video => "She has passed the video certification authenticity"; + /// "She has not yet verified identity authenticity" + String get not_video => "She has not yet verified identity authenticity"; + /// "She is starting a date." + String get her_appointment => "She is starting a date."; + /// "He joined through paid" + String get pay_join => "He joined through paid"; + /// "He passed the identity security review" + String get passed_review => "He passed the identity security review"; + /// "He joined from user /s1's invitation code" + String get invited_user => "He joined from user /s1's invitation code"; + /// "He is starting a date." + String get his_appointment => "He is starting a date."; + /// "Her dynamics" + String get her_dynamics => "Her dynamics"; + /// "His dynamics" + String get his_dynamics => "His dynamics"; + /// "She is very low-key" + String get low_key => "She is very low-key"; + /// "He is very low-key" + String get low_key2 => "He is very low-key"; + /// "Her photo album" + String get her_photo => "Her photo album"; + /// "His photo album" + String get his_photo => "His photo album"; + /// "He set up the album lock" + String get set_lock => "He set up the album lock"; + /// "She set up the album lock" + String get set_lock2 => "She set up the album lock"; + /// "Unlock album (/s1), members free" + String get free_unlock => "Unlock album (/s1), members free"; + /// "Unlock /s1 album" + String get unlock_user => "Unlock /s1 album"; + /// "Paid unlock (/s1 H coin)" + String get pay_unlock => "Paid unlock (/s1 H coin)"; + /// "Free for members" + String get become_member => "Free for members"; + /// "Whether to use 1 chance to unlock the album of /s1" + String get consumption_once => "Whether to use 1 chance to unlock the album of /s1"; + /// "(You still have /s1 chance today)" + String get remaining_once => "(You still have /s1 chance today)"; + /// "You have run out of free opportunities today, would you like to give /s1 to unlock all the information for /s2?" + String get no_times => "You have run out of free opportunities today, would you like to give /s1 to unlock all the information for /s2?"; + /// "Pay" + String get pay => "Pay"; + /// "He set a limit, see the information need to request his consent" + String get view_user => "He set a limit, see the information need to request his consent"; + /// "She set a limit, see the information need to request her consent" + String get view_user2 => "She set a limit, see the information need to request her consent"; + /// "You need to send your photo to the other party. Rest assured, your photo will be destroyed 2 seconds after the other party presses the screen to view it." + String get need_photo => "You need to send your photo to the other party. Rest assured, your photo will be destroyed 2 seconds after the other party presses the screen to view it."; + /// "Choose a photo" + String get choose_photo => "Choose a photo"; + /// "The application has been sent, and you will receive a message reminder after the other party confirms" + String get send_application => "The application has been sent, and you will receive a message reminder after the other party confirms"; + /// "You have not certified yet" + String get not_authenticate => "You have not certified yet"; + /// "Only after authenticating your authenticity can you interact with others" + String get after_authenticate => "Only after authenticating your authenticity can you interact with others"; + /// "Authenticate now" + String get authenticate_now => "Authenticate now"; + /// "Destroy after viewing" + String get destroy_after => "Destroy after viewing"; + /// "Destroyed" + String get destroyed => "Destroyed"; + /// "Red packet photo" + String get red_photo1 => "Red packet photo"; + /// "Please ask me for a private chat." + String get ask_me => "Please ask me for a private chat."; + /// "Filled in, click to view" + String get filled_in => "Filled in, click to view"; + /// "Unlock all the information" + String get unlock_information => "Unlock all the information"; + /// "Use 1 free unlock" + String get unlock_choose => "Use 1 free unlock"; + /// "Your true evaluation" + String get your_evaluation => "Your true evaluation"; + /// "Her true evaluation" + String get her_evaluation => "Her true evaluation"; + /// "His true evaluation" + String get his_evaluation => "His true evaluation"; + /// "Evaluate" + String get evaluate => "Evaluate"; + /// "Friendly" + String get friendly => "Friendly"; + /// "Interesting" + String get interesting => "Interesting"; + /// "Readily" + String get readily => "Readily"; + /// "Patient" + String get patient => "Patient"; + /// "Indifferent" + String get indifferent => "Indifferent"; + /// "Bad temper" + String get bad_temper => "Bad temper"; + /// "Courtesy" + String get courtesy => "Courtesy"; + /// "Generous" + String get generous => "Generous"; + /// "Lie" + String get lie => "Lie"; + /// "Unfriendly" + String get unfriendly => "Unfriendly"; + /// "Anonymous evaluation" + String get anonymous_evaluation => "Anonymous evaluation"; + /// "You haven't dated her yet, can't evaluate" + String get cant_evaluate => "You haven't dated her yet, can't evaluate"; + /// "He hasn't dated you yet, can't evaluate" + String get cant_evaluate2 => "He hasn't dated you yet, can't evaluate"; + /// "Please provide relevant screenshots so that we can follow up to verify" + String get bad_evaluate => "Please provide relevant screenshots so that we can follow up to verify"; + /// "Submit" + String get submit => "Submit"; + /// "Evaluation success" + String get evaluation_success => "Evaluation success"; + /// "Private chat" + String get private_chat => "Private chat"; + /// "Close message reminder" + String get close_reminder => "Close message reminder"; + /// "Close message reminder success" + String get closed_reminder => "Close message reminder success"; + /// "Open message reminder" + String get open_reminder => "Open message reminder"; + /// "Open message reminder success" + String get opened_reminder => "Open message reminder success"; + /// "Her social account" + String get her_account => "Her social account"; + /// "His social account" + String get his_account => "His social account"; + /// "Copy" + String get copy => "Copy"; + /// "Send my social account to her" + String get send_account => "Send my social account to her"; + /// "Enter your social account" + String get enter_account => "Enter your social account"; + /// "For example: We chat abc" + String get for_example => "For example: We chat abc"; + /// "Sent to her" + String get sent_she => "Sent to her"; + /// "Voice chat" + String get chat => "Voice chat"; + /// "The other party turned off the voice chat function" + String get cantt_voice => "The other party turned off the voice chat function"; + /// "Active voice after authenticating your authenticity" + String get authentication_voice => "Active voice after authenticating your authenticity"; + /// "Requesting voice chat" + String get requesting_voice => "Requesting voice chat"; + /// "Waiting to answer" + String get waitting_answer => "Waiting to answer"; + /// "Answer" + String get answer => "Answer"; + /// "Hang up" + String get hang_up => "Hang up"; + /// "Chatting" + String get chatting => "Chatting"; + /// "Handsfree" + String get handsfree => "Handsfree"; + /// "Giving a gift" + String get giving_gift => "Giving a gift"; + /// "Give a gift success" + String get give_success => "Give a gift success"; + /// "The other party has given a gift" + String get others_gift => "The other party has given a gift"; + /// "You have given a gift worth /s1 H coin" + String get given_gift => "You have given a gift worth /s1 H coin"; + /// "You have earned /s1 H coin" + String get earned_gift => "You have earned /s1 H coin"; + /// "Available balance /s1" + String get available_balance => "Available balance /s1"; + /// "Recharge" + String get recharge => "Recharge"; + /// "Give" + String get give => "Give"; + /// "Sorry, your balance is not enough." + String get balance_insufficien => "Sorry, your balance is not enough."; + /// "Please recharge the gift before giving it" + String get first_recharge => "Please recharge the gift before giving it"; + /// "This chat gives /s1 H coin" + String get give_coin => "This chat gives /s1 H coin"; + /// "This chat gets /s1 H coin" + String get get_coin => "This chat gets /s1 H coin"; + /// "This chat gives /s1 H coin and gets /s2 H coin" + String get give_get => "This chat gives /s1 H coin and gets /s2 H coin"; + /// "Chat is over, duration /s1" + String get chat_over => "Chat is over, duration /s1"; + /// "Message center" + String get message_center => "Message center"; + /// "You can start a private chat on the person's user details page." + String get can_chat => "You can start a private chat on the person's user details page."; + /// "Text chat" + String get text_chat => "Text chat"; + /// "System information" + String get system_information => "System information"; + /// "System notification" + String get system_notification => "System notification"; + /// "The situation of the user /s1 you reported is not true. Please provide more valid evidence. Thank you!" + String get report_failure => "The situation of the user /s1 you reported is not true. Please provide more valid evidence. Thank you!"; + /// "The fact that you reported the user /s1 is true and the system has processed the user." + String get report_success => "The fact that you reported the user /s1 is true and the system has processed the user."; + /// "Invitation code application is successful! Invitation code [/s1] (click to copy)" + String get successful_application => "Invitation code application is successful! Invitation code [/s1] (click to copy)"; + /// "The invitation code is applied successfully, thank you for introducing friends! Invitation code [/s1] (click to copy)" + String get successful_application2 => "The invitation code is applied successfully, thank you for introducing friends! Invitation code [/s1] (click to copy)"; + /// "Invitation code application failed! Unfortunately, your application failed to pass the review. Please fill in the real information to effectively improve the approval rate." + String get application_failed => "Invitation code application failed! Unfortunately, your application failed to pass the review. Please fill in the real information to effectively improve the approval rate."; + /// "【Important Notice】:" + String get important_notice => "【Important Notice】:"; + /// "Your certification information does not meet the requirements, please modify and resubmit." + String get authentication_failed => "Your certification information does not meet the requirements, please modify and resubmit."; + /// "1. Please take the certification video according to the certification requirements." + String get request1 => "1. Please take the certification video according to the certification requirements."; + /// "2. Please upload a clear facial photo of the facial features" + String get request2 => "2. Please upload a clear facial photo of the facial features"; + /// "Congratulations, your certification application has been approved" + String get successful_authentication => "Congratulations, your certification application has been approved"; + /// "Your newly uploaded photo has not been approved. Please re-upload as required." + String get re_upload => "Your newly uploaded photo has not been approved. Please re-upload as required."; + /// "Congratulations, your newly uploaded photo has been successfully reviewed." + String get upload_success => "Congratulations, your newly uploaded photo has been successfully reviewed."; + /// "Your appointment registration has been deleted due to violations. Multiple violations or serious circumstances will limit or even limit your account. Please follow and remember. Thank you for your cooperation." + String get caveat => "Your appointment registration has been deleted due to violations. Multiple violations or serious circumstances will limit or even limit your account. Please follow and remember. Thank you for your cooperation."; + /// "Your comment has been deleted due to violations. Multiple violations or serious circumstances will restrict or even limit your account. Please follow and remember. Thank you for your cooperation." + String get caveat2 => "Your comment has been deleted due to violations. Multiple violations or serious circumstances will restrict or even limit your account. Please follow and remember. Thank you for your cooperation."; + /// "Radio message" + String get radio_message => "Radio message"; + /// "There is no such message for the time being." + String get no_message => "There is no such message for the time being."; + /// "/s1 posted a treaty message in /s2, click to view" + String get dating_news => "/s1 posted a treaty message in /s2, click to view"; + /// "Go and see" + String get go_see => "Go and see"; + /// "/s1 liked your updates" + String get thumbs_up => "/s1 liked your updates"; + /// "/s1 liked your date show" + String get thumbs_up2 => "/s1 liked your date show"; + /// "/s1 commented on your activity" + String get comment1 => "/s1 commented on your activity"; + /// "/s1 commented on your dating show" + String get comment2 => "/s1 commented on your dating show"; + /// "/s1 replied to your comment" + String get replied_comment => "/s1 replied to your comment"; + /// "/s1 has signed up for your date show" + String get signed_up => "/s1 has signed up for your date show"; + /// "Your favorite user /s1 posted a treaty, click to view" + String get favorite_user => "Your favorite user /s1 posted a treaty, click to view"; + /// "Your favorite user /s1 posted a dynamic, click to view" + String get favorite_user2 => "Your favorite user /s1 posted a dynamic, click to view"; + /// "Wallet reminder" + String get wallet_reminder => "Wallet reminder"; + /// "/s1 paid (/s2 H coin) to view your red packet photo" + String get paid_you => "/s1 paid (/s2 H coin) to view your red packet photo"; + /// "/s1 paid (/s2 H coin) to view your album" + String get paid_you2 => "/s1 paid (/s2 H coin) to view your album"; + /// "/s1 paid to unlock all your information" + String get paid_you3 => "/s1 paid to unlock all your information"; + /// "View application" + String get view_application => "View application"; + /// "/s1Request to view your details page" + String get view_application2 => "/s1Request to view your details page"; + /// "Allowed (valid for 15 days)" + String get aging => "Allowed (valid for 15 days)"; + /// "Refuse" + String get refuse => "Refuse"; + /// "Passed request" + String get passed_request => "Passed request"; + /// "/s1 has been approved by your review and is valid for 15 days." + String get l15_days => "/s1 has been approved by your review and is valid for 15 days."; + /// "Evaluation Notifications" + String get evaluation_notice => "Evaluation Notifications"; + /// "Please rate her" + String get rate_her => "Please rate her"; + /// "A woman who has contacted you has evaluated you: /s1" + String get received_evaluation => "A woman who has contacted you has evaluated you: /s1"; + /// "A man who has contacted you has evaluated you: /s1" + String get received_evaluation2 => "A man who has contacted you has evaluated you: /s1"; + /// "If the evaluation is not true, you can apply for the above and we will verify it." + String get application_appeal => "If the evaluation is not true, you can apply for the above and we will verify it."; + /// "I want to appeal" + String get appeal => "I want to appeal"; + /// "Already appealed" + String get appealed => "Already appealed"; + /// "We will check the situation as soon as possible and tell you the result by email." + String get waiting_results => "We will check the situation as soon as possible and tell you the result by email."; + /// "Your appeal is evaluated: /s1 appeal is successful and we will withdraw this review for you." + String get successful_appeal => "Your appeal is evaluated: /s1 appeal is successful and we will withdraw this review for you."; + /// "Social account" + String get social_account => "Social account"; + /// "/s1 sent you his social account" + String get get_account => "/s1 sent you his social account"; + /// "Edit information" + String get edit_information => "Edit information"; + /// "Save" + String get save => "Save"; + /// "You passed the identity security verification" + String get passed_verification1 => "You passed the identity security verification"; + /// "You join through the invitation code of the veteran user /s1" + String get by_code => "You join through the invitation code of the veteran user /s1"; + /// "You join by paying" + String get by_paying => "You join by paying"; + /// "You have authenticated identity authenticity through video" + String get passed_verification => "You have authenticated identity authenticity through video"; + /// "You have not verified identity authenticity" + String get not_certified => "You have not verified identity authenticity"; + /// "We are certifying your authenticity" + String get verificating => "We are certifying your authenticity"; + /// "Certified girls are more popular" + String get real_girl => "Certified girls are more popular"; + /// "In certification" + String get certificating => "In certification"; + /// "Please re-upload the video" + String get re_upload2 => "Please re-upload the video"; + /// "Update certification" + String get update_certification => "Update certification"; + /// "Join members to enjoy privileges" + String get enjoy_privileges => "Join members to enjoy privileges"; + /// "/s1 expires" + String get expires => "/s1 expires"; + /// "Wallet" + String get wallet => "Wallet"; + /// "Privacy" + String get setting => "Privacy"; + /// "My dynamic" + String get my_dynamic => "My dynamic"; + /// "My album" + String get my_album => "My album"; + /// "Upload my first photo" + String get first_photo => "Upload my first photo"; + /// "Have photos to attract more men" + String get no_photo => "Have photos to attract more men"; + /// "Upload photos" + String get upload_photos => "Upload photos"; + /// "Upload video" + String get upload_video => "Upload video"; + /// "Upload photos" + String get upload => "Upload photos"; + /// "Set red packet photo" + String get set_photo => "Set red packet photo"; + /// "Long press to drag the photo" + String get photo_order => "Long press to drag the photo"; + /// "My evaluation" + String get my_evaluation => "My evaluation"; + /// "My show" + String get my_show => "My show"; + /// "I like" + String get i_like => "I like"; + /// "Your favorite lady will show here" + String get your_favorite => "Your favorite lady will show here"; + /// "The guy you like will show here" + String get your_favorite2 => "The guy you like will show here"; + /// "No data" + String get no_data => "No data"; + /// "Historical visitor" + String get historical_visitor => "Historical visitor"; + /// "Have /s1 people seen you" + String get visit_you => "Have /s1 people seen you"; + /// "/s1 person has destroyed your photo" + String get visit_photo => "/s1 person has destroyed your photo"; + /// "One-click recovery" + String get recovery_photo => "One-click recovery"; + /// "Setting" + String get setting2 => "Setting"; + /// "Help a friend apply for an invitation code" + String get apply_code => "Help a friend apply for an invitation code"; + /// "The application invitation code is free, and we will evaluate whether to issue the invitation code based on your historical spending. In order to maintain the atmosphere of the park, please send the invitation code to a reliable friend." + String get issue_choose => "The application invitation code is free, and we will evaluate whether to issue the invitation code based on your historical spending. In order to maintain the atmosphere of the park, please send the invitation code to a reliable friend."; + /// "Successfully submit an application" + String get successfully_submit => "Successfully submit an application"; + /// "Share the app to a friend" + String get share_app => "Share the app to a friend"; + /// "Help" + String get need_help => "Help"; + /// "Contact Customer Service" + String get need_help2 => "Contact Customer Service"; + /// "In order to improve service efficiency, if there is your problem below, please reply directly to the serial number!" + String get need_help3 => "In order to improve service efficiency, if there is your problem below, please reply directly to the serial number!"; + /// "[1] What is the reason why the account is frozen?" + String get question1 => "[1] What is the reason why the account is frozen?"; + /// "In any of the following cases, the account will be frozen: 1 liar 2 intermediary 3 harassment advertisement 4 more people report 5 already have other accounts 6 times issued illegal radio broadcasts ignore warning 7 users themselves request cancellation" + String get answer1 => "In any of the following cases, the account will be frozen: 1 liar 2 intermediary 3 harassment advertisement 4 more people report 5 already have other accounts 6 times issued illegal radio broadcasts ignore warning 7 users themselves request cancellation"; + /// "[2] When can the cash in the wallet be cashed out?" + String get question2 => "[2] When can the cash in the wallet be cashed out?"; + /// "All proceeds will go directly to the wallet, withdrawal takes three days (starting with the time of collection), the amount collected after three days will enter the wallet, the amount >=10 yuan can be withdrawn" + String get answer2 => "All proceeds will go directly to the wallet, withdrawal takes three days (starting with the time of collection), the amount collected after three days will enter the wallet, the amount >=10 yuan can be withdrawn"; + /// "[3] Why didn't I show the red packet I gave?" + String get question3 => "[3] Why didn't I show the red packet I gave?"; + /// "It may be caused by a network cause. Rest assured, in this case the other party can not receive your red packet, the red packet will be automatically refunded after 24 hours." + String get answer3 => "It may be caused by a network cause. Rest assured, in this case the other party can not receive your red packet, the red packet will be automatically refunded after 24 hours."; + /// "[4] How long does it take to withdraw cash?" + String get question4 => "[4] How long does it take to withdraw cash?"; + /// "Expected to arrive within two business days. Tips: Please confirm the account number is correct!" + String get answer4 => "Expected to arrive within two business days. Tips: Please confirm the account number is correct!"; + /// "[5] How to report other users/radio broadcasts anonymously?" + String get question5 => "[5] How to report other users/radio broadcasts anonymously?"; + /// "Go to the other party's details page or select a radio station broadcast, click on the top right corner and select [Anonymous Report], please fill in the relevant report information to report it." + String get answer5 => "Go to the other party's details page or select a radio station broadcast, click on the top right corner and select [Anonymous Report], please fill in the relevant report information to report it."; + /// "[6] How to become an authenticated user?" + String get question6 => "[6] How to become an authenticated user?"; + /// "The certification must meet the following requirements: 1Personal information to fill in a valid social account 2 Album at least upload a clear face photo 3 See the verification code on the certification page, write the nickname + verification code 4 on the paper, hold the paper, Take a video with your face and click Upload Authentication Video" + String get answer6 => "The certification must meet the following requirements: 1Personal information to fill in a valid social account 2 Album at least upload a clear face photo 3 See the verification code on the certification page, write the nickname + verification code 4 on the paper, hold the paper, Take a video with your face and click Upload Authentication Video"; + /// "[7] Can the certified video be hidden?" + String get question7 => "[7] Can the certified video be hidden?"; + /// "Can choose whether to display: User Center - click on the authentication video - bottom left 'Show the certified video on my details page'" + String get answer7 => "Can choose whether to display: User Center - click on the authentication video - bottom left 'Show the certified video on my details page'"; + /// "[8] How to avoid the certification being cancelled?" + String get question8 => "[8] How to avoid the certification being cancelled?"; + /// "The photo album has at least one photo of me." + String get answer8 => "The photo album has at least one photo of me."; + /// "[9] What is the reason for the dynamic deletion?" + String get question9 => "[9] What is the reason for the dynamic deletion?"; + /// "Dynamics cannot publish sensitive maps, sensitive words, including but not limited to implied or explicit words, cannot post personal information (including avatars, nicknames, contact details), violations will be deleted" + String get answer9 => "Dynamics cannot publish sensitive maps, sensitive words, including but not limited to implied or explicit words, cannot post personal information (including avatars, nicknames, contact details), violations will be deleted"; + /// "[10] How to cancel the account?" + String get question10 => "[10] How to cancel the account?"; + /// "If you cancel the account, you will not be able to log in to the app. If you want to use the service later, you will need to re-register. Please consider carefully. If you still decide to cancel your account, please reply to the serial number [12] contact customer service." + String get answer10 => "If you cancel the account, you will not be able to log in to the app. If you want to use the service later, you will need to re-register. Please consider carefully. If you still decide to cancel your account, please reply to the serial number [12] contact customer service."; + /// "[11] What should I do if I forget my password?" + String get question11 => "[11] What should I do if I forget my password?"; + /// "Users who register by mobile phone number or who have a mobile phone number can reset their password by using the \"Forgot Password\" function in the upper right corner of the login page. Unbound users, please bind the phone number first, then set a new login password." + String get answer11 => "Users who register by mobile phone number or who have a mobile phone number can reset their password by using the \"Forgot Password\" function in the upper right corner of the login page. Unbound users, please bind the phone number first, then set a new login password."; + /// "[12] Other questions / transfer customer service" + String get question12 => "[12] Other questions / transfer customer service"; + /// "Hello, what can I do for you? Please describe your problem (Customer service time is 8:00 every day - 02:00 the next day, due to the large number of consultations, you may need to wait for a reply)" + String get answer12 => "Hello, what can I do for you? Please describe your problem (Customer service time is 8:00 every day - 02:00 the next day, due to the large number of consultations, you may need to wait for a reply)"; + /// "Certification center" + String get certification_center => "Certification center"; + /// "Example of certified video capture mode" + String get for_example2 => "Example of certified video capture mode"; + /// "Certification conditions" + String get certification_conditions => "Certification conditions"; + /// "1. Good personal image" + String get conditions1 => "1. Good personal image"; + /// "2. Upload at least one photo of yourself in the album" + String get conditions2 => "2. Upload at least one photo of yourself in the album"; + /// "Verification method" + String get verification_method => "Verification method"; + /// "1. Take a piece of paper and write your nickname and the following verification code:" + String get method3 => "1. Take a piece of paper and write your nickname and the following verification code:"; + /// "2. Hold this piece of paper and take a video with your face (3~15 seconds)" + String get method4 => "2. Hold this piece of paper and take a video with your face (3~15 seconds)"; + /// "Upload certification video" + String get upload_video2 => "Upload certification video"; + /// "After the authentication is successful, your avatar will have a real logo." + String get after_authentication => "After the authentication is successful, your avatar will have a real logo."; + /// "Display the certified video on my details page" + String get show_video => "Display the certified video on my details page"; + /// "Uploaded certified video" + String get uploaded_video => "Uploaded certified video"; + /// "During the review (within 24 hours)" + String get under_review => "During the review (within 24 hours)"; + /// "Certification status" + String get certification_status => "Certification status"; + /// "You have been certified" + String get certified => "You have been certified"; + /// "Authentication waiting to be resubmitted" + String get wait_resubmitted => "Authentication waiting to be resubmitted"; + /// "Your certified video does not meet the requirements due to:" + String get reason_failure => "Your certified video does not meet the requirements due to:"; + /// "Please take the certification video according to the certification requirements." + String get claim => "Please take the certification video according to the certification requirements."; + /// "Please upload a photo of the face of the facial features in the album." + String get claim2 => "Please upload a photo of the face of the facial features in the album."; + /// "Re-upload the certification video" + String get re_upload_video => "Re-upload the certification video"; + /// "Update upload certification video" + String get update_video => "Update upload certification video"; + /// "H coin" + String get mask_coin => "H coin"; + /// "You can get H coins by recharging, etc." + String get get_way => "You can get H coins by recharging, etc."; + /// "It can be used to chat and give gifts when chatting." + String get coin_use => "It can be used to chat and give gifts when chatting."; + /// "H coin total" + String get coin_total => "H coin total"; + /// "Can be redeemed" + String get can_redeemed => "Can be redeemed"; + /// "/s1 account" + String get who_account => "/s1 account"; + /// "Bind /s1 account" + String get bind_account => "Bind /s1 account"; + /// "Your /s1 account" + String get your_account => "Your /s1 account"; + /// "You got the /s1 H coin by recharging" + String get get_coin2 => "You got the /s1 H coin by recharging"; + /// "/s1viewed your social account" + String get viewed_your => "/s1viewed your social account"; + /// "/s1 presented a gift: 1 /s2" + String get give_gift => "/s1 presented a gift: 1 /s2"; + /// "+/s1 H coin" + String get add_coin => "+/s1 H coin"; + /// "You give 1 /s1 to /s2" + String get give_one => "You give 1 /s1 to /s2"; + /// "-/s1 H coin" + String get less_coin => "-/s1 H coin"; + /// "Exchange cash" + String get exchange_cash => "Exchange cash"; + /// "Withdrawal application" + String get withdrawal_application => "Withdrawal application"; + /// "You have /s1 H coins to convert to /s2, and /s3 H coins remaining after redemption. Are you sure to redeem?" + String get redeem_choose => "You have /s1 H coins to convert to /s2, and /s3 H coins remaining after redemption. Are you sure to redeem?"; + /// "Application submitted" + String get application_submitted => "Application submitted"; + /// "We will handle it within 2 working days. If you have any questions, please contact customer service." + String get working_days => "We will handle it within 2 working days. If you have any questions, please contact customer service."; + /// "Cash" + String get cash => "Cash"; + /// "Whenever you receive a red packet on the chat page, the red packet amount will be here. No one reported that you can redeem cash within 3 days, the system charges 5% fee" + String get handling_fee => "Whenever you receive a red packet on the chat page, the red packet amount will be here. No one reported that you can redeem cash within 3 days, the system charges 5% fee"; + /// "Total account" + String get total_account => "Total account"; + /// "Insufficient amount, cannot be redeemed" + String get cannot_redeemed => "Insufficient amount, cannot be redeemed"; + /// "Successful redemption" + String get successful_redemption => "Successful redemption"; + /// "Your account total is /s1, this time you can redeem /s2, will you redeem it?" + String get redeem_choose2 => "Your account total is /s1, this time you can redeem /s2, will you redeem it?"; + /// "Personal details" + String get personal_details => "Personal details"; + /// "Public (recommended)" + String get public => "Public (recommended)"; + /// "Paid View album" + String get paid_album => "Paid View album"; + /// "Others must pay to view your photo album, the cost is up to you, which may reduce your traffic" + String get must_pay => "Others must pay to view your photo album, the cost is up to you, which may reduce your traffic"; + /// "Set the view amount" + String get set_amount1 => "Set the view amount"; + /// "Please upload photos before setting up paid albums" + String get first_upload => "Please upload photos before setting up paid albums"; + /// "Can only be viewed by my permission" + String get need_permission => "Can only be viewed by my permission"; + /// "Must send photos to me, can view my homepage after I allow it" + String get permission_choose => "Must send photos to me, can view my homepage after I allow it"; + /// "Hide me from a list of people nearby" + String get hide_me => "Hide me from a list of people nearby"; + /// "Hide my distance" + String get hide_distance => "Hide my distance"; + /// "Hide my social account" + String get hide_account => "Hide my social account"; + /// "Chat settings" + String get chat_setting => "Chat settings"; + /// "Allow authorized people to initiate a voice chat with me" + String get chat_me => "Allow authorized people to initiate a voice chat with me"; + /// "Successfully saved" + String get successfully_saved => "Successfully saved"; + /// "You have not posted dynamic" + String get on_dynamic => "You have not posted dynamic"; + /// "Release dynamics" + String get release_dynamics => "Release dynamics"; + /// "Dynamic details" + String get dynamic_details => "Dynamic details"; + /// "Release" + String get release => "Release"; + /// "I posted" + String get i_posted => "I posted"; + /// "Delete dynamic" + String get delete_dynamic => "Delete dynamic"; + /// "Are you sure you want to delete this dynamic?" + String get delete_choose => "Are you sure you want to delete this dynamic?"; + /// "Posted on /s1" + String get posted_on => "Posted on /s1"; + /// "Thumbs up" + String get thumbs_up3 => "Thumbs up"; + /// "Already praised" + String get already_praised => "Already praised"; + /// "Comment" + String get comment => "Comment"; + /// "Send" + String get send => "Send"; + /// "Comment closed" + String get comment_closed => "Comment closed"; + /// "Only publishers can see your comment" + String get your_comment => "Only publishers can see your comment"; + /// "Everyone can see your comment" + String get everyone_comment => "Everyone can see your comment"; + /// "Prohibit comments" + String get prohibit_comments => "Prohibit comments"; + /// "Comments disabled" + String get comments_disabled => "Comments disabled"; + /// "Open Comments" + String get open_comments => "Open Comments"; + /// "Already open comment" + String get already_open => "Already open comment"; + /// "Reply" + String get reply => "Reply"; + /// "Report" + String get report => "Report"; + /// "Are you sure you want to report this comment?" + String get report_choose => "Are you sure you want to report this comment?"; + /// "Successful report, we will deal with it as soon as possible" + String get successful_report => "Successful report, we will deal with it as soon as possible"; + /// "Successfully deleted" + String get successfully_deleted => "Successfully deleted"; + /// "People who talk about civilization are more popular. Don't post vulgar, pornographic, or otherwise revealing the privacy of others." + String get please_civilization => "People who talk about civilization are more popular. Don't post vulgar, pornographic, or otherwise revealing the privacy of others."; + /// "Hidden with the same sex user" + String get same_sex => "Hidden with the same sex user"; + /// "Members are free, non-members need /s1 H coin" + String get member_free => "Members are free, non-members need /s1 H coin"; + /// "Certified women are free 3 times, then need to pay /s1H coins" + String get certified_free => "Certified women are free 3 times, then need to pay /s1H coins"; + /// "Please enter text or select image" + String get enter_something => "Please enter text or select image"; + /// "Paid release (/s1 H coin)" + String get raid_release => "Paid release (/s1 H coin)"; + /// "Free for members" + String get become_member2 => "Free for members"; + /// "Immediate certification, free release" + String get now_certification => "Immediate certification, free release"; + /// "Successfully released" + String get successfully_released => "Successfully released"; + /// "You haven't posted a program yet." + String get no_program => "You haven't posted a program yet."; + /// "Program details" + String get program_details => "Program details"; + /// "Program theme" + String get program_theme => "Program theme"; + /// "Click to select" + String get click_select => "Click to select"; + /// "City" + String get city => "City"; + /// "Select City" + String get select_city => "Select City"; + /// "Time" + String get time => "Time"; + /// "Select date" + String get select_date => "Select date"; + /// "Select time" + String get select_time => "Select time"; + /// "Unlimited time" + String get unlimited_time => "Unlimited time"; + /// "Supplementary explanation" + String get supplementary_explanation => "Supplementary explanation"; + /// "Image" + String get image => "Image"; + /// "Delete program" + String get delete_program => "Delete program"; + /// "Are you sure you want to delete this program?" + String get delete_choose2 => "Are you sure you want to delete this program?"; + /// "Please select a program theme" + String get please_choose => "Please select a program theme"; + /// "Please select the desired object" + String get please_choose2 => "Please select the desired object"; + /// "Please select city" + String get please_choose3 => "Please select city"; + /// "Please select a date" + String get please_choose4 => "Please select a date"; + /// "Please select time" + String get please_choose5 => "Please select time"; + /// "Release program" + String get release_program => "Release program"; + /// "Sign up" + String get sign_up => "Sign up"; + /// "End registration" + String get end_registration => "End registration"; + /// "Are you sure you want to end your appointment?" + String get end_choose => "Are you sure you want to end your appointment?"; + /// "Contact her" + String get contact_her => "Contact her"; + /// "Talk to him privately" + String get talk_him => "Talk to him privately"; + /// "Are you sure you want to report this registration information?" + String get report_choose2 => "Are you sure you want to report this registration information?"; + /// "Release time" + String get release_time => "Release time"; + /// "Activity time" + String get activity_time => "Activity time"; + /// "Any sex" + String get any_sex => "Any sex"; + /// "Look Ms." + String get look_women => "Look Ms."; + /// "Look Men" + String get look_men => "Look Men"; + /// "Unlimited area" + String get unlimited_area => "Unlimited area"; + /// "The program has been deleted" + String get program_deleted => "The program has been deleted"; + /// "Non-members can't comment" + String get cant_comment => "Non-members can't comment"; + /// "Join" + String get sign_up2 => "Join"; + /// "Registration needs to send your photo of the face (only the other party can see)" + String get need_photo2 => "Registration needs to send your photo of the face (only the other party can see)"; + /// "Registration is successful, if the other party feels appropriate, you will be contacted." + String get registration_success => "Registration is successful, if the other party feels appropriate, you will be contacted."; + /// "Has ended" + String get has_ended => "Has ended"; + /// "Men can't sign up for men's shows" + String get men_cant => "Men can't sign up for men's shows"; + /// "Ms. can't sign up for a lady's show" + String get ms_cant => "Ms. can't sign up for a lady's show"; + /// "Men can't comment on men's shows" + String get men_cant2 => "Men can't comment on men's shows"; + /// "Ms. can't comment on the lady's show" + String get ms_cant2 => "Ms. can't comment on the lady's show"; + /// "Message push, change password" + String get message_push => "Message push, change password"; + /// "Phone number" + String get phone_number => "Phone number"; + /// "Bind phone number" + String get bind_phone1 => "Bind phone number"; + /// "Bind your phone number to make your account safer" + String get more_safer => "Bind your phone number to make your account safer"; + /// "Do you want to modify the bound mobile number?" + String get modify_choose => "Do you want to modify the bound mobile number?"; + /// "Change password" + String get change_password => "Change password"; + /// "Users need to bind the mobile phone number before they can set the login password." + String get first_bind => "Users need to bind the mobile phone number before they can set the login password."; + /// "Old password" + String get old_password => "Old password"; + /// "Please enter your current login password" + String get current_password => "Please enter your current login password"; + /// "New password" + String get new_password => "New password"; + /// "Please set a new password, at least 6 digits" + String get set_new => "Please set a new password, at least 6 digits"; + /// "Clear image cache" + String get clear_cache => "Clear image cache"; + /// "Cleared successfully" + String get cleared_successfully => "Cleared successfully"; + /// "User agreement" + String get user_agreement1 => "User agreement"; + /// "Sign out" + String get sign_out => "Sign out"; + /// "Are you sure you want to log out?" + String get out_choose => "Are you sure you want to log out?"; + /// "Push settings" + String get push_settings => "Push settings"; + /// "Permission denied" + String get permission_denied => "Permission denied"; + /// "Message push settings" + String get push_setting2 => "Message push settings"; + /// "Private chat message" + String get private_chat2 => "Private chat message"; + /// "Have a new date" + String get new_date => "Have a new date"; + /// "A lady passed my request" + String get passed_request2 => "A lady passed my request"; + /// "Some men apply to view my profile page" + String get men_view => "Some men apply to view my profile page"; + /// "Some men look at my social account" + String get men_view2 => "Some men look at my social account"; + /// "Some men look at my red packet photos" + String get men_view3 => "Some men look at my red packet photos"; + /// "Someone who has viewed me sent me a social account" + String get men_view4 => "Someone who has viewed me sent me a social account"; + /// "Invitation code applied successfully" + String get applied_successfully => "Invitation code applied successfully"; + /// "Will open the corresponding message type when opened" + String get after_open => "Will open the corresponding message type when opened"; + /// "If you have paid her/he in the last 3 days, we will automatically refund the amount to you after we verify the report." + String get if_something => "If you have paid her/he in the last 3 days, we will automatically refund the amount to you after we verify the report."; + /// "Advertise" + String get advertise => "Advertise"; + /// "False photo" + String get false_photo => "False photo"; + /// "Erotic vulgarity" + String get erotic_vulgarity => "Erotic vulgarity"; + /// "Harassment" + String get harassment => "Harassment"; + /// "She is a liar" + String get she_liar => "She is a liar"; + /// "He is a liar" + String get he_liar => "He is a liar"; + /// "Please provide relevant screenshots so that we can follow up to verify" + String get provide_screenshots => "Please provide relevant screenshots so that we can follow up to verify"; + /// "Please describe the details (within 100 words)" + String get describe_details => "Please describe the details (within 100 words)"; + /// "Please select the reason for reporting" + String get report_reason => "Please select the reason for reporting"; + /// "Report success" + String get report_success2 => "Report success"; + /// "Successfully modified" + String get successfully_modified => "Successfully modified"; + /// "Boy" + String get boy => "Boy"; + /// "Girl" + String get girl => "Girl"; + /// "Applied" + String get already_applied => "Applied"; + /// "View registration" + String get view_registration => "View registration"; + /// "Expand" + String get expand => "Expand"; + /// "Collapse" + String get collapse => "Collapse"; + /// "Application Notifications" + String get application_notice => "Application Notifications"; + /// "Someone agrees with your application" + String get agrees_application => "Someone agrees with your application"; + /// "Red packet photo" + String get red_photo => "Red packet photo"; + /// "Do not upload illegal nudity photos/videos, or severely" + String get dont => "Do not upload illegal nudity photos/videos, or severely"; + /// "Current version" + String get current_version => "Current version"; + /// "Binding bank card" + String get bank_card => "Binding bank card"; + /// "Please select an account bank" + String get choose_bank => "Please select an account bank"; + /// "Please enter the bank card number" + String get bank_number => "Please enter the bank card number"; + /// "Please enter the ID number" + String get id_number => "Please enter the ID number"; + /// "Name" + String get name => "Name"; + /// "Bank card number" + String get bank_number2 => "Bank card number"; + /// "License number" + String get license_number => "License number"; + /// "Bind phone number" + String get bind_phone => "Bind phone number"; + /// "His homepage" + String get his_homepage => "His homepage"; + /// "Her homepage" + String get her_homepage => "Her homepage"; + /// "WeChat payment" + String get wechat_pay => "WeChat payment"; + /// "Facebook payment" + String get facebook_pay => "Facebook payment"; + /// "Google pay" + String get google_pay => "Google pay"; + /// "Payment successful" + String get payment_successful => "Payment successful"; + /// "Set withdrawal amount" + String get set_amount => "Set withdrawal amount"; + /// "Please enter the number of H coins" + String get enter_amount => "Please enter the number of H coins"; + /// "Can withdraw" + String get can_withdraw => "Can withdraw"; + /// "Language settings" + String get language_set => "Language settings"; + /// "User Agreement" + String get user_agreement => "User Agreement"; + /// "Renewal fee" + String get renewal_fee => "Renewal fee"; + /// "Open immediately" + String get open_immediately => "Open immediately"; + /// "Total" + String get total => "Total"; + /// "Half a month" + String get half_month => "Half a month"; + /// "/s1 month" + String get month2 => "/s1 month"; + /// "Cancel shield" + String get cancel_shield => "Cancel shield"; + /// "Blacklist" + String get blacklist2 => "Blacklist"; + /// "(Members can extend the time by 6 seconds)" + String get longTime => "(Members can extend the time by 6 seconds)"; + /// "Press and hold the screen to view" + String get longClick => "Press and hold the screen to view"; + /// "Please finish the program that is in effect first" + String get stop_program => "Please finish the program that is in effect first"; + /// "Men can't collect men" + String get not_love => "Men can't collect men"; + /// "Women can't collect women" + String get not_love2 => "Women can't collect women"; + /// "Women can post for free" + String get women_free => "Women can post for free"; + /// "He has not uploaded photos yet" + String get not_up_man => "He has not uploaded photos yet"; + /// "She has not uploaded photos yet" + String get not_up_women => "She has not uploaded photos yet"; + /// "Do not conduct illegal transactions through the platform. If it is reported, it will be processed as a seal." + String get not_illage => "Do not conduct illegal transactions through the platform. If it is reported, it will be processed as a seal."; + /// "Signed" + String get alreay_join => "Signed"; + /// "Are you sure you want to delete this photo?" + String get sure_delete => "Are you sure you want to delete this photo?"; + /// "Fill in now" + String get white_now => "Fill in now"; + /// "You haven't filled out a personal introduction yet, and the attractive personal introduction has a great impact on the success of the appointment." + String get personal => "You haven't filled out a personal introduction yet, and the attractive personal introduction has a great impact on the success of the appointment."; + /// "Success" + String get success => "Success"; + /// "Fail" + String get fail => "Fail"; + /// "Only certified users can set red packet photos" + String get moneyPageTip => "Only certified users can set red packet photos"; + /// "You have already signed up and will contact you if they feel it is appropriate." + String get alreadyJoin => "You have already signed up and will contact you if they feel it is appropriate."; + /// "Violation warning" + String get waring => "Violation warning"; + /// "Respect user privacy, do not take screenshots. If you have another time, you will be prohibited from viewing other user photos." + String get userPravicy => "Respect user privacy, do not take screenshots. If you have another time, you will be prohibited from viewing other user photos."; + /// "Appointment time has expired, please edit" + String get outTime => "Appointment time has expired, please edit"; + /// "under review" + String get reviewing => "under review"; + /// "Successful review" + String get reviewed => "Successful review"; + /// "Audit failure" + String get reviewedFail => "Audit failure"; + /// "Users need to bind the bank card before they can withdraw cash." + String get needCard => "Users need to bind the bank card before they can withdraw cash."; + /// "Ms. can't comment on the dynamics of women" + String get women_not_d => "Ms. can't comment on the dynamics of women"; + /// "Men can't comment on men's dynamics" + String get man_not_d => "Men can't comment on men's dynamics"; + /// "Have photos to attract women." + String get have_picture => "Have photos to attract women."; + /// "Sliding cancels sending" + String get up_cancle => "Sliding cancels sending"; + /// "Message cannot be empty" + String get msg_not => "Message cannot be empty"; + /// "This feature requires permission to record" + String get need_record => "This feature requires permission to record"; + /// "Downloading video file" + String get downloading_video => "Downloading video file"; + /// "Please re-enter the question number" + String get reinput => "Please re-enter the question number"; + /// "Your activity is reported anonymously by the user. After the system verifies that the activity has been deleted, please do not violate the rules." + String get dy_delete => "Your activity is reported anonymously by the user. After the system verifies that the activity has been deleted, please do not violate the rules."; + /// "Your program is reported anonymously by the user. After the system has verified that the program has been deleted, please do not violate the rules." + String get pro_delete => "Your program is reported anonymously by the user. After the system has verified that the program has been deleted, please do not violate the rules."; + /// "Your comment has been reported anonymously by the user. The system has verified that the comment has been deleted. Please do not violate the rules." + String get con_delete => "Your comment has been reported anonymously by the user. The system has verified that the comment has been deleted. Please do not violate the rules."; + /// "Reported by anonymous users, the system verifies that you have recently violated the rules and has received your recent return of H currency. If there is a next time, the account will be frozen." + String get coin_returen => "Reported by anonymous users, the system verifies that you have recently violated the rules and has received your recent return of H currency. If there is a next time, the account will be frozen."; + /// "Illegal acts such as pornography and obscenity are prohibited during the call." + String get voicing => "Illegal acts such as pornography and obscenity are prohibited during the call."; + /// "Customer service" + String get help => "Customer service"; + /// "Manual translation on" + String get translate_on => "Manual translation on"; + /// "Manual translation off" + String get translate_off => "Manual translation off"; + /// "Consuming /s1 H coins will be renewed for SVIP" + String get becomeSvip => "Consuming /s1 H coins will be renewed for SVIP"; + /// "Svip permission can be turned on" + String get need_svip => "Svip permission can be turned on"; + /// "SVIP cannot be renewed as VIP" + String get cannot_vip => "SVIP cannot be renewed as VIP"; + /// "You are offline and cannot send and receive messages" + String get offline => "You are offline and cannot send and receive messages"; + /// "The account is logged in on another device, you are offline" + String get otherLogin => "The account is logged in on another device, you are offline"; + /// "No new news for the time being" + String get no_new => "No new news for the time being"; + /// "Translated" + String get over => "Translated"; + /// "Are you sure you want to make a bad review of this translation?" + String get bad_ev => "Are you sure you want to make a bad review of this translation?"; + /// "Right 5" + String get right5 => "Right 5"; + /// "Right 6" + String get right6 => "Right 6"; + /// "Gentleman" + String get man_vi => "Gentleman"; + /// "Lady" + String get women_vi => "Lady"; + /// "In order to improve service efficiency, if there is your problem below, please reply directly to the serial number!" + String get kf_tips => "In order to improve service efficiency, if there is your problem below, please reply directly to the serial number!"; + /// "Rejected" + String get rejected => "Rejected"; + /// "You have purchased /s1H coins to buy members." + String get buy_vip => "You have purchased /s1H coins to buy members."; + /// "You consumed /s1H coins to post a dynamic program." + String get buy_program => "You consumed /s1H coins to post a dynamic program."; + /// "Your H currency withdrawal request has been processed, transferred /s1 to your account, please check" + String get del_add_money => "Your H currency withdrawal request has been processed, transferred /s1 to your account, please check"; + /// "The /s1H currency you applied for withdrawal is under review." + String get adding_money => "The /s1H currency you applied for withdrawal is under review."; + /// "Free translation commissioner real-time translation" + String get free_translate => "Free translation commissioner real-time translation"; + /// "Exclusive customer service for you" + String get personalTraff => "Exclusive customer service for you"; + /// "In human translation..." + String get ManTranslate => "In human translation..."; + /// "In machine translation..." + String get robotTranslate => "In machine translation..."; + /// "Manual translation completed" + String get translated => "Manual translation completed"; + /// "Healthy communication, please do not broadcast vulgar content, once it is found, it will be deleted." + String get delete_progarm => "Healthy communication, please do not broadcast vulgar content, once it is found, it will be deleted."; + /// "Targeting permission is not turned on" + String get open_location => "Targeting permission is not turned on"; + /// "Please enable targeting in your phone settings to get additional user distance" + String get get_location => "Please enable targeting in your phone settings to get additional user distance"; + /// "Press again to exit" + String get confirm_exit => "Press again to exit"; + /// "Free broadcasts per day /s1 chance" + String get free_program => "Free broadcasts per day /s1 chance"; + /// "Image" + String get picture => "Image"; + /// "Camera" + String get camera => "Camera"; + /// "Video" + String get video => "Video"; + /// "Red packet" + String get red_money => "Red packet"; + /// "Paste" + String get stick => "Paste"; + /// "Hold and talk" + String get press_say => "Hold and talk"; + /// "/s1 received your red packet" + String get get_money => "/s1 received your red packet"; + /// "You received the red packet of /s1" + String get you_get_money => "You received the red packet of /s1"; + /// "/s1 red packet" + String get ones_money => "/s1 red packet"; + /// "Red packet has expired" + String get money_over => "Red packet has expired"; + /// "Download file failed" + String get downloading_fail => "Download file failed"; + /// "Downloading video file" + String get downloading => "Downloading video file"; + /// "Unclaimed red packet will be refunded after 24 hours" + String get back_money => "Unclaimed red packet will be refunded after 24 hours"; + /// "Red packet does not exist" + String get no_money => "Red packet does not exist"; + /// "Red packet has been received" + String get already_money => "Red packet has been received"; + /// "Expired, has been refunded to the account" + String get back_user => "Expired, has been refunded to the account"; + /// "Waiting for the other party" + String get waiting_user => "Waiting for the other party"; + /// "The other party has received" + String get other_get => "The other party has received"; + /// "Take the money and spend it." + String get little => "Take the money and spend it."; + /// "Cash into the red packet" + String get put_money => "Cash into the red packet"; + /// "Amount" + String get mount => "Amount"; + /// "Expired" + String get over_time => "Expired"; + /// "Received" + String get has_get => "Received"; + /// "No gifts for the time being" + String get no_gift => "No gifts for the time being"; + /// "Gift" + String get sent_gift => "Gift"; + /// "If you fill in successfully, you can get /s1H coins, which cannot be modified after binding." + String get fill_tips => "If you fill in successfully, you can get /s1H coins, which cannot be modified after binding."; + /// "Bind invitation code" + String get bind_code => "Bind invitation code"; + /// "Invitation code" + String get invide_code => "Invitation code"; + /// "Confirm deletion" + String get confirm_delete => "Confirm deletion"; + /// "You have already evaluated" + String get has_eva => "You have already evaluated"; + /// "open" + String get open => "open"; + /// "Voice" + String get voice => "Voice"; + /// "Release send" + String get release_send => "Release send"; + /// "Recording time is too short" + String get time_little => "Recording time is too short"; + /// "The other party is not online, can't connect to Mai" + String get not_online => "The other party is not online, can't connect to Mai"; + /// "You sent a red packet of /s2 H coin to /s1" + String get give_red_money => "You sent a red packet of /s2 H coin to /s1"; + /// "You received /s1’s red packet of /s2 H coins." + String get get_red_money => "You received /s1’s red packet of /s2 H coins."; + /// "You have won the /s1 /s2H coin" + String get give_other_money => "You have won the /s1 /s2H coin"; + /// "You got a reward for /s2 H coins of /s1." + String get get_other_money => "You got a reward for /s2 H coins of /s1."; + /// "Super member" + String get svip => "Super member"; + /// "Recommend" + String get recommend => "Recommend"; + /// "You paid (/s2H coins) to view the red packet photo of /s1" + String get paid_you4 => "You paid (/s2H coins) to view the red packet photo of /s1"; + /// "You paid for /s2H coins to view /s1's album" + String get paid_you5 => "You paid for /s2H coins to view /s1's album"; + /// "You paid to unlock all the information of /s1" + String get paid_you6 => "You paid to unlock all the information of /s1"; + /// "Hibok license and service agreement" + String get UG_LINE0 => "Hibok license and service agreement"; + /// "[First and Introduction]" + String get UG_LINE1 => "[First and Introduction]"; + /// "Qianhai Youlong Technology Co., Ltd. (hereinafter referred to as “Qianhai Youlong Technology Co., Ltd.”) hereby reminds users to carefully read and fully understand this Service Agreement (hereinafter referred to as “Agreement”). Users should carefully read and fully understand this Agreement. The terms, including the exemption or limitation of Qianhai Youlong Technology Co., Ltd.'s liability and the restrictions on the rights of users. Please read carefully and choose to accept or not accept this Agreement (minors should be accompanied by a legal guardian). You are not authorized to register, log in or use the services covered by this Agreement unless you accept all of the terms of this Agreement. Your registration, login, use, etc. will be deemed acceptance of this Agreement and you agree to be bound by the terms of this Agreement." + String get UG_LINE2 => "Qianhai Youlong Technology Co., Ltd. (hereinafter referred to as “Qianhai Youlong Technology Co., Ltd.”) hereby reminds users to carefully read and fully understand this Service Agreement (hereinafter referred to as “Agreement”). Users should carefully read and fully understand this Agreement. The terms, including the exemption or limitation of Qianhai Youlong Technology Co., Ltd.'s liability and the restrictions on the rights of users. Please read carefully and choose to accept or not accept this Agreement (minors should be accompanied by a legal guardian). You are not authorized to register, log in or use the services covered by this Agreement unless you accept all of the terms of this Agreement. Your registration, login, use, etc. will be deemed acceptance of this Agreement and you agree to be bound by the terms of this Agreement."; + /// "This Agreement is an agreement between you (hereinafter referred to as \"User\" and Qianhai Youlong Technology Co., Ltd. regarding the registration, registration and use of the \"Hibok service\". This Agreement describes the relationship between Qianhai Youlong Technology Co., Ltd. and the User regarding \"Hibok services\". Rights and obligations. “User” means the individual or organization that registers, logs in, uses, and browses the Service. Your acceptance of this Agreement is subject to all terms and conditions, including any modifications made by Qianhai Youlong Technology Co., Ltd. to any Terms of Service at any time. The Agreement may be updated by Qianhai Youlong Technology Co., Ltd. at any time. The updated terms of the agreement will be replaced by the original terms of the agreement without prior notice. Users can check the terms of the latest agreement in this app. After Qianhai Youlong Technology Co., Ltd. amends the terms of the agreement, If the user does not accept the revised terms, please stop using the services provided by Qianhai Youlong Technology Co., Ltd. immediately, and the user's continued use of the services provided by Qianhai Youlong Technology Co., Ltd. will be deemed to have accepted the revised agreement." + String get UG_LINE3 => "This Agreement is an agreement between you (hereinafter referred to as \"User\" and Qianhai Youlong Technology Co., Ltd. regarding the registration, registration and use of the \"Hibok service\". This Agreement describes the relationship between Qianhai Youlong Technology Co., Ltd. and the User regarding \"Hibok services\". Rights and obligations. “User” means the individual or organization that registers, logs in, uses, and browses the Service. Your acceptance of this Agreement is subject to all terms and conditions, including any modifications made by Qianhai Youlong Technology Co., Ltd. to any Terms of Service at any time. The Agreement may be updated by Qianhai Youlong Technology Co., Ltd. at any time. The updated terms of the agreement will be replaced by the original terms of the agreement without prior notice. Users can check the terms of the latest agreement in this app. After Qianhai Youlong Technology Co., Ltd. amends the terms of the agreement, If the user does not accept the revised terms, please stop using the services provided by Qianhai Youlong Technology Co., Ltd. immediately, and the user's continued use of the services provided by Qianhai Youlong Technology Co., Ltd. will be deemed to have accepted the revised agreement."; + /// "First, the use of rules" + String get UG_LINE4 => "First, the use of rules"; + /// "1. The user fully understands and agrees that only the platform for information sharing, transmission and acquisition is provided to the user. The user must be responsible for all actions under the registered account, including but not limited to any content you transmit and any resulting results. ." + String get UG_LINE5 => "1. The user fully understands and agrees that only the platform for information sharing, transmission and acquisition is provided to the user. The user must be responsible for all actions under the registered account, including but not limited to any content you transmit and any resulting results. ."; + /// "2. Qianhai Youlong Technology Co., Ltd. assumes no responsibility for any content transmitted by or through the Services that does not reflect Qianhai Youlong Technology Co., Ltd.'s views or policies." + String get UG_LINE6 => "2. Qianhai Youlong Technology Co., Ltd. assumes no responsibility for any content transmitted by or through the Services that does not reflect Qianhai Youlong Technology Co., Ltd.'s views or policies."; + /// "3. The user fully understands and agrees that it is a social information browsing product based on the user relationship network. The user must bear full responsibility for the authenticity, legality and validity of the registered information, and the user must not impersonate others; Any information shall be transmitted in the name; no malicious use of the registered account may cause misidentification by other users; otherwise, Qianhai Youlong Technology Co., Ltd. shall have the right to immediately stop providing the service, recover the account number and assume all legal liabilities arising therefrom." + String get UG_LINE7 => "3. The user fully understands and agrees that it is a social information browsing product based on the user relationship network. The user must bear full responsibility for the authenticity, legality and validity of the registered information, and the user must not impersonate others; Any information shall be transmitted in the name; no malicious use of the registered account may cause misidentification by other users; otherwise, Qianhai Youlong Technology Co., Ltd. shall have the right to immediately stop providing the service, recover the account number and assume all legal liabilities arising therefrom."; + /// "4. The user shall be solely responsible for the authenticity, legality, harmlessness and validity of the information transmitted on the website. Any legal liability related to the information transmitted by the user shall be borne by the user and shall not be related to Qianhai Youlong Technology Co., Ltd." + String get UG_LINE8 => "4. The user shall be solely responsible for the authenticity, legality, harmlessness and validity of the information transmitted on the website. Any legal liability related to the information transmitted by the user shall be borne by the user and shall not be related to Qianhai Youlong Technology Co., Ltd."; + /// "5. Qianhai Youlong Technology Co., Ltd. reserves the right to change, suspend, limit, terminate or revoke the services of any or all of the services of the Service at any time without any notice due to business development needs, and the user shall bear this risk." + String get UG_LINE9 => "5. Qianhai Youlong Technology Co., Ltd. reserves the right to change, suspend, limit, terminate or revoke the services of any or all of the services of the Service at any time without any notice due to business development needs, and the user shall bear this risk."; + /// "6. The services provided may include advertisements, and the user agrees to display advertisements provided by third-party suppliers and partners during use." + String get UG_LINE10 => "6. The services provided may include advertisements, and the user agrees to display advertisements provided by third-party suppliers and partners during use."; + /// "7. Users may not use or service to make, upload, copy or send the following content:" + String get UG_LINE11 => "7. Users may not use or service to make, upload, copy or send the following content:"; + /// "(1) against the basic principles established by the Constitution;" + String get UG_LINE12 => "(1) against the basic principles established by the Constitution;"; + /// "(2) endangering national security, divulging state secrets, subverting state power, and undermining national unity;" + String get UG_LINE13 => "(2) endangering national security, divulging state secrets, subverting state power, and undermining national unity;"; + /// "(3) damaging national honors and interests;" + String get UG_LINE14 => "(3) damaging national honors and interests;"; + /// "(4) Inciting ethnic hatred, ethnic discrimination, and undermining national unity;" + String get UG_LINE15 => "(4) Inciting ethnic hatred, ethnic discrimination, and undermining national unity;"; + /// "(5) Destroying the state's religious policies and promoting cults and feudal superstitions;" + String get UG_LINE16 => "(5) Destroying the state's religious policies and promoting cults and feudal superstitions;"; + /// "(6) Spreading rumors, disrupting social order and undermining social stability;" + String get UG_LINE17 => "(6) Spreading rumors, disrupting social order and undermining social stability;"; + /// "(7) spreading obscenity, pornography, gambling, violence, murder, terror or abetment;" + String get UG_LINE18 => "(7) spreading obscenity, pornography, gambling, violence, murder, terror or abetment;"; + /// "(8) insulting or slandering others and infringing upon the lawful rights and interests of others;" + String get UG_LINE19 => "(8) insulting or slandering others and infringing upon the lawful rights and interests of others;"; + /// "(9) Information containing other content prohibited by laws and administrative regulations." + String get UG_LINE20 => "(9) Information containing other content prohibited by laws and administrative regulations."; + /// "8. Qianhai Youlong Technology Co., Ltd. may, in its reasonable judgment, cease to transmit any of the foregoing in accordance with law, in violation of relevant laws and regulations or the provisions of this Agreement; or infringement, obstruction, threats to the rights or safety of any person, or the act of impersonating another person. And shall have the right, at its sole discretion, to take appropriate legal action against any person who violates these Terms, including but not limited to removing illegal, infringing, improper, etc. from the Service, terminating the violators' membership and preventing them from Use all or part of the service, and keep relevant information and report to relevant departments according to laws and regulations." + String get UG_LINE21 => "8. Qianhai Youlong Technology Co., Ltd. may, in its reasonable judgment, cease to transmit any of the foregoing in accordance with law, in violation of relevant laws and regulations or the provisions of this Agreement; or infringement, obstruction, threats to the rights or safety of any person, or the act of impersonating another person. And shall have the right, at its sole discretion, to take appropriate legal action against any person who violates these Terms, including but not limited to removing illegal, infringing, improper, etc. from the Service, terminating the violators' membership and preventing them from Use all or part of the service, and keep relevant information and report to relevant departments according to laws and regulations."; + /// "9. User rights and obligations:" + String get UG_LINE22 => "9. User rights and obligations:"; + /// "(1) The ownership of the Qianhai Youlong Technology Co., Ltd. account is owned by Qianhai Youlong Technology Co., Ltd. After the user completes the application for registration, he or she will obtain the right to use the account. The right to use belongs to the initial applicant and is prohibited from being donated, borrowed, rented, transferred or sold. Qianhai Youlong Technology Co., Ltd. has the right to recycle the user's account due to business needs, and has the right to use the user's photos, videos, voices, etc. for product promotion activities." + String get UG_LINE23 => "(1) The ownership of the Qianhai Youlong Technology Co., Ltd. account is owned by Qianhai Youlong Technology Co., Ltd. After the user completes the application for registration, he or she will obtain the right to use the account. The right to use belongs to the initial applicant and is prohibited from being donated, borrowed, rented, transferred or sold. Qianhai Youlong Technology Co., Ltd. has the right to recycle the user's account due to business needs, and has the right to use the user's photos, videos, voices, etc. for product promotion activities."; + /// "(2) The user has the right to change or delete the personal data, registration information and transmission content on Qianhai Youlong Technology Co., Ltd. However, please note that deleting the information will also delete any text and images you have stored in the system. The user is responsible for this risk." + String get UG_LINE24 => "(2) The user has the right to change or delete the personal data, registration information and transmission content on Qianhai Youlong Technology Co., Ltd. However, please note that deleting the information will also delete any text and images you have stored in the system. The user is responsible for this risk."; + /// "(3) The user is responsible for the safekeeping of the registered account information and the account password. The user is responsible for the registered account and the behavior under the password. The User agrees not to use the account number or password of another member under any circumstances. You agree to notify Qianhai Youlong Technology Co., Ltd. immediately if you suspect that someone else is using your account or password." + String get UG_LINE25 => "(3) The user is responsible for the safekeeping of the registered account information and the account password. The user is responsible for the registered account and the behavior under the password. The User agrees not to use the account number or password of another member under any circumstances. You agree to notify Qianhai Youlong Technology Co., Ltd. immediately if you suspect that someone else is using your account or password."; + /// "(4) The User shall abide by the terms of this Agreement and use the Service correctly and appropriately. If the User violates any of the terms of this Agreement, Qianhai Youlong Technology Co., Ltd. shall have the right to terminate the service of the default user Qianhai Youlong Technology Co., Ltd. account in accordance with the Agreement. At the same time, Qianhai Youlong Technology Co., Ltd. reserves the right to withdraw Qianhai Youlong Technology Co., Ltd. account number and username at any time." + String get UG_LINE26 => "(4) The User shall abide by the terms of this Agreement and use the Service correctly and appropriately. If the User violates any of the terms of this Agreement, Qianhai Youlong Technology Co., Ltd. shall have the right to terminate the service of the default user Qianhai Youlong Technology Co., Ltd. account in accordance with the Agreement. At the same time, Qianhai Youlong Technology Co., Ltd. reserves the right to withdraw Qianhai Youlong Technology Co., Ltd. account number and username at any time."; + /// "(5) If the user has his or her common English account, the user has the right to register the English account as an account first, but if the user does not register the account after the service is online, or the user has registered the WeChat account, but If the English account is not used as the WeChat account, the user is deemed to have waived the right to register the English account as a WeChat account. Qianhai Youlong Technology Co., Ltd. has the right to recycle and distribute the English account to other users, so as to avoid wasting resources. The problem is the user's responsibility." + String get UG_LINE27 => "(5) If the user has his or her common English account, the user has the right to register the English account as an account first, but if the user does not register the account after the service is online, or the user has registered the WeChat account, but If the English account is not used as the WeChat account, the user is deemed to have waived the right to register the English account as a WeChat account. Qianhai Youlong Technology Co., Ltd. has the right to recycle and distribute the English account to other users, so as to avoid wasting resources. The problem is the user's responsibility."; + /// "(6) If the user does not log in to the account after registering the account for a long time, Qianhai Youlong Technology Co., Ltd. has the right to recycle the account, so as to avoid wasting resources, and the problems are caused by the user." + String get UG_LINE28 => "(6) If the user does not log in to the account after registering the account for a long time, Qianhai Youlong Technology Co., Ltd. has the right to recycle the account, so as to avoid wasting resources, and the problems are caused by the user."; + /// "(7) The user may use the report function to maintain the user platform's rights and interests. If the user receives the report feedback, the reported user is obliged to inform or cooperate with the customer service personnel to verify the situation. The report content is verified. The mask park has the right to warn and restrict the user. The account usage function and other methods restrict the user's violations. The serious violation of the Hibok has the right to directly freeze the account, and the balance in the account is not returned. If the account is frozen and needs to be appealed, the user can contact customer service." + String get UG_LINE29 => "(7) The user may use the report function to maintain the user platform's rights and interests. If the user receives the report feedback, the reported user is obliged to inform or cooperate with the customer service personnel to verify the situation. The report content is verified. The mask park has the right to warn and restrict the user. The account usage function and other methods restrict the user's violations. The serious violation of the Hibok has the right to directly freeze the account, and the balance in the account is not returned. If the account is frozen and needs to be appealed, the user can contact customer service."; + /// "Second, privacy protection" + String get UG_LINE30 => "Second, privacy protection"; + /// "The user agrees that the personal privacy information refers to those information that can personally identify the user or involve personal communication, including the following information: the user's real name, mobile phone number, WeChat account, facebook account, and IP address. The non-personal private information refers to the general information that the user clearly and objectively reflects the basic record information of the Qianhai Youlong Technology Co., Ltd. server and all other personal privacy information, and the above-mentioned private information that the user agrees to disclose. . Respecting the privacy of the user's personal privacy information is a consistent system of Qianhai Youlong Technology Co., Ltd. Qianhai Youlong Technology Co., Ltd. will take reasonable steps to protect the user's personal privacy information. Qianhai Youlong Technology Co., Ltd., in addition to legal or legal requirements or government consent. The user's personal privacy information will not be disclosed or disclosed to third parties other than the partner unit without the user's consent. However, the user chooses to agree at the time of registration, or the user and Qianhai Youlong Technology Co., Ltd. and the cooperation unit have otherwise agreed on the disclosure or use of the user's personal information, and the user shall bear any risk that may arise, Qianhai Youlong Technology Co., Ltd. does not Responsible. At the same time, in order to operate and improve Qianhai Youlong Technology Co., Ltd.'s technology and services, Qianhai Youlong Technology Co., Ltd. may collect or provide non-personal private information to users of third parties, which will help Qianhai Youlong Technology Co., Ltd. to provide users with a better user experience and improve Quality of service of Qianhai Youlong Technology Co., Ltd. Qianhai Youlong Technology Co., Ltd. collects data based on user interactions with Qianhai Youlong Technology Co., Ltd. and user choices, including user privacy settings and products and features used by users. Data collected by Qianhai Youlong Technology Co., Ltd. may include SDK/API/JS code version, IP address, platform, timestamp, application identifier, application version, application distribution channel, standalone device identifier, iOS advertising identifier (IDFA), Android ad Primary identifier, network card (MAC) address, International Mobile Equipment Identity (IMEI), device model, terminal manufacturer, terminal device operating system version, session start/stop time, language location, time zone, and network status (WiFi, etc.) Hard disk, CPU and battery usage, etc. This will enable Qianhai Youlong Technology Co., Ltd. to conduct internal data analysis and research, third-party SDK statistical services, and improve Qianhai Youlong Technology Co., Ltd.'s products or services. In order to ensure the authenticity of the user's identity, the user is provided with better security protection, and the biometric information (such as personal sensitive information) such as identity information or facial features that the user needs to submit is required to complete the real person authentication required or necessary for the specific product service. The above information will only be used to verify the authenticity of the user's identity. The above information provided by the user will continue to be authorized by Qianhai Youlong Technology Co., Ltd. during the user's use of the Service. Qianhai Youlong Technology Co., Ltd. will stop using it when the user logs out of the account. The above information will be stored in the People's Republic of China. For cross-border transmission, Qianhai Youlong Technology Co., Ltd. will separately obtain the user's authorization. App user authenticity authentication requires the user to provide some information that can verify the authenticity of the user's identity. Relevant information is only used for platform review and will not be disclosed to any other users or for commercial purposes, except for legal or related departments requesting intervention." + String get UG_LINE31 => "The user agrees that the personal privacy information refers to those information that can personally identify the user or involve personal communication, including the following information: the user's real name, mobile phone number, WeChat account, facebook account, and IP address. The non-personal private information refers to the general information that the user clearly and objectively reflects the basic record information of the Qianhai Youlong Technology Co., Ltd. server and all other personal privacy information, and the above-mentioned private information that the user agrees to disclose. . Respecting the privacy of the user's personal privacy information is a consistent system of Qianhai Youlong Technology Co., Ltd. Qianhai Youlong Technology Co., Ltd. will take reasonable steps to protect the user's personal privacy information. Qianhai Youlong Technology Co., Ltd., in addition to legal or legal requirements or government consent. The user's personal privacy information will not be disclosed or disclosed to third parties other than the partner unit without the user's consent. However, the user chooses to agree at the time of registration, or the user and Qianhai Youlong Technology Co., Ltd. and the cooperation unit have otherwise agreed on the disclosure or use of the user's personal information, and the user shall bear any risk that may arise, Qianhai Youlong Technology Co., Ltd. does not Responsible. At the same time, in order to operate and improve Qianhai Youlong Technology Co., Ltd.'s technology and services, Qianhai Youlong Technology Co., Ltd. may collect or provide non-personal private information to users of third parties, which will help Qianhai Youlong Technology Co., Ltd. to provide users with a better user experience and improve Quality of service of Qianhai Youlong Technology Co., Ltd. Qianhai Youlong Technology Co., Ltd. collects data based on user interactions with Qianhai Youlong Technology Co., Ltd. and user choices, including user privacy settings and products and features used by users. Data collected by Qianhai Youlong Technology Co., Ltd. may include SDK/API/JS code version, IP address, platform, timestamp, application identifier, application version, application distribution channel, standalone device identifier, iOS advertising identifier (IDFA), Android ad Primary identifier, network card (MAC) address, International Mobile Equipment Identity (IMEI), device model, terminal manufacturer, terminal device operating system version, session start/stop time, language location, time zone, and network status (WiFi, etc.) Hard disk, CPU and battery usage, etc. This will enable Qianhai Youlong Technology Co., Ltd. to conduct internal data analysis and research, third-party SDK statistical services, and improve Qianhai Youlong Technology Co., Ltd.'s products or services. In order to ensure the authenticity of the user's identity, the user is provided with better security protection, and the biometric information (such as personal sensitive information) such as identity information or facial features that the user needs to submit is required to complete the real person authentication required or necessary for the specific product service. The above information will only be used to verify the authenticity of the user's identity. The above information provided by the user will continue to be authorized by Qianhai Youlong Technology Co., Ltd. during the user's use of the Service. Qianhai Youlong Technology Co., Ltd. will stop using it when the user logs out of the account. The above information will be stored in the People's Republic of China. For cross-border transmission, Qianhai Youlong Technology Co., Ltd. will separately obtain the user's authorization. App user authenticity authentication requires the user to provide some information that can verify the authenticity of the user's identity. Relevant information is only used for platform review and will not be disclosed to any other users or for commercial purposes, except for legal or related departments requesting intervention."; + /// "Third, Qianhai Youlong Technology Co., Ltd. Trademark Information " + String get UG_LINE32 => "Third, Qianhai Youlong Technology Co., Ltd. Trademark Information "; + /// "The logos, characters or their components, and other Qianhai Youlong Technology Co., Ltd. logos and products and service names involved in Qianhai Youlong Technology Co., Ltd.'s services are trademarks of Qianhai Youlong Technology Co., Ltd. (hereinafter referred to as “Qianhai Youlong Technology Co., Ltd. Logo”). The Qianhai Youlong Technology Co., Ltd. logo may not be displayed or used or otherwise disposed of in any way without the prior written consent of Qianhai Youlong Technology Co., Ltd., and may not indicate to others that you have the right to display, use, or otherwise be authorized to deal with the Qianhai Youlong Technology Co., Ltd. logo." + String get UG_LINE33 => "The logos, characters or their components, and other Qianhai Youlong Technology Co., Ltd. logos and products and service names involved in Qianhai Youlong Technology Co., Ltd.'s services are trademarks of Qianhai Youlong Technology Co., Ltd. (hereinafter referred to as “Qianhai Youlong Technology Co., Ltd. Logo”). The Qianhai Youlong Technology Co., Ltd. logo may not be displayed or used or otherwise disposed of in any way without the prior written consent of Qianhai Youlong Technology Co., Ltd., and may not indicate to others that you have the right to display, use, or otherwise be authorized to deal with the Qianhai Youlong Technology Co., Ltd. logo."; + /// "Fourth, legal responsibility and exemption" + String get UG_LINE34 => "Fourth, legal responsibility and exemption"; + /// "1. The user violates the provisions of this Agreement or the relevant terms of service, resulting in or arising from any claims, claims or losses claimed by any third party, including reasonable attorneys' fees, and the user agrees to compensate Qianhai Youlong Technology Co., Ltd. and the partner company, affiliates, And protect it from damage." + String get UG_LINE35 => "1. The user violates the provisions of this Agreement or the relevant terms of service, resulting in or arising from any claims, claims or losses claimed by any third party, including reasonable attorneys' fees, and the user agrees to compensate Qianhai Youlong Technology Co., Ltd. and the partner company, affiliates, And protect it from damage."; + /// "2. Qianhai Youlong Technology Co., Ltd. and its partners are not responsible for any losses suffered by users due to communication line failures, technical problems, network, computer failures, system instability and other various force majeure causes of third parties such as the telecommunications department." + String get UG_LINE36 => "2. Qianhai Youlong Technology Co., Ltd. and its partners are not responsible for any losses suffered by users due to communication line failures, technical problems, network, computer failures, system instability and other various force majeure causes of third parties such as the telecommunications department."; + /// "3. Due to technical failures and other irresistible incidents affecting the normal operation of the service, Qianhai Youlong Technology Co., Ltd. and the cooperation unit promised to cooperate with the relevant units in the first time to deal with the repairs in time, but all losses suffered by the users, Qianhai Youlong Technology Co., Ltd. and The partner unit is not responsible." + String get UG_LINE37 => "3. Due to technical failures and other irresistible incidents affecting the normal operation of the service, Qianhai Youlong Technology Co., Ltd. and the cooperation unit promised to cooperate with the relevant units in the first time to deal with the repairs in time, but all losses suffered by the users, Qianhai Youlong Technology Co., Ltd. and The partner unit is not responsible."; + /// "4. This service, like most Internet services, may be affected by various security issues, including but not limited to user reasons, network service quality, social environment and other factors. For example, other users use the user's data to cause real life. Harassment; other software downloaded or installed by users or other websites that are visited contain \"Trojan Horse\" and other viruses, which threaten the security of the user's computer information and data, which in turn affects the normal use of the service. Users should strengthen the information security and user information protection awareness, and pay attention to strengthen password protection to avoid loss and harassment." + String get UG_LINE38 => "4. This service, like most Internet services, may be affected by various security issues, including but not limited to user reasons, network service quality, social environment and other factors. For example, other users use the user's data to cause real life. Harassment; other software downloaded or installed by users or other websites that are visited contain \"Trojan Horse\" and other viruses, which threaten the security of the user's computer information and data, which in turn affects the normal use of the service. Users should strengthen the information security and user information protection awareness, and pay attention to strengthen password protection to avoid loss and harassment."; + /// "5. Users must understand that the use of this service may be affected by unstable factors in various links due to Internet services. Therefore, the service has the risk of service interruption or failure to meet user requirements due to force majeure, computer virus or hacker attack, system instability, user location, user shutdown, and any other technology, internet, communication line reasons. The user is responsible for the above risks and Qianhai Youlong Technology Co., Ltd. does not guarantee. Qianhai Youlong Technology Co., Ltd. assumes no responsibility for the fact that the user cannot send and receive reading information or receive incorrect information." + String get UG_LINE39 => "5. Users must understand that the use of this service may be affected by unstable factors in various links due to Internet services. Therefore, the service has the risk of service interruption or failure to meet user requirements due to force majeure, computer virus or hacker attack, system instability, user location, user shutdown, and any other technology, internet, communication line reasons. The user is responsible for the above risks and Qianhai Youlong Technology Co., Ltd. does not guarantee. Qianhai Youlong Technology Co., Ltd. assumes no responsibility for the fact that the user cannot send and receive reading information or receive incorrect information."; + /// "6. The user must understand that there are threats, defamatory, offensive or illegal content or acts or violations of the rights of others (including intellectual property rights) from any other person in the course of using the service. The risk of anonymous or impersonal information is subject to the above risks. Qianhai Youlong Technology Co., Ltd. and the partner company do not make any type of guarantee for the service, whether explicit or implied, including all relevant information authenticity, merchantability, suitable for a certain A specific use, title and non-infringement of implied warranties and conditions shall not be liable for any direct, indirect, incidental, special or consequential damages resulting from any improper or unlawful use of the Services by the User." + String get UG_LINE40 => "6. The user must understand that there are threats, defamatory, offensive or illegal content or acts or violations of the rights of others (including intellectual property rights) from any other person in the course of using the service. The risk of anonymous or impersonal information is subject to the above risks. Qianhai Youlong Technology Co., Ltd. and the partner company do not make any type of guarantee for the service, whether explicit or implied, including all relevant information authenticity, merchantability, suitable for a certain A specific use, title and non-infringement of implied warranties and conditions shall not be liable for any direct, indirect, incidental, special or consequential damages resulting from any improper or unlawful use of the Services by the User."; + /// "7. The information content defined by Qianhai Youlong Technology Co., Ltd. includes: text, software, sound, photos, videos, graphics; all content in the advertisement; commercial information provided by Qianhai Youlong Technology Co., Ltd. for users, all of which are subject to copyright, trademark, and other intellectual property rights. And the protection of ownership laws. Therefore, users can only use these contents under the authorization of Qianhai Youlong Technology Co., Ltd. and advertisers, and cannot copy, modify, compile, or create derivative products related to the content." + String get UG_LINE41 => "7. The information content defined by Qianhai Youlong Technology Co., Ltd. includes: text, software, sound, photos, videos, graphics; all content in the advertisement; commercial information provided by Qianhai Youlong Technology Co., Ltd. for users, all of which are subject to copyright, trademark, and other intellectual property rights. And the protection of ownership laws. Therefore, users can only use these contents under the authorization of Qianhai Youlong Technology Co., Ltd. and advertisers, and cannot copy, modify, compile, or create derivative products related to the content."; + /// "8. Under no circumstances shall Qianhai Youlong Technology Co., Ltd. be liable for any indirect, consequential, punitive, incidental, special or penal damages, including loss of profits suffered as a result of the user's use of the Services, even if notified of the The possibility of loss is also the same). Notwithstanding the fact that this Agreement may contain conflicting rules, Qianhai Youlong Technology Co., Ltd.'s entire liability to you, for whatever reason or behavior, shall not exceed the fees paid to Qianhai Youlong Technology Co., Ltd. during your membership due to the use of the Services." + String get UG_LINE42 => "8. Under no circumstances shall Qianhai Youlong Technology Co., Ltd. be liable for any indirect, consequential, punitive, incidental, special or penal damages, including loss of profits suffered as a result of the user's use of the Services, even if notified of the The possibility of loss is also the same). Notwithstanding the fact that this Agreement may contain conflicting rules, Qianhai Youlong Technology Co., Ltd.'s entire liability to you, for whatever reason or behavior, shall not exceed the fees paid to Qianhai Youlong Technology Co., Ltd. during your membership due to the use of the Services."; + /// "Five, membership terms" + String get UG_LINE43 => "Five, membership terms"; + /// "1. Hibok members have equal rights to members and shall abide by Qianhai Youlong Technology Co., Ltd.'s specifications and rules, including but not limited to these Terms of Service and the User Agreement." + String get UG_LINE44 => "1. Hibok members have equal rights to members and shall abide by Qianhai Youlong Technology Co., Ltd.'s specifications and rules, including but not limited to these Terms of Service and the User Agreement."; + /// "2. The loss related to the suspension of membership services due to violation of the Qianhai Youlong Technology Co., Ltd. User Agreement shall be borne by the user." + String get UG_LINE45 => "2. The loss related to the suspension of membership services due to violation of the Qianhai Youlong Technology Co., Ltd. User Agreement shall be borne by the user."; + /// "3. Members can enjoy the value-added services of Hibok members during the membership period." + String get UG_LINE46 => "3. Members can enjoy the value-added services of Hibok members during the membership period."; + /// "4. If the member actively terminates or cancels the membership during the validity period of the membership, Qianhai Youlong Technology Co., Ltd. is not responsible for refunding the service fee corresponding to the validity period of the remaining membership of the member." + String get UG_LINE47 => "4. If the member actively terminates or cancels the membership during the validity period of the membership, Qianhai Youlong Technology Co., Ltd. is not responsible for refunding the service fee corresponding to the validity period of the remaining membership of the member."; + /// "5. Members shall bear the legal responsibility for transmitting, publishing information and using Hibok free services or fee-based services in Hibok. Members' use of Hibok services, including free services and fee-based services, shall abide by various laws, regulations, rules and regulations. file." + String get UG_LINE48 => "5. Members shall bear the legal responsibility for transmitting, publishing information and using Hibok free services or fee-based services in Hibok. Members' use of Hibok services, including free services and fee-based services, shall abide by various laws, regulations, rules and regulations. file."; + /// "6. After the membership service is opened, it cannot be transferred or unsubscribed." + String get UG_LINE49 => "6. After the membership service is opened, it cannot be transferred or unsubscribed."; + /// "7. In the course of the use of Qianhai Youlong Technology Co., Ltd.'s free service or fee-based service, there is a violation of laws and regulations. Qianhai Youlong Technology Co., Ltd. reserves the right to cancel the membership of the member without any compensation, and the member shall bear full responsibility." + String get UG_LINE50 => "7. In the course of the use of Qianhai Youlong Technology Co., Ltd.'s free service or fee-based service, there is a violation of laws and regulations. Qianhai Youlong Technology Co., Ltd. reserves the right to cancel the membership of the member without any compensation, and the member shall bear full responsibility."; + /// "Six other terms" + String get UG_LINE51 => "Six other terms"; + /// "1. Qianhai Youlong Technology Co., Ltd. solemnly reminds users to pay attention to the terms of the Agreement that exempt Qianhai Youlong Technology Co., Ltd. from liability and aggravate user obligations. Please read carefully and consider risks. Minors should read this Agreement accompanied by a legal guardian. The final interpretation and modification of the above terms and conditions is owned by Qianhai Youlong Technology Co., Ltd." + String get UG_LINE52 => "1. Qianhai Youlong Technology Co., Ltd. solemnly reminds users to pay attention to the terms of the Agreement that exempt Qianhai Youlong Technology Co., Ltd. from liability and aggravate user obligations. Please read carefully and consider risks. Minors should read this Agreement accompanied by a legal guardian. The final interpretation and modification of the above terms and conditions is owned by Qianhai Youlong Technology Co., Ltd."; + /// "2. The invalidity of some or all of the terms set forth in this Agreement shall not affect the validity of other terms." + String get UG_LINE53 => "2. The invalidity of some or all of the terms set forth in this Agreement shall not affect the validity of other terms."; + /// "3. The interpretation, validity and settlement of disputes in this Agreement shall apply to the laws of the People's Republic of China. If there is any dispute or dispute between the user and Qianhai Youlong Technology Co., Ltd., it should be settled through friendly negotiation. If the negotiation fails, the user hereby completely agrees to submit the dispute or dispute to the people's court of Qianhai Youlong Technology Co., Ltd.'s domicile." + String get UG_LINE54 => "3. The interpretation, validity and settlement of disputes in this Agreement shall apply to the laws of the People's Republic of China. If there is any dispute or dispute between the user and Qianhai Youlong Technology Co., Ltd., it should be settled through friendly negotiation. If the negotiation fails, the user hereby completely agrees to submit the dispute or dispute to the people's court of Qianhai Youlong Technology Co., Ltd.'s domicile."; + /// "4. The copyright of this Agreement is owned by Qianhai Youlong Technology Co., Ltd., and Qianhai Youlong Technology Co., Ltd. reserves all rights to interpret and modify." + String get UG_LINE55 => "4. The copyright of this Agreement is owned by Qianhai Youlong Technology Co., Ltd., and Qianhai Youlong Technology Co., Ltd. reserves all rights to interpret and modify."; + /// "Qianhai Youlong Technology Co., Ltd." + String get UG_LINE56 => "Qianhai Youlong Technology Co., Ltd."; + /// "Network anomaly" + String get net_error => "Network anomaly"; + /// "Please type in your name" + String get enter_name => "Please type in your name"; + /// "Aa" + String get translate => "Aa"; + /// "Location" + String get locate => "Location"; + /// "Press and hold the recording, release the send" + String get voice_tips => "Press and hold the recording, release the send"; + /// "Unlock" + String get unlock => "Unlock"; + /// "Enter chat content" + String get input_content => "Enter chat content"; + /// "Connecting..." + String get connecting => "Connecting..."; + /// "Landing..." + String get logining => "Landing..."; + /// "/s1 rejected your request to view" + String get reject_reply => "/s1 rejected your request to view"; + /// "You can redeem H coin within 3 days after no one reports it (1: 1000Vietnamese Dong)" + String get warning_text => "You can redeem H coin within 3 days after no one reports it (1: 1000Vietnamese Dong)"; + /// "The number of inputs is not greater than /s1" + String get more_big => "The number of inputs is not greater than /s1"; + /// "The number of inputs is not less than /s1" + String get little_min => "The number of inputs is not less than /s1"; + /// "/s1 invites you to a call" + String get voice_msg => "/s1 invites you to a call"; + /// "You rewarded each other /s1 /s2" + String get send_gift => "You rewarded each other /s1 /s2"; + /// "Your opponent rewarded you /s1 /s2" + String get receive_gift => "Your opponent rewarded you /s1 /s2"; + /// "Non-members cannot register" + String get cannot_join => "Non-members cannot register"; + /// "Returned" + String get alreay_back => "Returned"; + /// "File is too large" + String get video_more_big => "File is too large"; + /// "Select all" + String get select_all => "Select all"; + /// "Reconnect" + String get re_connect => "Reconnect"; + /// "Release to send, swipe to cancel" + String get voice_tips2 => "Release to send, swipe to cancel"; + /// "country" + String get country => "country"; + /// "Under review" + String get have_picture_view => "Under review"; + /// "Speaker play" + String get speaker_play => "Speaker play"; + /// "Handset playback" + String get handset_playback => "Handset playback"; + /// "Turn Off Speaker" + String get play_model => "Turn Off Speaker"; + /// "Password is too short" + String get password_less => "Password is too short"; + /// "Years old" + String get years_old => "Years old"; + /// "After an anonymous user reports, the system verifies that you have recently violated the rules. Do not perform any illegal actions. If the next time, the account will be frozen" + String get coin_returen1 => "After an anonymous user reports, the system verifies that you have recently violated the rules. Do not perform any illegal actions. If the next time, the account will be frozen"; + /// "Already the latest version" + String get already_new => "Already the latest version"; + /// "Experience now" + String get test_it => "Experience now"; + /// "Discover new version" + String get found_new => "Discover new version"; + /// "ad" + String get ad => "ad"; + /// "Focus" + String get attention => "Focus"; + /// "Fans" + String get fans => "Fans"; + /// "/s1 applies to view my profile" + String get apply_see => "/s1 applies to view my profile"; + /// "/s1 passed my review request" + String get agree_apply => "/s1 passed my review request"; + /// "/s1 viewed my red envelope photo" + String get see_redBag => "/s1 viewed my red envelope photo"; + /// "remind" + String get notice => "remind"; + /// "Turn on notification permissions for notifications" + String get notice_open => "Turn on notification permissions for notifications"; + /// "Notification permission is not turned on" + String get open_notice => "Notification permission is not turned on"; + /// "Notifications are not turned on and cannot be received" + String get not_open => "Notifications are not turned on and cannot be received"; + /// "The /s1 H coin you applied for withdrawal has been returned, please confirm that the bound account is correct" + String get withdraw_fail => "The /s1 H coin you applied for withdrawal has been returned, please confirm that the bound account is correct"; + /// "Moments" + String get dynamics => "Moments"; + /// "Remark" + String get Remark => "Remark"; + /// "Setting Notes" + String get setRemark => "Setting Notes"; + /// "/s1 comment" + String get content_num => "/s1 comment"; + /// "/s1H Coins for Points Exchange" + String get Redeem => "/s1H Coins for Points Exchange"; + /// "No access to phone storage" + String get location_permission => "No access to phone storage"; + /// "No access to the camera" + String get camera_permission => "No access to the camera"; + /// "No access to albums" + String get photo_permission => "No access to albums"; + /// "No access to microphone" + String get video_permission => "No access to microphone"; + /// "The red envelope you sent has expired" + String get your_redMoney_over => "The red envelope you sent has expired"; + /// "The red envelope sent by the other party has expired" + String get other_redMoney_over => "The red envelope sent by the other party has expired"; + /// "Looks like something went wrong ..." + String get server_error_tips => "Looks like something went wrong ..."; + /// "emoji" + String get emoji => "emoji"; + /// "Sign up today to receive /s1 points" + String get today_score => "Sign up today to receive /s1 points"; + /// "1. Daily sign-in can receive points. The more accumulated days, the higher the points. \n2. The points can be exchanged for H coins. The exchange will consume the corresponding points. Please redeem carefully. \n3. The sign-in will be reset on the last day of each month. Redeem in time." + String get sign_tips => "1. Daily sign-in can receive points. The more accumulated days, the higher the points. \n2. The points can be exchanged for H coins. The exchange will consume the corresponding points. Please redeem carefully. \n3. The sign-in will be reset on the last day of each month. Redeem in time."; + /// "Sign in" + String get sign_in => "Sign in"; + /// "My scores" + String get my_score => "My scores"; + /// "Sign in now" + String get signin_now => "Sign in now"; + /// "Accumulated sign in for /s1 day" + String get sign_in_day => "Accumulated sign in for /s1 day"; + /// "Redeemed" + String get have_get => "Redeemed"; + /// "Scan" + String get scan => "Scan"; + /// "My QR code" + String get my_qr => "My QR code"; + /// "Scan and add friends" + String get scan_and_add => "Scan and add friends"; + /// "Amap" + String get amap => "Amap"; + /// "Baidu Map" + String get baidumap => "Baidu Map"; + /// "Google Map" + String get googlemap => "Google Map"; + /// "Apple Map" + String get applemap => "Apple Map"; + /// "Go open" + String get go_open => "Go open"; + /// "Preview" + String get Preview => "Preview"; + /// "Photo album" + String get Photo_album => "Photo album"; + /// "All pictures" + String get all_photo => "All pictures"; + /// "You have selected /s1 pictures" + String get have_select => "You have selected /s1 pictures"; + /// "Loading..." + String get loading => "Loading..."; + /// "You have new chat messages" + String get new_chat_msg => "You have new chat messages"; + /// "You have new Lianmai news" + String get new_video_msg => "You have new Lianmai news"; + /// "/s1 apply to be your friend" + String get apply_friends => "/s1 apply to be your friend"; + /// "/s1 passed your friend request" + String get applyed_friends => "/s1 passed your friend request"; + /// "No access to contacts" + String get contact_permission => "No access to contacts"; + /// "Contacts" + String get contact => "Contacts"; + /// "search" + String get search => "search"; + /// "Add friends from contacts" + String get contact_add => "Add friends from contacts"; + /// "Find" + String get find => "Find"; + /// "Translation robot" + String get translate_robot => "Translation robot"; + /// "Hello i'm a translation robot..." + String get robot_hello => "Hello i'm a translation robot..."; + /// "Simplified Chinese" + String get Simplified_Chinese => "Simplified Chinese"; + /// "Traditional Chinese" + String get traditional_Chinese => "Traditional Chinese"; + /// "English" + String get english => "English"; + /// "Vietnamese" + String get Vietnamese => "Vietnamese"; + /// "Korean" + String get Korean => "Korean"; + /// "Japanese" + String get Japanese => "Japanese"; + /// "add friend" + String get add_friends => "add friend"; + /// "stranger" + String get stranger => "stranger"; + /// "Receive messages from strangers" + String get receive_stranger => "Receive messages from strangers"; + /// "SignIn" + String get signin => "SignIn"; + /// "They refuse to receive messages from strangers, continue to unlock all information?" + String get stranger_close => "They refuse to receive messages from strangers, continue to unlock all information?"; + /// "add" + String get add => "add"; + /// "added" + String get added => "added"; + /// "They refuse to receive messages from strangers." + String get stranger_close_tips => "They refuse to receive messages from strangers."; + /// "Translation failed" + String get translate_fail => "Translation failed"; + /// "Please upload photos first, and then set up red envelope photos. " + String get no_photos => "Please upload photos first, and then set up red envelope photos. "; + /// "Your appeal evaluation: /s1 the appeal failed. " + String get successful_appeal1 => "Your appeal evaluation: /s1 the appeal failed. "; + /// "Add succeeded and wait for their consent" + String get add_success => "Add succeeded and wait for their consent"; + /// "Payment by others" + String get other_pay => "Payment by others"; + /// "Friend verification " + String get friend_verification => "Friend verification "; + /// "You have sent a verification application and wait for them to pass" + String get add_friends_tips => "You have sent a verification application and wait for them to pass"; + /// "I am /s1" + String get i_am => "I am /s1"; + /// "Agree" + String get agree => "Agree"; + /// "\"Hi\"You need to approve the Privacy Agreement before use " + String get privacyAgreement => "\"Hi\"You need to approve the Privacy Agreement before use "; + /// "Privacy Agreement" + String get privacy => "Privacy Agreement"; + /// "Hi!someone has applied to add you as a friend and to see who it is " + String get notification_addfriend => "Hi!someone has applied to add you as a friend and to see who it is "; + /// "You can only add friends face to face " + String get distance_long => "You can only add friends face to face "; + /// "For accuracy of translation, please do not abbreviate " + String get chat_tips => "For accuracy of translation, please do not abbreviate "; + /// "Fans list " + String get fans_list => "Fans list "; + /// "During beta test" + String get system_not_open => "During beta test"; + /// "Withdrawal is not supported for IOS client at present. You can withdraw by Android client, or click the button below" + String get service_withdraw_tips => "Withdrawal is not supported for IOS client at present. You can withdraw by Android client, or click the button below"; + /// "Click to withdraw " + String get withdraw_tips => "Click to withdraw "; + /// "Add member " + String get add_member => "Add member "; + /// "Delete member" + String get delete_member => "Delete member"; + /// "Change group name" + String get change_group_name => "Change group name"; + /// "My group nickname" + String get my_group_nickname => "My group nickname"; + /// "Group chat" + String get group_chat => "Group chat"; + /// "Create group chat" + String get create_group_chat => "Create group chat"; + /// "You need to send a verification application and wait for them to pass " + String get added_friends_tips => "You need to send a verification application and wait for them to pass "; + /// "Group chat name" + String get group_chat_name => "Group chat name"; + /// "You can set your group nickname here, which will only be displayed in this group " + String get my_group_nickname_tips => "You can set your group nickname here, which will only be displayed in this group "; + /// "Male god message" + String get man_gold => "Male god message"; + /// "Goddess message" + String get woman_gold => "Goddess message"; + /// "Choose a new group owner" + String get choose_group_owner => "Choose a new group owner"; + /// "Group announcement" + String get group_announcement => "Group announcement"; + /// "Chat news" + String get chat_news => "Chat news"; + /// "Group QR code" + String get group_qr => "Group QR code"; + /// "Group management" + String get group_setting => "Group management"; + /// "Close news notice" + String get close_news_notice => "Close news notice"; + /// "Sticky on top" + String get set_chat_top => "Sticky on top"; + /// "Show group member nicknames" + String get show_group_member_name => "Show group member nicknames"; + /// "No other members in the group chat will be notified and this group chat message will not be received anymore " + String get quit_group_tips => "No other members in the group chat will be notified and this group chat message will not be received anymore "; + /// "Quit and delete" + String get quit_and_delete => "Quit and delete"; + /// "Show more members" + String get show_more_member => "Show more members"; + /// "Invitation confirmation" + String get group_invite => "Invitation confirmation"; + /// "Transfer of group ownership" + String get change_group_owner => "Transfer of group ownership"; + /// "After enabling, group members need confirmation from the group owner to invite friends to the group. Scanning QR code to enter the group will also be disabled" + String get group_setting_tips => "After enabling, group members need confirmation from the group owner to invite friends to the group. Scanning QR code to enter the group will also be disabled"; + /// "Invitation details" + String get invite_detail => "Invitation details"; + /// "Unnamed" + String get undefine_name => "Unnamed"; + /// "Group QR code business card" + String get group_qr_code => "Group QR code business card"; + /// "The QR code is valid within 7 days (before /s1 month /s2 days), re-entry will be updated" + String get group_qr_code_tips => "The QR code is valid within 7 days (before /s1 month /s2 days), re-entry will be updated"; + /// "Goddess heat" + String get Goddess_heat => "Goddess heat"; + /// "Gifts accumulated" + String get Goddess_heat_tips => "Gifts accumulated"; + /// "New friends" + String get new_friends => "New friends"; + /// "Three days ago" + String get before_three_day => "Three days ago"; + /// "Last three days" + String get after_three_day => "Last three days"; + /// "Clear chat history" + String get group_clean_chat_record => "Clear chat history"; + /// "Check" + String get check => "Check"; + /// "Request to add you as a friend" + String get apply_fro_friends => "Request to add you as a friend"; + /// "Non-members cannot withdraw" + String get no_vip_cannot_withdraw => "Non-members cannot withdraw"; + /// "This user is not authenticated, be careful not to be cheated" + String get not_true_woman => "This user is not authenticated, be careful not to be cheated"; + /// "Join group chat" + String get join_group => "Join group chat"; + /// "Login through Apple" + String get sign_in_apple => "Login through Apple"; + /// "Only group owner can edit group announcements" + String get only_host => "Only group owner can edit group announcements"; + /// "You sent /s1 gifts to others " + String get send_gift1 => "You sent /s1 gifts to others "; + /// "They sent /s1 gifts to you " + String get receive_gift1 => "They sent /s1 gifts to you "; + /// "You are no longer in this group " + String get not_in_group => "You are no longer in this group "; + /// "Creating, please wait " + String get creating_group => "Creating, please wait "; + /// "Article" + String get article => "Article"; + /// "Verification has been opened, and you can only enter the group by invitation" + String get group_open_verification => "Verification has been opened, and you can only enter the group by invitation"; + /// "Group members" + String get group_memeber => "Group members"; + /// "Invite friends to join in the group chat" + String get invite_members => "Invite friends to join in the group chat"; + /// "/s1 persons in total" + String get total_members => "/s1 persons in total"; + /// "QR code expired " + String get qr_outtime => "QR code expired "; + /// "No group information" + String get no_goupr_info => "No group information"; + /// "You invited /s1 to join the group chat " + String get you_invite => "You invited /s1 to join the group chat "; + /// "You are invited into group chat by /s1 " + String get invite_you => "You are invited into group chat by /s1 "; + /// "/s1 invites /s2 to join the group chat " + String get invite_someone => "/s1 invites /s2 to join the group chat "; + /// "You" + String get you => "You"; + /// "/s1 moves /s2 out of group chat " + String get delete_group => "/s1 moves /s2 out of group chat "; + /// "You have become a new group owner" + String get you_group_owner => "You have become a new group owner"; + /// "/s1 has become a new group owner " + String get someone_group_owner => "/s1 has become a new group owner "; + /// "The group name has been changed to /s1 " + String get change_group_owner1 => "The group name has been changed to /s1 "; + /// " Group announcement has been updated " + String get update_group_announce => " Group announcement has been updated "; + /// "You join group chat by scanning QR code" + String get you_qr => "You join group chat by scanning QR code"; + /// "/s1 join group chat by scanning QR code " + String get others_qr => "/s1 join group chat by scanning QR code "; + /// " \"/s1 \" want to invite /S2 friends to join the group chat \$ to confirm \$" + String get invite_confirm => " \"/s1 \" want to invite /S2 friends to join the group chat \$ to confirm \$"; + /// " \" /s1 \"want to invite \" /s2 \" to join the group chat " + String get want_invite_confirm => " \" /s1 \"want to invite \" /s2 \" to join the group chat "; + /// " \"/s1 \"joins group chat, confirmed" + String get join_group_confirm => " \"/s1 \"joins group chat, confirmed"; + /// "You are invited into group chat by /s1 " + String get you_invite_gourp => "You are invited into group chat by /s1 "; + /// " \"/s1\" joins group chat " + String get someone_join_group => " \"/s1\" joins group chat "; + /// " Group owner has opened the \" group chat invitation confirmation \", group members can invite friends into the group only after group owner's confirmation " + String get group_setting_tips1 => " Group owner has opened the \" group chat invitation confirmation \", group members can invite friends into the group only after group owner's confirmation "; + /// "The group owner has restored the default group entering method " + String get group_setting_tips2 => "The group owner has restored the default group entering method "; + /// " Group members have reached the upper limit " + String get members_max => " Group members have reached the upper limit "; + /// " The number of groups has reached the upper limit " + String get group_max => " The number of groups has reached the upper limit "; + /// "my bills" + String get my_money_info => "my bills"; + /// "my balance" + String get my_left_money => "my balance"; + /// "H coins can be obtained by recharging or exchange, and cannot be withdrawn" + String get money_tips => "H coins can be obtained by recharging or exchange, and cannot be withdrawn"; + /// "income details" + String get get_money_detail => "income details"; + /// "Hibox revenue" + String get hibok_money => "Hibox revenue"; + /// "exchange h coins " + String get charge_h => "exchange h coins "; + /// "withdrawal rules" + String get charge_tips => "withdrawal rules"; + /// "variable positioning" + String get splash_tips1 => "variable positioning"; + /// "Translation robot" + String get splash_tips2 => "Translation robot"; + /// "friends-making APP" + String get splash_tips3 => "friends-making APP"; + /// "gorgeous goddess, choose what you love " + String get splash_tips_content1 => "gorgeous goddess, choose what you love "; + /// "chat together by voice interaction" + String get splash_tips_content2 => "chat together by voice interaction"; + /// "solving language problems" + String get splash_tips_content3 => "solving language problems"; + /// "experience immediately" + String get splash_go => "experience immediately"; + /// "you exchanged /s1H coins through your income" + String get change_h_coin => "you exchanged /s1H coins through your income"; + /// " your application is successful, and the system has refunded" + String get Representation_succes => " your application is successful, and the system has refunded"; + /// " presented by system " + String get system_give => " presented by system "; + /// "your withdrawal application failed and has been returned" + String get exchange_fail => "your withdrawal application failed and has been returned"; + /// "exchange /s1H coins through Hibox income " + String get hibok_exchange => "exchange /s1H coins through Hibox income "; + /// "binding invitation code succeeded" + String get bind_code_success => "binding invitation code succeeded"; + /// " you have spent /s1H coins on manual translation" + String get translate_money => " you have spent /s1H coins on manual translation"; + /// " system return cancelled" + String get system_back => " system return cancelled"; + /// "you gave rewards to others " + String get you_give => "you gave rewards to others "; + /// " you got rewards from others" + String get you_get => " you got rewards from others"; + /// " number of exchanges (unit K) " + String get enter_num_qian => " number of exchanges (unit K) "; + /// " number of withdrawals (unit K) " + String get enter_num_qian1 => " number of withdrawals (unit K) "; + /// "翻译券" + String get daily_translate_voucher => "翻译券"; + /// "通知消息" + String get msg_notice => "通知消息"; + /// "选择提醒的人" + String get select_notice_people => "选择提醒的人"; + /// "查找手机号" + String get search_phone => "查找手机号"; + /// "用户不存在" + String get not_have_user => "用户不存在"; + /// "你不能添加自己" + String get not_add_Myself => "你不能添加自己"; + /// "对方已拉黑了你" + String get you_are_blaklisted => "对方已拉黑了你"; + /// "确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)" + String get confrim_recovery => "确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)"; + /// "發送到" + String get send_to => "發送到"; +} + +class _I18n_en_US extends I18n { + const _I18n_en_US(); + + @override + TextDirection get textDirection => TextDirection.ltr; +} + +class _I18n_vi_VN extends I18n { + const _I18n_vi_VN(); + + /// "Hibok" + @override + String get appName => "Hibok"; + /// "Đăng nhập" + @override + String get login => "Đăng nhập"; + /// "Đăng ký" + @override + String get registration => "Đăng ký"; + /// "Cách đăng nhập khác" + @override + String get other_login => "Cách đăng nhập khác"; + /// "Số tài khoản" + @override + String get account => "Số tài khoản"; + /// "Vui lòng nhập số tài khoản" + @override + String get enter_username => "Vui lòng nhập số tài khoản"; + /// "Mật khẩu" + @override + String get password => "Mật khẩu"; + /// "Nhập mật khẩu" + @override + String get enter_password => "Nhập mật khẩu"; + /// "Quên mật khẩu" + @override + String get forget_password => "Quên mật khẩu"; + /// "Đặt lại mật khẩu" + @override + String get reset_password => "Đặt lại mật khẩu"; + /// "Đăng ký số điện thoại" + @override + String get number_registration => "Đăng ký số điện thoại"; + /// "Nhập số điện thoại" + @override + String get enter_number => "Nhập số điện thoại"; + /// "Mã xác thực" + @override + String get code => "Mã xác thực"; + /// "Nhập mã xác thực" + @override + String get enter_code => "Nhập mã xác thực"; + /// "Gửi mã xác thực" + @override + String get send_code => "Gửi mã xác thực"; + /// "Gửi lại" + @override + String get send_again => "Gửi lại"; + /// "Cài đặt mật khẩu" + @override + String get set_password => "Cài đặt mật khẩu"; + /// "Mật khẩu không được dưới 6 ký tự" + @override + String get password_limit => "Mật khẩu không được dưới 6 ký tự"; + /// "Xác lập mật khẩu" + @override + String get set_password2 => "Xác lập mật khẩu"; + /// "Tiếp theo" + @override + String get next_step => "Tiếp theo"; + /// "Click vào đây để xác nhận bạn đã đọc và đồng ý với \"điều khoản sử dụng\"" + @override + String get agreed_agreement => "Click vào đây để xác nhận bạn đã đọc và đồng ý với \"điều khoản sử dụng\""; + /// "Xin nhập mật khẩu đăng nhập" + @override + String get enter_password2 => "Xin nhập mật khẩu đăng nhập"; + /// "Cài đặt lại" + @override + String get reset_now => "Cài đặt lại"; + /// "Chọn giới tính" + @override + String get choose_gender => "Chọn giới tính"; + /// "Bạn là" + @override + String get who => "Bạn là"; + /// "Xác định" + @override + String get determine => "Xác định"; + /// "không thể sủa đổi sau khi đã xác định giới tính" + @override + String get cannot_modified => "không thể sủa đổi sau khi đã xác định giới tính"; + /// "Nhắc nhở" + @override + String get tip => "Nhắc nhở"; + /// "Bạn sắp hoàn tất đăng ký, bạn thực sự muốn bỏ cuộc?" + @override + String get choose_quit => "Bạn sắp hoàn tất đăng ký, bạn thực sự muốn bỏ cuộc?"; + /// "Xác nhận" + @override + String get confirm => "Xác nhận"; + /// "Sử dụng" + @override + String get use => "Sử dụng"; + /// "Hủy" + @override + String get cancel => "Hủy"; + /// "Đóng" + @override + String get close => "Đóng"; + /// "Xóa" + @override + String get delete => "Xóa"; + /// "Bỏ qua" + @override + String get forget_it => "Bỏ qua"; + /// "OK" + @override + String get ok => "OK"; + /// "Sau khi đăng ký bạn sẽ không thể sửa đổi giới tính của mình. Bạn có chắc không?" + @override + String get choose_quit2 => "Sau khi đăng ký bạn sẽ không thể sửa đổi giới tính của mình. Bạn có chắc không?"; + /// "Nhắc nhở:bạn không thể tiến hành giao lưu với người dùng cùng giới" + @override + String get tip_content => "Nhắc nhở:bạn không thể tiến hành giao lưu với người dùng cùng giới"; + /// "Chào mừng bạn" + @override + String get welcome => "Chào mừng bạn"; + /// "Vui lòng nhập mã mời" + @override + String get enter_incode => "Vui lòng nhập mã mời"; + /// "Hibok chỉ phục vụ khách hàng nam cung cấp mã mời" + @override + String get must_incode => "Hibok chỉ phục vụ khách hàng nam cung cấp mã mời"; + /// "Mã mời của bạn" + @override + String get your_incode => "Mã mời của bạn"; + /// "Chưa có mã mời? Bạn có thể lấy mã mời theo những cách sau" + @override + String get how_get => "Chưa có mã mời? Bạn có thể lấy mã mời theo những cách sau"; + /// "Cách 1" + @override + String get method1 => "Cách 1"; + /// "Đăng ký miễn phí" + @override + String get free => "Đăng ký miễn phí"; + /// "Đăng ký ngay" + @override + String get apply_now => "Đăng ký ngay"; + /// "Nhận mã mời" + @override + String get check_incode => "Nhận mã mời"; + /// "Bạn cần điền một số thông tin cá nhân, chúng tôi sẽ gửi mã mời cho bạn sau khi hoàn thành xét duyệt." + @override + String get so_get => "Bạn cần điền một số thông tin cá nhân, chúng tôi sẽ gửi mã mời cho bạn sau khi hoàn thành xét duyệt."; + /// "Đăng ký mã mời" + @override + String get apply_incode => "Đăng ký mã mời"; + /// "Vị trí" + @override + String get location => "Vị trí"; + /// "Thành phố bạn đang ở" + @override + String get cityname => "Thành phố bạn đang ở"; + /// "Kênh thông tin" + @override + String get message_channel => "Kênh thông tin"; + /// "Bạn biết đến APP này qua đâu?" + @override + String get how_know => "Bạn biết đến APP này qua đâu?"; + /// "Wechat" + @override + String get wechat_number => "Wechat"; + /// "Tài khoản Wechat của bạn" + @override + String get your_wechat => "Tài khoản Wechat của bạn"; + /// "Facebook" + @override + String get facebook => "Facebook"; + /// "Facebook của bạn" + @override + String get your_facebook => "Facebook của bạn"; + /// "Gửi yêu cầu" + @override + String get submit_application => "Gửi yêu cầu"; + /// "Vui lòng nhập tên Thành Phố bạn đang ở" + @override + String get enter_city => "Vui lòng nhập tên Thành Phố bạn đang ở"; + /// "Bạn biết APP này qua kênh thông tin nào?" + @override + String get so_know => "Bạn biết APP này qua kênh thông tin nào?"; + /// "Xin cung cấp mạng xã hội của bạn cho chúng tôi" + @override + String get your_social => "Xin cung cấp mạng xã hội của bạn cho chúng tôi"; + /// "Chúng tôi sẽ xử lý sớm yêu cầu của bạn.Nếu xét duyệt được thông qua chúng tôi sẽ gửi mã mời vào trung tâm tin nhắn của bạn." + @override + String get receive_incode => "Chúng tôi sẽ xử lý sớm yêu cầu của bạn.Nếu xét duyệt được thông qua chúng tôi sẽ gửi mã mời vào trung tâm tin nhắn của bạn."; + /// "Mã mời vẫn chưa được gửi đi, sau khi hoàn tất thao tác gửi đơn yêu cầu, vui lòng chờ trong giây lát!" + @override + String get wait_incode => "Mã mời vẫn chưa được gửi đi, sau khi hoàn tất thao tác gửi đơn yêu cầu, vui lòng chờ trong giây lát!"; + /// "Xin mã mời thành công" + @override + String get successful_application1 => "Xin mã mời thành công"; + /// "Xin mã mời thất bại" + @override + String get application_failed1 => "Xin mã mời thất bại"; + /// "Sao chép thành công" + @override + String get successful_copy => "Sao chép thành công"; + /// "Cách 2" + @override + String get method2 => "Cách 2"; + /// "Trở thành VIP" + @override + String get joinvip => "Trở thành VIP"; + /// "Tham gia ngay" + @override + String get join_now => "Tham gia ngay"; + /// "Đã tham gia" + @override + String get joined => "Đã tham gia"; + /// "Sau khi gia nhập bạn sẽ có thêm nhiều đặc quyền, bao gồm đăng ký không cần mã mời" + @override + String get join_odds => "Sau khi gia nhập bạn sẽ có thêm nhiều đặc quyền, bao gồm đăng ký không cần mã mời"; + /// "Bạn chưa gia nhập thành viên" + @override + String get not_joinvip => "Bạn chưa gia nhập thành viên"; + /// "Sau khi gia nhập bạn có thể đăng ký mà không cần mã mời" + @override + String get join_after => "Sau khi gia nhập bạn có thể đăng ký mà không cần mã mời"; + /// "Hoàn tất xác nhận mã mời" + @override + String get incode_passed => "Hoàn tất xác nhận mã mời"; + /// "Chào mừng bạn tham gia! Xin đừng tiết lộ số tài khoản của bạn cho người khác, khi phát hiện đăng nhập bất thường tài khoản sẽ tự động đóng băng." + @override + String get welcome_join => "Chào mừng bạn tham gia! Xin đừng tiết lộ số tài khoản của bạn cho người khác, khi phát hiện đăng nhập bất thường tài khoản sẽ tự động đóng băng."; + /// "Trung tâm thành viên" + @override + String get member_centre => "Trung tâm thành viên"; + /// "Đặc quyền của thành viên" + @override + String get members_privilege => "Đặc quyền của thành viên"; + /// "Right 1" + @override + String get see_more => "Right 1"; + /// "Tài khoản không giới hạn số lượng xem mỗi ngày" + @override + String get unlimited_see => "Tài khoản không giới hạn số lượng xem mỗi ngày"; + /// "Right 2" + @override + String get see_cheaper => "Right 2"; + /// "Xem album và tài khoản miễn phí /s1 lần trong một ngày" + @override + String get free10 => "Xem album và tài khoản miễn phí /s1 lần trong một ngày"; + /// "Right 3" + @override + String get see_longer => "Right 3"; + /// "Thời gian xem ảnh tự hủy sẽ chỉnh từ 2 giây thành /s1 giây." + @override + String get towto6 => "Thời gian xem ảnh tự hủy sẽ chỉnh từ 2 giây thành /s1 giây."; + /// "Right 4" + @override + String get see_better => "Right 4"; + /// "Cơ hội miễn phí phát sóng 3/ngày." + @override + String get free_release => "Cơ hội miễn phí phát sóng 3/ngày."; + /// "Chọn các gói" + @override + String get choose_price => "Chọn các gói"; + /// "Phương thức thanh toán" + @override + String get pay_method => "Phương thức thanh toán"; + /// "Số tiền thanh toán" + @override + String get pay_amount => "Số tiền thanh toán"; + /// "Số dư ví không đủ" + @override + String get not_enough => "Số dư ví không đủ"; + /// "Xác nhận thanh toán" + @override + String get confirm_pay => "Xác nhận thanh toán"; + /// "Hoàn tất thông tin" + @override + String get complete_material => "Hoàn tất thông tin"; + /// "Thông tin cơ bản" + @override + String get basic_information => "Thông tin cơ bản"; + /// "Tải ảnh đại diện" + @override + String get upload_avatar => "Tải ảnh đại diện"; + /// "Vui lòng chọn" + @override + String get choose => "Vui lòng chọn"; + /// "Vui lòng điền vào" + @override + String get fill_out => "Vui lòng điền vào"; + /// "Có thể chọn nhiều mục cùng lúc" + @override + String get choose_multiple => "Có thể chọn nhiều mục cùng lúc"; + /// "Tùy chọn" + @override + String get optional => "Tùy chọn"; + /// "Điền vào ít nhất /s1" + @override + String get least => "Điền vào ít nhất /s1"; + /// "Giới thiệu bản thân" + @override + String get introduce_yourself => "Giới thiệu bản thân"; + /// "Chọn tối đa /s1" + @override + String get most => "Chọn tối đa /s1"; + /// "Biệt danh" + @override + String get nickname => "Biệt danh"; + /// "Biệt danh không được quá 20 ký tự" + @override + String get only1_8 => "Biệt danh không được quá 20 ký tự"; + /// "TP hiện tại" + @override + String get Resident_city => "TP hiện tại"; + /// "Vui lòng chọn thành phố hiện tại" + @override + String get Please_select_a_resident_city => "Vui lòng chọn thành phố hiện tại"; + /// "Cần Thơ" + @override + String get City1 => "Cần Thơ"; + /// "Đà Nẵng" + @override + String get City2 => "Đà Nẵng"; + /// "Hải Phòng" + @override + String get City3 => "Hải Phòng"; + /// "Hà Nội" + @override + String get City4 => "Hà Nội"; + /// "Hồ Chí Minh" + @override + String get City5 => "Hồ Chí Minh"; + /// "An Giang" + @override + String get City6 => "An Giang"; + /// "Bắc Giang" + @override + String get City7 => "Bắc Giang"; + /// "Bắc Cạn" + @override + String get City8 => "Bắc Cạn"; + /// "Bạc Liêu" + @override + String get City9 => "Bạc Liêu"; + /// "Bắc Ninh" + @override + String get City10 => "Bắc Ninh"; + /// "Bà Rịa- Vũng Tàu" + @override + String get City11 => "Bà Rịa- Vũng Tàu"; + /// "Bến Tre" + @override + String get City12 => "Bến Tre"; + /// "Bình Định" + @override + String get City13 => "Bình Định"; + /// "Bình Dương" + @override + String get City14 => "Bình Dương"; + /// "Bình Phước" + @override + String get City15 => "Bình Phước"; + /// "Bình Thuận" + @override + String get City16 => "Bình Thuận"; + /// "Cà Mau" + @override + String get City17 => "Cà Mau"; + /// "Cao Bằng" + @override + String get City18 => "Cao Bằng"; + /// "Đà Lạt" + @override + String get City19 => "Đà Lạt"; + /// "Đắc Nông" + @override + String get City20 => "Đắc Nông"; + /// "Điện Biên" + @override + String get City21 => "Điện Biên"; + /// "Đồng Nai" + @override + String get City22 => "Đồng Nai"; + /// "Đồng Tháp" + @override + String get City23 => "Đồng Tháp"; + /// "Gia Lai" + @override + String get City24 => "Gia Lai"; + /// "Hà Giang" + @override + String get City25 => "Hà Giang"; + /// "Hải Dương" + @override + String get City26 => "Hải Dương"; + /// "Hà Nam" + @override + String get City27 => "Hà Nam"; + /// "Hà Tĩnh" + @override + String get City28 => "Hà Tĩnh"; + /// "Hòa Bình" + @override + String get City29 => "Hòa Bình"; + /// "Hậu Giang" + @override + String get City30 => "Hậu Giang"; + /// "Hưng Yên" + @override + String get City31 => "Hưng Yên"; + /// "Khánh Hòa" + @override + String get City32 => "Khánh Hòa"; + /// "Kiên Giang" + @override + String get City33 => "Kiên Giang"; + /// "Kon Tum" + @override + String get City34 => "Kon Tum"; + /// "Lai Châu" + @override + String get City35 => "Lai Châu"; + /// "Lâm Đồng" + @override + String get City36 => "Lâm Đồng"; + /// "Lạng Sơn" + @override + String get City37 => "Lạng Sơn"; + /// "Lào Cai" + @override + String get City38 => "Lào Cai"; + /// "Long An" + @override + String get City39 => "Long An"; + /// "Nghệ An" + @override + String get City40 => "Nghệ An"; + /// "Ninh Bình" + @override + String get City41 => "Ninh Bình"; + /// "Ninh Thuận" + @override + String get City42 => "Ninh Thuận"; + /// "Phú Thọ" + @override + String get City43 => "Phú Thọ"; + /// "Phú Yên" + @override + String get City44 => "Phú Yên"; + /// "Quảng Bình" + @override + String get City45 => "Quảng Bình"; + /// "Quảng Nam" + @override + String get City46 => "Quảng Nam"; + /// "Quảng Ngãi" + @override + String get City47 => "Quảng Ngãi"; + /// "Quảng Ninh" + @override + String get City48 => "Quảng Ninh"; + /// "Quảng Trị" + @override + String get City49 => "Quảng Trị"; + /// "Sóc Trăng" + @override + String get City50 => "Sóc Trăng"; + /// "Sơn La" + @override + String get City51 => "Sơn La"; + /// "Tây Ninh" + @override + String get City52 => "Tây Ninh"; + /// "Thái Bình" + @override + String get City53 => "Thái Bình"; + /// "Thái Nguyên" + @override + String get City54 => "Thái Nguyên"; + /// "Thanh Hóa" + @override + String get City55 => "Thanh Hóa"; + /// "Thừa Thiên- Huế" + @override + String get City56 => "Thừa Thiên- Huế"; + /// "Tiền Giang" + @override + String get City57 => "Tiền Giang"; + /// "Trà Vinh" + @override + String get City58 => "Trà Vinh"; + /// "Tuyên Quang" + @override + String get City59 => "Tuyên Quang"; + /// "Vĩnh Long" + @override + String get City60 => "Vĩnh Long"; + /// "Vĩnh Phúc" + @override + String get City61 => "Vĩnh Phúc"; + /// "Yên Bái" + @override + String get City62 => "Yên Bái"; + /// "Nam Định" + @override + String get City63 => "Nam Định"; + /// "Ngày sinh" + @override + String get birthday => "Ngày sinh"; + /// "Chọn ngày sinh" + @override + String get choose_birthday => "Chọn ngày sinh"; + /// "Năm" + @override + String get year => "Năm"; + /// "Tháng" + @override + String get month => "Tháng"; + /// "Ngày" + @override + String get day => "Ngày"; + /// "Giờ" + @override + String get hour => "Giờ"; + /// "Phút" + @override + String get minute => "Phút"; + /// "Giây" + @override + String get second => "Giây"; + /// "Mới đây" + @override + String get just => "Mới đây"; + /// "/s1 phút trước" + @override + String get minute_ago => "/s1 phút trước"; + /// "/s1 giờ trước" + @override + String get hour_ago => "/s1 giờ trước"; + /// "/s1 ngày trước" + @override + String get day_ago => "/s1 ngày trước"; + /// "/s1 tuần trước" + @override + String get week_ago => "/s1 tuần trước"; + /// "/s1 tháng trước" + @override + String get month_ago => "/s1 tháng trước"; + /// "Sáng" + @override + String get morning => "Sáng"; + /// "Trưa" + @override + String get noon => "Trưa"; + /// "Chiều" + @override + String get afternoon => "Chiều"; + /// "Tối" + @override + String get night => "Tối"; + /// "Cả ngày" + @override + String get all_day => "Cả ngày"; + /// "Hôm qua" + @override + String get yesterday => "Hôm qua"; + /// "Hôm trước" + @override + String get two_yesterday => "Hôm trước"; + /// "Sáng đêm" + @override + String get overnight => "Sáng đêm"; + /// "Cái" + @override + String get one => "Cái"; + /// "Mười" + @override + String get ten => "Mười"; + /// "Trăm" + @override + String get hundred => "Trăm"; + /// "Nghìn" + @override + String get thousand => "Nghìn"; + /// "Mười nghìn" + @override + String get ten_thousand => "Mười nghìn"; + /// "Chòm sao Bạch Dương" + @override + String get aries => "Chòm sao Bạch Dương"; + /// "Chòm sao Kim Ngưu" + @override + String get taurus => "Chòm sao Kim Ngưu"; + /// "Chòm sao Song Tử" + @override + String get gemini => "Chòm sao Song Tử"; + /// "Chòm sao Cự Giải" + @override + String get cancer => "Chòm sao Cự Giải"; + /// "Chòm sao Sư Tử" + @override + String get leo => "Chòm sao Sư Tử"; + /// "Chòm sao Xử Nữ" + @override + String get virgo => "Chòm sao Xử Nữ"; + /// "Chòm sao Thiên Bình" + @override + String get libra => "Chòm sao Thiên Bình"; + /// "Chòm sao Bọ Cạp" + @override + String get scorpio => "Chòm sao Bọ Cạp"; + /// "Chòm sao Nhân Mã" + @override + String get sagittarius => "Chòm sao Nhân Mã"; + /// "Chòm sao Ma Kết" + @override + String get capricorn => "Chòm sao Ma Kết"; + /// "Chòm sao Bảo Bình" + @override + String get aquarius => "Chòm sao Bảo Bình"; + /// "Chòm sao Song Ngư" + @override + String get pisces => "Chòm sao Song Ngư"; + /// "Thứ hai" + @override + String get monday => "Thứ hai"; + /// "Thứ ba" + @override + String get tuesday => "Thứ ba"; + /// "Thứ tư" + @override + String get wednesday => "Thứ tư"; + /// "Thứ năm" + @override + String get thursday => "Thứ năm"; + /// "Thứ sáu" + @override + String get friday => "Thứ sáu"; + /// "Thứ bảy" + @override + String get saturday => "Thứ bảy"; + /// "Chủ nhật" + @override + String get sunday => "Chủ nhật"; + /// "chuyên nghiệp" + @override + String get job => "chuyên nghiệp"; + /// "Chọn một nghề nghiệp" + @override + String get choose_career => "Chọn một nghề nghiệp"; + /// "Công nghệ thông tin" + @override + String get career1 => "Công nghệ thông tin"; + /// "Internet" + @override + String get career2 => "Internet"; + /// "CNTT" + @override + String get career3 => "CNTT"; + /// "Hoạt động viễn thông" + @override + String get career4 => "Hoạt động viễn thông"; + /// "Trò chơi trực tuyến" + @override + String get career5 => "Trò chơi trực tuyến"; + /// "Bảo hiểm tài chính" + @override + String get career6 => "Bảo hiểm tài chính"; + /// "Đầu tư" + @override + String get career7 => "Đầu tư"; + /// "Quỹ đầu tư" + @override + String get career8 => "Quỹ đầu tư"; + /// "Bảo hiểm" + @override + String get career9 => "Bảo hiểm"; + /// "Ngân hàng" + @override + String get career10 => "Ngân hàng"; + /// "Thế chấp/ cầm cố" + @override + String get career11 => "Thế chấp/ cầm cố"; + /// "Dịch vụ kinh doanh" + @override + String get career12 => "Dịch vụ kinh doanh"; + /// "Tư vấn" + @override + String get career13 => "Tư vấn"; + /// "Kinh doanh cá thể" + @override + String get career14 => "Kinh doanh cá thể"; + /// "Beauty salon" + @override + String get career15 => "Beauty salon"; + /// "Du lịch" + @override + String get career16 => "Du lịch"; + /// "Khách sạn- nhà hàng" + @override + String get career17 => "Khách sạn- nhà hàng"; + /// "Giải trí" + @override + String get career18 => "Giải trí"; + /// "Thương mại" + @override + String get career19 => "Thương mại"; + /// "Xe hơi" + @override + String get career20 => "Xe hơi"; + /// "Bất động sản" + @override + String get career21 => "Bất động sản"; + /// "Quản lý tòa nhà" + @override + String get career22 => "Quản lý tòa nhà"; + /// "Trang trí nội thất" + @override + String get career23 => "Trang trí nội thất"; + /// "Thám tử" + @override + String get career24 => "Thám tử"; + /// "Công trình sản xuất" + @override + String get career25 => "Công trình sản xuất"; + /// "Kiến Trúc" + @override + String get career26 => "Kiến Trúc"; + /// "Xây dựng dân dụng" + @override + String get career27 => "Xây dựng dân dụng"; + /// "Chế tạo cơ khí" + @override + String get career28 => "Chế tạo cơ khí"; + /// "Điện tử" + @override + String get career29 => "Điện tử"; + /// "Khoa học Y Sinh" + @override + String get career30 => "Khoa học Y Sinh"; + /// "Thực phẩm" + @override + String get career31 => "Thực phẩm"; + /// "Trang Phục" + @override + String get career32 => "Trang Phục"; + /// "Năng lượng" + @override + String get career33 => "Năng lượng"; + /// "Giao thông vận tải" + @override + String get career34 => "Giao thông vận tải"; + /// "Hàng không" + @override + String get career35 => "Hàng không"; + /// "Đường sắt" + @override + String get career36 => "Đường sắt"; + /// "Vận tải hàng hải" + @override + String get career37 => "Vận tải hàng hải"; + /// "Giao thông công cộng" + @override + String get career38 => "Giao thông công cộng"; + /// "Vận tải hàng hóa" + @override + String get career39 => "Vận tải hàng hóa"; + /// "Kênh truyền thông văn hóa" + @override + String get career40 => "Kênh truyền thông văn hóa"; + /// "Nhà xuất bản" + @override + String get career41 => "Nhà xuất bản"; + /// "Thiết kế" + @override + String get career42 => "Thiết kế"; + /// "Truyền bá văn hóa" + @override + String get career43 => "Truyền bá văn hóa"; + /// "Quảng cáo sáng tạo" + @override + String get career44 => "Quảng cáo sáng tạo"; + /// "Anime" + @override + String get career45 => "Anime"; + /// "Quảng bá triển lãm" + @override + String get career46 => "Quảng bá triển lãm"; + /// "Nhiếp ảnh" + @override + String get career47 => "Nhiếp ảnh"; + /// "Thể thao giải trí" + @override + String get career48 => "Thể thao giải trí"; + /// "Phim ảnh" + @override + String get career49 => "Phim ảnh"; + /// "Thể thao thể thao" + @override + String get career50 => "Thể thao thể thao"; + /// "Âm nhạc" + @override + String get career51 => "Âm nhạc"; + /// "Người mẫu" + @override + String get career52 => "Người mẫu"; + /// "Tiện ích công cộng" + @override + String get career53 => "Tiện ích công cộng"; + /// "Y tế" + @override + String get career54 => "Y tế"; + /// "Pháp luật" + @override + String get career55 => "Pháp luật"; + /// "Giáo dục" + @override + String get career56 => "Giáo dục"; + /// "Cơ quan chính phủ" + @override + String get career57 => "Cơ quan chính phủ"; + /// "Công ích" + @override + String get career58 => "Công ích"; + /// "Học sinh/ Sinh viên" + @override + String get career59 => "Học sinh/ Sinh viên"; + /// "Không" + @override + String get career60 => "Không"; + /// "Chương trình" + @override + String get program => "Chương trình"; + /// "Vui lòng chọn quốc tịch" + @override + String get select_program => "Vui lòng chọn quốc tịch"; + /// "TDTT" + @override + String get healthy_exercise => "TDTT"; + /// "Tiệc đêm" + @override + String get night_party => "Tiệc đêm"; + /// "Sành ăn" + @override + String get gourmet_party => "Sành ăn"; + /// "Xem phim" + @override + String get watch_movie => "Xem phim"; + /// "Chơi game" + @override + String get play_games => "Chơi game"; + /// "Du lịch" + @override + String get travel_together => "Du lịch"; + /// "Trò chuyện" + @override + String get voice_chat => "Trò chuyện"; + /// "Khác" + @override + String get other => "Khác"; + /// "Mẫu lý tưởng" + @override + String get expect_lover => "Mẫu lý tưởng"; + /// "Vui lòng chọn mẫu người yêu lý tưởng của bạn" + @override + String get choose_lover => "Vui lòng chọn mẫu người yêu lý tưởng của bạn"; + /// "Gương mặt đẹp" + @override + String get beautiful => "Gương mặt đẹp"; + /// "Thổ hào" + @override + String get rich => "Thổ hào"; + /// "Quan tâm và yêu thương tôi" + @override + String get care_me => "Quan tâm và yêu thương tôi"; + /// "Cảm giác là trên hết" + @override + String get look_feeling => "Cảm giác là trên hết"; + /// "Không quan trọng" + @override + String get doesnt_matter => "Không quan trọng"; + /// "Vui lòng nhập ít nhất một tài khoản xã hội" + @override + String get least_account => "Vui lòng nhập ít nhất một tài khoản xã hội"; + /// "Ẩn tài khoản xã hội" + @override + String get hide_account1 => "Ẩn tài khoản xã hội"; + /// "Những thông tin khác" + @override + String get more_information => "Những thông tin khác"; + /// "Chiều cao" + @override + String get height => "Chiều cao"; + /// "Cân nặng" + @override + String get weight => "Cân nặng"; + /// "Không hiển thị" + @override + String get not_show => "Không hiển thị"; + /// "Giới thiệu" + @override + String get self_introduction => "Giới thiệu"; + /// "Đăng ký thành công" + @override + String get registration_success1 => "Đăng ký thành công"; + /// "Thoát?" + @override + String get exit => "Thoát?"; + /// "Bạn chưa hoàn thiện thông tin cá nhân. Lần sau đăng nhập trực tiếp bằng tài khoản đã đăng ký" + @override + String get exit_registration => "Bạn chưa hoàn thiện thông tin cá nhân. Lần sau đăng nhập trực tiếp bằng tài khoản đã đăng ký"; + /// "Phai nam giới không thể xem thông tin của phái nam" + @override + String get cant_see => "Phai nam giới không thể xem thông tin của phái nam"; + /// "Phái nữ giới không thể xem thông tin của phái nữ!" + @override + String get cant_see2 => "Phái nữ giới không thể xem thông tin của phái nữ!"; + /// "Bạn còn có thể xem /s1 quý cô ngày hôm nay" + @override + String get see_one => "Bạn còn có thể xem /s1 quý cô ngày hôm nay"; + /// "Không phải thành viên chỉ có thể xem 15 quý cô mỗi ngày" + @override + String get only_see => "Không phải thành viên chỉ có thể xem 15 quý cô mỗi ngày"; + /// "Tiếp tục xem" + @override + String get continue_see => "Tiếp tục xem"; + /// "Tài khoản đã đóng băng" + @override + String get user_frozen => "Tài khoản đã đóng băng"; + /// "Nhập biệt danh / nghề nghiệp để tìm kiếm" + @override + String get search_user => "Nhập biệt danh / nghề nghiệp để tìm kiếm"; + /// "Gần đây" + @override + String get nearby => "Gần đây"; + /// "Thành viên" + @override + String get member => "Thành viên"; + /// "Bạn mới" + @override + String get new_registration => "Bạn mới"; + /// "Xác thực" + @override + String get authenticate => "Xác thực"; + /// "Trực tuyến" + @override + String get first_online => "Trực tuyến"; + /// "Định vị là tắt, khoảng cách không thể được tính" + @override + String get not_positioned => "Định vị là tắt, khoảng cách không thể được tính"; + /// "Vẫn chưa xác nhận" + @override + String get unknown => "Vẫn chưa xác nhận"; + /// "Bảo mật" + @override + String get secrecy => "Bảo mật"; + /// "Sưu tập" + @override + String get collection => "Sưu tập"; + /// "Hủy sưu tập" + @override + String get cancel_collection => "Hủy sưu tập"; + /// "Đã hủy sưu tập" + @override + String get canceled_collection => "Đã hủy sưu tập"; + /// "Yêu thích" + @override + String get like => "Yêu thích"; + /// "Yêu thích" + @override + String get added_like => "Yêu thích"; + /// "Đã hủy yêu thích" + @override + String get canceled_like => "Đã hủy yêu thích"; + /// "Danh sách đen" + @override + String get blacklist => "Danh sách đen"; + /// "Bạn sẽ không thể thấy đối phương và hoạt động gần đây của họ, có chắc là bạn muốn thế không?" + @override + String get blacklist_choose => "Bạn sẽ không thể thấy đối phương và hoạt động gần đây của họ, có chắc là bạn muốn thế không?"; + /// "Đã thêm vào danh sách đen" + @override + String get blacklisted => "Đã thêm vào danh sách đen"; + /// "Bạn đã thêm đối Phương vào danh sách đen và từ chối nhận tin nhắn" + @override + String get reject_message => "Bạn đã thêm đối Phương vào danh sách đen và từ chối nhận tin nhắn"; + /// "Xóa khỏi danh sách đen" + @override + String get remove_blacklist => "Xóa khỏi danh sách đen"; + /// "Đã xóa khỏi danh sách đen" + @override + String get blacklist_removed => "Đã xóa khỏi danh sách đen"; + /// "Bạn đã xóa đối Phương khỏi danh sách đen và hủy chế độ từ chối tin nhắn" + @override + String get receive_message => "Bạn đã xóa đối Phương khỏi danh sách đen và hủy chế độ từ chối tin nhắn"; + /// "Trực tuyến" + @override + String get online => "Trực tuyến"; + /// "Album thu phí" + @override + String get paid_photo => "Album thu phí"; + /// "Xin" + @override + String get application_view => "Xin"; + /// "Đã duyệt" + @override + String get passed => "Đã duyệt"; + /// "Công viên" + @override + String get park => "Công viên"; + /// "Radio" + @override + String get radio => "Radio"; + /// "Tin nhắn" + @override + String get news => "Tin nhắn"; + /// "Tôi" + @override + String get me => "Tôi"; + /// "Các thao tác khác" + @override + String get more_operations => "Các thao tác khác"; + /// "Báo cáo ẩn danh" + @override + String get anonymous_report => "Báo cáo ẩn danh"; + /// "Video" + @override + String get certified_video => "Video"; + /// "Em ấy đã được xác thực danh tính qua video" + @override + String get passed_video => "Em ấy đã được xác thực danh tính qua video"; + /// "Em ấy vẫn chưa xác thực danh tính" + @override + String get not_video => "Em ấy vẫn chưa xác thực danh tính"; + /// "Em ấy đang phát tin hẹn hò" + @override + String get her_appointment => "Em ấy đang phát tin hẹn hò"; + /// "Anh ta đã đóng phí để gia nhập" + @override + String get pay_join => "Anh ta đã đóng phí để gia nhập"; + /// "Anh ta đã thông qua xác nhận thân phận" + @override + String get passed_review => "Anh ta đã thông qua xác nhận thân phận"; + /// "Anh ấy đã gia nhập thông qua mã mời từ tài khoản VIP /s1" + @override + String get invited_user => "Anh ấy đã gia nhập thông qua mã mời từ tài khoản VIP /s1"; + /// "Anh ấy đang phát tin hẹn hò" + @override + String get his_appointment => "Anh ấy đang phát tin hẹn hò"; + /// "Hoạt động của em ấy" + @override + String get her_dynamics => "Hoạt động của em ấy"; + /// "Hoạt động của anh ấy" + @override + String get his_dynamics => "Hoạt động của anh ấy"; + /// "Em ấy rất khiêm nhường" + @override + String get low_key => "Em ấy rất khiêm nhường"; + /// "Anh ấy rất khiêm nhường" + @override + String get low_key2 => "Anh ấy rất khiêm nhường"; + /// "Album ảnh của em ấy" + @override + String get her_photo => "Album ảnh của em ấy"; + /// "Album ảnh của anh ấy" + @override + String get his_photo => "Album ảnh của anh ấy"; + /// "Anh ấy đã khóa album" + @override + String get set_lock => "Anh ấy đã khóa album"; + /// "Em ấy đã khóa album" + @override + String get set_lock2 => "Em ấy đã khóa album"; + /// "Mở khóa album (/s1) miễn phí cho các thành viên" + @override + String get free_unlock => "Mở khóa album (/s1) miễn phí cho các thành viên"; + /// "Mở Khóa album của /s1" + @override + String get unlock_user => "Mở Khóa album của /s1"; + /// "Mở khóa trả phí (/s1H coin)" + @override + String get pay_unlock => "Mở khóa trả phí (/s1H coin)"; + /// "Miễn phí cho các thành viên" + @override + String get become_member => "Miễn phí cho các thành viên"; + /// "Bạn muốn sử dụng 01 cơ hội để mở khóa album /s1" + @override + String get consumption_once => "Bạn muốn sử dụng 01 cơ hội để mở khóa album /s1"; + /// "(Hôm nay bạn vẫn còn /s1 cơ hội)" + @override + String get remaining_once => "(Hôm nay bạn vẫn còn /s1 cơ hội)"; + /// "Cơ hội miễn phí hôm nay của bạn đã hết, có muốn tặng tất cả thông tin mở khóa của /s2 cho /s1 không?" + @override + String get no_times => "Cơ hội miễn phí hôm nay của bạn đã hết, có muốn tặng tất cả thông tin mở khóa của /s2 cho /s1 không?"; + /// "Thanh toán" + @override + String get pay => "Thanh toán"; + /// "Anh ta đã thiết lập chế độ xem hạn chế, cần có sự đồng ý của anh ta để xem tiếp" + @override + String get view_user => "Anh ta đã thiết lập chế độ xem hạn chế, cần có sự đồng ý của anh ta để xem tiếp"; + /// "Cô ta đã thiết lập chế độ xem hạn chế, cần có sự đồng ý của anh ta để xem tiếp" + @override + String get view_user2 => "Cô ta đã thiết lập chế độ xem hạn chế, cần có sự đồng ý của anh ta để xem tiếp"; + /// "Muốn xem tiếp, bạn phải gửi một tấm ảnh của bạn cho đối phương. Hãy yên tâm, ảnh của bạn sẽ tự hủy sau 2 giây- tính từ lúc đối phương bấm nút xem." + @override + String get need_photo => "Muốn xem tiếp, bạn phải gửi một tấm ảnh của bạn cho đối phương. Hãy yên tâm, ảnh của bạn sẽ tự hủy sau 2 giây- tính từ lúc đối phương bấm nút xem."; + /// "Chọn ảnh" + @override + String get choose_photo => "Chọn ảnh"; + /// "Yêu cầu đã được gửi đi, sau khi đối phương xác nhận bạn sẽ nhận được tin nhắn nhắc nhở" + @override + String get send_application => "Yêu cầu đã được gửi đi, sau khi đối phương xác nhận bạn sẽ nhận được tin nhắn nhắc nhở"; + /// "Bạn vẫn chưa tiến hành xác thực" + @override + String get not_authenticate => "Bạn vẫn chưa tiến hành xác thực"; + /// "Chỉ sau khi tính xác thực của bạn được chứng nhận, bạn mới có thể tương tác với người khác" + @override + String get after_authenticate => "Chỉ sau khi tính xác thực của bạn được chứng nhận, bạn mới có thể tương tác với người khác"; + /// "Xác thực ngay" + @override + String get authenticate_now => "Xác thực ngay"; + /// "Hủy sau khi xem" + @override + String get destroy_after => "Hủy sau khi xem"; + /// "Đã hủy" + @override + String get destroyed => "Đã hủy"; + /// "Ảnh lì xì sẽ được tiêu hủy sau khi xem" + @override + String get red_photo1 => "Ảnh lì xì sẽ được tiêu hủy sau khi xem"; + /// "Hãy chat riêng để hỏi tôi" + @override + String get ask_me => "Hãy chat riêng để hỏi tôi"; + /// "Đã nhập, bấm vào để xem" + @override + String get filled_in => "Đã nhập, bấm vào để xem"; + /// "Mở khóa tất cả dữ liệu" + @override + String get unlock_information => "Mở khóa tất cả dữ liệu"; + /// "Sử dụng 1 mở khóa miễn phí" + @override + String get unlock_choose => "Sử dụng 1 mở khóa miễn phí"; + /// "Nhận xét thực tế của bạn" + @override + String get your_evaluation => "Nhận xét thực tế của bạn"; + /// "Nhận xét thực tế của em ấy" + @override + String get her_evaluation => "Nhận xét thực tế của em ấy"; + /// "Nhận xét thực tế của anh ấy" + @override + String get his_evaluation => "Nhận xét thực tế của anh ấy"; + /// "Nhận xét" + @override + String get evaluate => "Nhận xét"; + /// "Thân thiện" + @override + String get friendly => "Thân thiện"; + /// "Thú vị" + @override + String get interesting => "Thú vị"; + /// "Thẳng thắn " + @override + String get readily => "Thẳng thắn "; + /// "Kiên nhẫn" + @override + String get patient => "Kiên nhẫn"; + /// "Thờ ơ" + @override + String get indifferent => "Thờ ơ"; + /// "Nóng nảy" + @override + String get bad_temper => "Nóng nảy"; + /// "Lịch sự" + @override + String get courtesy => "Lịch sự"; + /// "Hào phóng" + @override + String get generous => "Hào phóng"; + /// "Bốc đồng" + @override + String get lie => "Bốc đồng"; + /// "Unfriendly" + @override + String get unfriendly => "Unfriendly"; + /// "Đánh giá ẩn danh" + @override + String get anonymous_evaluation => "Đánh giá ẩn danh"; + /// "Bạn chưa hẹn hò với em ấy,không thể đánh giá" + @override + String get cant_evaluate => "Bạn chưa hẹn hò với em ấy,không thể đánh giá"; + /// "Anh ấy chưa hẹn hò với bạn không thể đánh giá" + @override + String get cant_evaluate2 => "Anh ấy chưa hẹn hò với bạn không thể đánh giá"; + /// "Vui lòng cung cấp ảnh chụp màn hình liên quan để chúng tôi theo dõi và xác thực" + @override + String get bad_evaluate => "Vui lòng cung cấp ảnh chụp màn hình liên quan để chúng tôi theo dõi và xác thực"; + /// "Gửi" + @override + String get submit => "Gửi"; + /// "Đánh giá thành công" + @override + String get evaluation_success => "Đánh giá thành công"; + /// "Trò chuyện" + @override + String get private_chat => "Trò chuyện"; + /// "Tắt chế độ tin nhắn nhắc nhở" + @override + String get close_reminder => "Tắt chế độ tin nhắn nhắc nhở"; + /// "Chế độ tin nhắn nhắc nhở đã tắt thành công" + @override + String get closed_reminder => "Chế độ tin nhắn nhắc nhở đã tắt thành công"; + /// "Bật tin nhắn nhắc nhở" + @override + String get open_reminder => "Bật tin nhắn nhắc nhở"; + /// "Chế độ tin nhắn nhắc nhở đã bật thành công" + @override + String get opened_reminder => "Chế độ tin nhắn nhắc nhở đã bật thành công"; + /// "Tài khoản mạng xà hội của em ấy" + @override + String get her_account => "Tài khoản mạng xà hội của em ấy"; + /// "Tài khoản mạng xà hội của anh ấy" + @override + String get his_account => "Tài khoản mạng xà hội của anh ấy"; + /// "Sao chép" + @override + String get copy => "Sao chép"; + /// "Gửi tài khoản mạng xã hội của tôi cho em ấy" + @override + String get send_account => "Gửi tài khoản mạng xã hội của tôi cho em ấy"; + /// "Nhập số tài khoản mạng xã hội của bạn" + @override + String get enter_account => "Nhập số tài khoản mạng xã hội của bạn"; + /// "Tài khoản Wechat abc" + @override + String get for_example => "Tài khoản Wechat abc"; + /// "Gửi cho em ấy" + @override + String get sent_she => "Gửi cho em ấy"; + /// "Nối mic" + @override + String get chat => "Nối mic"; + /// "Đối phương đã tắt chức năng trò chuyện trực tuyến" + @override + String get cantt_voice => "Đối phương đã tắt chức năng trò chuyện trực tuyến"; + /// "Sau khi tính xác thực của bạn được chứng nhận, bạn mới có thể trò chuyện trực tuyến" + @override + String get authentication_voice => "Sau khi tính xác thực của bạn được chứng nhận, bạn mới có thể trò chuyện trực tuyến"; + /// "Đang yêu cầu kết nối trò chuyện trực tuyến" + @override + String get requesting_voice => "Đang yêu cầu kết nối trò chuyện trực tuyến"; + /// "Đang đợi đối phương kết nối" + @override + String get waitting_answer => "Đang đợi đối phương kết nối"; + /// "Kết nối" + @override + String get answer => "Kết nối"; + /// "Ngắt kết nối" + @override + String get hang_up => "Ngắt kết nối"; + /// "Đang trò chuyện trực tuyên" + @override + String get chatting => "Đang trò chuyện trực tuyên"; + /// "Chế độ loa ngoài" + @override + String get handsfree => "Chế độ loa ngoài"; + /// "Thưởng" + @override + String get giving_gift => "Thưởng"; + /// "Thưởng thành công" + @override + String get give_success => "Thưởng thành công"; + /// "Đối phương đã tặng quà" + @override + String get others_gift => "Đối phương đã tặng quà"; + /// "Bạn đã thưởng cho đối phương một món quà trị giá /s1" + @override + String get given_gift => "Bạn đã thưởng cho đối phương một món quà trị giá /s1"; + /// "Bạn đã được tặng /s1H coin" + @override + String get earned_gift => "Bạn đã được tặng /s1H coin"; + /// "Số dư khả dụng /s1" + @override + String get available_balance => "Số dư khả dụng /s1"; + /// "Nạp tiền" + @override + String get recharge => "Nạp tiền"; + /// "Quà tặng" + @override + String get give => "Quà tặng"; + /// "Xin lỗi số dư của bạn không đủ" + @override + String get balance_insufficien => "Xin lỗi số dư của bạn không đủ"; + /// "Vui lòng nạp tiền trước khi tặng quà" + @override + String get first_recharge => "Vui lòng nạp tiền trước khi tặng quà"; + /// "Thưởng /s1H coin cho lần trò chuyện trực tuyến này" + @override + String get give_coin => "Thưởng /s1H coin cho lần trò chuyện trực tuyến này"; + /// "Lần trò chuyện trực tuyến này, bạn được thưởng /s1H coin" + @override + String get get_coin => "Lần trò chuyện trực tuyến này, bạn được thưởng /s1H coin"; + /// "Lần trò chuyện trực tuyến này bạn thưởng đối phương /s1H coin và được thưởng /s2H coin" + @override + String get give_get => "Lần trò chuyện trực tuyến này bạn thưởng đối phương /s1H coin và được thưởng /s2H coin"; + /// "Thời lượng cuộc trò chuyện trực tuyến này là /s1" + @override + String get chat_over => "Thời lượng cuộc trò chuyện trực tuyến này là /s1"; + /// "Trung tâm tin nhắn" + @override + String get message_center => "Trung tâm tin nhắn"; + /// "Bạn có thể mời đối phương trò chuyện riêng thông qua trang thông tin người dùng" + @override + String get can_chat => "Bạn có thể mời đối phương trò chuyện riêng thông qua trang thông tin người dùng"; + /// "Trò chuyện" + @override + String get text_chat => "Trò chuyện"; + /// "Tin nhắn hệ thông" + @override + String get system_information => "Tin nhắn hệ thông"; + /// "Thông báo hệ thống" + @override + String get system_notification => "Thông báo hệ thống"; + /// "Báo cáo người dùng /s1 của bạn không xác thực. Vui lòng cung cấp bằng chứng xác thực hơn mới tiếp tục báo cáo, xin cảm ơn!" + @override + String get report_failure => "Báo cáo người dùng /s1 của bạn không xác thực. Vui lòng cung cấp bằng chứng xác thực hơn mới tiếp tục báo cáo, xin cảm ơn!"; + /// "Báo cáo người dùng /s1 của bạn là chính xác. Hệ thống đang tiến hành xử lý người dùng này!" + @override + String get report_success => "Báo cáo người dùng /s1 của bạn là chính xác. Hệ thống đang tiến hành xử lý người dùng này!"; + /// "Yêu cầu cấp mã mời của bạn đã được duyệt! Mã mời 【/s1】(click vào để sao chép)" + @override + String get successful_application => "Yêu cầu cấp mã mời của bạn đã được duyệt! Mã mời 【/s1】(click vào để sao chép)"; + /// "Yêu cầu cấp mã mời của bạn đã được duyệt! Cám ơn bạn đã giới thiệu bạn bè cho chúng tôi! Mã mời 【/s1】(click vào để sao chép)" + @override + String get successful_application2 => "Yêu cầu cấp mã mời của bạn đã được duyệt! Cám ơn bạn đã giới thiệu bạn bè cho chúng tôi! Mã mời 【/s1】(click vào để sao chép)"; + /// "Yêu cầu cấp mã mời thất bại! Rất tiếc, yêu cầu của bạn không được thông qua, xin cung cấp thông tin chính xác để mã mời được xét duyệt." + @override + String get application_failed => "Yêu cầu cấp mã mời thất bại! Rất tiếc, yêu cầu của bạn không được thông qua, xin cung cấp thông tin chính xác để mã mời được xét duyệt."; + /// "[Thông báo quan trọng]" + @override + String get important_notice => "[Thông báo quan trọng]"; + /// "Thông tin xác thực của bạn không phù hợp, yêu cầu chỉnh sửa và gửi lại cho chúng tôi!" + @override + String get authentication_failed => "Thông tin xác thực của bạn không phù hợp, yêu cầu chỉnh sửa và gửi lại cho chúng tôi!"; + /// "1. Hãy quay video xác thực theo yêu cầu" + @override + String get request1 => "1. Hãy quay video xác thực theo yêu cầu"; + /// "2. Vui lòng tải ảnh có thể thấy rõ đặc điểm nhận dạng của bạn lên album" + @override + String get request2 => "2. Vui lòng tải ảnh có thể thấy rõ đặc điểm nhận dạng của bạn lên album"; + /// "Xin chúc mừng! Yêu cầu xác thực của bạn đã được duyệt" + @override + String get successful_authentication => "Xin chúc mừng! Yêu cầu xác thực của bạn đã được duyệt"; + /// "Ảnh mới tải lên của bạn chưa được duyệt. Vui lòng tải lại theo yêu cầu" + @override + String get re_upload => "Ảnh mới tải lên của bạn chưa được duyệt. Vui lòng tải lại theo yêu cầu"; + /// "Xin chúc mừng, ảnh mới tải lên của bạn đã được duyệt" + @override + String get upload_success => "Xin chúc mừng, ảnh mới tải lên của bạn đã được duyệt"; + /// "Đăng ký hẹn hò của bạn đã bị xóa vì vi phạm. Nếu vi phạm nhiều lần hoặc trường hợp nghiêm trọng hệ thống sẽ tiến hành hạn chế thậm chí đóng tài khoản của bạn. Xin nhớ và tuân thủ! Cảm ơn bạn đã phối hợp!" + @override + String get caveat => "Đăng ký hẹn hò của bạn đã bị xóa vì vi phạm. Nếu vi phạm nhiều lần hoặc trường hợp nghiêm trọng hệ thống sẽ tiến hành hạn chế thậm chí đóng tài khoản của bạn. Xin nhớ và tuân thủ! Cảm ơn bạn đã phối hợp!"; + /// "Nhận xét của bạn đã bị xóa do vi phạm, Nếu vi phạm nhiều lần hoặc trường hợp nghiêm trọng hệ thống sẽ tiến hành hạn chế thậm chí đóng tài khoản của bạn. Xin nhớ và tuân thủ! Cảm ơn bạn đã phối hợp!" + @override + String get caveat2 => "Nhận xét của bạn đã bị xóa do vi phạm, Nếu vi phạm nhiều lần hoặc trường hợp nghiêm trọng hệ thống sẽ tiến hành hạn chế thậm chí đóng tài khoản của bạn. Xin nhớ và tuân thủ! Cảm ơn bạn đã phối hợp!"; + /// "Tin nhắn radio" + @override + String get radio_message => "Tin nhắn radio"; + /// "Tạm thời không có tin nhắn như thế" + @override + String get no_message => "Tạm thời không có tin nhắn như thế"; + /// "/s1 đã gửi một tin nhắn hẹn hò trên /s2, nhấp vào đây để xem" + @override + String get dating_news => "/s1 đã gửi một tin nhắn hẹn hò trên /s2, nhấp vào đây để xem"; + /// "Vào xem" + @override + String get go_see => "Vào xem"; + /// "/s1 thích hoạt động của bạn" + @override + String get thumbs_up => "/s1 thích hoạt động của bạn"; + /// "/s1 thích chương trình hẹn hò của bạn" + @override + String get thumbs_up2 => "/s1 thích chương trình hẹn hò của bạn"; + /// "/s1 đã nhận xét về hoạt động của bạn" + @override + String get comment1 => "/s1 đã nhận xét về hoạt động của bạn"; + /// "/s1 nhận xét về chương trình hẹn hò của bạn" + @override + String get comment2 => "/s1 nhận xét về chương trình hẹn hò của bạn"; + /// "/s1 đã trả lời nhận xét của bạn" + @override + String get replied_comment => "/s1 đã trả lời nhận xét của bạn"; + /// "/s1 đã đăng ký tham gia chương trình của bạn" + @override + String get signed_up => "/s1 đã đăng ký tham gia chương trình của bạn"; + /// "Người dùng bạn yêu thích /s1 đã đăng một tin hẹn hò, nhấp vào đây để xem" + @override + String get favorite_user => "Người dùng bạn yêu thích /s1 đã đăng một tin hẹn hò, nhấp vào đây để xem"; + /// "Người dùng bạn yêu thích /s1 đã cập nhật hoạt động mới nhất, nhấp vào đây để xem" + @override + String get favorite_user2 => "Người dùng bạn yêu thích /s1 đã cập nhật hoạt động mới nhất, nhấp vào đây để xem"; + /// "Hãy chú ý ví của bạn" + @override + String get wallet_reminder => "Hãy chú ý ví của bạn"; + /// "/s1 đã thanh toán (/s2H coin) để xem ảnh phong bì của bạn" + @override + String get paid_you => "/s1 đã thanh toán (/s2H coin) để xem ảnh phong bì của bạn"; + /// "/s1 đã thanh toăn (/s2H coin) để xem album của bạn" + @override + String get paid_you2 => "/s1 đã thanh toăn (/s2H coin) để xem album của bạn"; + /// "/s1 đã trả tiền để mở khóa tất cả thông tin của bạn" + @override + String get paid_you3 => "/s1 đã trả tiền để mở khóa tất cả thông tin của bạn"; + /// "Kiểm tra yêu cầu của bạn" + @override + String get view_application => "Kiểm tra yêu cầu của bạn"; + /// "/s1 muốn xem trang chủ của bạn" + @override + String get view_application2 => "/s1 muốn xem trang chủ của bạn"; + /// "Cho phép (thời hạn 15 ngày)" + @override + String get aging => "Cho phép (thời hạn 15 ngày)"; + /// "Từ chối" + @override + String get refuse => "Từ chối"; + /// "Yêu cầu đã được thông qua" + @override + String get passed_request => "Yêu cầu đã được thông qua"; + /// "Yêu cầu của /s1 đã được bạn cho phép, thời gian xem là 15 ngày" + @override + String get l15_days => "Yêu cầu của /s1 đã được bạn cho phép, thời gian xem là 15 ngày"; + /// "Thông báo nhận xét" + @override + String get evaluation_notice => "Thông báo nhận xét"; + /// "Bạn đã hẹn ò cùng /s1? Hãy nhanh chóng nhận xét em ấy nào!" + @override + String get rate_her => "Bạn đã hẹn ò cùng /s1? Hãy nhanh chóng nhận xét em ấy nào!"; + /// "Người đánh giá (ẩn danh) bạn là một phái nữ đã liên lạc với bạn: /s1" + @override + String get received_evaluation => "Người đánh giá (ẩn danh) bạn là một phái nữ đã liên lạc với bạn: /s1"; + /// "Người đánh giá (ẩn danh) bạn là một đàn ông đã liên lạc với bạn: /s1" + @override + String get received_evaluation2 => "Người đánh giá (ẩn danh) bạn là một đàn ông đã liên lạc với bạn: /s1"; + /// "Nếu đánh giá không đúng sự thật, bạn có thể báo cáo, chúng tôi sẽ tiến hành xác thực!" + @override + String get application_appeal => "Nếu đánh giá không đúng sự thật, bạn có thể báo cáo, chúng tôi sẽ tiến hành xác thực!"; + /// "Tôi muốn báo cáo" + @override + String get appeal => "Tôi muốn báo cáo"; + /// "Đã báo cáo" + @override + String get appealed => "Đã báo cáo"; + /// "Chúng tôi sẽ nhanh chóng xác tìm hiểu, kết quả sẽ được gửi đến hệ thông tin nhắn của bạn." + @override + String get waiting_results => "Chúng tôi sẽ nhanh chóng xác tìm hiểu, kết quả sẽ được gửi đến hệ thông tin nhắn của bạn."; + /// "/s1 báo cáo thành công, đánh giá sẽ bị xóa đi" + @override + String get successful_appeal => "/s1 báo cáo thành công, đánh giá sẽ bị xóa đi"; + /// "Tài khoản mạng xà hội" + @override + String get social_account => "Tài khoản mạng xà hội"; + /// "/s1 đã gửi cho bạn tài khoản mạng xã hội của anh ấy" + @override + String get get_account => "/s1 đã gửi cho bạn tài khoản mạng xã hội của anh ấy"; + /// "Chỉnh sử thông tin" + @override + String get edit_information => "Chỉnh sử thông tin"; + /// "Lưu lại" + @override + String get save => "Lưu lại"; + /// "Bạn đã thông qua xác minh bảo mật danh tính" + @override + String get passed_verification1 => "Bạn đã thông qua xác minh bảo mật danh tính"; + /// "Bạn tham gia thông qua mã mời của người dùng VIP /s1" + @override + String get by_code => "Bạn tham gia thông qua mã mời của người dùng VIP /s1"; + /// "Bạn đã thông qua bằng cách đóng phí gia nhập" + @override + String get by_paying => "Bạn đã thông qua bằng cách đóng phí gia nhập"; + /// "Tính xác thực của bạn đã được chứng nhận thông qua video" + @override + String get passed_verification => "Tính xác thực của bạn đã được chứng nhận thông qua video"; + /// "Danh tính của bạn vẫn chưa được xác thực" + @override + String get not_certified => "Danh tính của bạn vẫn chưa được xác thực"; + /// "Chúng tôi đang xác nhận tính xác thực của bạn" + @override + String get verificating => "Chúng tôi đang xác nhận tính xác thực của bạn"; + /// "Phái nữ đã được xác thực sẽ được chào đón hơn" + @override + String get real_girl => "Phái nữ đã được xác thực sẽ được chào đón hơn"; + /// "Đang xác thực" + @override + String get certificating => "Đang xác thực"; + /// "Vui lòng tải lại video" + @override + String get re_upload2 => "Vui lòng tải lại video"; + /// "Cập nhật xác thực" + @override + String get update_certification => "Cập nhật xác thực"; + /// "Nâng cấp hội viên để có thêm đặc quyền" + @override + String get enjoy_privileges => "Nâng cấp hội viên để có thêm đặc quyền"; + /// "/s1 hết hạn" + @override + String get expires => "/s1 hết hạn"; + /// "Ví" + @override + String get wallet => "Ví"; + /// "Quyền riêng tư" + @override + String get setting => "Quyền riêng tư"; + /// "Hoạt động của tôi" + @override + String get my_dynamic => "Hoạt động của tôi"; + /// "Album của tôi" + @override + String get my_album => "Album của tôi"; + /// "Tải hình ảnh đầu tiên của tôi" + @override + String get first_photo => "Tải hình ảnh đầu tiên của tôi"; + /// "Có hình ảnh bạn có thể thu hút hơn đối với phái nam" + @override + String get no_photo => "Có hình ảnh bạn có thể thu hút hơn đối với phái nam"; + /// "Tải ảnh" + @override + String get upload_photos => "Tải ảnh"; + /// "Tải video" + @override + String get upload_video => "Tải video"; + /// "Tải ảnh" + @override + String get upload => "Tải ảnh"; + /// "Cài đặt ảnh phong bì" + @override + String get set_photo => "Cài đặt ảnh phong bì"; + /// "Nhấn giữ và kéo ảnh để thay đổi vị trí của chúng" + @override + String get photo_order => "Nhấn giữ và kéo ảnh để thay đổi vị trí của chúng"; + /// "Nhận xét của tôi" + @override + String get my_evaluation => "Nhận xét của tôi"; + /// "Chương trình của tôi" + @override + String get my_show => "Chương trình của tôi"; + /// "Sở thích của tôi" + @override + String get i_like => "Sở thích của tôi"; + /// "Cô gái bạn yêu thích sẽ hiển thị ở đây" + @override + String get your_favorite => "Cô gái bạn yêu thích sẽ hiển thị ở đây"; + /// "Chàng trai bạn yêu thích sẽ hiển thị ở đây" + @override + String get your_favorite2 => "Chàng trai bạn yêu thích sẽ hiển thị ở đây"; + /// "Không có dữ liệu" + @override + String get no_data => "Không có dữ liệu"; + /// "Danh sách đã ghé thăm bạn" + @override + String get historical_visitor => "Danh sách đã ghé thăm bạn"; + /// "Có /s1 người đã ghé thăm bạn" + @override + String get visit_you => "Có /s1 người đã ghé thăm bạn"; + /// "Có /s1 người đã hủy ảnh của bạn" + @override + String get visit_photo => "Có /s1 người đã hủy ảnh của bạn"; + /// "Nhấp để phục hồi" + @override + String get recovery_photo => "Nhấp để phục hồi"; + /// "Cài đặt" + @override + String get setting2 => "Cài đặt"; + /// "Đăng ký mã mời cho bạn bè" + @override + String get apply_code => "Đăng ký mã mời cho bạn bè"; + /// "Mã mời sẽ được cấp miễn phí, chúng tôi sẽ cấp mã mời thông qua đánh giá lịch sử chi tiêu của bạn. Để duy trì bầu không khí trong công viên, vui lòng chỉ gửi mã mời cho người mà bạn tin cậy." + @override + String get issue_choose => "Mã mời sẽ được cấp miễn phí, chúng tôi sẽ cấp mã mời thông qua đánh giá lịch sử chi tiêu của bạn. Để duy trì bầu không khí trong công viên, vui lòng chỉ gửi mã mời cho người mà bạn tin cậy."; + /// "Yêu cầu của bạn đang được xử lý" + @override + String get successfully_submit => "Yêu cầu của bạn đang được xử lý"; + /// "Chia sẻ ứng dụng với bạn bè" + @override + String get share_app => "Chia sẻ ứng dụng với bạn bè"; + /// "Có vấn đề và cần giúp đỡ" + @override + String get need_help => "Có vấn đề và cần giúp đỡ"; + /// "Liên hệ nhân viên CSKH" + @override + String get need_help2 => "Liên hệ nhân viên CSKH"; + /// "Xin chào bạn, để nâng cao chất lượng phục vụ, nếu dưới đây có thắc mắc của bạn, vui lòng trả lời bằng cách nhập số thứ tự." + @override + String get need_help3 => "Xin chào bạn, để nâng cao chất lượng phục vụ, nếu dưới đây có thắc mắc của bạn, vui lòng trả lời bằng cách nhập số thứ tự."; + /// "[1]Tại sao tài khoản bị đóng băng?" + @override + String get question1 => "[1]Tại sao tài khoản bị đóng băng?"; + /// "\"xuất hiện một trong những tình trạng sau, tài khoản sẽ bị khóa: ① Lừa đảo② Môi giới③Quảng cáo quấy nhiễu④Bị nhiều người dùng báo cáo⑤Đã có tài khoản khác⑥Nhiều lần đăng tin radio sai phạm, xem thường cảnh cáo.⑦Người dùng tự yêu cầu xóa tài khoản.\"" + @override + String get answer1 => "\"xuất hiện một trong những tình trạng sau, tài khoản sẽ bị khóa: ① Lừa đảo② Môi giới③Quảng cáo quấy nhiễu④Bị nhiều người dùng báo cáo⑤Đã có tài khoản khác⑥Nhiều lần đăng tin radio sai phạm, xem thường cảnh cáo.⑦Người dùng tự yêu cầu xóa tài khoản.\""; + /// "[2]Khi nào mới có thể rút số dư trong ví?" + @override + String get question2 => "[2]Khi nào mới có thể rút số dư trong ví?"; + /// "Tất cả số tiền nhận được sẽ được chuyển trực tiếp vào ví, rút tiền phải mất ba ngày (bắt đầu từ thời điểm nhận tiền). Số tiền nhận được sau ba ngày sẽ chuyển vào ví. Bạn được phép rút khi số dư > = 10 nhân dân tệ " + @override + String get answer2 => "Tất cả số tiền nhận được sẽ được chuyển trực tiếp vào ví, rút tiền phải mất ba ngày (bắt đầu từ thời điểm nhận tiền). Số tiền nhận được sau ba ngày sẽ chuyển vào ví. Bạn được phép rút khi số dư > = 10 nhân dân tệ "; + /// "[3]Sao không hiển thị lì xì tôi đã gửi." + @override + String get question3 => "[3]Sao không hiển thị lì xì tôi đã gửi."; + /// "Có thể do lỗi mạng. Hãy yên tâm, trường hợp này đối phương không thể nhận được phong bì của bạn. Phong bì sẽ tự động trả về trong vòng 24 giờ." + @override + String get answer3 => "Có thể do lỗi mạng. Hãy yên tâm, trường hợp này đối phương không thể nhận được phong bì của bạn. Phong bì sẽ tự động trả về trong vòng 24 giờ."; + /// "[4]Rút tiền về tài khoản ngân hàng/ ví tiền mặt phải mất mấy ngày?" + @override + String get question4 => "[4]Rút tiền về tài khoản ngân hàng/ ví tiền mặt phải mất mấy ngày?"; + /// "Trong vòng 2 ngày tiền sẽ vào tài khoản sau khi bạn yêu cầu rút tiền mặt. Vui lòng nhập đúng số tài khoản ngân hàng/ ví tiền mặt khi rút tiền mặt." + @override + String get answer4 => "Trong vòng 2 ngày tiền sẽ vào tài khoản sau khi bạn yêu cầu rút tiền mặt. Vui lòng nhập đúng số tài khoản ngân hàng/ ví tiền mặt khi rút tiền mặt."; + /// "[5]Làm thế nào để báo cáo tài khoản khác / nội dung phát tán trên radio?" + @override + String get question5 => "[5]Làm thế nào để báo cáo tài khoản khác / nội dung phát tán trên radio?"; + /// "Vào trang chi tiết cùa đối phương hoặc chọn nội dung tin tức mà bạn muốn báo cáo, nhấp vào góc phải phía trên, chọn \"báo cáo ẩn danh\", sau đó điền đầy đủ các thông tin liên quan." + @override + String get answer5 => "Vào trang chi tiết cùa đối phương hoặc chọn nội dung tin tức mà bạn muốn báo cáo, nhấp vào góc phải phía trên, chọn \"báo cáo ẩn danh\", sau đó điền đầy đủ các thông tin liên quan."; + /// "[6]Làm sao để trở thành tài khoản được xác thực?" + @override + String get question6 => "[6]Làm sao để trở thành tài khoản được xác thực?"; + /// "\"Xác nhận tài khoản cần thỏa mãn các yêu cầu sau: ①Thông tin cá nhân có tài khoản mạng xã hội hợp lệ.②Có ít nhất một tấm ảnh rõ ràng trong album.③Kiểm tra mã xác thực trong trang xác thực, ghi mã xác thực + biệt danh của bạn lên một mảnh giấy.④Cầm mảnh giấy này trên tay, quay một đoạn video có thể nhìn thấy khuôn mặt chính diện của bạn và nội dung trên giấy. Tải video lên để xác thực.\"" + @override + String get answer6 => "\"Xác nhận tài khoản cần thỏa mãn các yêu cầu sau: ①Thông tin cá nhân có tài khoản mạng xã hội hợp lệ.②Có ít nhất một tấm ảnh rõ ràng trong album.③Kiểm tra mã xác thực trong trang xác thực, ghi mã xác thực + biệt danh của bạn lên một mảnh giấy.④Cầm mảnh giấy này trên tay, quay một đoạn video có thể nhìn thấy khuôn mặt chính diện của bạn và nội dung trên giấy. Tải video lên để xác thực.\""; + /// "[7]Video xác thực có thể không công khai không ?" + @override + String get question7 => "[7]Video xác thực có thể không công khai không ?"; + /// "Bạn có thể cài đặt công khai hoặc không công khai:Trung tâm người dùng- Nhấp vào góc dưới bên trái video xác thực, chọn \"Video xác thực hiển thị trong trang chi tiết của tôi\"" + @override + String get answer7 => "Bạn có thể cài đặt công khai hoặc không công khai:Trung tâm người dùng- Nhấp vào góc dưới bên trái video xác thực, chọn \"Video xác thực hiển thị trong trang chi tiết của tôi\""; + /// "[8]Làm thế nào để tránh bị hủy xác thực?" + @override + String get question8 => "[8]Làm thế nào để tránh bị hủy xác thực?"; + /// "Album ít nhất có một tấm ảnh của bản thân được gắn thẻ tag." + @override + String get answer8 => "Album ít nhất có một tấm ảnh của bản thân được gắn thẻ tag."; + /// "[9]Tại sao tin radio của bạn bị xóa?" + @override + String get question9 => "[9]Tại sao tin radio của bạn bị xóa?"; + /// "Radio không được phát tán tin tức, hình ảnh và các từ ngữ nhạy cảm, bao gồm cả nghĩa bóng lẫn nghĩa đen. Không được đăng thông tin cá nhân (bao gồm ảnh đại diện, biệt danh và phuơng pháp liên hệ). Vi phạm các quy định này kênh radio của bạn sẽ bị xóa." + @override + String get answer9 => "Radio không được phát tán tin tức, hình ảnh và các từ ngữ nhạy cảm, bao gồm cả nghĩa bóng lẫn nghĩa đen. Không được đăng thông tin cá nhân (bao gồm ảnh đại diện, biệt danh và phuơng pháp liên hệ). Vi phạm các quy định này kênh radio của bạn sẽ bị xóa."; + /// "[10] Làm thế nào để hủy tài khoản?" + @override + String get question10 => "[10] Làm thế nào để hủy tài khoản?"; + /// "Nếu hủy tài khoản bạn sẽ không thể đăng nhập vào ứng dụng. Sau này muốn tiếp tục sử dụng bạn phải đăng ký lại. Vui lòng xem xét cẩn thận, nếu bạn vẫn quyết định hủy tài khoản của mình vui lòng trả lời theo số thứ tự【12】 liên hệ hotline hỗ trợ người dùng." + @override + String get answer10 => "Nếu hủy tài khoản bạn sẽ không thể đăng nhập vào ứng dụng. Sau này muốn tiếp tục sử dụng bạn phải đăng ký lại. Vui lòng xem xét cẩn thận, nếu bạn vẫn quyết định hủy tài khoản của mình vui lòng trả lời theo số thứ tự【12】 liên hệ hotline hỗ trợ người dùng."; + /// "[11]Quên mật khẩu, làm thế nào?" + @override + String get question11 => "[11]Quên mật khẩu, làm thế nào?"; + /// "Đối với người dùng đăng ký tài khoản bằng số điện thoại di động hoặc đã liên kết số điện thoại di động, có thể vào trang đăng nhập, chọn \"quên mật khẩu\" để cài đặt lại mật khẩu.,Đối với người dùng chưa liên kết số điện thoại di động, xin vui lòng liên kêt số điện thoại di động, sau đó cài đặt lại mật khẩu mới." + @override + String get answer11 => "Đối với người dùng đăng ký tài khoản bằng số điện thoại di động hoặc đã liên kết số điện thoại di động, có thể vào trang đăng nhập, chọn \"quên mật khẩu\" để cài đặt lại mật khẩu.,Đối với người dùng chưa liên kết số điện thoại di động, xin vui lòng liên kêt số điện thoại di động, sau đó cài đặt lại mật khẩu mới."; + /// "[12]Các vấn đề khác/ chuyển đến hotline nhân viên hỗ trợ khách hàng." + @override + String get question12 => "[12]Các vấn đề khác/ chuyển đến hotline nhân viên hỗ trợ khách hàng."; + /// "Chào bạn, chúng tôi có thể giúp gì cho bạn? Xin nêu vấn đề của bạn (thời gian làm việc của bộ phận chăm sóc khách hàng 08:00 hôm nay- 02:00AM hôm sau, do số người cần tư vấn khá đông, bạn vui lòng đợi trong giây lát.)" + @override + String get answer12 => "Chào bạn, chúng tôi có thể giúp gì cho bạn? Xin nêu vấn đề của bạn (thời gian làm việc của bộ phận chăm sóc khách hàng 08:00 hôm nay- 02:00AM hôm sau, do số người cần tư vấn khá đông, bạn vui lòng đợi trong giây lát.)"; + /// "Trung tâm xác thực" + @override + String get certification_center => "Trung tâm xác thực"; + /// "Mẫu video xác thực" + @override + String get for_example2 => "Mẫu video xác thực"; + /// "Điều kiện xác thực" + @override + String get certification_conditions => "Điều kiện xác thực"; + /// "1. Hình tượng cá nhân tốt." + @override + String get conditions1 => "1. Hình tượng cá nhân tốt."; + /// "2. Có ít nhất một tấm ảnh cá nhân trong album." + @override + String get conditions2 => "2. Có ít nhất một tấm ảnh cá nhân trong album."; + /// "Phương thức xác thực" + @override + String get verification_method => "Phương thức xác thực"; + /// "1. Lấy một tờ giấy để viết tên hiệu của bạn và mã xác minh sau:" + @override + String get method3 => "1. Lấy một tờ giấy để viết tên hiệu của bạn và mã xác minh sau:"; + /// "2. Giữ mảnh giấy này trong tay và quay một đoạn video thấy rõ chính diện khuôn mặt bạn (3 - 15 giây)" + @override + String get method4 => "2. Giữ mảnh giấy này trong tay và quay một đoạn video thấy rõ chính diện khuôn mặt bạn (3 - 15 giây)"; + /// "Tải video xác thực" + @override + String get upload_video2 => "Tải video xác thực"; + /// "Sau khi xác thực thành công ảnh đại diện của bạn sẽ hiển thị logo Real." + @override + String get after_authentication => "Sau khi xác thực thành công ảnh đại diện của bạn sẽ hiển thị logo Real."; + /// "Video xác thực hiển thị trong trang chi tiết của tôi." + @override + String get show_video => "Video xác thực hiển thị trong trang chi tiết của tôi."; + /// "Video xác thực đã được tải lên." + @override + String get uploaded_video => "Video xác thực đã được tải lên."; + /// "Đang xét duyệt (trong vòng 24 giờ)" + @override + String get under_review => "Đang xét duyệt (trong vòng 24 giờ)"; + /// "Trạng thái xác thực" + @override + String get certification_status => "Trạng thái xác thực"; + /// "Bạn đã thông qua xác thực" + @override + String get certified => "Bạn đã thông qua xác thực"; + /// "Đang chờ để xác thực lại" + @override + String get wait_resubmitted => "Đang chờ để xác thực lại"; + /// "Video chứng nhận của bạn không đáp ứng các yêu cầu do:" + @override + String get reason_failure => "Video chứng nhận của bạn không đáp ứng các yêu cầu do:"; + /// "Vui lòng quay video xác thực theo yêu cầu." + @override + String get claim => "Vui lòng quay video xác thực theo yêu cầu."; + /// "Vui lòng tải một tấm ảnh có thể nhìn thấy rõ khuôn mặt của bạn lên album." + @override + String get claim2 => "Vui lòng tải một tấm ảnh có thể nhìn thấy rõ khuôn mặt của bạn lên album."; + /// "Tải lại video xác thực." + @override + String get re_upload_video => "Tải lại video xác thực."; + /// "Cập nhật video xác thực." + @override + String get update_video => "Cập nhật video xác thực."; + /// "H coin" + @override + String get mask_coin => "H coin"; + /// "Bạn có thể nạp h-coin trực tuyển hoặc chat online." + @override + String get get_way => "Bạn có thể nạp h-coin trực tuyển hoặc chat online."; + /// "H-coin dùng trong chat online hoặc tặng cho người khác." + @override + String get coin_use => "H-coin dùng trong chat online hoặc tặng cho người khác."; + /// "Tổng số H-coin" + @override + String get coin_total => "Tổng số H-coin"; + /// "Số coin có thể rút " + @override + String get can_redeemed => "Số coin có thể rút "; + /// "Tài khoản /s1" + @override + String get who_account => "Tài khoản /s1"; + /// "Liên kết tài khoản /s1" + @override + String get bind_account => "Liên kết tài khoản /s1"; + /// "Tài khoản /s1 của bạn" + @override + String get your_account => "Tài khoản /s1 của bạn"; + /// "Bạn đã nhận được /s1H coin bằn cách nạp tiền vào tài khoản." + @override + String get get_coin2 => "Bạn đã nhận được /s1H coin bằn cách nạp tiền vào tài khoản."; + /// "/s1 đã xem tài khoản mạng xã hội của bạn" + @override + String get viewed_your => "/s1 đã xem tài khoản mạng xã hội của bạn"; + /// "1 coin/s2" + @override + String get give_gift => "1 coin/s2"; + /// "+/s1H coin" + @override + String get add_coin => "+/s1H coin"; + /// "Bạn đã tặng 1 cái /s1 cho /s2" + @override + String get give_one => "Bạn đã tặng 1 cái /s1 cho /s2"; + /// "-/s1H coin " + @override + String get less_coin => "-/s1H coin "; + /// "Rút tiền mặt" + @override + String get exchange_cash => "Rút tiền mặt"; + /// "Yêu cầu rút tiền mặt" + @override + String get withdrawal_application => "Yêu cầu rút tiền mặt"; + /// "Bạn có /s1H coin có thể đổi thành /s2, sau khi đổi bạn còn /s3H coin, bạn có muốn đổi không?" + @override + String get redeem_choose => "Bạn có /s1H coin có thể đổi thành /s2, sau khi đổi bạn còn /s3H coin, bạn có muốn đổi không?"; + /// "Yêu cầu rút tiền của bạn đã được gửi đi." + @override + String get application_submitted => "Yêu cầu rút tiền của bạn đã được gửi đi."; + /// "Chúng tôi sẽ xử lý trong vòn 02 ngày làm việc, có bất kỳ thắc mắc gì bạn có thể liên hệ hotline hỗ trợ người dùng." + @override + String get working_days => "Chúng tôi sẽ xử lý trong vòn 02 ngày làm việc, có bất kỳ thắc mắc gì bạn có thể liên hệ hotline hỗ trợ người dùng."; + /// "Tiền mặt" + @override + String get cash => "Tiền mặt"; + /// "Khi bạn nhận được phong bi trong trang trò chuyện, số dư sẽ được chuyển vào đây. Trong vòng 3 ngày không ai báo cáo về số dư này, bạn có thể quy đổi thành tiền mặt, phí thủ tục là 5%." + @override + String get handling_fee => "Khi bạn nhận được phong bi trong trang trò chuyện, số dư sẽ được chuyển vào đây. Trong vòng 3 ngày không ai báo cáo về số dư này, bạn có thể quy đổi thành tiền mặt, phí thủ tục là 5%."; + /// "Tổng số dư" + @override + String get total_account => "Tổng số dư"; + /// "Số dư không đủ không thể quy đổi" + @override + String get cannot_redeemed => "Số dư không đủ không thể quy đổi"; + /// "Quy đổi thành công" + @override + String get successful_redemption => "Quy đổi thành công"; + /// "Tổng số dư của bạn là /s1, lần này bạn có thể đổi /s2, bạn muốn đổi chứ?" + @override + String get redeem_choose2 => "Tổng số dư của bạn là /s1, lần này bạn có thể đổi /s2, bạn muốn đổi chứ?"; + /// "Thông tin cá nhân" + @override + String get personal_details => "Thông tin cá nhân"; + /// "Công khai (được khuyến nghị)" + @override + String get public => "Công khai (được khuyến nghị)"; + /// "Trả phí để xem album" + @override + String get paid_album => "Trả phí để xem album"; + /// "Người dùng khác phải trả phí để xem album của bạn. Chi phí xem album do bạn đặt ra, tuy nhiên có thể làm thế có thể khiến cho số lượng người xem của bạn bị giảm đi." + @override + String get must_pay => "Người dùng khác phải trả phí để xem album của bạn. Chi phí xem album do bạn đặt ra, tuy nhiên có thể làm thế có thể khiến cho số lượng người xem của bạn bị giảm đi."; + /// "Cài đặt kiểm tra số dư" + @override + String get set_amount1 => "Cài đặt kiểm tra số dư"; + /// "Vui lòng tải ảnh lên trước khi thiết lập album trả phí" + @override + String get first_upload => "Vui lòng tải ảnh lên trước khi thiết lập album trả phí"; + /// "Phải được tôi cho phép mới được xem" + @override + String get need_permission => "Phải được tôi cho phép mới được xem"; + /// "Người khác phải gửi ảnh cho tôi xác nhận danh tính mới được phép xem trang chủ của bạn, bạn muốn như thế?" + @override + String get permission_choose => "Người khác phải gửi ảnh cho tôi xác nhận danh tính mới được phép xem trang chủ của bạn, bạn muốn như thế?"; + /// "Giấu tôi khỏi danh sách những người gần đó" + @override + String get hide_me => "Giấu tôi khỏi danh sách những người gần đó"; + /// "Ẩn khoảng cách giữa tôi với người khác" + @override + String get hide_distance => "Ẩn khoảng cách giữa tôi với người khác"; + /// "Ẩn tài khoản của tôi với người khác" + @override + String get hide_account => "Ẩn tài khoản của tôi với người khác"; + /// "Hạn chế trò chuyện trực tuyến" + @override + String get chat_setting => "Hạn chế trò chuyện trực tuyến"; + /// "Cho phép người dùng \"được phép trò chuyện\" trò chuyện trực tuyến với tôi" + @override + String get chat_me => "Cho phép người dùng \"được phép trò chuyện\" trò chuyện trực tuyến với tôi"; + /// "Đã lưu thành công" + @override + String get successfully_saved => "Đã lưu thành công"; + /// "Bạn chưa đăng bất kỳ cập nhật nào" + @override + String get on_dynamic => "Bạn chưa đăng bất kỳ cập nhật nào"; + /// "Đăng hoạt động gần đây" + @override + String get release_dynamics => "Đăng hoạt động gần đây"; + /// "Chi tiết hoạt động" + @override + String get dynamic_details => "Chi tiết hoạt động"; + /// "Đăng" + @override + String get release => "Đăng"; + /// "Hoạt động của tôi" + @override + String get i_posted => "Hoạt động của tôi"; + /// "Xóa hoạt động" + @override + String get delete_dynamic => "Xóa hoạt động"; + /// "Bạn có chắc chắn muốn xóa hoạt động này?" + @override + String get delete_choose => "Bạn có chắc chắn muốn xóa hoạt động này?"; + /// "Đăng trên /s1" + @override + String get posted_on => "Đăng trên /s1"; + /// "Like" + @override + String get thumbs_up3 => "Like"; + /// "Đã like" + @override + String get already_praised => "Đã like"; + /// "Nhận xét" + @override + String get comment => "Nhận xét"; + /// "Gửi" + @override + String get send => "Gửi"; + /// "Bình luận đã đóng" + @override + String get comment_closed => "Bình luận đã đóng"; + /// "Chỉ người đăng có thể nhìn thấy nhận xét của bạn" + @override + String get your_comment => "Chỉ người đăng có thể nhìn thấy nhận xét của bạn"; + /// "Mọi người đều có thể thấy nhận xét của bạn" + @override + String get everyone_comment => "Mọi người đều có thể thấy nhận xét của bạn"; + /// "Cấm nhận xét" + @override + String get prohibit_comments => "Cấm nhận xét"; + /// "bật chế độ cấm nhận xét" + @override + String get comments_disabled => "bật chế độ cấm nhận xét"; + /// "Hủy chế độ cấm nhận xét" + @override + String get open_comments => "Hủy chế độ cấm nhận xét"; + /// "Đã hủy chế độ cấm nhận xét" + @override + String get already_open => "Đã hủy chế độ cấm nhận xét"; + /// "Trả lời" + @override + String get reply => "Trả lời"; + /// "Báo cáo" + @override + String get report => "Báo cáo"; + /// "Bạn có chắc chắn muốn báo cáo nhận xét này?" + @override + String get report_choose => "Bạn có chắc chắn muốn báo cáo nhận xét này?"; + /// "Báo cáo thành công, chúng tôi sẽ giải quyết nó trong thời gian sớm nhất!" + @override + String get successful_report => "Báo cáo thành công, chúng tôi sẽ giải quyết nó trong thời gian sớm nhất!"; + /// "Đã xóa thành công" + @override + String get successfully_deleted => "Đã xóa thành công"; + /// "Những người ăn nói văn hóa thường được chào đón hơn. Xin đừng phát ngôn thô tục, đăng tải nội dung khiêu dâm hoặc tiết lộ sự riêng tư của người khác!" + @override + String get please_civilization => "Những người ăn nói văn hóa thường được chào đón hơn. Xin đừng phát ngôn thô tục, đăng tải nội dung khiêu dâm hoặc tiết lộ sự riêng tư của người khác!"; + /// "Không cho người cùng giới tính thấy tôi" + @override + String get same_sex => "Không cho người cùng giới tính thấy tôi"; + /// "Thành viên miễn phí, không phải thành viên cần /s1H coin" + @override + String get member_free => "Thành viên miễn phí, không phải thành viên cần /s1H coin"; + /// "Phái nữ đã xác thực được miễn phí 3 lần, sau đó cần phải trả /s1H coin" + @override + String get certified_free => "Phái nữ đã xác thực được miễn phí 3 lần, sau đó cần phải trả /s1H coin"; + /// "Vui lòng nhập văn bản hoặc chọn hình ảnh" + @override + String get enter_something => "Vui lòng nhập văn bản hoặc chọn hình ảnh"; + /// "Đăng tải thu phí (/s1H coin)" + @override + String get raid_release => "Đăng tải thu phí (/s1H coin)"; + /// "Miễn phí cho các thành viên" + @override + String get become_member2 => "Miễn phí cho các thành viên"; + /// "Lập tức xác thực và miễn phí đăng bài" + @override + String get now_certification => "Lập tức xác thực và miễn phí đăng bài"; + /// "Đăng bài thành công" + @override + String get successfully_released => "Đăng bài thành công"; + /// "Bạn vẫn chưa đăng chương trình nào" + @override + String get no_program => "Bạn vẫn chưa đăng chương trình nào"; + /// "Chi tiết chương trình" + @override + String get program_details => "Chi tiết chương trình"; + /// "Chủ đề chương trình" + @override + String get program_theme => "Chủ đề chương trình"; + /// "Nhấn vào đây để chọn" + @override + String get click_select => "Nhấn vào đây để chọn"; + /// "Thành phố" + @override + String get city => "Thành phố"; + /// "Chọn thành phố" + @override + String get select_city => "Chọn thành phố"; + /// "Thời gian" + @override + String get time => "Thời gian"; + /// "Chọn ngày" + @override + String get select_date => "Chọn ngày"; + /// "Chọn thời gian" + @override + String get select_time => "Chọn thời gian"; + /// "Không giới hạn thời gian" + @override + String get unlimited_time => "Không giới hạn thời gian"; + /// "Ghi chú" + @override + String get supplementary_explanation => "Ghi chú"; + /// "Kèm hình" + @override + String get image => "Kèm hình"; + /// "Xóa chương trình" + @override + String get delete_program => "Xóa chương trình"; + /// "Bạn có chắc chắn muốn xóa chương trình này?" + @override + String get delete_choose2 => "Bạn có chắc chắn muốn xóa chương trình này?"; + /// "Vui lòng chọn chủ đề cho chương trình" + @override + String get please_choose => "Vui lòng chọn chủ đề cho chương trình"; + /// "Vui lòng chọn đối tượng mong muốn" + @override + String get please_choose2 => "Vui lòng chọn đối tượng mong muốn"; + /// "Vui lòng chọn một thành phố" + @override + String get please_choose3 => "Vui lòng chọn một thành phố"; + /// "Vui lòng chọn một ngày" + @override + String get please_choose4 => "Vui lòng chọn một ngày"; + /// "Vui lòng chọn thời gian" + @override + String get please_choose5 => "Vui lòng chọn thời gian"; + /// "Đăng chương trình" + @override + String get release_program => "Đăng chương trình"; + /// "Đăng ký" + @override + String get sign_up => "Đăng ký"; + /// "Kết thúc đăng ký" + @override + String get end_registration => "Kết thúc đăng ký"; + /// "Bạn có chắc là muốn kết thúc hẹn hò?" + @override + String get end_choose => "Bạn có chắc là muốn kết thúc hẹn hò?"; + /// "Liên lạc với em ấy" + @override + String get contact_her => "Liên lạc với em ấy"; + /// "Chat riêng với anh ấy" + @override + String get talk_him => "Chat riêng với anh ấy"; + /// "Có chắc là bạn muốn báo cáo thông tin đăng ký này?" + @override + String get report_choose2 => "Có chắc là bạn muốn báo cáo thông tin đăng ký này?"; + /// "Thời gian phát hành" + @override + String get release_time => "Thời gian phát hành"; + /// "Thời gian hoạt động" + @override + String get activity_time => "Thời gian hoạt động"; + /// "Không giới hạn giới tính" + @override + String get any_sex => "Không giới hạn giới tính"; + /// "Chỉ nhìn phái nữ" + @override + String get look_women => "Chỉ nhìn phái nữ"; + /// "Chỉ nhìn phái nam" + @override + String get look_men => "Chỉ nhìn phái nam"; + /// "Không giới hạn KV" + @override + String get unlimited_area => "Không giới hạn KV"; + /// "Chương trình đã bị xóa" + @override + String get program_deleted => "Chương trình đã bị xóa"; + /// "Không phải thành viên không thể nhận xét" + @override + String get cant_comment => "Không phải thành viên không thể nhận xét"; + /// "Đăng ký" + @override + String get sign_up2 => "Đăng ký"; + /// "Đăng ký cần phải gửi ảnh chính diện khuôn mặt của bạn (chỉ đối phương có thể nhìn thấy)" + @override + String get need_photo2 => "Đăng ký cần phải gửi ảnh chính diện khuôn mặt của bạn (chỉ đối phương có thể nhìn thấy)"; + /// "Đăng ký thành công, nếu đối phương cảm thấy thích hợp sẽ liên hệ bạn" + @override + String get registration_success => "Đăng ký thành công, nếu đối phương cảm thấy thích hợp sẽ liên hệ bạn"; + /// "Đã kết thúc" + @override + String get has_ended => "Đã kết thúc"; + /// "Phái nam không thể đăng ký chương trình của phái nam" + @override + String get men_cant => "Phái nam không thể đăng ký chương trình của phái nam"; + /// "Phái nữ không thể đăng ký chương trình của phái nữ" + @override + String get ms_cant => "Phái nữ không thể đăng ký chương trình của phái nữ"; + /// "Phái nam không thể nhận xét chương trình của phái nam" + @override + String get men_cant2 => "Phái nam không thể nhận xét chương trình của phái nam"; + /// "Phái nữ không thể nhận xét chương trình của phái nữ" + @override + String get ms_cant2 => "Phái nữ không thể nhận xét chương trình của phái nữ"; + /// "Đẩy tin nhắn, thay đổi mật khẩu" + @override + String get message_push => "Đẩy tin nhắn, thay đổi mật khẩu"; + /// "Số điện thoại di động" + @override + String get phone_number => "Số điện thoại di động"; + /// "Số điện thoại liên kết" + @override + String get bind_phone1 => "Số điện thoại liên kết"; + /// "Liên kết số điện thoại sẽ giúp cho tài khoản của bạn an toàn hơn" + @override + String get more_safer => "Liên kết số điện thoại sẽ giúp cho tài khoản của bạn an toàn hơn"; + /// "Bạn muốn thay đổi số điện thoại liên kết?" + @override + String get modify_choose => "Bạn muốn thay đổi số điện thoại liên kết?"; + /// "Thay đổi mật khẩu" + @override + String get change_password => "Thay đổi mật khẩu"; + /// "Người dùng cần liên kết số điện thoại di động trước khi cài đặt mật khẩu đăng nhập" + @override + String get first_bind => "Người dùng cần liên kết số điện thoại di động trước khi cài đặt mật khẩu đăng nhập"; + /// "Nhập mật khẩu gốc" + @override + String get old_password => "Nhập mật khẩu gốc"; + /// "Nhập mật khẩu đăng nhập hiện tại" + @override + String get current_password => "Nhập mật khẩu đăng nhập hiện tại"; + /// "Nhập mật khẩu mới" + @override + String get new_password => "Nhập mật khẩu mới"; + /// "Mật khẩu mới không dưới 06 ký tự" + @override + String get set_new => "Mật khẩu mới không dưới 06 ký tự"; + /// "Xóa bộ nhớ cache hình ảnh" + @override + String get clear_cache => "Xóa bộ nhớ cache hình ảnh"; + /// "Đã xóa thành công" + @override + String get cleared_successfully => "Đã xóa thành công"; + /// "Thỏa thuận người dùng" + @override + String get user_agreement1 => "Thỏa thuận người dùng"; + /// "Thoát ra" + @override + String get sign_out => "Thoát ra"; + /// "Bạn có chắc chắn muốn đăng xuất?" + @override + String get out_choose => "Bạn có chắc chắn muốn đăng xuất?"; + /// "Cài đặt lượt đẩy" + @override + String get push_settings => "Cài đặt lượt đẩy"; + /// "Quyền hạn đã bị từ chối" + @override + String get permission_denied => "Quyền hạn đã bị từ chối"; + /// "Cài đặt đẩy tin nhắn" + @override + String get push_setting2 => "Cài đặt đẩy tin nhắn"; + /// "Tin nhắn trờ chuyện riêng" + @override + String get private_chat2 => "Tin nhắn trờ chuyện riêng"; + /// "Có hẹn hò mới" + @override + String get new_date => "Có hẹn hò mới"; + /// "Có phái nữ yêu cầu xem dữ liệu" + @override + String get passed_request2 => "Có phái nữ yêu cầu xem dữ liệu"; + /// "Có phái nam yêu cầu xem dữ liệu" + @override + String get men_view => "Có phái nam yêu cầu xem dữ liệu"; + /// "Có anh chàng nào đấy xem tài khoản mạng xã hội của tôi" + @override + String get men_view2 => "Có anh chàng nào đấy xem tài khoản mạng xã hội của tôi"; + /// "Có phái nam yêu cầu xem avata" + @override + String get men_view3 => "Có phái nam yêu cầu xem avata"; + /// "Có anh chàng đã xem dữ liệu và gửi cho tôi tài khoản xã hội" + @override + String get men_view4 => "Có anh chàng đã xem dữ liệu và gửi cho tôi tài khoản xã hội"; + /// "Yêu cầu cấp mã mời đã thành công" + @override + String get applied_successfully => "Yêu cầu cấp mã mời đã thành công"; + /// "Giới thiệu tin tức liên quan sau khi bật" + @override + String get after_open => "Giới thiệu tin tức liên quan sau khi bật"; + /// "Nếu bạn đã thanh toán cho em ấy/ anh ấy trong 3 ngày gần đây, sau khi chúng tôi xác thực báo cáo, hệ thống sẽ tự động hoàn trả chi phí cho bạn." + @override + String get if_something => "Nếu bạn đã thanh toán cho em ấy/ anh ấy trong 3 ngày gần đây, sau khi chúng tôi xác thực báo cáo, hệ thống sẽ tự động hoàn trả chi phí cho bạn."; + /// "Đăng quảng cáo" + @override + String get advertise => "Đăng quảng cáo"; + /// "Ảnh không đúng thực tế" + @override + String get false_photo => "Ảnh không đúng thực tế"; + /// "Khiêu dâm thô tục" + @override + String get erotic_vulgarity => "Khiêu dâm thô tục"; + /// "Quấy rối" + @override + String get harassment => "Quấy rối"; + /// "Em ấy là một kẻ lừa đảo" + @override + String get she_liar => "Em ấy là một kẻ lừa đảo"; + /// "Anh ấy là một kẻ lừa đảo" + @override + String get he_liar => "Anh ấy là một kẻ lừa đảo"; + /// "Xin cung cấp ảnh chụp màn hình liên quan để chúng tôi theo dõi xác thực" + @override + String get provide_screenshots => "Xin cung cấp ảnh chụp màn hình liên quan để chúng tôi theo dõi xác thực"; + /// "Vui lòng mô tả chi tiết (trong vòng 100 từ)" + @override + String get describe_details => "Vui lòng mô tả chi tiết (trong vòng 100 từ)"; + /// "Vui lòng chọn lý do báo cáo" + @override + String get report_reason => "Vui lòng chọn lý do báo cáo"; + /// "Báo cáo thành công" + @override + String get report_success2 => "Báo cáo thành công"; + /// "Đã sửa đổi thành công" + @override + String get successfully_modified => "Đã sửa đổi thành công"; + /// "Nam" + @override + String get boy => "Nam"; + /// "Nữ" + @override + String get girl => "Nữ"; + /// "Đã gửi yêu cầu" + @override + String get already_applied => "Đã gửi yêu cầu"; + /// "Xem đăng ký" + @override + String get view_registration => "Xem đăng ký"; + /// "Mở rộng" + @override + String get expand => "Mở rộng"; + /// "Thu gọn" + @override + String get collapse => "Thu gọn"; + /// "Yêu cầu thông báo" + @override + String get application_notice => "Yêu cầu thông báo"; + /// "Có tài khoản khác đồng ý với yêu cầu của bạn" + @override + String get agrees_application => "Có tài khoản khác đồng ý với yêu cầu của bạn"; + /// "Ảnh phong bì" + @override + String get red_photo => "Ảnh phong bì"; + /// "Vui lòng không đăng tải hình ảnh/ video khỏa thân thô tục. Nếu vi phạm chúng tôi sẽ đóng tài khoản" + @override + String get dont => "Vui lòng không đăng tải hình ảnh/ video khỏa thân thô tục. Nếu vi phạm chúng tôi sẽ đóng tài khoản"; + /// "Phiên bản hiện tại" + @override + String get current_version => "Phiên bản hiện tại"; + /// "Liên kết thẻ ngân hàng" + @override + String get bank_card => "Liên kết thẻ ngân hàng"; + /// "Vui lòng chọn một ngân hàng" + @override + String get choose_bank => "Vui lòng chọn một ngân hàng"; + /// "Vui lòng nhập số thẻ ngân hàng" + @override + String get bank_number => "Vui lòng nhập số thẻ ngân hàng"; + /// "Vui lòng nhập số căn cước/ CMND" + @override + String get id_number => "Vui lòng nhập số căn cước/ CMND"; + /// "Tên họ" + @override + String get name => "Tên họ"; + /// "Số thẻ NH" + @override + String get bank_number2 => "Số thẻ NH"; + /// "Số thẻ CMND" + @override + String get license_number => "Số thẻ CMND"; + /// "Số ĐT liên kết" + @override + String get bind_phone => "Số ĐT liên kết"; + /// "Trang chủ của anh ấy" + @override + String get his_homepage => "Trang chủ của anh ấy"; + /// "Trang chủ của em ấy" + @override + String get her_homepage => "Trang chủ của em ấy"; + /// "Thanh toán WeChat" + @override + String get wechat_pay => "Thanh toán WeChat"; + /// "Thanh toán Facebook" + @override + String get facebook_pay => "Thanh toán Facebook"; + /// "Thanh toán bằng google" + @override + String get google_pay => "Thanh toán bằng google"; + /// "Thanh toán thành công" + @override + String get payment_successful => "Thanh toán thành công"; + /// "Cài đặt sô tiền rút" + @override + String get set_amount => "Cài đặt sô tiền rút"; + /// "Vui lòng nhập số lượng xu H" + @override + String get enter_amount => "Vui lòng nhập số lượng xu H"; + /// "Có thể rút tiền" + @override + String get can_withdraw => "Có thể rút tiền"; + /// "Cài đặt ngôn ngữ" + @override + String get language_set => "Cài đặt ngôn ngữ"; + /// "Thỏa thuận người dùng" + @override + String get user_agreement => "Thỏa thuận người dùng"; + /// "Tiếp tục trả phí" + @override + String get renewal_fee => "Tiếp tục trả phí"; + /// "Mở ngay lập tức" + @override + String get open_immediately => "Mở ngay lập tức"; + /// "Tổng cộng" + @override + String get total => "Tổng cộng"; + /// "Nửa tháng" + @override + String get half_month => "Nửa tháng"; + /// "/s1 tháng" + @override + String get month2 => "/s1 tháng"; + /// "Bỏ chặn" + @override + String get cancel_shield => "Bỏ chặn"; + /// "Danh sách đen" + @override + String get blacklist2 => "Danh sách đen"; + /// "(Thành viên có thể kéo dài thời gian đến 06 giây)" + @override + String get longTime => "(Thành viên có thể kéo dài thời gian đến 06 giây)"; + /// "Nhấn và giữ màn hình để xem" + @override + String get longClick => "Nhấn và giữ màn hình để xem"; + /// "Vui lòng kết thúc chương trình vẫn còn hiệu lực." + @override + String get stop_program => "Vui lòng kết thúc chương trình vẫn còn hiệu lực."; + /// "Đàn ông không thể sưu tập đàn ông" + @override + String get not_love => "Đàn ông không thể sưu tập đàn ông"; + /// "Phái nữ không thể sưu tập phái nữ!" + @override + String get not_love2 => "Phái nữ không thể sưu tập phái nữ!"; + /// "Hotgirl có thể miễn phí đăng tin" + @override + String get women_free => "Hotgirl có thể miễn phí đăng tin"; + /// "Anh ấy vẫn chưa tải hình ảnh" + @override + String get not_up_man => "Anh ấy vẫn chưa tải hình ảnh"; + /// "Chị ấy vẫn chưa tải hình ảnh" + @override + String get not_up_women => "Chị ấy vẫn chưa tải hình ảnh"; + /// "Cảm ơn bạn không thực hiện những hành vi phạm pháp trên APP, nếu bị báo và phát hiện sẽ bị xử lý bằng cách khóa tài khoản" + @override + String get not_illage => "Cảm ơn bạn không thực hiện những hành vi phạm pháp trên APP, nếu bị báo và phát hiện sẽ bị xử lý bằng cách khóa tài khoản"; + /// "Tôi đã ghi danh" + @override + String get alreay_join => "Tôi đã ghi danh"; + /// "Bạn có chắc là muốn xóa tấm ảnh này" + @override + String get sure_delete => "Bạn có chắc là muốn xóa tấm ảnh này"; + /// "Lập tức điền vào" + @override + String get white_now => "Lập tức điền vào"; + /// "Bạn vẫn chưa nhập vào mục \"giới thiệu bản thân\", lời giới thiệu thu hút người khác có sức ảnh hưởng rất lớn" + @override + String get personal => "Bạn vẫn chưa nhập vào mục \"giới thiệu bản thân\", lời giới thiệu thu hút người khác có sức ảnh hưởng rất lớn"; + /// "Thành công" + @override + String get success => "Thành công"; + /// "Thất bại" + @override + String get fail => "Thất bại"; + /// "Chỉ người dùng đã xác thực mới có thể cài đặc ảnh phong bì" + @override + String get moneyPageTip => "Chỉ người dùng đã xác thực mới có thể cài đặc ảnh phong bì"; + /// "Bạn đã đăng ký, đối phương sẽ liên lạc với bạn nếu họ cảm thấy phù hợp" + @override + String get alreadyJoin => "Bạn đã đăng ký, đối phương sẽ liên lạc với bạn nếu họ cảm thấy phù hợp"; + /// "Cảnh báo vi phạm" + @override + String get waring => "Cảnh báo vi phạm"; + /// "Tôn trọng quyền riêng tư của người dùng, cấm chụp ảnh màn hình người khác. Nếu có vi phạm lần sau, bạn sẽ bị cấm xem ảnh người dùng khác." + @override + String get userPravicy => "Tôn trọng quyền riêng tư của người dùng, cấm chụp ảnh màn hình người khác. Nếu có vi phạm lần sau, bạn sẽ bị cấm xem ảnh người dùng khác."; + /// "Thời gian hẹn hò đã hết hạn, vui lòng chỉnh sửa" + @override + String get outTime => "Thời gian hẹn hò đã hết hạn, vui lòng chỉnh sửa"; + /// "Xác thực" + @override + String get reviewing => "Xác thực"; + /// "Xét duyệt thành công" + @override + String get reviewed => "Xét duyệt thành công"; + /// "Xét duyệt thất bại" + @override + String get reviewedFail => "Xét duyệt thất bại"; + /// "Người dùng phải liên kết thể ngân hàng trước khi rút tiền mặt" + @override + String get needCard => "Người dùng phải liên kết thể ngân hàng trước khi rút tiền mặt"; + /// "Phái nữ không thể nhận xét về hoạt động của phái nữ" + @override + String get women_not_d => "Phái nữ không thể nhận xét về hoạt động của phái nữ"; + /// "Phái nam không thể nhận xét về hoạt động của phái nam" + @override + String get man_not_d => "Phái nam không thể nhận xét về hoạt động của phái nam"; + /// "Có hình ảnh bạn có thể thu hút hơn đối với phái nữ" + @override + String get have_picture => "Có hình ảnh bạn có thể thu hút hơn đối với phái nữ"; + /// "Trượt lên để hủy gửi" + @override + String get up_cancle => "Trượt lên để hủy gửi"; + /// "Tin nhắn không thể bỏ trống" + @override + String get msg_not => "Tin nhắn không thể bỏ trống"; + /// "Chức năng này phải cho phép ghi âm" + @override + String get need_record => "Chức năng này phải cho phép ghi âm"; + /// "Đang tải file video" + @override + String get downloading_video => "Đang tải file video"; + /// "Xin nhập lại thứ tự câu hỏi" + @override + String get reinput => "Xin nhập lại thứ tự câu hỏi"; + /// "Hoạt động của bạn bị báo cáo ẩn danh. Sau khi xác nhận, hệ thống đã xóa hoạt động này. Xin đừng tiến hàng thao tác sai trái!" + @override + String get dy_delete => "Hoạt động của bạn bị báo cáo ẩn danh. Sau khi xác nhận, hệ thống đã xóa hoạt động này. Xin đừng tiến hàng thao tác sai trái!"; + /// "Chương trình của bạn bị báo cáo ẩn danh. Sau khi xác nhận, hệ thống đã xóa chương trình này. Xin đừng tiến hàng thao tác sai trái!" + @override + String get pro_delete => "Chương trình của bạn bị báo cáo ẩn danh. Sau khi xác nhận, hệ thống đã xóa chương trình này. Xin đừng tiến hàng thao tác sai trái!"; + /// "Nhận xét của bạn bị báo cáo ẩn danh. Sau khi xác nhận, hệ thống đã xóa nhận xét này. Xin đừng tiến hàng thao tác sai trái!" + @override + String get con_delete => "Nhận xét của bạn bị báo cáo ẩn danh. Sau khi xác nhận, hệ thống đã xóa nhận xét này. Xin đừng tiến hàng thao tác sai trái!"; + /// "Sau khi nhận được báo cáo từ người dùng ẩn danh, hệ thống xác nhận gần đây bạn đã có hành động sai trái, nên đã tiến hành hoàn trả những H-coin gần đây của bạn. Nếu tái phạm, chưng tôi sẽ khóa tài khoản." + @override + String get coin_returen => "Sau khi nhận được báo cáo từ người dùng ẩn danh, hệ thống xác nhận gần đây bạn đã có hành động sai trái, nên đã tiến hành hoàn trả những H-coin gần đây của bạn. Nếu tái phạm, chưng tôi sẽ khóa tài khoản."; + /// "Cấm tất cả hành vi dâm ô trái pháp luật trong khi thực hiện cuộc gọi, một khi phát hiện chúng tôi sẽ tiến hành khóa tài khoản." + @override + String get voicing => "Cấm tất cả hành vi dâm ô trái pháp luật trong khi thực hiện cuộc gọi, một khi phát hiện chúng tôi sẽ tiến hành khóa tài khoản."; + /// "Nhân viên CSKH" + @override + String get help => "Nhân viên CSKH"; + /// "Mở chức năng người dịch" + @override + String get translate_on => "Mở chức năng người dịch"; + /// "Tắt chức năng người dịch" + @override + String get translate_off => "Tắt chức năng người dịch"; + /// "Đã dùng /s1H coin để tái tục SIVP" + @override + String get becomeSvip => "Đã dùng /s1H coin để tái tục SIVP"; + /// "Bật quyền hạn SIVP" + @override + String get need_svip => "Bật quyền hạn SIVP"; + /// "Không thể tái tục SVIP, trở thành VIP" + @override + String get cannot_vip => "Không thể tái tục SVIP, trở thành VIP"; + /// "Bạn đã thoát, không thể gửi và nhận tin nhắn" + @override + String get offline => "Bạn đã thoát, không thể gửi và nhận tin nhắn"; + /// "Tài khoản đăng nhặp trên thiết bị khác, bạn đã thoát" + @override + String get otherLogin => "Tài khoản đăng nhặp trên thiết bị khác, bạn đã thoát"; + /// "Tạm thời chưa có tin nhắn mới" + @override + String get no_new => "Tạm thời chưa có tin nhắn mới"; + /// "Đã dịch xong" + @override + String get over => "Đã dịch xong"; + /// "Bạn có chắc là dislike ?" + @override + String get bad_ev => "Bạn có chắc là dislike ?"; + /// "Right 5" + @override + String get right5 => "Right 5"; + /// "Right 6" + @override + String get right6 => "Right 6"; + /// "Anh ơi" + @override + String get man_vi => "Anh ơi"; + /// "Em ơi" + @override + String get women_vi => "Em ơi"; + /// "để nâng cao chất lượng phục vụ, nếu dưới đây có thắc mắc của bạn, vui lòng trả lời bằng cách nhập số thứ tự" + @override + String get kf_tips => "để nâng cao chất lượng phục vụ, nếu dưới đây có thắc mắc của bạn, vui lòng trả lời bằng cách nhập số thứ tự"; + /// "Đã từ chối" + @override + String get rejected => "Đã từ chối"; + /// "Bạn đã tiêu thụ /s1 H tệ để mua thành viên." + @override + String get buy_vip => "Bạn đã tiêu thụ /s1 H tệ để mua thành viên."; + /// "Bạn đã tiêu thụ /s1 H tệ để đăng hoạt động." + @override + String get buy_program => "Bạn đã tiêu thụ /s1 H tệ để đăng hoạt động."; + /// "Yêu cầu rút tiền H của bạn đã được xử lý và chuyển /s1 vào tài khoản của bạn, vui lòng kiểm tra!" + @override + String get del_add_money => "Yêu cầu rút tiền H của bạn đã được xử lý và chuyển /s1 vào tài khoản của bạn, vui lòng kiểm tra!"; + /// "Yêu cầu rút tiền /s1 H của bạn đang được xét duyệt." + @override + String get adding_money => "Yêu cầu rút tiền /s1 H của bạn đang được xét duyệt."; + /// "miễn phí hưởng nhân viên dịch thuật kịp thời" + @override + String get free_translate => "miễn phí hưởng nhân viên dịch thuật kịp thời"; + /// "Nhân viên CSKH vì bạn phục vụ" + @override + String get personalTraff => "Nhân viên CSKH vì bạn phục vụ"; + /// "Người dịch đang dịch..." + @override + String get ManTranslate => "Người dịch đang dịch..."; + /// "Máy đang dịch..." + @override + String get robotTranslate => "Máy đang dịch..."; + /// "Người dịch đã hoàn thành" + @override + String get translated => "Người dịch đã hoàn thành"; + /// "Giao tiếp lành mạnh, xin đừng phát nội dung thô tục, một khi phát hiện sẽ bị xóa." + @override + String get delete_progarm => "Giao tiếp lành mạnh, xin đừng phát nội dung thô tục, một khi phát hiện sẽ bị xóa."; + /// "Quyền định vị chưa được bật" + @override + String get open_location => "Quyền định vị chưa được bật"; + /// "Vui lòng bật quyền định vị trong cài đặt điện thoại của bạn để biết khoảng cách người khác." + @override + String get get_location => "Vui lòng bật quyền định vị trong cài đặt điện thoại của bạn để biết khoảng cách người khác."; + /// "Nhấn lần nữa để thoát" + @override + String get confirm_exit => "Nhấn lần nữa để thoát"; + /// "Cơ hội miễn phí phát sóng /s1 /ngày " + @override + String get free_program => "Cơ hội miễn phí phát sóng /s1 /ngày "; + /// "Hình ảnh" + @override + String get picture => "Hình ảnh"; + /// "Máy ảnh" + @override + String get camera => "Máy ảnh"; + /// "Video" + @override + String get video => "Video"; + /// "Tiền lì xì" + @override + String get red_money => "Tiền lì xì"; + /// "Dán" + @override + String get stick => "Dán"; + /// "Giữ để nói " + @override + String get press_say => "Giữ để nói "; + /// "/s1 đã nhận được tiền lì xì của bạn" + @override + String get get_money => "/s1 đã nhận được tiền lì xì của bạn"; + /// "Bạn đã nhận được tiền lì xì của /s1" + @override + String get you_get_money => "Bạn đã nhận được tiền lì xì của /s1"; + /// "Tiền lì xì của /s1 " + @override + String get ones_money => "Tiền lì xì của /s1 "; + /// "Tiền lì xì đã hết hạn" + @override + String get money_over => "Tiền lì xì đã hết hạn"; + /// "Tải tập tin thất bại" + @override + String get downloading_fail => "Tải tập tin thất bại"; + /// "Đang tải tập tin video" + @override + String get downloading => "Đang tải tập tin video"; + /// "Tiền lì xì chưa nhận, sẽ được yêu cầu hoàn trả sau 24 giờ! " + @override + String get back_money => "Tiền lì xì chưa nhận, sẽ được yêu cầu hoàn trả sau 24 giờ! "; + /// "Tiền lì xì không tồn tại" + @override + String get no_money => "Tiền lì xì không tồn tại"; + /// "Tiền lì xì đã nhận" + @override + String get already_money => "Tiền lì xì đã nhận"; + /// "Đã hết hạn, đã được hoàn trả vào tài khoản" + @override + String get back_user => "Đã hết hạn, đã được hoàn trả vào tài khoản"; + /// "Đang chờ bên kia nhận" + @override + String get waiting_user => "Đang chờ bên kia nhận"; + /// "Bên kia đã nhận" + @override + String get other_get => "Bên kia đã nhận"; + /// "Của ít lòng nhiều, cứ lấy mà tiêu" + @override + String get little => "Của ít lòng nhiều, cứ lấy mà tiêu"; + /// "Tăng thêm tiền mặt vào phong bì" + @override + String get put_money => "Tăng thêm tiền mặt vào phong bì"; + /// "Số tiền" + @override + String get mount => "Số tiền"; + /// "Đã hết hạn" + @override + String get over_time => "Đã hết hạn"; + /// "Đã nhận" + @override + String get has_get => "Đã nhận"; + /// "Hiện tại không có phần quà nào" + @override + String get no_gift => "Hiện tại không có phần quà nào"; + /// "Quà tặng" + @override + String get sent_gift => "Quà tặng"; + /// "Khi bạn điền thông tin thành công sẽ nhận được /s1H tề, không thể sửa đổi sau khi liên kết." + @override + String get fill_tips => "Khi bạn điền thông tin thành công sẽ nhận được /s1H tề, không thể sửa đổi sau khi liên kết."; + /// "Liên kết mã mời" + @override + String get bind_code => "Liên kết mã mời"; + /// "Mã mời" + @override + String get invide_code => "Mã mời"; + /// "Xác nhận xóa" + @override + String get confirm_delete => "Xác nhận xóa"; + /// "Bạn đã nhận xét rồi" + @override + String get has_eva => "Bạn đã nhận xét rồi"; + /// "Mở" + @override + String get open => "Mở"; + /// "Giọng nói" + @override + String get voice => "Giọng nói"; + /// "Buông ra để gửi" + @override + String get release_send => "Buông ra để gửi"; + /// "Thời gian ghi âm quá ngắn" + @override + String get time_little => "Thời gian ghi âm quá ngắn"; + /// "Đối phương không trực tuyến, không thể kết nối mic" + @override + String get not_online => "Đối phương không trực tuyến, không thể kết nối mic"; + /// "Bạn đã gửi một lì xì /s2 H đến /s1" + @override + String get give_red_money => "Bạn đã gửi một lì xì /s2 H đến /s1"; + /// "Bạn đã nhận được một lì xì /s2 H của /s1" + @override + String get get_red_money => "Bạn đã nhận được một lì xì /s2 H của /s1"; + /// "Bạn đã thưởng /s1 /s2H" + @override + String get give_other_money => "Bạn đã thưởng /s1 /s2H"; + /// "Bạn đã nhận được lì xì /s2H của /s1" + @override + String get get_other_money => "Bạn đã nhận được lì xì /s2H của /s1"; + /// "Siêu hội viên" + @override + String get svip => "Siêu hội viên"; + /// "Đề xuất" + @override + String get recommend => "Đề xuất"; + /// "Bạn đã trả (/s2H xu) để xem ảnh phong bì màu đỏ của /s1" + @override + String get paid_you4 => "Bạn đã trả (/s2H xu) để xem ảnh phong bì màu đỏ của /s1"; + /// "Bạn đã trả (/s2H xu) để xem album của /s1" + @override + String get paid_you5 => "Bạn đã trả (/s2H xu) để xem album của /s1"; + /// "Bạn đã trả tiền để mở khóa tất cả thông tin của /s1" + @override + String get paid_you6 => "Bạn đã trả tiền để mở khóa tất cả thông tin của /s1"; + /// "Hibok giấy phép và thỏa thuận dịch vụ" + @override + String get UG_LINE0 => "Hibok giấy phép và thỏa thuận dịch vụ"; + /// "[Đầu tiên và giới thiệu]" + @override + String get UG_LINE1 => "[Đầu tiên và giới thiệu]"; + /// "Qianhai Youlong Technology Co., Ltd. (sau đây gọi tắt là Cy Qianhai Youlong Technology Co., Ltd.) sau đây nhắc nhở người dùng đọc kỹ và hiểu đầy đủ Thỏa thuận dịch vụ này (sau đây gọi là Thỏa thuận ràng buộc). Người dùng nên đọc kỹ và hiểu đầy đủ Thỏa thuận này. Các điều khoản, bao gồm miễn trừ hoặc giới hạn trách nhiệm pháp lý của Qianhai Youlong Technology Co., Ltd. và các hạn chế về quyền của người dùng. Vui lòng đọc kỹ và chọn chấp nhận hoặc không chấp nhận Thỏa thuận này (trẻ vị thành niên phải có người giám hộ hợp pháp kèm theo). Bạn không được phép đăng ký, đăng nhập hoặc sử dụng các dịch vụ trong Thỏa thuận này trừ khi bạn chấp nhận tất cả các điều khoản của Thỏa thuận này. Việc đăng ký, đăng nhập, sử dụng, v.v. của bạn sẽ được coi là chấp nhận Thỏa thuận này và bạn đồng ý bị ràng buộc bởi các điều khoản của Thỏa thuận này." + @override + String get UG_LINE2 => "Qianhai Youlong Technology Co., Ltd. (sau đây gọi tắt là Cy Qianhai Youlong Technology Co., Ltd.) sau đây nhắc nhở người dùng đọc kỹ và hiểu đầy đủ Thỏa thuận dịch vụ này (sau đây gọi là Thỏa thuận ràng buộc). Người dùng nên đọc kỹ và hiểu đầy đủ Thỏa thuận này. Các điều khoản, bao gồm miễn trừ hoặc giới hạn trách nhiệm pháp lý của Qianhai Youlong Technology Co., Ltd. và các hạn chế về quyền của người dùng. Vui lòng đọc kỹ và chọn chấp nhận hoặc không chấp nhận Thỏa thuận này (trẻ vị thành niên phải có người giám hộ hợp pháp kèm theo). Bạn không được phép đăng ký, đăng nhập hoặc sử dụng các dịch vụ trong Thỏa thuận này trừ khi bạn chấp nhận tất cả các điều khoản của Thỏa thuận này. Việc đăng ký, đăng nhập, sử dụng, v.v. của bạn sẽ được coi là chấp nhận Thỏa thuận này và bạn đồng ý bị ràng buộc bởi các điều khoản của Thỏa thuận này."; + /// "Thỏa thuận này là một thỏa thuận giữa bạn (sau đây gọi là \"Người dùng\" và Qianhai Youlong Technology Co., Ltd. về việc đăng ký, đăng ký và sử dụng \"dịch vụ Hibok\". Thỏa thuận này mô tả mối quan hệ giữa Qianhai Youlong Technology Co., Ltd. và Người dùng về \"dịch vụ Hibok\". Quyền và nghĩa vụ. Người dùng có nghĩa là cá nhân hoặc tổ chức đăng ký, đăng nhập, sử dụng và duyệt Dịch vụ. Việc bạn chấp nhận Thỏa thuận này tuân theo tất cả các điều khoản và điều kiện, bao gồm mọi sửa đổi do Qianhai Youlong Technology Co., Ltd. thực hiện đối với mọi Điều khoản dịch vụ bất kỳ lúc nào. Thỏa thuận có thể được Qianhai Youlong Technology Co., Ltd. cập nhật bất cứ lúc nào. Các điều khoản cập nhật của thỏa thuận sẽ được thay thế bằng các điều khoản ban đầu của thỏa thuận mà không cần thông báo trước. Người dùng có thể kiểm tra các điều khoản của thỏa thuận mới nhất trong ứng dụng này. Sau khi Qianhai Youlong Technology Co., Ltd. sửa đổi các điều khoản của thỏa thuận, Nếu người dùng không chấp nhận các điều khoản sửa đổi, xin vui lòng ngừng sử dụng nó ngay lập tức dịch vụ Cyhd TNHH cung cấp, người dùng tiếp tục sử dụng dịch vụ Cyhd TNHH lời đề nghị sẽ được coi là đã chấp nhận thỏa thuận sửa đổi." + @override + String get UG_LINE3 => "Thỏa thuận này là một thỏa thuận giữa bạn (sau đây gọi là \"Người dùng\" và Qianhai Youlong Technology Co., Ltd. về việc đăng ký, đăng ký và sử dụng \"dịch vụ Hibok\". Thỏa thuận này mô tả mối quan hệ giữa Qianhai Youlong Technology Co., Ltd. và Người dùng về \"dịch vụ Hibok\". Quyền và nghĩa vụ. Người dùng có nghĩa là cá nhân hoặc tổ chức đăng ký, đăng nhập, sử dụng và duyệt Dịch vụ. Việc bạn chấp nhận Thỏa thuận này tuân theo tất cả các điều khoản và điều kiện, bao gồm mọi sửa đổi do Qianhai Youlong Technology Co., Ltd. thực hiện đối với mọi Điều khoản dịch vụ bất kỳ lúc nào. Thỏa thuận có thể được Qianhai Youlong Technology Co., Ltd. cập nhật bất cứ lúc nào. Các điều khoản cập nhật của thỏa thuận sẽ được thay thế bằng các điều khoản ban đầu của thỏa thuận mà không cần thông báo trước. Người dùng có thể kiểm tra các điều khoản của thỏa thuận mới nhất trong ứng dụng này. Sau khi Qianhai Youlong Technology Co., Ltd. sửa đổi các điều khoản của thỏa thuận, Nếu người dùng không chấp nhận các điều khoản sửa đổi, xin vui lòng ngừng sử dụng nó ngay lập tức dịch vụ Cyhd TNHH cung cấp, người dùng tiếp tục sử dụng dịch vụ Cyhd TNHH lời đề nghị sẽ được coi là đã chấp nhận thỏa thuận sửa đổi."; + /// "Đầu tiên, việc sử dụng các quy tắc" + @override + String get UG_LINE4 => "Đầu tiên, việc sử dụng các quy tắc"; + /// "1、 Người dùng hoàn toàn hiểu và đồng ý rằng chỉ cung cấp nền tảng chia sẻ, truyền tải và thu thập thông tin cho người dùng. Người dùng phải chịu trách nhiệm cho tất cả các hành động trong tài khoản đã đăng ký, bao gồm nhưng không giới hạn bất kỳ nội dung nào bạn truyền và bất kỳ kết quả nào. ." + @override + String get UG_LINE5 => "1、 Người dùng hoàn toàn hiểu và đồng ý rằng chỉ cung cấp nền tảng chia sẻ, truyền tải và thu thập thông tin cho người dùng. Người dùng phải chịu trách nhiệm cho tất cả các hành động trong tài khoản đã đăng ký, bao gồm nhưng không giới hạn bất kỳ nội dung nào bạn truyền và bất kỳ kết quả nào. ."; + /// "2、 Qianhai Youlong Technology Co., Ltd. không chịu trách nhiệm cho bất kỳ nội dung nào được truyền tải bởi hoặc thông qua các Dịch vụ không phản ánh quan điểm hoặc chính sách của Qianhai Youlong Technology Co., Ltd.." + @override + String get UG_LINE6 => "2、 Qianhai Youlong Technology Co., Ltd. không chịu trách nhiệm cho bất kỳ nội dung nào được truyền tải bởi hoặc thông qua các Dịch vụ không phản ánh quan điểm hoặc chính sách của Qianhai Youlong Technology Co., Ltd.."; + /// "3、 Người dùng hoàn toàn hiểu và đồng ý rằng đó là sản phẩm duyệt thông tin xã hội dựa trên mạng quan hệ người dùng. Người dùng phải chịu trách nhiệm hoàn toàn về tính xác thực, tính hợp pháp và tính hợp lệ của thông tin đã đăng ký và người dùng không được mạo danh người khác; Mọi thông tin sẽ được truyền đi dưới tên, không sử dụng độc hại tài khoản đã đăng ký có thể gây nhầm lẫn cho người dùng khác, nếu không, Qianhai Youlong Technology Co., Ltd. có quyền ngừng cung cấp dịch vụ ngay lập tức, phục hồi số tài khoản và chịu mọi trách nhiệm pháp lý phát sinh từ đó." + @override + String get UG_LINE7 => "3、 Người dùng hoàn toàn hiểu và đồng ý rằng đó là sản phẩm duyệt thông tin xã hội dựa trên mạng quan hệ người dùng. Người dùng phải chịu trách nhiệm hoàn toàn về tính xác thực, tính hợp pháp và tính hợp lệ của thông tin đã đăng ký và người dùng không được mạo danh người khác; Mọi thông tin sẽ được truyền đi dưới tên, không sử dụng độc hại tài khoản đã đăng ký có thể gây nhầm lẫn cho người dùng khác, nếu không, Qianhai Youlong Technology Co., Ltd. có quyền ngừng cung cấp dịch vụ ngay lập tức, phục hồi số tài khoản và chịu mọi trách nhiệm pháp lý phát sinh từ đó."; + /// "4、Người dùng phải tự chịu trách nhiệm về tính xác thực, tính hợp pháp, vô hại và tính hợp lệ của thông tin được truyền trên trang web. Mọi trách nhiệm pháp lý liên quan đến thông tin do người dùng truyền tải sẽ do người dùng chịu và không liên quan đến Qianhai Youlong Technology Co., Ltd.." + @override + String get UG_LINE8 => "4、Người dùng phải tự chịu trách nhiệm về tính xác thực, tính hợp pháp, vô hại và tính hợp lệ của thông tin được truyền trên trang web. Mọi trách nhiệm pháp lý liên quan đến thông tin do người dùng truyền tải sẽ do người dùng chịu và không liên quan đến Qianhai Youlong Technology Co., Ltd.."; + /// "5、Qianhai Youlong Technology Co., Ltd. có quyền thay đổi, đình chỉ, giới hạn, chấm dứt hoặc thu hồi dịch vụ của bất kỳ hoặc tất cả các dịch vụ của Dịch vụ bất cứ lúc nào mà không cần thông báo do nhu cầu phát triển kinh doanh và người dùng phải chịu rủi ro này." + @override + String get UG_LINE9 => "5、Qianhai Youlong Technology Co., Ltd. có quyền thay đổi, đình chỉ, giới hạn, chấm dứt hoặc thu hồi dịch vụ của bất kỳ hoặc tất cả các dịch vụ của Dịch vụ bất cứ lúc nào mà không cần thông báo do nhu cầu phát triển kinh doanh và người dùng phải chịu rủi ro này."; + /// "6、Các dịch vụ được cung cấp có thể bao gồm quảng cáo và người dùng đồng ý hiển thị quảng cáo được cung cấp bởi các nhà cung cấp và đối tác bên thứ ba trong quá trình sử dụng." + @override + String get UG_LINE10 => "6、Các dịch vụ được cung cấp có thể bao gồm quảng cáo và người dùng đồng ý hiển thị quảng cáo được cung cấp bởi các nhà cung cấp và đối tác bên thứ ba trong quá trình sử dụng."; + /// "7、 Người dùng không được sử dụng hoặc dịch vụ để thực hiện, tải lên, sao chép hoặc gửi nội dung sau:" + @override + String get UG_LINE11 => "7、 Người dùng không được sử dụng hoặc dịch vụ để thực hiện, tải lên, sao chép hoặc gửi nội dung sau:"; + /// "(1) chống lại các nguyên tắc cơ bản được thiết lập bởi Hiến pháp;" + @override + String get UG_LINE12 => "(1) chống lại các nguyên tắc cơ bản được thiết lập bởi Hiến pháp;"; + /// "(2) gây nguy hiểm cho an ninh quốc gia, tiết lộ bí mật nhà nước, lật đổ quyền lực nhà nước và phá hoại đoàn kết dân tộc;" + @override + String get UG_LINE13 => "(2) gây nguy hiểm cho an ninh quốc gia, tiết lộ bí mật nhà nước, lật đổ quyền lực nhà nước và phá hoại đoàn kết dân tộc;"; + /// "(3) làm tổn hại danh dự và lợi ích quốc gia;" + @override + String get UG_LINE14 => "(3) làm tổn hại danh dự và lợi ích quốc gia;"; + /// "(4) Kích động hận thù dân tộc, phân biệt sắc tộc và phá hoại đoàn kết dân tộc;" + @override + String get UG_LINE15 => "(4) Kích động hận thù dân tộc, phân biệt sắc tộc và phá hoại đoàn kết dân tộc;"; + /// "(5) Phá hủy các chính sách tôn giáo của nhà nước và thúc đẩy các giáo phái và mê tín phong kiến;" + @override + String get UG_LINE16 => "(5) Phá hủy các chính sách tôn giáo của nhà nước và thúc đẩy các giáo phái và mê tín phong kiến;"; + /// "(6) Truyền bá tin đồn, phá vỡ trật tự xã hội và phá hoại sự ổn định xã hội;" + @override + String get UG_LINE17 => "(6) Truyền bá tin đồn, phá vỡ trật tự xã hội và phá hoại sự ổn định xã hội;"; + /// "(7) truyền bá những điều tục tĩu, khiêu dâm, đánh bạc, bạo lực, giết người, khủng bố hoặc xóa bỏ;" + @override + String get UG_LINE18 => "(7) truyền bá những điều tục tĩu, khiêu dâm, đánh bạc, bạo lực, giết người, khủng bố hoặc xóa bỏ;"; + /// "(8) xúc phạm hoặc vu khống người khác và xâm phạm quyền và lợi ích hợp pháp của người khác;" + @override + String get UG_LINE19 => "(8) xúc phạm hoặc vu khống người khác và xâm phạm quyền và lợi ích hợp pháp của người khác;"; + /// "(9) Thông tin chứa nội dung khác bị cấm theo luật pháp và các quy định hành chính." + @override + String get UG_LINE20 => "(9) Thông tin chứa nội dung khác bị cấm theo luật pháp và các quy định hành chính."; + /// "8、Cyhd TNHH thể, trong phán quyết hợp lý của nó, vi phạm pháp luật liên quan và các quy định hoặc thoả thuận này; hoặc vi phạm, kiến, mối đe dọa của bất kỳ quyền hoặc sự an toàn, hoặc mạo danh, Cyhd TNHH ngay để ngăn chặn bất kỳ luật giao thông nói trên Và có quyền, theo toàn quyền quyết định của mình, có hành động pháp lý phù hợp với bất kỳ người nào vi phạm các Điều khoản này, bao gồm nhưng không giới hạn trong việc loại bỏ bất hợp pháp, vi phạm, không đúng cách, v.v. khỏi Dịch vụ, chấm dứt tư cách thành viên của những người vi phạm và ngăn chặn họ khỏi Sử dụng tất cả hoặc một phần của dịch vụ, và giữ thông tin liên quan và báo cáo cho các bộ phận liên quan theo luật pháp và quy định." + @override + String get UG_LINE21 => "8、Cyhd TNHH thể, trong phán quyết hợp lý của nó, vi phạm pháp luật liên quan và các quy định hoặc thoả thuận này; hoặc vi phạm, kiến, mối đe dọa của bất kỳ quyền hoặc sự an toàn, hoặc mạo danh, Cyhd TNHH ngay để ngăn chặn bất kỳ luật giao thông nói trên Và có quyền, theo toàn quyền quyết định của mình, có hành động pháp lý phù hợp với bất kỳ người nào vi phạm các Điều khoản này, bao gồm nhưng không giới hạn trong việc loại bỏ bất hợp pháp, vi phạm, không đúng cách, v.v. khỏi Dịch vụ, chấm dứt tư cách thành viên của những người vi phạm và ngăn chặn họ khỏi Sử dụng tất cả hoặc một phần của dịch vụ, và giữ thông tin liên quan và báo cáo cho các bộ phận liên quan theo luật pháp và quy định."; + /// "9、Quyền và nghĩa vụ của người dùng: " + @override + String get UG_LINE22 => "9、Quyền và nghĩa vụ của người dùng: "; + /// "(1) Tài khoản Cyhd TNHH thuộc sở hữu của tất cả Qianhai Youlong Technology Co., Ltd., sau khi người dùng hoàn thành việc áp dụng cho các thủ tục đăng ký, để có được quyền sử dụng các tài khoản, được cấp giấy phép cho người nộp đơn ban đầu cho đăng ký bị cấm món quà, cho mượn, cho thuê, chuyển nhượng hoặc bán. Cyhd Giới hạn do nhu cầu hoạt động, chúng tôi có quyền thu hồi tài khoản người dùng và truy cập vào ảnh của người dùng, video, âm thanh và các hoạt động quảng bá sản phẩm khác." + @override + String get UG_LINE23 => "(1) Tài khoản Cyhd TNHH thuộc sở hữu của tất cả Qianhai Youlong Technology Co., Ltd., sau khi người dùng hoàn thành việc áp dụng cho các thủ tục đăng ký, để có được quyền sử dụng các tài khoản, được cấp giấy phép cho người nộp đơn ban đầu cho đăng ký bị cấm món quà, cho mượn, cho thuê, chuyển nhượng hoặc bán. Cyhd Giới hạn do nhu cầu hoạt động, chúng tôi có quyền thu hồi tài khoản người dùng và truy cập vào ảnh của người dùng, video, âm thanh và các hoạt động quảng bá sản phẩm khác."; + /// "(2) người dùng có quyền thay đổi, xóa trên Qianhai Youlong Technology Co., Ltd.. Dữ liệu cá nhân, thông tin đăng ký và nội dung chuyển nhượng, nhưng lưu ý rằng xóa thông tin cũng sẽ loại bỏ bất kỳ của bạn được lưu trữ trong hệ thống các văn bản và hình ảnh. Người dùng chịu trách nhiệm cho rủi ro này." + @override + String get UG_LINE24 => "(2) người dùng có quyền thay đổi, xóa trên Qianhai Youlong Technology Co., Ltd.. Dữ liệu cá nhân, thông tin đăng ký và nội dung chuyển nhượng, nhưng lưu ý rằng xóa thông tin cũng sẽ loại bỏ bất kỳ của bạn được lưu trữ trong hệ thống các văn bản và hình ảnh. Người dùng chịu trách nhiệm cho rủi ro này."; + /// "(3) Người dùng chịu trách nhiệm bảo mật thông tin tài khoản đã đăng ký và mật khẩu tài khoản. Người dùng chịu trách nhiệm về tài khoản đã đăng ký và hành vi theo mật khẩu. Người dùng đồng ý không sử dụng số tài khoản hoặc mật khẩu của thành viên khác trong mọi trường hợp. Bạn đồng ý thông báo cho Qianhai Youlong Technology Co., Ltd. ngay lập tức nếu bạn nghi ngờ rằng ai đó đang sử dụng tài khoản hoặc mật khẩu của bạn." + @override + String get UG_LINE25 => "(3) Người dùng chịu trách nhiệm bảo mật thông tin tài khoản đã đăng ký và mật khẩu tài khoản. Người dùng chịu trách nhiệm về tài khoản đã đăng ký và hành vi theo mật khẩu. Người dùng đồng ý không sử dụng số tài khoản hoặc mật khẩu của thành viên khác trong mọi trường hợp. Bạn đồng ý thông báo cho Qianhai Youlong Technology Co., Ltd. ngay lập tức nếu bạn nghi ngờ rằng ai đó đang sử dụng tài khoản hoặc mật khẩu của bạn."; + /// "(4) Người dùng phải tuân thủ các điều khoản của Thỏa thuận này và sử dụng Dịch vụ một cách chính xác và phù hợp. Nếu Người dùng vi phạm bất kỳ điều khoản nào của Thỏa thuận này, Qianhai Youlong Technology Co., Ltd. có quyền chấm dứt dịch vụ của tài khoản Qianhai Youlong Technology Co., Ltd. của người dùng mặc định theo Thỏa thuận. Đồng thời, Qianhai Youlong Technology Co., Ltd. có quyền rút số tài khoản và tên người dùng Qianhai Youlong Technology Co., Ltd. bất cứ lúc nào." + @override + String get UG_LINE26 => "(4) Người dùng phải tuân thủ các điều khoản của Thỏa thuận này và sử dụng Dịch vụ một cách chính xác và phù hợp. Nếu Người dùng vi phạm bất kỳ điều khoản nào của Thỏa thuận này, Qianhai Youlong Technology Co., Ltd. có quyền chấm dứt dịch vụ của tài khoản Qianhai Youlong Technology Co., Ltd. của người dùng mặc định theo Thỏa thuận. Đồng thời, Qianhai Youlong Technology Co., Ltd. có quyền rút số tài khoản và tên người dùng Qianhai Youlong Technology Co., Ltd. bất cứ lúc nào."; + /// "(5) Nếu người dùng có tài khoản tiếng Anh thông thường của mình, người dùng có quyền đăng ký tài khoản tiếng Anh trước tiên, nhưng nếu người dùng không đăng ký tài khoản sau khi dịch vụ trực tuyến hoặc người dùng đã đăng ký tài khoản WeChat, nhưng Nếu tài khoản tiếng Anh không được sử dụng làm tài khoản WeChat, người dùng được coi là đã từ bỏ quyền đăng ký tài khoản tiếng Anh dưới dạng tài khoản WeChat. Qianhai Youlong Technology Co., Ltd. có quyền tái chế và phân phối tài khoản tiếng Anh cho người dùng khác, để tránh lãng phí tài nguyên. Vấn đề là trách nhiệm của người dùng." + @override + String get UG_LINE27 => "(5) Nếu người dùng có tài khoản tiếng Anh thông thường của mình, người dùng có quyền đăng ký tài khoản tiếng Anh trước tiên, nhưng nếu người dùng không đăng ký tài khoản sau khi dịch vụ trực tuyến hoặc người dùng đã đăng ký tài khoản WeChat, nhưng Nếu tài khoản tiếng Anh không được sử dụng làm tài khoản WeChat, người dùng được coi là đã từ bỏ quyền đăng ký tài khoản tiếng Anh dưới dạng tài khoản WeChat. Qianhai Youlong Technology Co., Ltd. có quyền tái chế và phân phối tài khoản tiếng Anh cho người dùng khác, để tránh lãng phí tài nguyên. Vấn đề là trách nhiệm của người dùng."; + /// "(6) Nếu người dùng không đăng nhập vào tài khoản sau khi đăng ký tài khoản trong một thời gian dài, Qianhai Youlong Technology Co., Ltd. có quyền tái chế tài khoản, để tránh lãng phí tài nguyên và các sự cố do người dùng gây ra." + @override + String get UG_LINE28 => "(6) Nếu người dùng không đăng nhập vào tài khoản sau khi đăng ký tài khoản trong một thời gian dài, Qianhai Youlong Technology Co., Ltd. có quyền tái chế tài khoản, để tránh lãng phí tài nguyên và các sự cố do người dùng gây ra."; + /// "(7) người dùng có thể sử dụng tính năng suy giảm tranh chấp duy trì sự quan tâm sử dụng trong nền tảng này, nếu các báo cáo sử dụng thông tin phản hồi nhận được, chủ động thông báo cho người sử dụng có nghĩa vụ báo cáo hoặc xác minh tình hình với các nhân viên dịch vụ khách hàng để báo cáo để xác minh các nội dung là đúng sự thật, mặt nạ đậu quyền những lời cảnh báo người sử dụng, hạn chế chức năng tài khoản và vi phạm hạn chế chế độ người dùng khác, người phạm tội nghiêm trọng Hibok hưởng trực tiếp đóng băng tài khoản, và số dư trong tài khoản sẽ không được trả lại. Nếu tài khoản bị đóng băng và cần được kháng cáo, người dùng có thể liên hệ với dịch vụ khách hàng." + @override + String get UG_LINE29 => "(7) người dùng có thể sử dụng tính năng suy giảm tranh chấp duy trì sự quan tâm sử dụng trong nền tảng này, nếu các báo cáo sử dụng thông tin phản hồi nhận được, chủ động thông báo cho người sử dụng có nghĩa vụ báo cáo hoặc xác minh tình hình với các nhân viên dịch vụ khách hàng để báo cáo để xác minh các nội dung là đúng sự thật, mặt nạ đậu quyền những lời cảnh báo người sử dụng, hạn chế chức năng tài khoản và vi phạm hạn chế chế độ người dùng khác, người phạm tội nghiêm trọng Hibok hưởng trực tiếp đóng băng tài khoản, và số dư trong tài khoản sẽ không được trả lại. Nếu tài khoản bị đóng băng và cần được kháng cáo, người dùng có thể liên hệ với dịch vụ khách hàng."; + /// "Thứ hai, bảo vệ quyền riêng tư" + @override + String get UG_LINE30 => "Thứ hai, bảo vệ quyền riêng tư"; + /// "Người dùng đồng ý rằng thông tin bảo mật cá nhân đề cập đến những thông tin có thể nhận dạng cá nhân người dùng hoặc liên quan đến giao tiếp cá nhân, bao gồm các thông tin sau: tên thật, số điện thoại di động, tài khoản WeChat, tài khoản facebook và địa chỉ IP. Thông tin riêng tư phi cá nhân đề cập đến thông tin chung mà người dùng phản ánh rõ ràng và khách quan thông tin hồ sơ cơ bản của máy chủ Qianhai Youlong Technology Co., Ltd. và tất cả thông tin bảo mật cá nhân khác và thông tin cá nhân nêu trên mà người dùng đồng ý tiết lộ. . Tôn trọng quyền riêng tư của thông tin cá nhân của người dùng là một hệ thống nhất quán của Qianhai Youlong Technology Co., Ltd.. Qianhai Youlong Technology Co., Ltd. sẽ thực hiện các bước hợp lý để bảo vệ thông tin cá nhân của người dùng. Qianhai Youlong Technology Co., Ltd., ngoài các yêu cầu pháp lý hoặc pháp lý hoặc sự đồng ý của chính phủ. Thông tin riêng tư cá nhân của người dùng sẽ không được tiết lộ hoặc tiết lộ cho các bên thứ ba ngoài đơn vị đối tác mà không có sự đồng ý của người dùng. Tuy nhiên, người dùng chọn đồng ý tại thời điểm đăng ký hoặc người dùng và Qianhai Youlong Technology Co., Ltd. và đơn vị hợp tác đã đồng ý khác về việc tiết lộ hoặc sử dụng thông tin cá nhân của người dùng và người dùng sẽ chịu mọi rủi ro có thể phát sinh, Qianhai Youlong Technology Co., Ltd. không Có trách nhiệm. Đồng thời, để vận hành và cải thiện công nghệ và dịch vụ của Qianhai Youlong Technology Co., Ltd., Qianhai Youlong Technology Co., Ltd. có thể thu thập hoặc cung cấp thông tin cá nhân cho người dùng của bên thứ ba, giúp Qianhai Youlong Technology Co., Ltd. cung cấp cho người dùng trải nghiệm người dùng tốt hơn và cải thiện Chất lượng dịch vụ của Qianhai Youlong Technology Co., Ltd.. Qianhai Youlong Technology Co., Ltd. thu thập dữ liệu dựa trên tương tác của người dùng với Qianhai Youlong Technology Co., Ltd. và các lựa chọn của người dùng, bao gồm các cài đặt quyền riêng tư của người dùng và các sản phẩm và tính năng được người dùng sử dụng. Dữ liệu do Qianhai Youlong Technology Co., Ltd. thu thập có thể bao gồm phiên bản mã SDK / API / JS, địa chỉ IP, nền tảng, dấu thời gian, số nhận dạng ứng dụng, phiên bản ứng dụng, kênh phân phối ứng dụng, số nhận dạng thiết bị độc lập, số nhận dạng quảng cáo iOS (IDFA), quảng cáo Android Số nhận dạng chính, địa chỉ card mạng (MAC), Nhận dạng thiết bị di động quốc tế (IMEI), kiểu thiết bị, nhà sản xuất thiết bị đầu cuối, phiên bản hệ điều hành thiết bị đầu cuối, thời gian bắt đầu / dừng phiên, vị trí ngôn ngữ, múi giờ và trạng thái mạng (WiFi, v.v.) Sử dụng đĩa cứng, CPU và pin, v.v. Điều này sẽ cho phép Qianhai Youlong Technology Co., Ltd. tiến hành phân tích và nghiên cứu dữ liệu nội bộ, dịch vụ thống kê SDK của bên thứ ba và cải thiện các sản phẩm hoặc dịch vụ của Qianhai Youlong Technology Co., Ltd.. Để đảm bảo tính xác thực của danh tính người dùng, để cung cấp bảo mật tốt hơn với các thông tin nhận dạng người dùng, hoặc đặc điểm khuôn mặt như thông tin người dùng sinh trắc học phải nộp (cả hai thuộc về thông tin cá nhân nhạy cảm) để hoàn thành các sản phẩm cụ thể yêu cầu hoặc dịch vụ cần thiết để sống chứng nhận. Thông tin trên sẽ chỉ được sử dụng để xác minh tính xác thực của danh tính người dùng. Thông tin trên do người dùng cung cấp sẽ tiếp tục được Qianhai Youlong Technology Co., Ltd. ủy quyền trong quá trình sử dụng Dịch vụ của người dùng. Qianhai Youlong Technology Co., Ltd. sẽ ngừng sử dụng nó khi người dùng đăng xuất khỏi tài khoản. Các thông tin trên sẽ được lưu trữ tại Cộng hòa Nhân dân Trung Hoa. Đối với truyền dẫn xuyên biên giới, Qianhai Youlong Technology Co., Ltd. sẽ có được sự cho phép của người dùng. Xác thực tính xác thực của người dùng ứng dụng yêu cầu người dùng cung cấp một số thông tin có thể xác minh tính xác thực của danh tính người dùng. Thông tin liên quan chỉ được sử dụng để đánh giá nền tảng và sẽ không được tiết lộ cho bất kỳ người dùng nào khác hoặc cho mục đích thương mại, ngoại trừ các bộ phận pháp lý hoặc liên quan yêu cầu can thiệp." + @override + String get UG_LINE31 => "Người dùng đồng ý rằng thông tin bảo mật cá nhân đề cập đến những thông tin có thể nhận dạng cá nhân người dùng hoặc liên quan đến giao tiếp cá nhân, bao gồm các thông tin sau: tên thật, số điện thoại di động, tài khoản WeChat, tài khoản facebook và địa chỉ IP. Thông tin riêng tư phi cá nhân đề cập đến thông tin chung mà người dùng phản ánh rõ ràng và khách quan thông tin hồ sơ cơ bản của máy chủ Qianhai Youlong Technology Co., Ltd. và tất cả thông tin bảo mật cá nhân khác và thông tin cá nhân nêu trên mà người dùng đồng ý tiết lộ. . Tôn trọng quyền riêng tư của thông tin cá nhân của người dùng là một hệ thống nhất quán của Qianhai Youlong Technology Co., Ltd.. Qianhai Youlong Technology Co., Ltd. sẽ thực hiện các bước hợp lý để bảo vệ thông tin cá nhân của người dùng. Qianhai Youlong Technology Co., Ltd., ngoài các yêu cầu pháp lý hoặc pháp lý hoặc sự đồng ý của chính phủ. Thông tin riêng tư cá nhân của người dùng sẽ không được tiết lộ hoặc tiết lộ cho các bên thứ ba ngoài đơn vị đối tác mà không có sự đồng ý của người dùng. Tuy nhiên, người dùng chọn đồng ý tại thời điểm đăng ký hoặc người dùng và Qianhai Youlong Technology Co., Ltd. và đơn vị hợp tác đã đồng ý khác về việc tiết lộ hoặc sử dụng thông tin cá nhân của người dùng và người dùng sẽ chịu mọi rủi ro có thể phát sinh, Qianhai Youlong Technology Co., Ltd. không Có trách nhiệm. Đồng thời, để vận hành và cải thiện công nghệ và dịch vụ của Qianhai Youlong Technology Co., Ltd., Qianhai Youlong Technology Co., Ltd. có thể thu thập hoặc cung cấp thông tin cá nhân cho người dùng của bên thứ ba, giúp Qianhai Youlong Technology Co., Ltd. cung cấp cho người dùng trải nghiệm người dùng tốt hơn và cải thiện Chất lượng dịch vụ của Qianhai Youlong Technology Co., Ltd.. Qianhai Youlong Technology Co., Ltd. thu thập dữ liệu dựa trên tương tác của người dùng với Qianhai Youlong Technology Co., Ltd. và các lựa chọn của người dùng, bao gồm các cài đặt quyền riêng tư của người dùng và các sản phẩm và tính năng được người dùng sử dụng. Dữ liệu do Qianhai Youlong Technology Co., Ltd. thu thập có thể bao gồm phiên bản mã SDK / API / JS, địa chỉ IP, nền tảng, dấu thời gian, số nhận dạng ứng dụng, phiên bản ứng dụng, kênh phân phối ứng dụng, số nhận dạng thiết bị độc lập, số nhận dạng quảng cáo iOS (IDFA), quảng cáo Android Số nhận dạng chính, địa chỉ card mạng (MAC), Nhận dạng thiết bị di động quốc tế (IMEI), kiểu thiết bị, nhà sản xuất thiết bị đầu cuối, phiên bản hệ điều hành thiết bị đầu cuối, thời gian bắt đầu / dừng phiên, vị trí ngôn ngữ, múi giờ và trạng thái mạng (WiFi, v.v.) Sử dụng đĩa cứng, CPU và pin, v.v. Điều này sẽ cho phép Qianhai Youlong Technology Co., Ltd. tiến hành phân tích và nghiên cứu dữ liệu nội bộ, dịch vụ thống kê SDK của bên thứ ba và cải thiện các sản phẩm hoặc dịch vụ của Qianhai Youlong Technology Co., Ltd.. Để đảm bảo tính xác thực của danh tính người dùng, để cung cấp bảo mật tốt hơn với các thông tin nhận dạng người dùng, hoặc đặc điểm khuôn mặt như thông tin người dùng sinh trắc học phải nộp (cả hai thuộc về thông tin cá nhân nhạy cảm) để hoàn thành các sản phẩm cụ thể yêu cầu hoặc dịch vụ cần thiết để sống chứng nhận. Thông tin trên sẽ chỉ được sử dụng để xác minh tính xác thực của danh tính người dùng. Thông tin trên do người dùng cung cấp sẽ tiếp tục được Qianhai Youlong Technology Co., Ltd. ủy quyền trong quá trình sử dụng Dịch vụ của người dùng. Qianhai Youlong Technology Co., Ltd. sẽ ngừng sử dụng nó khi người dùng đăng xuất khỏi tài khoản. Các thông tin trên sẽ được lưu trữ tại Cộng hòa Nhân dân Trung Hoa. Đối với truyền dẫn xuyên biên giới, Qianhai Youlong Technology Co., Ltd. sẽ có được sự cho phép của người dùng. Xác thực tính xác thực của người dùng ứng dụng yêu cầu người dùng cung cấp một số thông tin có thể xác minh tính xác thực của danh tính người dùng. Thông tin liên quan chỉ được sử dụng để đánh giá nền tảng và sẽ không được tiết lộ cho bất kỳ người dùng nào khác hoặc cho mục đích thương mại, ngoại trừ các bộ phận pháp lý hoặc liên quan yêu cầu can thiệp."; + /// "Thông tin nhãn hiệu của Qianhai Youlong Technology Co., Ltd. Logo" + @override + String get UG_LINE32 => "Thông tin nhãn hiệu của Qianhai Youlong Technology Co., Ltd. Logo"; + /// "Ký tự hoặc các thành phần của chúng và các logo và sản phẩm và tên dịch vụ khác của Qianhai Youlong Technology Co., Ltd. có liên quan đến các dịch vụ của Qianhai Youlong Technology Co., Ltd. là các nhãn hiệu của Qianhai Youlong Technology Co., Ltd. (sau đây gọi là Logo Qianhai Youlong Technology Co., Ltd. Logo). Logo Qianhai Youlong Technology Co., Ltd. có thể không được hiển thị hoặc sử dụng hoặc xử lý theo bất kỳ cách nào nếu không có sự đồng ý trước bằng văn bản của Qianhai Youlong Technology Co., Ltd. và không được cho người khác biết rằng bạn có quyền hiển thị, sử dụng hoặc được ủy quyền để xử lý logo Qianhai Youlong Technology Co., Ltd.." + @override + String get UG_LINE33 => "Ký tự hoặc các thành phần của chúng và các logo và sản phẩm và tên dịch vụ khác của Qianhai Youlong Technology Co., Ltd. có liên quan đến các dịch vụ của Qianhai Youlong Technology Co., Ltd. là các nhãn hiệu của Qianhai Youlong Technology Co., Ltd. (sau đây gọi là Logo Qianhai Youlong Technology Co., Ltd. Logo). Logo Qianhai Youlong Technology Co., Ltd. có thể không được hiển thị hoặc sử dụng hoặc xử lý theo bất kỳ cách nào nếu không có sự đồng ý trước bằng văn bản của Qianhai Youlong Technology Co., Ltd. và không được cho người khác biết rằng bạn có quyền hiển thị, sử dụng hoặc được ủy quyền để xử lý logo Qianhai Youlong Technology Co., Ltd.."; + /// "Thứ tư, trách nhiệm pháp lý và miễn trừ" + @override + String get UG_LINE34 => "Thứ tư, trách nhiệm pháp lý và miễn trừ"; + /// "1. Người dùng vi phạm các quy định của Thỏa thuận này hoặc các điều khoản dịch vụ có liên quan, dẫn đến hoặc phát sinh từ bất kỳ khiếu nại, khiếu nại hoặc tổn thất nào được yêu cầu bởi bất kỳ bên thứ ba nào, bao gồm phí luật sư hợp lý và người dùng đồng ý bồi thường cho Qianhai Youlong Technology Co., Ltd. và công ty đối tác, các chi nhánh, Và bảo vệ nó khỏi thiệt hại." + @override + String get UG_LINE35 => "1. Người dùng vi phạm các quy định của Thỏa thuận này hoặc các điều khoản dịch vụ có liên quan, dẫn đến hoặc phát sinh từ bất kỳ khiếu nại, khiếu nại hoặc tổn thất nào được yêu cầu bởi bất kỳ bên thứ ba nào, bao gồm phí luật sư hợp lý và người dùng đồng ý bồi thường cho Qianhai Youlong Technology Co., Ltd. và công ty đối tác, các chi nhánh, Và bảo vệ nó khỏi thiệt hại."; + /// "2. Qianhai Youlong Technology Co., Ltd. và các đối tác không chịu trách nhiệm cho bất kỳ tổn thất nào của người dùng do lỗi đường truyền, sự cố kỹ thuật, mạng, lỗi máy tính, mất ổn định hệ thống và các nguyên nhân bất khả kháng khác của các bên thứ ba như bộ phận viễn thông." + @override + String get UG_LINE36 => "2. Qianhai Youlong Technology Co., Ltd. và các đối tác không chịu trách nhiệm cho bất kỳ tổn thất nào của người dùng do lỗi đường truyền, sự cố kỹ thuật, mạng, lỗi máy tính, mất ổn định hệ thống và các nguyên nhân bất khả kháng khác của các bên thứ ba như bộ phận viễn thông."; + /// "3, do sự kiện thất bại bất khả kháng kỹ thuật ảnh hưởng đến hoạt động bình thường của dịch vụ, Qianhai Youlong Technology Co., Ltd. và cam kết đối tác với các đơn vị có liên quan trong lần đầu tiên với việc xử lý kịp thời sửa chữa, nhưng tất cả các tổn thất của người sử dụng và do đó, Qianhai Youlong Technology Co., Ltd. và Đơn vị đối tác không chịu trách nhiệm." + @override + String get UG_LINE37 => "3, do sự kiện thất bại bất khả kháng kỹ thuật ảnh hưởng đến hoạt động bình thường của dịch vụ, Qianhai Youlong Technology Co., Ltd. và cam kết đối tác với các đơn vị có liên quan trong lần đầu tiên với việc xử lý kịp thời sửa chữa, nhưng tất cả các tổn thất của người sử dụng và do đó, Qianhai Youlong Technology Co., Ltd. và Đơn vị đối tác không chịu trách nhiệm."; + /// "4, các dịch vụ tương tự như hầu hết các dịch vụ Internet, tùy thuộc vào các yếu tố bao gồm, nhưng không giới hạn người sử dụng lý trí, chất lượng dịch vụ mạng, xã hội và sự khác biệt về môi trường chưa bị nhiễm khuẩn với một loạt các vấn đề an ninh, chẳng hạn như những người khác sử dụng dữ liệu của người dùng, dẫn đến trong cuộc sống thực Quấy rối, phần mềm khác được tải xuống hoặc cài đặt bởi người dùng hoặc các trang web khác được truy cập có chứa \"Trojan Horse\" và các vi-rút khác, đe dọa đến tính bảo mật của thông tin và dữ liệu máy tính của người dùng, do đó ảnh hưởng đến việc sử dụng dịch vụ thông thường. Người dùng nên tăng cường bảo mật thông tin và nhận thức bảo vệ thông tin người dùng và chú ý tăng cường bảo vệ mật khẩu để tránh mất mát và quấy rối." + @override + String get UG_LINE38 => "4, các dịch vụ tương tự như hầu hết các dịch vụ Internet, tùy thuộc vào các yếu tố bao gồm, nhưng không giới hạn người sử dụng lý trí, chất lượng dịch vụ mạng, xã hội và sự khác biệt về môi trường chưa bị nhiễm khuẩn với một loạt các vấn đề an ninh, chẳng hạn như những người khác sử dụng dữ liệu của người dùng, dẫn đến trong cuộc sống thực Quấy rối, phần mềm khác được tải xuống hoặc cài đặt bởi người dùng hoặc các trang web khác được truy cập có chứa \"Trojan Horse\" và các vi-rút khác, đe dọa đến tính bảo mật của thông tin và dữ liệu máy tính của người dùng, do đó ảnh hưởng đến việc sử dụng dịch vụ thông thường. Người dùng nên tăng cường bảo mật thông tin và nhận thức bảo vệ thông tin người dùng và chú ý tăng cường bảo vệ mật khẩu để tránh mất mát và quấy rối."; + /// "5. Người dùng phải hiểu rằng việc sử dụng dịch vụ này có thể bị ảnh hưởng bởi các yếu tố không ổn định trong các liên kết khác nhau do các dịch vụ Internet. Do đó, dịch vụ có nguy cơ bị gián đoạn dịch vụ hoặc không đáp ứng yêu cầu của người dùng do bất khả kháng, virus máy tính hoặc tin tặc tấn công, mất ổn định hệ thống, vị trí người dùng, tắt máy và bất kỳ lý do công nghệ, internet, đường truyền thông nào khác. Người dùng chịu trách nhiệm cho các rủi ro trên và Qianhai Youlong Technology Co., Ltd. không đảm bảo. Qianhai Youlong Technology Co., Ltd. không chịu trách nhiệm cho việc người dùng không thể gửi và nhận thông tin đọc hoặc nhận thông tin không chính xác." + @override + String get UG_LINE39 => "5. Người dùng phải hiểu rằng việc sử dụng dịch vụ này có thể bị ảnh hưởng bởi các yếu tố không ổn định trong các liên kết khác nhau do các dịch vụ Internet. Do đó, dịch vụ có nguy cơ bị gián đoạn dịch vụ hoặc không đáp ứng yêu cầu của người dùng do bất khả kháng, virus máy tính hoặc tin tặc tấn công, mất ổn định hệ thống, vị trí người dùng, tắt máy và bất kỳ lý do công nghệ, internet, đường truyền thông nào khác. Người dùng chịu trách nhiệm cho các rủi ro trên và Qianhai Youlong Technology Co., Ltd. không đảm bảo. Qianhai Youlong Technology Co., Ltd. không chịu trách nhiệm cho việc người dùng không thể gửi và nhận thông tin đọc hoặc nhận thông tin không chính xác."; + /// "6, người dùng phải hiểu, có sử dụng quy trình dịch vụ này, trong đó có nội dung đe dọa, phỉ báng, xúc phạm hoặc bất hợp pháp hay hành vi của bất kỳ người nào khác, hoặc vi phạm quyền của người khác (kể cả sở hữu trí tuệ) của Qianhai Youlong Technology Co., Ltd. và công ty đối tác không thực hiện bất kỳ loại bảo đảm nào cho dịch vụ, dù rõ ràng hay ngụ ý, bao gồm tất cả tính xác thực thông tin liên quan, tính thương mại, phù hợp với một số nhất định Việc sử dụng cụ thể, tiêu đề và không vi phạm các bảo đảm và điều kiện ngụ ý sẽ không chịu trách nhiệm cho bất kỳ thiệt hại trực tiếp, gián tiếp, ngẫu nhiên, đặc biệt hoặc hậu quả nào từ việc sử dụng Dịch vụ không đúng hoặc bất hợp pháp của Người dùng." + @override + String get UG_LINE40 => "6, người dùng phải hiểu, có sử dụng quy trình dịch vụ này, trong đó có nội dung đe dọa, phỉ báng, xúc phạm hoặc bất hợp pháp hay hành vi của bất kỳ người nào khác, hoặc vi phạm quyền của người khác (kể cả sở hữu trí tuệ) của Qianhai Youlong Technology Co., Ltd. và công ty đối tác không thực hiện bất kỳ loại bảo đảm nào cho dịch vụ, dù rõ ràng hay ngụ ý, bao gồm tất cả tính xác thực thông tin liên quan, tính thương mại, phù hợp với một số nhất định Việc sử dụng cụ thể, tiêu đề và không vi phạm các bảo đảm và điều kiện ngụ ý sẽ không chịu trách nhiệm cho bất kỳ thiệt hại trực tiếp, gián tiếp, ngẫu nhiên, đặc biệt hoặc hậu quả nào từ việc sử dụng Dịch vụ không đúng hoặc bất hợp pháp của Người dùng."; + /// "7.Nội dung thông tin được xác định bởi Qianhai Youlong Technology Co., Ltd. bao gồm: văn bản, phần mềm, âm thanh, hình ảnh, video, đồ họa, tất cả nội dung trong quảng cáo, thông tin thương mại do Qianhai Youlong Technology Co., Ltd. cung cấp cho người dùng, tất cả đều thuộc bản quyền, nhãn hiệu và các quyền sở hữu trí tuệ khác. Và việc bảo vệ luật sở hữu. Do đó, người dùng chỉ có thể được sử dụng theo Qianhai Youlong Technology Co., Ltd. và các nhà quảng cáo có thẩm quyền của nội dung, nhưng không sao chép trái phép, sửa đổi, biên soạn này. Những nội dung, hoặc tạo ra các sản phẩm phái sinh nội dung liên quan đến." + @override + String get UG_LINE41 => "7.Nội dung thông tin được xác định bởi Qianhai Youlong Technology Co., Ltd. bao gồm: văn bản, phần mềm, âm thanh, hình ảnh, video, đồ họa, tất cả nội dung trong quảng cáo, thông tin thương mại do Qianhai Youlong Technology Co., Ltd. cung cấp cho người dùng, tất cả đều thuộc bản quyền, nhãn hiệu và các quyền sở hữu trí tuệ khác. Và việc bảo vệ luật sở hữu. Do đó, người dùng chỉ có thể được sử dụng theo Qianhai Youlong Technology Co., Ltd. và các nhà quảng cáo có thẩm quyền của nội dung, nhưng không sao chép trái phép, sửa đổi, biên soạn này. Những nội dung, hoặc tạo ra các sản phẩm phái sinh nội dung liên quan đến."; + /// "8.trong mọi trường hợp, Cyhd TNHH chịu trách nhiệm về bất kỳ thiệt hại gián tiếp, gián tiếp, trừng phạt, ngẫu nhiên, đặc biệt hoặc trừng phạt, bao gồm cả lợi nhuận bị mất phải chịu đựng bởi người dùng sử dụng dịch vụ, trách nhiệm (ngay cả khi thông báo về Khả năng mất mát cũng vậy). Mặc dù thỏa thuận này có thể có điều khoản trái, Cyhd TNHH hoàn toàn trách nhiệm đối với cam kết của bạn, vì bất cứ lý do nào, hoặc những loại hành vi, không bao giờ vượt quá việc bạn sử dụng phí dịch vụ thanh toán cho các thành viên TNHH Cyhd trong giai đoạn này." + @override + String get UG_LINE42 => "8.trong mọi trường hợp, Cyhd TNHH chịu trách nhiệm về bất kỳ thiệt hại gián tiếp, gián tiếp, trừng phạt, ngẫu nhiên, đặc biệt hoặc trừng phạt, bao gồm cả lợi nhuận bị mất phải chịu đựng bởi người dùng sử dụng dịch vụ, trách nhiệm (ngay cả khi thông báo về Khả năng mất mát cũng vậy). Mặc dù thỏa thuận này có thể có điều khoản trái, Cyhd TNHH hoàn toàn trách nhiệm đối với cam kết của bạn, vì bất cứ lý do nào, hoặc những loại hành vi, không bao giờ vượt quá việc bạn sử dụng phí dịch vụ thanh toán cho các thành viên TNHH Cyhd trong giai đoạn này."; + /// "Năm, điều khoản thành viên" + @override + String get UG_LINE43 => "Năm, điều khoản thành viên"; + /// "1. thành viên Hibok có quyền bình đẳng với các thành viên và sẽ tuân thủ các thông số và quy tắc của Qianhai Youlong Technology Co., Ltd., bao gồm nhưng không giới hạn trong các Điều khoản dịch vụ này và Thỏa thuận người dùng." + @override + String get UG_LINE44 => "1. thành viên Hibok có quyền bình đẳng với các thành viên và sẽ tuân thủ các thông số và quy tắc của Qianhai Youlong Technology Co., Ltd., bao gồm nhưng không giới hạn trong các Điều khoản dịch vụ này và Thỏa thuận người dùng."; + /// "2. Mất mát liên quan đến việc đình chỉ dịch vụ thành viên do vi phạm Thỏa thuận người dùng Qianhai Youlong Technology Co., Ltd. sẽ do người dùng chịu." + @override + String get UG_LINE45 => "2. Mất mát liên quan đến việc đình chỉ dịch vụ thành viên do vi phạm Thỏa thuận người dùng Qianhai Youlong Technology Co., Ltd. sẽ do người dùng chịu."; + /// "3. Thành viên có thể tận hưởng các dịch vụ giá trị gia tăng của các thành viên Hibok trong thời gian thành viên." + @override + String get UG_LINE46 => "3. Thành viên có thể tận hưởng các dịch vụ giá trị gia tăng của các thành viên Hibok trong thời gian thành viên."; + /// "4. Nếu thành viên chủ động chấm dứt hoặc hủy bỏ tư cách thành viên trong thời gian hiệu lực của thành viên, Qianhai Youlong Technology Co., Ltd. không chịu trách nhiệm hoàn trả phí dịch vụ tương ứng với thời hạn hiệu lực của thành viên còn lại của thành viên." + @override + String get UG_LINE47 => "4. Nếu thành viên chủ động chấm dứt hoặc hủy bỏ tư cách thành viên trong thời gian hiệu lực của thành viên, Qianhai Youlong Technology Co., Ltd. không chịu trách nhiệm hoàn trả phí dịch vụ tương ứng với thời hạn hiệu lực của thành viên còn lại của thành viên."; + /// "5, các thành viên truyền sinh trong Hibok, việc phát hành các thông tin và sử dụng các dịch vụ miễn phí trách nhiệm pháp lý Hibok hoặc trả thành viên dịch vụ để sử dụng dịch vụ Hibok, bao gồm các dịch vụ miễn phí và trả hành động dịch vụ, thực hiện theo tất cả các luật, quy định, quy chuẩn Tập tin." + @override + String get UG_LINE48 => "5, các thành viên truyền sinh trong Hibok, việc phát hành các thông tin và sử dụng các dịch vụ miễn phí trách nhiệm pháp lý Hibok hoặc trả thành viên dịch vụ để sử dụng dịch vụ Hibok, bao gồm các dịch vụ miễn phí và trả hành động dịch vụ, thực hiện theo tất cả các luật, quy định, quy chuẩn Tập tin."; + /// "6. Sau khi dịch vụ thành viên được mở, nó không thể được chuyển nhượng hoặc hủy đăng ký." + @override + String get UG_LINE49 => "6. Sau khi dịch vụ thành viên được mở, nó không thể được chuyển nhượng hoặc hủy đăng ký."; + /// "7, do các thành viên trong việc sử dụng Cyhd TNHH dịch vụ miễn phí, dịch vụ thanh toán, có những hành vi vi phạm pháp luật và các quy định, Cyhd TNHH có quyền hủy bỏ thành viên của thành viên mà không đưa ra bất kỳ bồi thường, và các thành viên phải chịu trách nhiệm hoàn toàn." + @override + String get UG_LINE50 => "7, do các thành viên trong việc sử dụng Cyhd TNHH dịch vụ miễn phí, dịch vụ thanh toán, có những hành vi vi phạm pháp luật và các quy định, Cyhd TNHH có quyền hủy bỏ thành viên của thành viên mà không đưa ra bất kỳ bồi thường, và các thành viên phải chịu trách nhiệm hoàn toàn."; + /// "Sáu điều khoản khác" + @override + String get UG_LINE51 => "Sáu điều khoản khác"; + /// "1. Qianhai Youlong Technology Co., Ltd. nhắc nhở người dùng chú ý đến các điều khoản của Thỏa thuận miễn trừ trách nhiệm pháp lý của Qianhai Youlong Technology Co., Ltd. và làm nặng thêm nghĩa vụ của người dùng. Vui lòng đọc kỹ và xem xét rủi ro. Người chưa thành niên nên đọc Thỏa thuận này kèm theo người giám hộ hợp pháp. Việc giải thích và sửa đổi cuối cùng các điều khoản và điều kiện trên thuộc sở hữu của Qianhai Youlong Technology Co., Ltd.." + @override + String get UG_LINE52 => "1. Qianhai Youlong Technology Co., Ltd. nhắc nhở người dùng chú ý đến các điều khoản của Thỏa thuận miễn trừ trách nhiệm pháp lý của Qianhai Youlong Technology Co., Ltd. và làm nặng thêm nghĩa vụ của người dùng. Vui lòng đọc kỹ và xem xét rủi ro. Người chưa thành niên nên đọc Thỏa thuận này kèm theo người giám hộ hợp pháp. Việc giải thích và sửa đổi cuối cùng các điều khoản và điều kiện trên thuộc sở hữu của Qianhai Youlong Technology Co., Ltd.."; + /// "2. Sự vô hiệu của một số hoặc tất cả các điều khoản được quy định trong Thỏa thuận này sẽ không ảnh hưởng đến hiệu lực của các điều khoản khác." + @override + String get UG_LINE53 => "2. Sự vô hiệu của một số hoặc tất cả các điều khoản được quy định trong Thỏa thuận này sẽ không ảnh hưởng đến hiệu lực của các điều khoản khác."; + /// "3. Việc giải thích, hiệu lực và giải quyết tranh chấp trong Thỏa thuận này sẽ được áp dụng cho luật pháp của Cộng hòa Nhân dân Trung Hoa. Nếu bất kỳ tranh chấp hay tranh cãi giữa người dùng và Qianhai Youlong Technology Co., Ltd., trước hết phải được giải quyết thông qua hiệp thương hữu nghị, tư vấn thất bại, người sử dụng trong này hoàn toàn đồng ý đưa tranh chấp hoặc cãi Cyhd TNHH nơi cư trú có trách nhiệm thẩm quyền." + @override + String get UG_LINE54 => "3. Việc giải thích, hiệu lực và giải quyết tranh chấp trong Thỏa thuận này sẽ được áp dụng cho luật pháp của Cộng hòa Nhân dân Trung Hoa. Nếu bất kỳ tranh chấp hay tranh cãi giữa người dùng và Qianhai Youlong Technology Co., Ltd., trước hết phải được giải quyết thông qua hiệp thương hữu nghị, tư vấn thất bại, người sử dụng trong này hoàn toàn đồng ý đưa tranh chấp hoặc cãi Cyhd TNHH nơi cư trú có trách nhiệm thẩm quyền."; + /// "4. Bản quyền của Thỏa thuận này thuộc sở hữu của Qianhai Youlong Technology Co., Ltd. và Qianhai Youlong Technology Co., Ltd. bảo lưu mọi quyền để giải thích và sửa đổi." + @override + String get UG_LINE55 => "4. Bản quyền của Thỏa thuận này thuộc sở hữu của Qianhai Youlong Technology Co., Ltd. và Qianhai Youlong Technology Co., Ltd. bảo lưu mọi quyền để giải thích và sửa đổi."; + /// "Qianhai Youlong Technology Co., Ltd." + @override + String get UG_LINE56 => "Qianhai Youlong Technology Co., Ltd."; + /// "Mạng bất thường" + @override + String get net_error => "Mạng bất thường"; + /// "Vui lòng nhập tên" + @override + String get enter_name => "Vui lòng nhập tên"; + /// "Dịch" + @override + String get translate => "Dịch"; + /// "Vị trí" + @override + String get locate => "Vị trí"; + /// "Giữ để nói, buông ra để gửi" + @override + String get voice_tips => "Giữ để nói, buông ra để gửi"; + /// "Mở khóa" + @override + String get unlock => "Mở khóa"; + /// "Nhập nội dung" + @override + String get input_content => "Nhập nội dung"; + /// "Đang kết nối..." + @override + String get connecting => "Đang kết nối..."; + /// "Đang đăng nhập..." + @override + String get logining => "Đang đăng nhập..."; + /// "/s1 đã từ chối yêu cầu để xem của bạn" + @override + String get reject_reply => "/s1 đã từ chối yêu cầu để xem của bạn"; + /// "Tròng vòng 3 ngầy nếu không có ai báo cáo, bạn có thể đổi H coin thành tiền mặt(1:1000Việt nam)" + @override + String get warning_text => "Tròng vòng 3 ngầy nếu không có ai báo cáo, bạn có thể đổi H coin thành tiền mặt(1:1000Việt nam)"; + /// "Số lượng đầu vào không lớn hơn /s1" + @override + String get more_big => "Số lượng đầu vào không lớn hơn /s1"; + /// "Số lượng đầu vào không ít hơn /s1" + @override + String get little_min => "Số lượng đầu vào không ít hơn /s1"; + /// "/s1 mời bạn gọi" + @override + String get voice_msg => "/s1 mời bạn gọi"; + /// "Bạn đã thưởng cho đối phương /s1 cái /s2" + @override + String get send_gift => "Bạn đã thưởng cho đối phương /s1 cái /s2"; + /// "Đối phương đã thưởng cho bạn /s1 cái /s2" + @override + String get receive_gift => "Đối phương đã thưởng cho bạn /s1 cái /s2"; + /// "Không phải thành viên không thể đăng ký" + @override + String get cannot_join => "Không phải thành viên không thể đăng ký"; + /// "Trả lại" + @override + String get alreay_back => "Trả lại"; + /// "Tệp quá lớn" + @override + String get video_more_big => "Tệp quá lớn"; + /// "Chọn tất cả" + @override + String get select_all => "Chọn tất cả"; + /// "Kết nối lại" + @override + String get re_connect => "Kết nối lại"; + /// "Buông ra để gửi, vuốt để hủy" + @override + String get voice_tips2 => "Buông ra để gửi, vuốt để hủy"; + /// "Quốc tịch" + @override + String get country => "Quốc tịch"; + /// "Đang xem xét" + @override + String get have_picture_view => "Đang xem xét"; + /// "Loa chơi" + @override + String get speaker_play => "Loa chơi"; + /// "Phát loa ngoài" + @override + String get handset_playback => "Phát loa ngoài"; + /// "Chế độ loa ngoài" + @override + String get play_model => "Chế độ loa ngoài"; + /// "Mật khẩu quá ngắn" + @override + String get password_less => "Mật khẩu quá ngắn"; + /// "Tuổi" + @override + String get years_old => "Tuổi"; + /// "Khi bị người giấu tên tố cáo, hệ thống tiến hành kiểm tra và xác minh gần đây bạn có hành vi vi phạm xin hãy dừng lại hành động đó. Nếu tiếp tục vi phạm tài khoản của bạn của bạn sẽ bị đóng băng" + @override + String get coin_returen1 => "Khi bị người giấu tên tố cáo, hệ thống tiến hành kiểm tra và xác minh gần đây bạn có hành vi vi phạm xin hãy dừng lại hành động đó. Nếu tiếp tục vi phạm tài khoản của bạn của bạn sẽ bị đóng băng"; + /// "Đây là phiên bản mới nhất" + @override + String get already_new => "Đây là phiên bản mới nhất"; + /// "Trải nghiệm ngay" + @override + String get test_it => "Trải nghiệm ngay"; + /// "Phát hiện phiên bản mới" + @override + String get found_new => "Phát hiện phiên bản mới"; + /// "Quảng cáo" + @override + String get ad => "Quảng cáo"; + /// "Theo dõi" + @override + String get attention => "Theo dõi"; + /// "Fans" + @override + String get fans => "Fans"; + /// "/s1 xin xem trang tài liệu của tôi." + @override + String get apply_see => "/s1 xin xem trang tài liệu của tôi."; + /// "/s1 đã thông qua yêu cầu xem của tôi" + @override + String get agree_apply => "/s1 đã thông qua yêu cầu xem của tôi"; + /// "/s1 xem ảnh lì xì của tôi" + @override + String get see_redBag => "/s1 xem ảnh lì xì của tôi"; + /// "Nhắc nhở" + @override + String get notice => "Nhắc nhở"; + /// "Vui lòng bật quyền thông báo trong cài đặt điện thoại của bạn để nhận thông báo" + @override + String get notice_open => "Vui lòng bật quyền thông báo trong cài đặt điện thoại của bạn để nhận thông báo"; + /// "Quyền thông báo chưa được bật" + @override + String get open_notice => "Quyền thông báo chưa được bật"; + /// "Quyền thông báo chưa được mở, không nhận được thông báo." + @override + String get not_open => "Quyền thông báo chưa được mở, không nhận được thông báo."; + /// "coin /s1H mà bạn xin rút tiền đã được trả lại, xin xác nhận tài khoản liên kết của bạn có đúng không!" + @override + String get withdraw_fail => "coin /s1H mà bạn xin rút tiền đã được trả lại, xin xác nhận tài khoản liên kết của bạn có đúng không!"; + /// "Hoạt động" + @override + String get dynamics => "Hoạt động"; + /// "Ghi chú" + @override + String get Remark => "Ghi chú"; + /// "Cài đặt ghi chú" + @override + String get setRemark => "Cài đặt ghi chú"; + /// "/s1 bình luận" + @override + String get content_num => "/s1 bình luận"; + /// "Điểm sẽ đổi được /s1H coin " + @override + String get Redeem => "Điểm sẽ đổi được /s1H coin "; + /// "Không có quyền truy cập vào bộ nhớ điện thoại" + @override + String get location_permission => "Không có quyền truy cập vào bộ nhớ điện thoại"; + /// "Không có quyền truy cập camera" + @override + String get camera_permission => "Không có quyền truy cập camera"; + /// "Không có quyền truy cập vào album" + @override + String get photo_permission => "Không có quyền truy cập vào album"; + /// "Không có quyền truy cập micro" + @override + String get video_permission => "Không có quyền truy cập micro"; + /// "Lỉ xỉ bạn gửi đã hết hạn" + @override + String get your_redMoney_over => "Lỉ xỉ bạn gửi đã hết hạn"; + /// "Đồi phương gửi lì xì đã hết hạn " + @override + String get other_redMoney_over => "Đồi phương gửi lì xì đã hết hạn "; + /// "Có vẻ đã xảy ra lỗi ..." + @override + String get server_error_tips => "Có vẻ đã xảy ra lỗi ..."; + /// "icon" + @override + String get emoji => "icon"; + /// "Báo danh trong ngày để nhận /s1 điểm tích lũy" + @override + String get today_score => "Báo danh trong ngày để nhận /s1 điểm tích lũy"; + /// "1. Báo danh hàng ngày để tích lũy điểm, số ngày tích lũy càng nhiều điêm tích lũy càng cao. \n2. Điểm tích lũy có thể đổi thành H coin, khi đổi sẽ tiêu hao điểm tích lũy tương đương, hãy thận trọng khi đổi. \n3.Báo danh sẽ được đặt lại vào ngày cuối cùng của tháng, xóa điểm tích lũy. Hãy kịp thời đổi điểm tích lũy nhé!" + @override + String get sign_tips => "1. Báo danh hàng ngày để tích lũy điểm, số ngày tích lũy càng nhiều điêm tích lũy càng cao. \n2. Điểm tích lũy có thể đổi thành H coin, khi đổi sẽ tiêu hao điểm tích lũy tương đương, hãy thận trọng khi đổi. \n3.Báo danh sẽ được đặt lại vào ngày cuối cùng của tháng, xóa điểm tích lũy. Hãy kịp thời đổi điểm tích lũy nhé!"; + /// "Báo danh" + @override + String get sign_in => "Báo danh"; + /// "Điểm tích lũy của tôi" + @override + String get my_score => "Điểm tích lũy của tôi"; + /// "Báo danh ngay" + @override + String get signin_now => "Báo danh ngay"; + /// "Tích lũy báo danh /s1 ngày" + @override + String get sign_in_day => "Tích lũy báo danh /s1 ngày"; + /// "Đã hối đổi" + @override + String get have_get => "Đã hối đổi"; + /// "Quét mã" + @override + String get scan => "Quét mã"; + /// "Mã QR của tôi" + @override + String get my_qr => "Mã QR của tôi"; + /// "Quét mã và thêm bạn bè" + @override + String get scan_and_add => "Quét mã và thêm bạn bè"; + /// "Bản đồ Gouda" + @override + String get amap => "Bản đồ Gouda"; + /// "Bản đồ Yahoo" + @override + String get baidumap => "Bản đồ Yahoo"; + /// "Bản đồ Google" + @override + String get googlemap => "Bản đồ Google"; + /// "Bản đồ Apple" + @override + String get applemap => "Bản đồ Apple"; + /// "Đi mở ra" + @override + String get go_open => "Đi mở ra"; + /// "Xem trước" + @override + String get Preview => "Xem trước"; + /// "Album ảnh" + @override + String get Photo_album => "Album ảnh"; + /// "Tất cả hình ảnh " + @override + String get all_photo => "Tất cả hình ảnh "; + /// "Bạn đã chọn /s1 hình ảnh" + @override + String get have_select => "Bạn đã chọn /s1 hình ảnh"; + /// "Đang tải ..." + @override + String get loading => "Đang tải ..."; + /// "Bạn có tin nhắn trò chuyện mới" + @override + String get new_chat_msg => "Bạn có tin nhắn trò chuyện mới"; + /// "Bạn có tin nhắn Liên mic mới" + @override + String get new_video_msg => "Bạn có tin nhắn Liên mic mới"; + /// "/s1 xin kết bạn" + @override + String get apply_friends => "/s1 xin kết bạn"; + /// "/s1 đã thông qua yêu cầu kết bạn của bạn" + @override + String get applyed_friends => "/s1 đã thông qua yêu cầu kết bạn của bạn"; + /// "Không có quyền truy cập vào danh bạ" + @override + String get contact_permission => "Không có quyền truy cập vào danh bạ"; + /// "Danh bạ" + @override + String get contact => "Danh bạ"; + /// "Tìm kiếm" + @override + String get search => "Tìm kiếm"; + /// "Thêm bạn bè từ danh bạ" + @override + String get contact_add => "Thêm bạn bè từ danh bạ"; + /// "Phát hiện" + @override + String get find => "Phát hiện"; + /// "Robot dịch" + @override + String get translate_robot => "Robot dịch"; + /// "Xin chào, tôi là robot dịch thuật ..." + @override + String get robot_hello => "Xin chào, tôi là robot dịch thuật ..."; + /// "Tiếng Trung giản thể" + @override + String get Simplified_Chinese => "Tiếng Trung giản thể"; + /// "Tiếng Trung phồn thể" + @override + String get traditional_Chinese => "Tiếng Trung phồn thể"; + /// "Tiếng Anh" + @override + String get english => "Tiếng Anh"; + /// "Tiếng Việt" + @override + String get Vietnamese => "Tiếng Việt"; + /// "Tiếng Hàn" + @override + String get Korean => "Tiếng Hàn"; + /// "Tiếng Nhật" + @override + String get Japanese => "Tiếng Nhật"; + /// "Thêm bạn bè" + @override + String get add_friends => "Thêm bạn bè"; + /// "Người lạ" + @override + String get stranger => "Người lạ"; + /// "Nhận tin nhắn từ người lạ" + @override + String get receive_stranger => "Nhận tin nhắn từ người lạ"; + /// "SignIn" + @override + String get signin => "SignIn"; + /// "Đối phương từ chối nhận tin nhắn từ người lạ, bạn có tiếp tục mở khóa tất cả thông tin không." + @override + String get stranger_close => "Đối phương từ chối nhận tin nhắn từ người lạ, bạn có tiếp tục mở khóa tất cả thông tin không."; + /// "Thêm" + @override + String get add => "Thêm"; + /// "Đã thêm" + @override + String get added => "Đã thêm"; + /// "Đối phương từ chối nhận tin nhắn từ người lạ." + @override + String get stranger_close_tips => "Đối phương từ chối nhận tin nhắn từ người lạ."; + /// "Lỗi dịch" + @override + String get translate_fail => "Lỗi dịch"; + /// "Vui lòng tải ảnh lên trước khi cài đặt ảnh lì xì." + @override + String get no_photos => "Vui lòng tải ảnh lên trước khi cài đặt ảnh lì xì."; + /// "Đánh giá kháng án của bạn: /s1 kháng án thất bại." + @override + String get successful_appeal1 => "Đánh giá kháng án của bạn: /s1 kháng án thất bại."; + /// "Thêm thành công, đợi đối phương đồng ý" + @override + String get add_success => "Thêm thành công, đợi đối phương đồng ý"; + /// "Người khác trả hộ" + @override + String get other_pay => "Người khác trả hộ"; + /// "Xác thực bạn bè" + @override + String get friend_verification => "Xác thực bạn bè"; + /// "Đơn xin xác thực của bạn đã gửi và chờ đối phương thông qua" + @override + String get add_friends_tips => "Đơn xin xác thực của bạn đã gửi và chờ đối phương thông qua"; + /// "Tôi là/s1" + @override + String get i_am => "Tôi là/s1"; + /// "Cho phép" + @override + String get agree => "Cho phép"; + /// "\"Hi\"Bạn cần đồng ý với \"Thỏa thuận quyền riêng tư\" để sử dụng" + @override + String get privacyAgreement => "\"Hi\"Bạn cần đồng ý với \"Thỏa thuận quyền riêng tư\" để sử dụng"; + /// "Thỏa thuận quyền riêng tư" + @override + String get privacy => "Thỏa thuận quyền riêng tư"; + /// "Hi! có người yêu cầu thêm bạn, xem đó là ai" + @override + String get notification_addfriend => "Hi! có người yêu cầu thêm bạn, xem đó là ai"; + /// "Thêm bạn bè cần đối diện với nhau mới thêm được ha" + @override + String get distance_long => "Thêm bạn bè cần đối diện với nhau mới thêm được ha"; + /// "Để nâng cao tính chính xác của nội dung dịch, vui lòng đừng viết tắt" + @override + String get chat_tips => "Để nâng cao tính chính xác của nội dung dịch, vui lòng đừng viết tắt"; + /// "Danh sách fans" + @override + String get fans_list => "Danh sách fans"; + /// "Đang kiểm tra chức năng" + @override + String get system_not_open => "Đang kiểm tra chức năng"; + /// "Hiện tại khách hàng IOS chưa hỗ trợ chức năng rút tiền,bạn có thể sử dụng Android để rút hoặc click vào nút phía dưới" + @override + String get service_withdraw_tips => "Hiện tại khách hàng IOS chưa hỗ trợ chức năng rút tiền,bạn có thể sử dụng Android để rút hoặc click vào nút phía dưới"; + /// "Click vào đây để rút tiền" + @override + String get withdraw_tips => "Click vào đây để rút tiền"; + /// "Thêm thành viên" + @override + String get add_member => "Thêm thành viên"; + /// "Xóa thành viên" + @override + String get delete_member => "Xóa thành viên"; + /// "Sửa đổi tên nhóm" + @override + String get change_group_name => "Sửa đổi tên nhóm"; + /// "Biệt danh của tôi trong nhóm " + @override + String get my_group_nickname => "Biệt danh của tôi trong nhóm "; + /// "Trò chuyện nhóm" + @override + String get group_chat => "Trò chuyện nhóm"; + /// "Tạo nhóm trò chuyện" + @override + String get create_group_chat => "Tạo nhóm trò chuyện"; + /// "Bạn cần gửi đơn xin xác thực và chờ đối phương thông qua" + @override + String get added_friends_tips => "Bạn cần gửi đơn xin xác thực và chờ đối phương thông qua"; + /// "Tên nhóm trò chuyện" + @override + String get group_chat_name => "Tên nhóm trò chuyện"; + /// "Tại đây bạn có thể đặt biệt hiệu của mình trong nhóm này, và biệt danh này chỉ được hiển thị trong nhóm này" + @override + String get my_group_nickname_tips => "Tại đây bạn có thể đặt biệt hiệu của mình trong nhóm này, và biệt danh này chỉ được hiển thị trong nhóm này"; + /// "Động thái nam thần" + @override + String get man_gold => "Động thái nam thần"; + /// "Động thái nữ thần" + @override + String get woman_gold => "Động thái nữ thần"; + /// "Chọn nhóm chủ mới" + @override + String get choose_group_owner => "Chọn nhóm chủ mới"; + /// "Thông báo nhóm" + @override + String get group_announcement => "Thông báo nhóm"; + /// "Tin nhắn trò chuyện" + @override + String get chat_news => "Tin nhắn trò chuyện"; + /// "Mã QR nhóm" + @override + String get group_qr => "Mã QR nhóm"; + /// "Quản lý nhóm" + @override + String get group_setting => "Quản lý nhóm"; + /// "Thông báo tắt tiếng" + @override + String get close_news_notice => "Thông báo tắt tiếng"; + /// "Dính ở trên đầu" + @override + String get set_chat_top => "Dính ở trên đầu"; + /// "Hiển thị biệt danh thành viên nhóm" + @override + String get show_group_member_name => "Hiển thị biệt danh thành viên nhóm"; + /// "Sau khi thoát nhóm sẽ không thông báo cho các thành viên khác trong cuộc trò chuyện nhóm, và không nhận được tin nhắn trò chuyện nhóm này nữa" + @override + String get quit_group_tips => "Sau khi thoát nhóm sẽ không thông báo cho các thành viên khác trong cuộc trò chuyện nhóm, và không nhận được tin nhắn trò chuyện nhóm này nữa"; + /// "Thoát và xóa" + @override + String get quit_and_delete => "Thoát và xóa"; + /// "Xem thêm thành viên nhóm" + @override + String get show_more_member => "Xem thêm thành viên nhóm"; + /// "Xác nhận lời mời trò chuyện nhóm" + @override + String get group_invite => "Xác nhận lời mời trò chuyện nhóm"; + /// "Chuyển quyền quản lý nhóm" + @override + String get change_group_owner => "Chuyển quyền quản lý nhóm"; + /// "Sau khi kích hoạt, các thành viên nhóm mời bạn bè vào nhóm cần được sự đồng ý của chủ nhóm, đồng thời quét mã QR cũng ngưng sử dụng" + @override + String get group_setting_tips => "Sau khi kích hoạt, các thành viên nhóm mời bạn bè vào nhóm cần được sự đồng ý của chủ nhóm, đồng thời quét mã QR cũng ngưng sử dụng"; + /// "Chi tiết lời mời" + @override + String get invite_detail => "Chi tiết lời mời"; + /// "Chưa đặt tên" + @override + String get undefine_name => "Chưa đặt tên"; + /// "Danh thiếp mã QR nhóm" + @override + String get group_qr_code => "Danh thiếp mã QR nhóm"; + /// "Mã QR có hiệu lực trong vòng 7 ngày (ngày /s2 tháng /s1), nhập lại sẽ được cập nhật." + @override + String get group_qr_code_tips => "Mã QR có hiệu lực trong vòng 7 ngày (ngày /s2 tháng /s1), nhập lại sẽ được cập nhật."; + /// "Nhiệt độ nữ thần" + @override + String get Goddess_heat => "Nhiệt độ nữ thần"; + /// "Quà tặng tích lũy" + @override + String get Goddess_heat_tips => "Quà tặng tích lũy"; + /// "Bạn mới" + @override + String get new_friends => "Bạn mới"; + /// "3 ngày trước" + @override + String get before_three_day => "3 ngày trước"; + /// "3 ngày gần đây " + @override + String get after_three_day => "3 ngày gần đây "; + /// "Xóa nội dung trò chuyện" + @override + String get group_clean_chat_record => "Xóa nội dung trò chuyện"; + /// "Xem thêm" + @override + String get check => "Xem thêm"; + /// "Yêu cầu thêm bạn làm bạn bè" + @override + String get apply_fro_friends => "Yêu cầu thêm bạn làm bạn bè"; + /// "Không phải thành viên không thể rút tiền mặt" + @override + String get no_vip_cannot_withdraw => "Không phải thành viên không thể rút tiền mặt"; + /// "Người dùng này chưa được xác thực, hãy cẩn thận với lừa đảo" + @override + String get not_true_woman => "Người dùng này chưa được xác thực, hãy cẩn thận với lừa đảo"; + /// "Tham gia trò chuyện nhóm" + @override + String get join_group => "Tham gia trò chuyện nhóm"; + /// "Đăng nhập qua Apple" + @override + String get sign_in_apple => "Đăng nhập qua Apple"; + /// "Thông báo nhóm chỉ chủ nhóm mới có thể chỉnh sửa" + @override + String get only_host => "Thông báo nhóm chỉ chủ nhóm mới có thể chỉnh sửa"; + /// "Bạn đã thưởng cho đối phương /s1 quà tặng" + @override + String get send_gift1 => "Bạn đã thưởng cho đối phương /s1 quà tặng"; + /// "Đối phương thưởng cho bạn /s1 quà tặng" + @override + String get receive_gift1 => "Đối phương thưởng cho bạn /s1 quà tặng"; + /// "Bạn đã không còn trong nhóm" + @override + String get not_in_group => "Bạn đã không còn trong nhóm"; + /// "Đang sáng lập, vui lòng đợi" + @override + String get creating_group => "Đang sáng lập, vui lòng đợi"; + /// "Điều" + @override + String get article => "Điều"; + /// "Nhóm này đã bật vào nhóm phải xác thực và chỉ có thể thông qua lời mời mới được tham gia " + @override + String get group_open_verification => "Nhóm này đã bật vào nhóm phải xác thực và chỉ có thể thông qua lời mời mới được tham gia "; + /// "Thành viên nhóm" + @override + String get group_memeber => "Thành viên nhóm"; + /// "Đã mời /s1 bạn bè tham gia trò chuyện nhóm" + @override + String get invite_members => "Đã mời /s1 bạn bè tham gia trò chuyện nhóm"; + /// "Tổng /s1 người" + @override + String get total_members => "Tổng /s1 người"; + /// "Mã QR đã hết hạn" + @override + String get qr_outtime => "Mã QR đã hết hạn"; + /// "Không có thông tin nhóm này" + @override + String get no_goupr_info => "Không có thông tin nhóm này"; + /// " Bạn đã mời /s1 tham gia trò chuyện nhóm" + @override + String get you_invite => " Bạn đã mời /s1 tham gia trò chuyện nhóm"; + /// "Bạn đã được mời vào trò chuyện nhóm này bởi /s1" + @override + String get invite_you => "Bạn đã được mời vào trò chuyện nhóm này bởi /s1"; + /// "/s1 đã mời /s2 tham gia trò chuyện nhóm" + @override + String get invite_someone => "/s1 đã mời /s2 tham gia trò chuyện nhóm"; + /// "Bạn" + @override + String get you => "Bạn"; + /// "/s1 đã xóa /s2 khỏi trò chuyện nhóm này" + @override + String get delete_group => "/s1 đã xóa /s2 khỏi trò chuyện nhóm này"; + /// " Bạn đã trở thành chủ nhóm mới của nhóm " + @override + String get you_group_owner => " Bạn đã trở thành chủ nhóm mới của nhóm "; + /// "/s1 đã trở thành chủ nhóm mới của nhóm này" + @override + String get someone_group_owner => "/s1 đã trở thành chủ nhóm mới của nhóm này"; + /// " Tên nhóm được đổi thành /s1" + @override + String get change_group_owner1 => " Tên nhóm được đổi thành /s1"; + /// "Thông báo nhóm đã được cập nhật" + @override + String get update_group_announce => "Thông báo nhóm đã được cập nhật"; + /// "Bạn tham gia trò chuyện nhóm bằng cách quét mã QR" + @override + String get you_qr => "Bạn tham gia trò chuyện nhóm bằng cách quét mã QR"; + /// " /s1 Tham gia trò chuyện nhóm bằng cách quét mã QR" + @override + String get others_qr => " /s1 Tham gia trò chuyện nhóm bằng cách quét mã QR"; + /// "\"/s1\" muốn mời /s2 bạn bè vào nhóm trò chuyện \$ Đi để xác nhận \$" + @override + String get invite_confirm => "\"/s1\" muốn mời /s2 bạn bè vào nhóm trò chuyện \$ Đi để xác nhận \$"; + /// " \"/s1\" Muốn mời \"/s2\" để tham gia trò chuyện nhóm" + @override + String get want_invite_confirm => " \"/s1\" Muốn mời \"/s2\" để tham gia trò chuyện nhóm"; + /// "\"/s1\" Tham gia trò chuyện nhóm Xác nhận" + @override + String get join_group_confirm => "\"/s1\" Tham gia trò chuyện nhóm Xác nhận"; + /// "Bạn đã được mời vào một cuộc trò chuyện nhóm bởi /s1" + @override + String get you_invite_gourp => "Bạn đã được mời vào một cuộc trò chuyện nhóm bởi /s1"; + /// " \"/s1\"Tham gia trò chuyện nhóm " + @override + String get someone_join_group => " \"/s1\"Tham gia trò chuyện nhóm "; + /// " Chủ nhóm đã bật \"Xác nhận lời mời trò chuyện nhóm \", các thành viên nhóm cần xác nhận từ chủ nhóm để mời bạn bè vào nhóm" + @override + String get group_setting_tips1 => " Chủ nhóm đã bật \"Xác nhận lời mời trò chuyện nhóm \", các thành viên nhóm cần xác nhận từ chủ nhóm để mời bạn bè vào nhóm"; + /// "Chủ nhóm đã khôi phục phương thức tham gia nhóm mặc định" + @override + String get group_setting_tips2 => "Chủ nhóm đã khôi phục phương thức tham gia nhóm mặc định"; + /// " Số thành viên nhóm đã đạt đến giới hạn" + @override + String get members_max => " Số thành viên nhóm đã đạt đến giới hạn"; + /// "Số lượng nhóm đã đạt đến giới hạn" + @override + String get group_max => "Số lượng nhóm đã đạt đến giới hạn"; + /// "Hóa đơn của tôi" + @override + String get my_money_info => "Hóa đơn của tôi"; + /// "Số dư của tôi" + @override + String get my_left_money => "Số dư của tôi"; + /// "H-coin có thể nạp trực tiếp hoặc hối đổi, nhưng không thể rút tiền mặt." + @override + String get money_tips => "H-coin có thể nạp trực tiếp hoặc hối đổi, nhưng không thể rút tiền mặt."; + /// "Thu nhập cụ thể" + @override + String get get_money_detail => "Thu nhập cụ thể"; + /// "Thu nhập Hibox" + @override + String get hibok_money => "Thu nhập Hibox"; + /// "Hối đổi H-coin" + @override + String get charge_h => "Hối đổi H-coin"; + /// "Quy tắc rút tiền" + @override + String get charge_tips => "Quy tắc rút tiền"; + /// "Định vị đa dạng" + @override + String get splash_tips1 => "Định vị đa dạng"; + /// "Robot dịch" + @override + String get splash_tips2 => "Robot dịch"; + /// "APP hẹn hò" + @override + String get splash_tips3 => "APP hẹn hò"; + /// "Nữ thần đa dạng, chọn bạn yêu thích" + @override + String get splash_tips_content1 => "Nữ thần đa dạng, chọn bạn yêu thích"; + /// "Cùng nhau chat voice" + @override + String get splash_tips_content2 => "Cùng nhau chat voice"; + /// "Giải quyết vấn đề ngôn ngữ" + @override + String get splash_tips_content3 => "Giải quyết vấn đề ngôn ngữ"; + /// "Trải nghiệm ngay" + @override + String get splash_go => "Trải nghiệm ngay"; + /// "Bạn đã thông qua hối đổi thu nhập được /s1H coin" + @override + String get change_h_coin => "Bạn đã thông qua hối đổi thu nhập được /s1H coin"; + /// "Yêu cầu của bạn đã thành công, và hệ thống đã hoàn tiền" + @override + String get Representation_succes => "Yêu cầu của bạn đã thành công, và hệ thống đã hoàn tiền"; + /// "Hệ thống tặng" + @override + String get system_give => "Hệ thống tặng"; + /// "Yêu cầu rút tiền của bạn thất bại và đã được trả lại" + @override + String get exchange_fail => "Yêu cầu rút tiền của bạn thất bại và đã được trả lại"; + /// "Thông qua thu nhập Hibox hối đổi được /s1H coin" + @override + String get hibok_exchange => "Thông qua thu nhập Hibox hối đổi được /s1H coin"; + /// "Liên kết mã mời thành công" + @override + String get bind_code_success => "Liên kết mã mời thành công"; + /// "Bạn đã dành /s1H coin để sự dụng người dịch" + @override + String get translate_money => "Bạn đã dành /s1H coin để sự dụng người dịch"; + /// "Hệ thống hủy bỏ trả lại" + @override + String get system_back => "Hệ thống hủy bỏ trả lại"; + /// "Bạn thưởng cho đối phương" + @override + String get you_give => "Bạn thưởng cho đối phương"; + /// "Đối phương thưởng cho bạn" + @override + String get you_get => "Đối phương thưởng cho bạn"; + /// "Số lượng hối đổi (đơn vị K)" + @override + String get enter_num_qian => "Số lượng hối đổi (đơn vị K)"; + /// "Số lượng tiền rút (đơn vị K)" + @override + String get enter_num_qian1 => "Số lượng tiền rút (đơn vị K)"; + /// "翻译券" + @override + String get daily_translate_voucher => "翻译券"; + /// "通知消息" + @override + String get msg_notice => "通知消息"; + /// "选择提醒的人" + @override + String get select_notice_people => "选择提醒的人"; + /// "查找手机号" + @override + String get search_phone => "查找手机号"; + /// "用户不存在" + @override + String get not_have_user => "用户不存在"; + /// "你不能添加自己" + @override + String get not_add_Myself => "你不能添加自己"; + /// "对方已拉黑了你" + @override + String get you_are_blaklisted => "对方已拉黑了你"; + /// "确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)" + @override + String get confrim_recovery => "确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)"; + /// "發送到" + @override + String get send_to => "發送到"; + + @override + TextDirection get textDirection => TextDirection.ltr; +} + +class _I18n_zh_HK extends I18n { + const _I18n_zh_HK(); + + /// "Hi公園" + @override + String get appName => "Hi公園"; + /// "登錄" + @override + String get login => "登錄"; + /// "注册" + @override + String get registration => "注册"; + /// "其他登錄" + @override + String get other_login => "其他登錄"; + /// "賬號" + @override + String get account => "賬號"; + /// "請輸入賬號" + @override + String get enter_username => "請輸入賬號"; + /// "密碼" + @override + String get password => "密碼"; + /// "輸入密碼" + @override + String get enter_password => "輸入密碼"; + /// "忘記密碼" + @override + String get forget_password => "忘記密碼"; + /// "重置密碼" + @override + String get reset_password => "重置密碼"; + /// "手機號註冊" + @override + String get number_registration => "手機號註冊"; + /// "請輸入手機號" + @override + String get enter_number => "請輸入手機號"; + /// "驗證碼" + @override + String get code => "驗證碼"; + /// "請輸入收到的驗證碼" + @override + String get enter_code => "請輸入收到的驗證碼"; + /// "發送驗證碼" + @override + String get send_code => "發送驗證碼"; + /// "重新發送" + @override + String get send_again => "重新發送"; + /// "設置密碼" + @override + String get set_password => "設置密碼"; + /// "密碼不少於6位" + @override + String get password_limit => "密碼不少於6位"; + /// "請設置登錄密碼" + @override + String get set_password2 => "請設置登錄密碼"; + /// "下一步" + @override + String get next_step => "下一步"; + /// "點擊進入表示你已閱讀並同意《用戶協議》" + @override + String get agreed_agreement => "點擊進入表示你已閱讀並同意《用戶協議》"; + /// "請輸入登錄密碼" + @override + String get enter_password2 => "請輸入登錄密碼"; + /// "立即重置" + @override + String get reset_now => "立即重置"; + /// "選擇性別" + @override + String get choose_gender => "選擇性別"; + /// "你是..." + @override + String get who => "你是..."; + /// "確定" + @override + String get determine => "確定"; + /// "選擇性別後無法修改" + @override + String get cannot_modified => "選擇性別後無法修改"; + /// "提示" + @override + String get tip => "提示"; + /// "你即將完成註冊,是否現在退出?" + @override + String get choose_quit => "你即將完成註冊,是否現在退出?"; + /// "確認" + @override + String get confirm => "確認"; + /// "使用" + @override + String get use => "使用"; + /// "取消" + @override + String get cancel => "取消"; + /// "關閉" + @override + String get close => "關閉"; + /// "刪除" + @override + String get delete => "刪除"; + /// "算了" + @override + String get forget_it => "算了"; + /// "好的" + @override + String get ok => "好的"; + /// "註冊後將不能修改性別,確定麼?" + @override + String get choose_quit2 => "註冊後將不能修改性別,確定麼?"; + /// "提示:你不能和同性別用戶進行交流" + @override + String get tip_content => "提示:你不能和同性別用戶進行交流"; + /// "歡迎" + @override + String get welcome => "歡迎"; + /// "請填寫邀請碼" + @override + String get enter_incode => "請填寫邀請碼"; + /// "Hi僅向擁有邀請碼的男士提供服務" + @override + String get must_incode => "Hi僅向擁有邀請碼的男士提供服務"; + /// "你的邀請碼" + @override + String get your_incode => "你的邀請碼"; + /// "沒有邀請碼?你可以通過以下方式獲取" + @override + String get how_get => "沒有邀請碼?你可以通過以下方式獲取"; + /// "方式1" + @override + String get method1 => "方式1"; + /// "免費申請" + @override + String get free => "免費申請"; + /// "馬上申請" + @override + String get apply_now => "馬上申請"; + /// "查收邀請碼" + @override + String get check_incode => "查收邀請碼"; + /// "你需要填寫一些個人信息,審核通過後回給你發送邀請碼" + @override + String get so_get => "你需要填寫一些個人信息,審核通過後回給你發送邀請碼"; + /// "申請邀請碼" + @override + String get apply_incode => "申請邀請碼"; + /// "所在地" + @override + String get location => "所在地"; + /// "你所在的城市名稱" + @override + String get cityname => "你所在的城市名稱"; + /// "信息渠道" + @override + String get message_channel => "信息渠道"; + /// "你從哪裡知道APP" + @override + String get how_know => "你從哪裡知道APP"; + /// "微信號" + @override + String get wechat_number => "微信號"; + /// "你的微信號" + @override + String get your_wechat => "你的微信號"; + /// "facebook" + @override + String get facebook => "facebook"; + /// "你的臉書" + @override + String get your_facebook => "你的臉書"; + /// "提交申請" + @override + String get submit_application => "提交申請"; + /// "請輸入所在城市" + @override + String get enter_city => "請輸入所在城市"; + /// "請告訴我們你獲取APP的信息渠道" + @override + String get so_know => "請告訴我們你獲取APP的信息渠道"; + /// "請告訴我們你的社交賬號" + @override + String get your_social => "請告訴我們你的社交賬號"; + /// "我們將盡快處理你的申請。如果通過審核,你會在消息中心收到我們發放的邀請碼" + @override + String get receive_incode => "我們將盡快處理你的申請。如果通過審核,你會在消息中心收到我們發放的邀請碼"; + /// "邀請碼還未發放,申請後請耐心等待!" + @override + String get wait_incode => "邀請碼還未發放,申請後請耐心等待!"; + /// "邀請碼申請成功!" + @override + String get successful_application1 => "邀請碼申請成功!"; + /// "邀請碼申請失敗!" + @override + String get application_failed1 => "邀請碼申請失敗!"; + /// "複製成功" + @override + String get successful_copy => "複製成功"; + /// "方式2" + @override + String get method2 => "方式2"; + /// "加入會員" + @override + String get joinvip => "加入會員"; + /// "立即加入" + @override + String get join_now => "立即加入"; + /// "已加入" + @override + String get joined => "已加入"; + /// "加入會員可享受各種特權,包括無需邀請碼註冊" + @override + String get join_odds => "加入會員可享受各種特權,包括無需邀請碼註冊"; + /// "你還沒有加入會員" + @override + String get not_joinvip => "你還沒有加入會員"; + /// "加入會員後,即可不需要邀請碼完成註冊" + @override + String get join_after => "加入會員後,即可不需要邀請碼完成註冊"; + /// "邀請碼驗證通過" + @override + String get incode_passed => "邀請碼驗證通過"; + /// "歡迎加入!請勿把你的賬號洩露給他人,一經發現登錄異常,賬戶會被自動凍結。" + @override + String get welcome_join => "歡迎加入!請勿把你的賬號洩露給他人,一經發現登錄異常,賬戶會被自動凍結。"; + /// "會員中心" + @override + String get member_centre => "會員中心"; + /// "會員特權" + @override + String get members_privilege => "會員特權"; + /// "看的更多" + @override + String get see_more => "看的更多"; + /// "每天不限次數查看用戶" + @override + String get unlimited_see => "每天不限次數查看用戶"; + /// "看的更省" + @override + String get see_cheaper => "看的更省"; + /// "每天/s1次免費機會查看付費相冊或者社交賬號" + @override + String get free10 => "每天/s1次免費機會查看付費相冊或者社交賬號"; + /// "看的更久" + @override + String get see_longer => "看的更久"; + /// "查看閱後即焚照片的時間從2秒提升到/s1秒" + @override + String get towto6 => "查看閱後即焚照片的時間從2秒提升到/s1秒"; + /// "看的更爽" + @override + String get see_better => "看的更爽"; + /// "免費發布約會廣播" + @override + String get free_release => "免費發布約會廣播"; + /// "選擇套餐" + @override + String get choose_price => "選擇套餐"; + /// "支付方式" + @override + String get pay_method => "支付方式"; + /// "支付金額" + @override + String get pay_amount => "支付金額"; + /// "錢包餘額不足" + @override + String get not_enough => "錢包餘額不足"; + /// "確認支付" + @override + String get confirm_pay => "確認支付"; + /// "完善資料" + @override + String get complete_material => "完善資料"; + /// "基本資料" + @override + String get basic_information => "基本資料"; + /// "上傳頭像" + @override + String get upload_avatar => "上傳頭像"; + /// "請選擇" + @override + String get choose => "請選擇"; + /// "請填寫" + @override + String get fill_out => "請填寫"; + /// "可以多選" + @override + String get choose_multiple => "可以多選"; + /// "選填" + @override + String get optional => "選填"; + /// "最少填寫/s1個" + @override + String get least => "最少填寫/s1個"; + /// "介紹一下自己" + @override + String get introduce_yourself => "介紹一下自己"; + /// "最多選擇/s1個" + @override + String get most => "最多選擇/s1個"; + /// "暱稱" + @override + String get nickname => "暱稱"; + /// "暱稱只能1-20個字符" + @override + String get only1_8 => "暱稱只能1-20個字符"; + /// "當前城市" + @override + String get Resident_city => "當前城市"; + /// "請選擇當前城市" + @override + String get Please_select_a_resident_city => "請選擇當前城市"; + /// "芹苴" + @override + String get City1 => "芹苴"; + /// "峴港" + @override + String get City2 => "峴港"; + /// "海防" + @override + String get City3 => "海防"; + /// "河內" + @override + String get City4 => "河內"; + /// "胡志明" + @override + String get City5 => "胡志明"; + /// "安江" + @override + String get City6 => "安江"; + /// "北江" + @override + String get City7 => "北江"; + /// "北件" + @override + String get City8 => "北件"; + /// "薄遼" + @override + String get City9 => "薄遼"; + /// "北寧" + @override + String get City10 => "北寧"; + /// "巴地頭頓" + @override + String get City11 => "巴地頭頓"; + /// "檳椥" + @override + String get City12 => "檳椥"; + /// "平定" + @override + String get City13 => "平定"; + /// "平陽" + @override + String get City14 => "平陽"; + /// "平福" + @override + String get City15 => "平福"; + /// "平順" + @override + String get City16 => "平順"; + /// "金甌" + @override + String get City17 => "金甌"; + /// "高平" + @override + String get City18 => "高平"; + /// "得樂" + @override + String get City19 => "得樂"; + /// "得農" + @override + String get City20 => "得農"; + /// "奠邊" + @override + String get City21 => "奠邊"; + /// "同奈" + @override + String get City22 => "同奈"; + /// "同塔" + @override + String get City23 => "同塔"; + /// "嘉萊" + @override + String get City24 => "嘉萊"; + /// "河江" + @override + String get City25 => "河江"; + /// "海陽" + @override + String get City26 => "海陽"; + /// "河南" + @override + String get City27 => "河南"; + /// "河靜" + @override + String get City28 => "河靜"; + /// "和平" + @override + String get City29 => "和平"; + /// "後江" + @override + String get City30 => "後江"; + /// "興安" + @override + String get City31 => "興安"; + /// "慶和" + @override + String get City32 => "慶和"; + /// "堅江" + @override + String get City33 => "堅江"; + /// "昆嵩" + @override + String get City34 => "昆嵩"; + /// "萊州" + @override + String get City35 => "萊州"; + /// "林同" + @override + String get City36 => "林同"; + /// "諒山" + @override + String get City37 => "諒山"; + /// "老街" + @override + String get City38 => "老街"; + /// "隆安" + @override + String get City39 => "隆安"; + /// "乂安" + @override + String get City40 => "乂安"; + /// "寧平" + @override + String get City41 => "寧平"; + /// "寧順" + @override + String get City42 => "寧順"; + /// "富壽" + @override + String get City43 => "富壽"; + /// "富安" + @override + String get City44 => "富安"; + /// "廣平" + @override + String get City45 => "廣平"; + /// "廣南" + @override + String get City46 => "廣南"; + /// "廣義" + @override + String get City47 => "廣義"; + /// "廣寧" + @override + String get City48 => "廣寧"; + /// "廣治" + @override + String get City49 => "廣治"; + /// "朔莊" + @override + String get City50 => "朔莊"; + /// "山羅" + @override + String get City51 => "山羅"; + /// "西寧" + @override + String get City52 => "西寧"; + /// "太平" + @override + String get City53 => "太平"; + /// "太原" + @override + String get City54 => "太原"; + /// "清化" + @override + String get City55 => "清化"; + /// "承天順化" + @override + String get City56 => "承天順化"; + /// "前江" + @override + String get City57 => "前江"; + /// "茶榮" + @override + String get City58 => "茶榮"; + /// "宣光" + @override + String get City59 => "宣光"; + /// "永隆" + @override + String get City60 => "永隆"; + /// "永富" + @override + String get City61 => "永富"; + /// "安沛" + @override + String get City62 => "安沛"; + /// "南定" + @override + String get City63 => "南定"; + /// "生日" + @override + String get birthday => "生日"; + /// "請選擇生日" + @override + String get choose_birthday => "請選擇生日"; + /// "年" + @override + String get year => "年"; + /// "月" + @override + String get month => "月"; + /// "日" + @override + String get day => "日"; + /// "時" + @override + String get hour => "時"; + /// "分" + @override + String get minute => "分"; + /// "秒" + @override + String get second => "秒"; + /// "剛剛" + @override + String get just => "剛剛"; + /// "/s1分鐘前" + @override + String get minute_ago => "/s1分鐘前"; + /// "/s1小時前" + @override + String get hour_ago => "/s1小時前"; + /// "/s1天前" + @override + String get day_ago => "/s1天前"; + /// "/s1週前" + @override + String get week_ago => "/s1週前"; + /// "/s1月前" + @override + String get month_ago => "/s1月前"; + /// "上午" + @override + String get morning => "上午"; + /// "中午" + @override + String get noon => "中午"; + /// "下午" + @override + String get afternoon => "下午"; + /// "晚上" + @override + String get night => "晚上"; + /// "一整天" + @override + String get all_day => "一整天"; + /// "昨天" + @override + String get yesterday => "昨天"; + /// "前天" + @override + String get two_yesterday => "前天"; + /// "通宵" + @override + String get overnight => "通宵"; + /// "個" + @override + String get one => "個"; + /// "十" + @override + String get ten => "十"; + /// "百" + @override + String get hundred => "百"; + /// "千" + @override + String get thousand => "千"; + /// "萬" + @override + String get ten_thousand => "萬"; + /// "白羊座" + @override + String get aries => "白羊座"; + /// "金牛座" + @override + String get taurus => "金牛座"; + /// "雙子座" + @override + String get gemini => "雙子座"; + /// "巨蟹座" + @override + String get cancer => "巨蟹座"; + /// "獅子座" + @override + String get leo => "獅子座"; + /// "處女座" + @override + String get virgo => "處女座"; + /// "天秤座" + @override + String get libra => "天秤座"; + /// "天蠍座" + @override + String get scorpio => "天蠍座"; + /// "射手座" + @override + String get sagittarius => "射手座"; + /// "摩羯座" + @override + String get capricorn => "摩羯座"; + /// "水瓶座" + @override + String get aquarius => "水瓶座"; + /// "雙魚座" + @override + String get pisces => "雙魚座"; + /// "星期一" + @override + String get monday => "星期一"; + /// "星期二" + @override + String get tuesday => "星期二"; + /// "星期三" + @override + String get wednesday => "星期三"; + /// "星期四" + @override + String get thursday => "星期四"; + /// "星期五" + @override + String get friday => "星期五"; + /// "星期六" + @override + String get saturday => "星期六"; + /// "星期天" + @override + String get sunday => "星期天"; + /// "職業" + @override + String get job => "職業"; + /// "請選擇職業" + @override + String get choose_career => "請選擇職業"; + /// "信息技術" + @override + String get career1 => "信息技術"; + /// "互聯網" + @override + String get career2 => "互聯網"; + /// "IT" + @override + String get career3 => "IT"; + /// "電信運營" + @override + String get career4 => "電信運營"; + /// "網絡遊戲" + @override + String get career5 => "網絡遊戲"; + /// "金融保險" + @override + String get career6 => "金融保險"; + /// "投資" + @override + String get career7 => "投資"; + /// "股票基金" + @override + String get career8 => "股票基金"; + /// "保險" + @override + String get career9 => "保險"; + /// "銀行" + @override + String get career10 => "銀行"; + /// "信託擔保" + @override + String get career11 => "信託擔保"; + /// "商業服務" + @override + String get career12 => "商業服務"; + /// "諮詢" + @override + String get career13 => "諮詢"; + /// "個體經營" + @override + String get career14 => "個體經營"; + /// "美容美髮" + @override + String get career15 => "美容美髮"; + /// "旅遊" + @override + String get career16 => "旅遊"; + /// "酒店餐飲" + @override + String get career17 => "酒店餐飲"; + /// "休閒娛樂" + @override + String get career18 => "休閒娛樂"; + /// "貿易" + @override + String get career19 => "貿易"; + /// "汽車" + @override + String get career20 => "汽車"; + /// "房地產" + @override + String get career21 => "房地產"; + /// "物業管理" + @override + String get career22 => "物業管理"; + /// "裝修裝潢" + @override + String get career23 => "裝修裝潢"; + /// "偵探" + @override + String get career24 => "偵探"; + /// "工程製造" + @override + String get career25 => "工程製造"; + /// "建築" + @override + String get career26 => "建築"; + /// "土木工程" + @override + String get career27 => "土木工程"; + /// "機械製造" + @override + String get career28 => "機械製造"; + /// "電子" + @override + String get career29 => "電子"; + /// "生物醫學" + @override + String get career30 => "生物醫學"; + /// "食品" + @override + String get career31 => "食品"; + /// "服裝" + @override + String get career32 => "服裝"; + /// "能源" + @override + String get career33 => "能源"; + /// "交通運輸" + @override + String get career34 => "交通運輸"; + /// "航空" + @override + String get career35 => "航空"; + /// "鐵路" + @override + String get career36 => "鐵路"; + /// "航運船舶" + @override + String get career37 => "航運船舶"; + /// "公共交通" + @override + String get career38 => "公共交通"; + /// "物流運輸" + @override + String get career39 => "物流運輸"; + /// "文化傳媒" + @override + String get career40 => "文化傳媒"; + /// "媒體出版" + @override + String get career41 => "媒體出版"; + /// "設計" + @override + String get career42 => "設計"; + /// "文化傳播" + @override + String get career43 => "文化傳播"; + /// "廣告創意" + @override + String get career44 => "廣告創意"; + /// "動漫" + @override + String get career45 => "動漫"; + /// "公關會展" + @override + String get career46 => "公關會展"; + /// "攝影" + @override + String get career47 => "攝影"; + /// "娛樂體育" + @override + String get career48 => "娛樂體育"; + /// "影視" + @override + String get career49 => "影視"; + /// "運動體育" + @override + String get career50 => "運動體育"; + /// "音樂" + @override + String get career51 => "音樂"; + /// "模特" + @override + String get career52 => "模特"; + /// "公共事業" + @override + String get career53 => "公共事業"; + /// "醫療" + @override + String get career54 => "醫療"; + /// "法律" + @override + String get career55 => "法律"; + /// "教育" + @override + String get career56 => "教育"; + /// "政府機構" + @override + String get career57 => "政府機構"; + /// "公益" + @override + String get career58 => "公益"; + /// "學生" + @override + String get career59 => "學生"; + /// "無" + @override + String get career60 => "無"; + /// "節目" + @override + String get program => "節目"; + /// "請選擇國籍" + @override + String get select_program => "請選擇國籍"; + /// "健康運動" + @override + String get healthy_exercise => "健康運動"; + /// "夜蒲聚會" + @override + String get night_party => "夜蒲聚會"; + /// "我是吃貨" + @override + String get gourmet_party => "我是吃貨"; + /// "看電影" + @override + String get watch_movie => "看電影"; + /// "玩遊戲" + @override + String get play_games => "玩遊戲"; + /// "結伴旅行" + @override + String get travel_together => "結伴旅行"; + /// "連麥聊天" + @override + String get voice_chat => "連麥聊天"; + /// "其他" + @override + String get other => "其他"; + /// "期望對象" + @override + String get expect_lover => "期望對象"; + /// "請選擇期望對象" + @override + String get choose_lover => "請選擇期望對象"; + /// "看臉" + @override + String get beautiful => "看臉"; + /// "土豪" + @override + String get rich => "土豪"; + /// "關愛我" + @override + String get care_me => "關愛我"; + /// "看感覺" + @override + String get look_feeling => "看感覺"; + /// "無所謂" + @override + String get doesnt_matter => "無所謂"; + /// "請至少填寫一種社交賬號" + @override + String get least_account => "請至少填寫一種社交賬號"; + /// "我的用戶資料隱藏社交賬號" + @override + String get hide_account1 => "我的用戶資料隱藏社交賬號"; + /// "更多信息" + @override + String get more_information => "更多信息"; + /// "身高" + @override + String get height => "身高"; + /// "體重" + @override + String get weight => "體重"; + /// "不顯示" + @override + String get not_show => "不顯示"; + /// "個人介紹" + @override + String get self_introduction => "個人介紹"; + /// "註冊成功" + @override + String get registration_success1 => "註冊成功"; + /// "確定退出麼" + @override + String get exit => "確定退出麼"; + /// "你還未完善個人信息,現在退出下次進入請用已註冊賬號直接登錄" + @override + String get exit_registration => "你還未完善個人信息,現在退出下次進入請用已註冊賬號直接登錄"; + /// "男士無法查看其他男士詳情" + @override + String get cant_see => "男士無法查看其他男士詳情"; + /// "女士無法查看其他女士詳情" + @override + String get cant_see2 => "女士無法查看其他女士詳情"; + /// "你今天還能查看/s1位女士" + @override + String get see_one => "你今天還能查看/s1位女士"; + /// "非會員用戶每天只能查看15位女士" + @override + String get only_see => "非會員用戶每天只能查看15位女士"; + /// "繼續查看" + @override + String get continue_see => "繼續查看"; + /// "用戶已凍結" + @override + String get user_frozen => "用戶已凍結"; + /// "請輸入暱稱/職業進行搜索" + @override + String get search_user => "請輸入暱稱/職業進行搜索"; + /// "附近" + @override + String get nearby => "附近"; + /// "會員" + @override + String get member => "會員"; + /// "新註冊" + @override + String get new_registration => "新註冊"; + /// "認證" + @override + String get authenticate => "認證"; + /// "在線" + @override + String get first_online => "在線"; + /// "未開啟定位,無法計算與其他用戶距離" + @override + String get not_positioned => "未開啟定位,無法計算與其他用戶距離"; + /// "未知" + @override + String get unknown => "未知"; + /// "保密" + @override + String get secrecy => "保密"; + /// "收藏" + @override + String get collection => "收藏"; + /// "取消收藏" + @override + String get cancel_collection => "取消收藏"; + /// "已取消收藏" + @override + String get canceled_collection => "已取消收藏"; + /// "加入喜歡" + @override + String get like => "加入喜歡"; + /// "已加入喜歡" + @override + String get added_like => "已加入喜歡"; + /// "已取消喜歡" + @override + String get canceled_like => "已取消喜歡"; + /// "拉黑" + @override + String get blacklist => "拉黑"; + /// "你們將無法再看到對方和對方的動態,確定嗎" + @override + String get blacklist_choose => "你們將無法再看到對方和對方的動態,確定嗎"; + /// "已加入黑名單" + @override + String get blacklisted => "已加入黑名單"; + /// "你已拉黑對方並拒收消息" + @override + String get reject_message => "你已拉黑對方並拒收消息"; + /// "移除黑名單" + @override + String get remove_blacklist => "移除黑名單"; + /// "已移除黑名單" + @override + String get blacklist_removed => "已移除黑名單"; + /// "你將對方移除黑名單並取消拒收消息" + @override + String get receive_message => "你將對方移除黑名單並取消拒收消息"; + /// "在線" + @override + String get online => "在線"; + /// "付費相冊" + @override + String get paid_photo => "付費相冊"; + /// "申請瀏覽" + @override + String get application_view => "申請瀏覽"; + /// "已通過" + @override + String get passed => "已通過"; + /// "公園" + @override + String get park => "公園"; + /// "電台" + @override + String get radio => "電台"; + /// "消息" + @override + String get news => "消息"; + /// "我" + @override + String get me => "我"; + /// "更多操作" + @override + String get more_operations => "更多操作"; + /// "匿名舉報" + @override + String get anonymous_report => "匿名舉報"; + /// "認證視頻" + @override + String get certified_video => "認證視頻"; + /// "她已通過視頻認證真實性" + @override + String get passed_video => "她已通過視頻認證真實性"; + /// "她還沒認證身份真實性" + @override + String get not_video => "她還沒認證身份真實性"; + /// "她正在發起約會哦" + @override + String get her_appointment => "她正在發起約會哦"; + /// "他通過付費加入" + @override + String get pay_join => "他通過付費加入"; + /// "他通過了身份安全審核" + @override + String get passed_review => "他通過了身份安全審核"; + /// "他通過資深用戶/s1贈送的邀請碼加入" + @override + String get invited_user => "他通過資深用戶/s1贈送的邀請碼加入"; + /// "他正在發起約會哦" + @override + String get his_appointment => "他正在發起約會哦"; + /// "她的動態" + @override + String get her_dynamics => "她的動態"; + /// "他的動態" + @override + String get his_dynamics => "他的動態"; + /// "她非常低調" + @override + String get low_key => "她非常低調"; + /// "他非常低調" + @override + String get low_key2 => "他非常低調"; + /// "她的相冊" + @override + String get her_photo => "她的相冊"; + /// "他的相冊" + @override + String get his_photo => "他的相冊"; + /// "他設置了相冊鎖" + @override + String get set_lock => "他設置了相冊鎖"; + /// "她設置了相冊鎖" + @override + String get set_lock2 => "她設置了相冊鎖"; + /// "解鎖相冊(/s1),會員免費" + @override + String get free_unlock => "解鎖相冊(/s1),會員免費"; + /// "解鎖/s1的相冊" + @override + String get unlock_user => "解鎖/s1的相冊"; + /// "付費解鎖(/s1 H幣)" + @override + String get pay_unlock => "付費解鎖(/s1 H幣)"; + /// "成為會員,免費解鎖" + @override + String get become_member => "成為會員,免費解鎖"; + /// "是否使用1次機會解鎖/s1的相冊" + @override + String get consumption_once => "是否使用1次機會解鎖/s1的相冊"; + /// "(你今天還有/s1次機會)" + @override + String get remaining_once => "(你今天還有/s1次機會)"; + /// "你今天的免費機會已用完,是否贈送/s1解鎖/s2的全部資料" + @override + String get no_times => "你今天的免費機會已用完,是否贈送/s1解鎖/s2的全部資料"; + /// "支付" + @override + String get pay => "支付"; + /// "他設置了限制,查看資料需要請求他的同意" + @override + String get view_user => "他設置了限制,查看資料需要請求他的同意"; + /// "她設置了限制,查看資料需要請求她的同意" + @override + String get view_user2 => "她設置了限制,查看資料需要請求她的同意"; + /// "申請查看需給對方發送一張你的照片。放心,你的照片會在對方長按屏幕查看的2秒後焚毀" + @override + String get need_photo => "申請查看需給對方發送一張你的照片。放心,你的照片會在對方長按屏幕查看的2秒後焚毀"; + /// "選擇照片" + @override + String get choose_photo => "選擇照片"; + /// "已發送申請,對方確認後你會收到消息提醒" + @override + String get send_application => "已發送申請,對方確認後你會收到消息提醒"; + /// "你還沒進行認證" + @override + String get not_authenticate => "你還沒進行認證"; + /// "認證你的真實性後,才能與他人互動" + @override + String get after_authenticate => "認證你的真實性後,才能與他人互動"; + /// "馬上認證" + @override + String get authenticate_now => "馬上認證"; + /// "閱後即焚" + @override + String get destroy_after => "閱後即焚"; + /// "已焚毀" + @override + String get destroyed => "已焚毀"; + /// "閱後即焚的紅包照片" + @override + String get red_photo1 => "閱後即焚的紅包照片"; + /// "請通過私聊向我索取" + @override + String get ask_me => "請通過私聊向我索取"; + /// "已填寫,點擊查看" + @override + String get filled_in => "已填寫,點擊查看"; + /// "解鎖全部資料" + @override + String get unlock_information => "解鎖全部資料"; + /// "使用1次免費解鎖" + @override + String get unlock_choose => "使用1次免費解鎖"; + /// "你的真實評價" + @override + String get your_evaluation => "你的真實評價"; + /// "她的真實評價" + @override + String get her_evaluation => "她的真實評價"; + /// "他的真實評價" + @override + String get his_evaluation => "他的真實評價"; + /// "評價" + @override + String get evaluate => "評價"; + /// "友好" + @override + String get friendly => "友好"; + /// "有趣" + @override + String get interesting => "有趣"; + /// "爽快" + @override + String get readily => "爽快"; + /// "耐心" + @override + String get patient => "耐心"; + /// "高冷" + @override + String get indifferent => "高冷"; + /// "爆脾氣" + @override + String get bad_temper => "爆脾氣"; + /// "禮貌" + @override + String get courtesy => "禮貌"; + /// "大方" + @override + String get generous => "大方"; + /// "口嗨" + @override + String get lie => "口嗨"; + /// "不友好" + @override + String get unfriendly => "不友好"; + /// "匿名評價" + @override + String get anonymous_evaluation => "匿名評價"; + /// "你還沒約過她,無法評價" + @override + String get cant_evaluate => "你還沒約過她,無法評價"; + /// "他還沒約過你,無法評價" + @override + String get cant_evaluate2 => "他還沒約過你,無法評價"; + /// "請提供相關截圖,以便我們跟進核實" + @override + String get bad_evaluate => "請提供相關截圖,以便我們跟進核實"; + /// "提交" + @override + String get submit => "提交"; + /// "評價成功" + @override + String get evaluation_success => "評價成功"; + /// "私聊" + @override + String get private_chat => "私聊"; + /// "關閉消息提醒" + @override + String get close_reminder => "關閉消息提醒"; + /// "關閉消息提醒成功" + @override + String get closed_reminder => "關閉消息提醒成功"; + /// "開啟消息提醒" + @override + String get open_reminder => "開啟消息提醒"; + /// "開啟消息提醒成功" + @override + String get opened_reminder => "開啟消息提醒成功"; + /// "她的社交賬號" + @override + String get her_account => "她的社交賬號"; + /// "他的社交賬號" + @override + String get his_account => "他的社交賬號"; + /// "複製" + @override + String get copy => "複製"; + /// "發送我的社交賬號給她" + @override + String get send_account => "發送我的社交賬號給她"; + /// "輸入你的社交賬號" + @override + String get enter_account => "輸入你的社交賬號"; + /// "比如:微信號abc" + @override + String get for_example => "比如:微信號abc"; + /// "發送給她" + @override + String get sent_she => "發送給她"; + /// "連麥" + @override + String get chat => "連麥"; + /// "對方關閉了連麥功能" + @override + String get cantt_voice => "對方關閉了連麥功能"; + /// "認證你的真實性後,才能主動連麥" + @override + String get authentication_voice => "認證你的真實性後,才能主動連麥"; + /// "正在請求連麥" + @override + String get requesting_voice => "正在請求連麥"; + /// "正在等待接聽" + @override + String get waitting_answer => "正在等待接聽"; + /// "接聽" + @override + String get answer => "接聽"; + /// "掛斷" + @override + String get hang_up => "掛斷"; + /// "連麥中" + @override + String get chatting => "連麥中"; + /// "免提" + @override + String get handsfree => "免提"; + /// "打赏" + @override + String get giving_gift => "打赏"; + /// "打賞成功" + @override + String get give_success => "打賞成功"; + /// "對方已打賞" + @override + String get others_gift => "對方已打賞"; + /// "你已打賞價值/s1H幣的禮物" + @override + String get given_gift => "你已打賞價值/s1H幣的禮物"; + /// "你已獲賞/s1H幣" + @override + String get earned_gift => "你已獲賞/s1H幣"; + /// "可用餘額/s1" + @override + String get available_balance => "可用餘額/s1"; + /// "充值" + @override + String get recharge => "充值"; + /// "贈送" + @override + String get give => "贈送"; + /// "抱歉,你的餘額不足了" + @override + String get balance_insufficien => "抱歉,你的餘額不足了"; + /// "請充值後再送禮物哦!" + @override + String get first_recharge => "請充值後再送禮物哦!"; + /// "本次連麥打賞/s1H幣" + @override + String get give_coin => "本次連麥打賞/s1H幣"; + /// "本次連麥獲賞/s1H幣" + @override + String get get_coin => "本次連麥獲賞/s1H幣"; + /// "本次連麥打賞/s1H幣,獲賞了/s2H幣" + @override + String get give_get => "本次連麥打賞/s1H幣,獲賞了/s2H幣"; + /// "連麥已結束,時長​/s1" + @override + String get chat_over => "連麥已結束,時長​/s1"; + /// "消息中心" + @override + String get message_center => "消息中心"; + /// "你可以在對方的用戶詳情頁發起私聊" + @override + String get can_chat => "你可以在對方的用戶詳情頁發起私聊"; + /// "聊天" + @override + String get text_chat => "聊天"; + /// "系統消息" + @override + String get system_information => "系統消息"; + /// "系統通知" + @override + String get system_notification => "系統通知"; + /// "你舉報用戶/s1的情況不屬實,請提供更有效的證據後再次舉報。謝謝!" + @override + String get report_failure => "你舉報用戶/s1的情況不屬實,請提供更有效的證據後再次舉報。謝謝!"; + /// "你舉報用戶/s1的情況屬實,系統已對該用戶進行處理" + @override + String get report_success => "你舉報用戶/s1的情況屬實,系統已對該用戶進行處理"; + /// "邀請碼申請成功!邀請碼【/s1】(點擊可複制)" + @override + String get successful_application => "邀請碼申請成功!邀請碼【/s1】(點擊可複制)"; + /// "邀請碼申請成功,感謝你介紹靠譜的朋友!邀請碼【/s1】(點擊可複制)" + @override + String get successful_application2 => "邀請碼申請成功,感謝你介紹靠譜的朋友!邀請碼【/s1】(點擊可複制)"; + /// "邀請碼申請失敗!很遺憾您的申請未能通過審核,請填寫真實信息將有效的提高審核通過率" + @override + String get application_failed => "邀請碼申請失敗!很遺憾您的申請未能通過審核,請填寫真實信息將有效的提高審核通過率"; + /// "【重要通知】:" + @override + String get important_notice => "【重要通知】:"; + /// "你的認證資料不符合要求,請修改後重新提交。" + @override + String get authentication_failed => "你的認證資料不符合要求,請修改後重新提交。"; + /// "1.請根據認證要求拍攝認證視頻" + @override + String get request1 => "1.請根據認證要求拍攝認證視頻"; + /// "2.請在相冊上傳五官清晰的正臉本人照片" + @override + String get request2 => "2.請在相冊上傳五官清晰的正臉本人照片"; + /// "恭喜,你的認證申請已通過審核" + @override + String get successful_authentication => "恭喜,你的認證申請已通過審核"; + /// "你新上傳的照片沒有通過審核,請根據要求重新上傳" + @override + String get re_upload => "你新上傳的照片沒有通過審核,請根據要求重新上傳"; + /// "恭喜,你新上傳的照片已成功通過審核" + @override + String get upload_success => "恭喜,你新上傳的照片已成功通過審核"; + /// "您的約會報名因違規被刪除,多次違規或情節嚴重系統將對您賬號進行限制甚至封號,請遵守謹記,謝謝配合" + @override + String get caveat => "您的約會報名因違規被刪除,多次違規或情節嚴重系統將對您賬號進行限制甚至封號,請遵守謹記,謝謝配合"; + /// "您的評論因違規被刪除,多次違規或情節嚴重系統將對您賬號進行限制甚至封號,請遵守謹記,謝謝配合" + @override + String get caveat2 => "您的評論因違規被刪除,多次違規或情節嚴重系統將對您賬號進行限制甚至封號,請遵守謹記,謝謝配合"; + /// "電台消息" + @override + String get radio_message => "電台消息"; + /// "暫時沒有此類消息" + @override + String get no_message => "暫時沒有此類消息"; + /// "/s1在/s2發布了一條約會消息,點擊查看" + @override + String get dating_news => "/s1在/s2發布了一條約會消息,點擊查看"; + /// "去看看" + @override + String get go_see => "去看看"; + /// "/s1讚了你的動態" + @override + String get thumbs_up => "/s1讚了你的動態"; + /// "/s1讚了你的約會節目" + @override + String get thumbs_up2 => "/s1讚了你的約會節目"; + /// "/s1評論了你的動態" + @override + String get comment1 => "/s1評論了你的動態"; + /// "/s1評論了你的約會節目" + @override + String get comment2 => "/s1評論了你的約會節目"; + /// "/s1回復了你的評論" + @override + String get replied_comment => "/s1回復了你的評論"; + /// "/s1報名了你的約會節目" + @override + String get signed_up => "/s1報名了你的約會節目"; + /// "你喜歡的用戶/s1發布了一條約會,點擊查看" + @override + String get favorite_user => "你喜歡的用戶/s1發布了一條約會,點擊查看"; + /// "你喜歡的用戶/s1發布了一條動態,點擊查看" + @override + String get favorite_user2 => "你喜歡的用戶/s1發布了一條動態,點擊查看"; + /// "錢包提醒" + @override + String get wallet_reminder => "錢包提醒"; + /// "/s1付費了(/s2H幣)查看了你的紅包照片" + @override + String get paid_you => "/s1付費了(/s2H幣)查看了你的紅包照片"; + /// "/s1付費了(/s2H幣)查看了你的相冊" + @override + String get paid_you2 => "/s1付費了(/s2H幣)查看了你的相冊"; + /// "/s1付費解鎖了你的全部資料" + @override + String get paid_you3 => "/s1付費解鎖了你的全部資料"; + /// "查看申請" + @override + String get view_application => "查看申請"; + /// "/s1請求查看你的詳情頁" + @override + String get view_application2 => "/s1請求查看你的詳情頁"; + /// "允許(有效期15天)" + @override + String get aging => "允許(有效期15天)"; + /// "拒絕" + @override + String get refuse => "拒絕"; + /// "已通過請求" + @override + String get passed_request => "已通過請求"; + /// "/s1已通過你的查看申請,有效期15天" + @override + String get l15_days => "/s1已通過你的查看申請,有效期15天"; + /// "評價通知" + @override + String get evaluation_notice => "評價通知"; + /// "已經約出/s1了嗎?趕快評價一下她吧" + @override + String get rate_her => "已經約出/s1了嗎?趕快評價一下她吧"; + /// "聯繫過你的女士用戶(匿名)對你進行了評價:/s1" + @override + String get received_evaluation => "聯繫過你的女士用戶(匿名)對你進行了評價:/s1"; + /// "聯繫過你的男士用戶(匿名)對你進行了評價:/s1" + @override + String get received_evaluation2 => "聯繫過你的男士用戶(匿名)對你進行了評價:/s1"; + /// "如果評價不屬實,你可申請上述,我們會進行核實" + @override + String get application_appeal => "如果評價不屬實,你可申請上述,我們會進行核實"; + /// "我要上訴" + @override + String get appeal => "我要上訴"; + /// "已申請上訴" + @override + String get appealed => "已申請上訴"; + /// "我們會盡快核實情況,並通過站內信告訴你處理結果" + @override + String get waiting_results => "我們會盡快核實情況,並通過站內信告訴你處理結果"; + /// "你上訴的評價:/s1上訴成功,我們將為你撤銷此評價。" + @override + String get successful_appeal => "你上訴的評價:/s1上訴成功,我們將為你撤銷此評價。"; + /// "社交賬號" + @override + String get social_account => "社交賬號"; + /// "/s1向你發送了他的社交賬號" + @override + String get get_account => "/s1向你發送了他的社交賬號"; + /// "編輯資料" + @override + String get edit_information => "編輯資料"; + /// "保存" + @override + String get save => "保存"; + /// "你通過了身份安全核實" + @override + String get passed_verification1 => "你通過了身份安全核實"; + /// "你通過資深用戶/s1的邀請碼加入" + @override + String get by_code => "你通過資深用戶/s1的邀請碼加入"; + /// "你通過付費加入" + @override + String get by_paying => "你通過付費加入"; + /// "你已通過視頻認證身份真實性" + @override + String get passed_verification => "你已通過視頻認證身份真實性"; + /// "你還沒有認證身份真實性" + @override + String get not_certified => "你還沒有認證身份真實性"; + /// "我們正在認證你的真實性" + @override + String get verificating => "我們正在認證你的真實性"; + /// "經過認證的女生更受歡迎哦" + @override + String get real_girl => "經過認證的女生更受歡迎哦"; + /// "認證中" + @override + String get certificating => "認證中"; + /// "待重新上傳視頻" + @override + String get re_upload2 => "待重新上傳視頻"; + /// "更新認證" + @override + String get update_certification => "更新認證"; + /// "升級會員尊享特權" + @override + String get enjoy_privileges => "升級會員尊享特權"; + /// "/s1到期" + @override + String get expires => "/s1到期"; + /// "錢包" + @override + String get wallet => "錢包"; + /// "隱私" + @override + String get setting => "隱私"; + /// "我的動態" + @override + String get my_dynamic => "我的動態"; + /// "我的相冊" + @override + String get my_album => "我的相冊"; + /// "上傳我的第一張照片" + @override + String get first_photo => "上傳我的第一張照片"; + /// "有照片才能吸引男士哦" + @override + String get no_photo => "有照片才能吸引男士哦"; + /// "上傳照片" + @override + String get upload_photos => "上傳照片"; + /// "上傳視頻" + @override + String get upload_video => "上傳視頻"; + /// "上傳照片" + @override + String get upload => "上傳照片"; + /// "設置紅包照片" + @override + String get set_photo => "設置紅包照片"; + /// "長按拖動可對照片排序" + @override + String get photo_order => "長按拖動可對照片排序"; + /// "我的評價" + @override + String get my_evaluation => "我的評價"; + /// "我的節目" + @override + String get my_show => "我的節目"; + /// "我喜歡的" + @override + String get i_like => "我喜歡的"; + /// "你喜歡的女士會顯示這裡" + @override + String get your_favorite => "你喜歡的女士會顯示這裡"; + /// "你喜歡的男士會顯示這裡" + @override + String get your_favorite2 => "你喜歡的男士會顯示這裡"; + /// "沒有數據" + @override + String get no_data => "沒有數據"; + /// "歷史訪客" + @override + String get historical_visitor => "歷史訪客"; + /// "有/s1個人看過你" + @override + String get visit_you => "有/s1個人看過你"; + /// "已有/s1個人焚毀了你的照片" + @override + String get visit_photo => "已有/s1個人焚毀了你的照片"; + /// "一鍵恢復" + @override + String get recovery_photo => "一鍵恢復"; + /// "設置" + @override + String get setting2 => "設置"; + /// "幫朋友申請邀請碼" + @override + String get apply_code => "幫朋友申請邀請碼"; + /// "申請邀請碼是免費的,我們會根據你的歷史消費來評估是否發放邀請碼。為維持公園的氛圍,請一定把邀請碼贈與靠譜的朋友" + @override + String get issue_choose => "申請邀請碼是免費的,我們會根據你的歷史消費來評估是否發放邀請碼。為維持公園的氛圍,請一定把邀請碼贈與靠譜的朋友"; + /// "成功遞交申請" + @override + String get successfully_submit => "成功遞交申請"; + /// "分享APP給朋友" + @override + String get share_app => "分享APP給朋友"; + /// "有問題需要幫助" + @override + String get need_help => "有問題需要幫助"; + /// "聯繫客服" + @override + String get need_help2 => "聯繫客服"; + /// "為了提高服務效率,如果下面有您的問題,請直接回复序號數字哦!" + @override + String get need_help3 => "為了提高服務效率,如果下面有您的問題,請直接回复序號數字哦!"; + /// "【1】賬號被凍結是什麼原因?" + @override + String get question1 => "【1】賬號被凍結是什麼原因?"; + /// "出現下述任意一種情況,賬號都會被凍結:①騙子②中介③騷擾廣告④多人舉報⑤已有其他賬號⑥多次發布違規電台廣播無視警告⑦用戶自己要求註銷" + @override + String get answer1 => "出現下述任意一種情況,賬號都會被凍結:①騙子②中介③騷擾廣告④多人舉報⑤已有其他賬號⑥多次發布違規電台廣播無視警告⑦用戶自己要求註銷"; + /// "【2】錢包現金什麼時候才能提現?" + @override + String get question2 => "【2】錢包現金什麼時候才能提現?"; + /// "所有收益會直接進入到錢包,提現需要三天(按收取時間計算開始),三天后收取的金額將會進入到錢包,金額>=10元即可提現" + @override + String get answer2 => "所有收益會直接進入到錢包,提現需要三天(按收取時間計算開始),三天后收取的金額將會進入到錢包,金額>=10元即可提現"; + /// "【3】我發出的紅包怎麼沒有顯示?" + @override + String get question3 => "【3】我發出的紅包怎麼沒有顯示?"; + /// "可能是網絡原因導致。放心,這種情況對方無法領取你的紅包,紅包將在24小時後自動退還到你的支付渠道" + @override + String get answer3 => "可能是網絡原因導致。放心,這種情況對方無法領取你的紅包,紅包將在24小時後自動退還到你的支付渠道"; + /// "【4】提現需要多久到賬?" + @override + String get question4 => "【4】提現需要多久到賬?"; + /// "提交提現申請後兩個工作日內到賬。溫馨提示:提現時請確認賬號無誤!" + @override + String get answer4 => "提交提現申請後兩個工作日內到賬。溫馨提示:提現時請確認賬號無誤!"; + /// "【5】如何匿名舉報其他用戶/電台廣播內容?" + @override + String get question5 => "【5】如何匿名舉報其他用戶/電台廣播內容?"; + /// "進入對方詳情頁或選擇某條電台廣播,點擊右上角選擇【匿名舉報】,請填寫相關舉報信息即可對其發起舉報。" + @override + String get answer5 => "進入對方詳情頁或選擇某條電台廣播,點擊右上角選擇【匿名舉報】,請填寫相關舉報信息即可對其發起舉報。"; + /// "【6】如何成為認證用戶?" + @override + String get question6 => "【6】如何成為認證用戶?"; + /// "認證通過需滿足以下要求:①個人資料填寫有效社交賬號②相冊至少上傳一張本人清晰的正臉照③在認證頁面查看驗證碼,在紙上寫上暱稱+驗證碼④拿著這張紙,與你的正臉合拍一段視頻,點擊上傳認證視頻" + @override + String get answer6 => "認證通過需滿足以下要求:①個人資料填寫有效社交賬號②相冊至少上傳一張本人清晰的正臉照③在認證頁面查看驗證碼,在紙上寫上暱稱+驗證碼④拿著這張紙,與你的正臉合拍一段視頻,點擊上傳認證視頻"; + /// "【7】認證的視頻可以不公開嗎?" + @override + String get question7 => "【7】認證的視頻可以不公開嗎?"; + /// "可以在設置裡選擇是否公開:用戶中心-點擊認證視頻-左下角'將認證視頻顯示在我的詳情頁'" + @override + String get answer7 => "可以在設置裡選擇是否公開:用戶中心-點擊認證視頻-左下角'將認證視頻顯示在我的詳情頁'"; + /// "【8】如何避免認證被取消?" + @override + String get question8 => "【8】如何避免認證被取消?"; + /// "相冊至少有一張被標記為本人的照片" + @override + String get answer8 => "相冊至少有一張被標記為本人的照片"; + /// "【9】電台廣播被刪除是什麼原因?" + @override + String get question9 => "【9】電台廣播被刪除是什麼原因?"; + /// "電台廣播不能發布敏感圖,敏感詞,包括但不限於暗示或明示性詞語,不能發布個人信息(包括頭像,暱稱,聯繫方式),違規電台廣播將被刪除" + @override + String get answer9 => "電台廣播不能發布敏感圖,敏感詞,包括但不限於暗示或明示性詞語,不能發布個人信息(包括頭像,暱稱,聯繫方式),違規電台廣播將被刪除"; + /// "【10】如何註銷賬號?" + @override + String get question10 => "【10】如何註銷賬號?"; + /// "註銷賬號將無法登錄APP,以後再想使用服務則需要重新註冊,請謹慎考慮。如果你仍然決定註銷賬號,請回复序號【12】聯繫客服" + @override + String get answer10 => "註銷賬號將無法登錄APP,以後再想使用服務則需要重新註冊,請謹慎考慮。如果你仍然決定註銷賬號,請回复序號【12】聯繫客服"; + /// "【11】忘記密碼怎麼辦?" + @override + String get question11 => "【11】忘記密碼怎麼辦?"; + /// "通過手機號碼註冊或者綁定手機號碼的用戶,可以通過登錄頁面右上角的“忘記密碼”功能重置密碼。未綁定用戶請先綁定手機號,再設置新的登錄密碼" + @override + String get answer11 => "通過手機號碼註冊或者綁定手機號碼的用戶,可以通過登錄頁面右上角的“忘記密碼”功能重置密碼。未綁定用戶請先綁定手機號,再設置新的登錄密碼"; + /// "【12】其他問題/轉接人工客服" + @override + String get question12 => "【12】其他問題/轉接人工客服"; + /// "你好,請問有什麼問題可以幫你?請描述你的問題(客服上班時間為每天8:00-次日02:00,由於諮詢人數較多,你可能需要等待回复)" + @override + String get answer12 => "你好,請問有什麼問題可以幫你?請描述你的問題(客服上班時間為每天8:00-次日02:00,由於諮詢人數較多,你可能需要等待回复)"; + /// "認證中心" + @override + String get certification_center => "認證中心"; + /// "認證視頻拍攝方式示例" + @override + String get for_example2 => "認證視頻拍攝方式示例"; + /// "認證條件" + @override + String get certification_conditions => "認證條件"; + /// "1.個人形象良好" + @override + String get conditions1 => "1.個人形象良好"; + /// "2.相冊中至少上傳一張本人照片" + @override + String get conditions2 => "2.相冊中至少上傳一張本人照片"; + /// "認證方式" + @override + String get verification_method => "認證方式"; + /// "1.取一張紙,寫上你的暱稱和以下驗證碼:" + @override + String get method3 => "1.取一張紙,寫上你的暱稱和以下驗證碼:"; + /// "2.拿著這張紙,與你的正臉合拍一段視頻(3~15秒)" + @override + String get method4 => "2.拿著這張紙,與你的正臉合拍一段視頻(3~15秒)"; + /// "上傳認證視頻" + @override + String get upload_video2 => "上傳認證視頻"; + /// "認證成功後,你的頭像會帶有real標誌" + @override + String get after_authentication => "認證成功後,你的頭像會帶有real標誌"; + /// "將認證視頻顯示在我的詳情頁" + @override + String get show_video => "將認證視頻顯示在我的詳情頁"; + /// "已上傳的認證視頻" + @override + String get uploaded_video => "已上傳的認證視頻"; + /// "審核中(24小時內)" + @override + String get under_review => "審核中(24小時內)"; + /// "認證狀態" + @override + String get certification_status => "認證狀態"; + /// "你已通過認證" + @override + String get certified => "你已通過認證"; + /// "認證待重提" + @override + String get wait_resubmitted => "認證待重提"; + /// "您的認證視頻不符合要求,原因是:" + @override + String get reason_failure => "您的認證視頻不符合要求,原因是:"; + /// "請根據認證要求拍攝認證視頻" + @override + String get claim => "請根據認證要求拍攝認證視頻"; + /// "請在相冊上傳清晰展示五官的正臉本人照片" + @override + String get claim2 => "請在相冊上傳清晰展示五官的正臉本人照片"; + /// "重新上傳認證視頻" + @override + String get re_upload_video => "重新上傳認證視頻"; + /// "更新上傳認證視頻" + @override + String get update_video => "更新上傳認證視頻"; + /// "H幣" + @override + String get mask_coin => "H幣"; + /// "你可以通過充值或者開麥等途徑獲得H幣。" + @override + String get get_way => "你可以通過充值或者開麥等途徑獲得H幣。"; + /// "H幣可用於使用連麥服務,並且在連麥時進行打賞。" + @override + String get coin_use => "H幣可用於使用連麥服務,並且在連麥時進行打賞。"; + /// "H幣總額" + @override + String get coin_total => "H幣總額"; + /// "可兌消" + @override + String get can_redeemed => "可兌消"; + /// "/s1賬號" + @override + String get who_account => "/s1賬號"; + /// "綁定/s1賬號" + @override + String get bind_account => "綁定/s1賬號"; + /// "你的/s1賬號" + @override + String get your_account => "你的/s1賬號"; + /// "你通過充值獲得了/s1H幣" + @override + String get get_coin2 => "你通過充值獲得了/s1H幣"; + /// "/s1查看了你的社交賬號" + @override + String get viewed_your => "/s1查看了你的社交賬號"; + /// "/s1贈送了禮物:1個/s2" + @override + String get give_gift => "/s1贈送了禮物:1個/s2"; + /// "+/s1H幣" + @override + String get add_coin => "+/s1H幣"; + /// "你贈送了1個/s1給/s2" + @override + String get give_one => "你贈送了1個/s1給/s2"; + /// "-/s1H幣" + @override + String get less_coin => "-/s1H幣"; + /// "提現" + @override + String get exchange_cash => "提現"; + /// "提現申請" + @override + String get withdrawal_application => "提現申請"; + /// "你有/s1枚H幣可兌換成/s2,兌換後剩餘/s3枚H幣。確定申請兌換嗎?" + @override + String get redeem_choose => "你有/s1枚H幣可兌換成/s2,兌換後剩餘/s3枚H幣。確定申請兌換嗎?"; + /// "提現申請已提交" + @override + String get application_submitted => "提現申請已提交"; + /// "我們將在2個工作日內處理,有疑問可諮詢客服" + @override + String get working_days => "我們將在2個工作日內處理,有疑問可諮詢客服"; + /// "現金" + @override + String get cash => "現金"; + /// "每當你再聊天頁面收到紅包,紅包金額都會進入這裡。金額進賬後3天內沒人舉報你即可提現,提現將收取5%手續費" + @override + String get handling_fee => "每當你再聊天頁面收到紅包,紅包金額都會進入這裡。金額進賬後3天內沒人舉報你即可提現,提現將收取5%手續費"; + /// "賬戶總額" + @override + String get total_account => "賬戶總額"; + /// "金額不足,無法兌消" + @override + String get cannot_redeemed => "金額不足,無法兌消"; + /// "兌消成功" + @override + String get successful_redemption => "兌消成功"; + /// "你的賬戶總額為/s1元,本次可提現/s2元,確定申請提現嗎?" + @override + String get redeem_choose2 => "你的賬戶總額為/s1元,本次可提現/s2元,確定申請提現嗎?"; + /// "個人詳情" + @override + String get personal_details => "個人詳情"; + /// "公開(推薦)" + @override + String get public => "公開(推薦)"; + /// "相冊付費查看" + @override + String get paid_album => "相冊付費查看"; + /// "他人必須付費才能查看你的相冊,費用由你定,這可能會降低你的訪問量" + @override + String get must_pay => "他人必須付費才能查看你的相冊,費用由你定,這可能會降低你的訪問量"; + /// "設置查看金額" + @override + String get set_amount1 => "設置查看金額"; + /// "請先上傳照片,再設置付費相冊" + @override + String get first_upload => "請先上傳照片,再設置付費相冊"; + /// "查看前需通過我驗證" + @override + String get need_permission => "查看前需通過我驗證"; + /// "他人必鬚髮照片讓你驗證身份後才能瀏覽你的主頁,確定嗎?" + @override + String get permission_choose => "他人必鬚髮照片讓你驗證身份後才能瀏覽你的主頁,確定嗎?"; + /// "在附近的人列表隱藏我" + @override + String get hide_me => "在附近的人列表隱藏我"; + /// "對他人隱藏我的距離" + @override + String get hide_distance => "對他人隱藏我的距離"; + /// "對他人隱藏我的社交賬號" + @override + String get hide_account => "對他人隱藏我的社交賬號"; + /// "連麥控制" + @override + String get chat_setting => "連麥控制"; + /// "允許有私聊權限的人對我發起連麥" + @override + String get chat_me => "允許有私聊權限的人對我發起連麥"; + /// "保存成功" + @override + String get successfully_saved => "保存成功"; + /// "你還沒有發布過動態" + @override + String get on_dynamic => "你還沒有發布過動態"; + /// "發布動態" + @override + String get release_dynamics => "發布動態"; + /// "動態詳情" + @override + String get dynamic_details => "動態詳情"; + /// "發布" + @override + String get release => "發布"; + /// "我發布的" + @override + String get i_posted => "我發布的"; + /// "刪除動態" + @override + String get delete_dynamic => "刪除動態"; + /// "確定要刪除這條動態嗎?" + @override + String get delete_choose => "確定要刪除這條動態嗎?"; + /// "發佈於/s1" + @override + String get posted_on => "發佈於/s1"; + /// "贊" + @override + String get thumbs_up3 => "贊"; + /// "已經贊過了" + @override + String get already_praised => "已經贊過了"; + /// "評論" + @override + String get comment => "評論"; + /// "發送" + @override + String get send => "發送"; + /// "評論已關閉" + @override + String get comment_closed => "評論已關閉"; + /// "只有發布者能看見你的評論" + @override + String get your_comment => "只有發布者能看見你的評論"; + /// "大家都能看見你的評論" + @override + String get everyone_comment => "大家都能看見你的評論"; + /// "禁止評論" + @override + String get prohibit_comments => "禁止評論"; + /// "已禁止評論" + @override + String get comments_disabled => "已禁止評論"; + /// "開放評論" + @override + String get open_comments => "開放評論"; + /// "已經開放評論" + @override + String get already_open => "已經開放評論"; + /// "回复" + @override + String get reply => "回复"; + /// "舉報" + @override + String get report => "舉報"; + /// "確定舉報這條評論嗎?" + @override + String get report_choose => "確定舉報這條評論嗎?"; + /// "舉報成功,我們會盡快處理" + @override + String get successful_report => "舉報成功,我們會盡快處理"; + /// "刪除成功" + @override + String get successfully_deleted => "刪除成功"; + /// "談吐文明的人更受歡迎,請勿發布低俗、色情交易、或曝光他人隱私的內容" + @override + String get please_civilization => "談吐文明的人更受歡迎,請勿發布低俗、色情交易、或曝光他人隱私的內容"; + /// "對同性別用戶隱藏" + @override + String get same_sex => "對同性別用戶隱藏"; + /// "會員免費,非會員需/s1H幣" + @override + String get member_free => "會員免費,非會員需/s1H幣"; + /// "已認證女士免費3次,之後需要支付/s1H幣" + @override + String get certified_free => "已認證女士免費3次,之後需要支付/s1H幣"; + /// "請輸入文字內容或選擇圖片" + @override + String get enter_something => "請輸入文字內容或選擇圖片"; + /// "付費發布(/s1H幣)" + @override + String get raid_release => "付費發布(/s1H幣)"; + /// "成為會員,免費發布" + @override + String get become_member2 => "成為會員,免費發布"; + /// "馬上認證,免費發布" + @override + String get now_certification => "馬上認證,免費發布"; + /// "發布成功" + @override + String get successfully_released => "發布成功"; + /// "你還沒有發布過節目" + @override + String get no_program => "你還沒有發布過節目"; + /// "節目詳情" + @override + String get program_details => "節目詳情"; + /// "節目主題" + @override + String get program_theme => "節目主題"; + /// "點擊選擇" + @override + String get click_select => "點擊選擇"; + /// "城市" + @override + String get city => "城市"; + /// "選擇城市" + @override + String get select_city => "選擇城市"; + /// "時間" + @override + String get time => "時間"; + /// "選擇日期" + @override + String get select_date => "選擇日期"; + /// "選擇時間" + @override + String get select_time => "選擇時間"; + /// "不限時間" + @override + String get unlimited_time => "不限時間"; + /// "補充說明" + @override + String get supplementary_explanation => "補充說明"; + /// "配圖" + @override + String get image => "配圖"; + /// "刪除節目" + @override + String get delete_program => "刪除節目"; + /// "確定要刪除這條節目嗎?" + @override + String get delete_choose2 => "確定要刪除這條節目嗎?"; + /// "請選擇節目主題" + @override + String get please_choose => "請選擇節目主題"; + /// "請選擇期望對象" + @override + String get please_choose2 => "請選擇期望對象"; + /// "請選擇城市" + @override + String get please_choose3 => "請選擇城市"; + /// "請選擇日期" + @override + String get please_choose4 => "請選擇日期"; + /// "請選擇時間" + @override + String get please_choose5 => "請選擇時間"; + /// "發布節目" + @override + String get release_program => "發布節目"; + /// "報名" + @override + String get sign_up => "報名"; + /// "結束報名" + @override + String get end_registration => "結束報名"; + /// "確定結束約會嗎?" + @override + String get end_choose => "確定結束約會嗎?"; + /// "聯繫她" + @override + String get contact_her => "聯繫她"; + /// "私聊他" + @override + String get talk_him => "私聊他"; + /// "確定舉報這條報名信息嗎?" + @override + String get report_choose2 => "確定舉報這條報名信息嗎?"; + /// "發佈時間" + @override + String get release_time => "發佈時間"; + /// "活動時間" + @override + String get activity_time => "活動時間"; + /// "不限性別" + @override + String get any_sex => "不限性別"; + /// "只看女士" + @override + String get look_women => "只看女士"; + /// "只看男士" + @override + String get look_men => "只看男士"; + /// "不限地區" + @override + String get unlimited_area => "不限地區"; + /// "該節目已刪除" + @override + String get program_deleted => "該節目已刪除"; + /// "非會員不能評論" + @override + String get cant_comment => "非會員不能評論"; + /// "我要報名" + @override + String get sign_up2 => "我要報名"; + /// "報名需要發送你的正臉照片(只有對方能看到)" + @override + String get need_photo2 => "報名需要發送你的正臉照片(只有對方能看到)"; + /// "報名成功,如果對方覺得合適將會聯繫你" + @override + String get registration_success => "報名成功,如果對方覺得合適將會聯繫你"; + /// "已結束" + @override + String get has_ended => "已結束"; + /// "男士不能報名男士的節目" + @override + String get men_cant => "男士不能報名男士的節目"; + /// "女士不能報名女士的節目" + @override + String get ms_cant => "女士不能報名女士的節目"; + /// "男士不能評論男士的節目" + @override + String get men_cant2 => "男士不能評論男士的節目"; + /// "女士不能評論女士的節目" + @override + String get ms_cant2 => "女士不能評論女士的節目"; + /// "消息推送、修改密碼" + @override + String get message_push => "消息推送、修改密碼"; + /// "手機號碼" + @override + String get phone_number => "手機號碼"; + /// "綁定手機號" + @override + String get bind_phone1 => "綁定手機號"; + /// "綁定手機號,讓你的賬戶更安全" + @override + String get more_safer => "綁定手機號,讓你的賬戶更安全"; + /// "你想修改綁定的手機號碼嗎?" + @override + String get modify_choose => "你想修改綁定的手機號碼嗎?"; + /// "修改密碼" + @override + String get change_password => "修改密碼"; + /// "用戶需要先綁定手機號碼才可以設置登錄密碼" + @override + String get first_bind => "用戶需要先綁定手機號碼才可以設置登錄密碼"; + /// "原密碼" + @override + String get old_password => "原密碼"; + /// "請輸入當前登錄密碼" + @override + String get current_password => "請輸入當前登錄密碼"; + /// "新密碼" + @override + String get new_password => "新密碼"; + /// "請設置新密碼,不少於6位" + @override + String get set_new => "請設置新密碼,不少於6位"; + /// "清除圖片緩存" + @override + String get clear_cache => "清除圖片緩存"; + /// "清除成功" + @override + String get cleared_successfully => "清除成功"; + /// "用戶使用協議" + @override + String get user_agreement1 => "用戶使用協議"; + /// "退出登錄" + @override + String get sign_out => "退出登錄"; + /// "確定退出賬號麼?" + @override + String get out_choose => "確定退出賬號麼?"; + /// "推送設置" + @override + String get push_settings => "推送設置"; + /// "權限已被拒絕" + @override + String get permission_denied => "權限已被拒絕"; + /// "消息推送設置" + @override + String get push_setting2 => "消息推送設置"; + /// "私聊消息" + @override + String get private_chat2 => "私聊消息"; + /// "有新的約會" + @override + String get new_date => "有新的約會"; + /// "有女士通過了我的查看請求" + @override + String get passed_request2 => "有女士通過了我的查看請求"; + /// "有男士申請查看我的資料頁" + @override + String get men_view => "有男士申請查看我的資料頁"; + /// "有男士查看我的社交賬號" + @override + String get men_view2 => "有男士查看我的社交賬號"; + /// "有男士查看我的紅包照片" + @override + String get men_view3 => "有男士查看我的紅包照片"; + /// "有已查看資料的男士給我發送社交賬號" + @override + String get men_view4 => "有已查看資料的男士給我發送社交賬號"; + /// "邀請碼申請成功" + @override + String get applied_successfully => "邀請碼申請成功"; + /// "打開後將推送相應消息類型" + @override + String get after_open => "打開後將推送相應消息類型"; + /// "如果你在最近3天曾向她/他支付過費用,我們核實舉報後,系統將自動向你退回消費金額" + @override + String get if_something => "如果你在最近3天曾向她/他支付過費用,我們核實舉報後,系統將自動向你退回消費金額"; + /// "發廣告" + @override + String get advertise => "發廣告"; + /// "虛假照片" + @override + String get false_photo => "虛假照片"; + /// "色情低俗" + @override + String get erotic_vulgarity => "色情低俗"; + /// "騷擾謾罵" + @override + String get harassment => "騷擾謾罵"; + /// "她是騙子" + @override + String get she_liar => "她是騙子"; + /// "他是騙子" + @override + String get he_liar => "他是騙子"; + /// "請提供相關截圖,以便我們跟進核實" + @override + String get provide_screenshots => "請提供相關截圖,以便我們跟進核實"; + /// "請描述詳情(100字內)" + @override + String get describe_details => "請描述詳情(100字內)"; + /// "請選擇舉報原因" + @override + String get report_reason => "請選擇舉報原因"; + /// "舉報成功" + @override + String get report_success2 => "舉報成功"; + /// "修改成功" + @override + String get successfully_modified => "修改成功"; + /// "男生" + @override + String get boy => "男生"; + /// "女生" + @override + String get girl => "女生"; + /// "已申請" + @override + String get already_applied => "已申請"; + /// "查看報名" + @override + String get view_registration => "查看報名"; + /// "展開" + @override + String get expand => "展開"; + /// "收起" + @override + String get collapse => "收起"; + /// "申請通知" + @override + String get application_notice => "申請通知"; + /// "有用戶同意你的申請" + @override + String get agrees_application => "有用戶同意你的申請"; + /// "紅包照片" + @override + String get red_photo => "紅包照片"; + /// "請勿上傳非法裸露低俗的照片/視頻,嚴重者將封號" + @override + String get dont => "請勿上傳非法裸露低俗的照片/視頻,嚴重者將封號"; + /// "當前版本" + @override + String get current_version => "當前版本"; + /// "綁定銀行卡" + @override + String get bank_card => "綁定銀行卡"; + /// "請選擇開戶行" + @override + String get choose_bank => "請選擇開戶行"; + /// "請輸入銀行卡號" + @override + String get bank_number => "請輸入銀行卡號"; + /// "請輸入證件號" + @override + String get id_number => "請輸入證件號"; + /// "姓名" + @override + String get name => "姓名"; + /// "銀行卡號" + @override + String get bank_number2 => "銀行卡號"; + /// "證件號" + @override + String get license_number => "證件號"; + /// "綁定手機號" + @override + String get bind_phone => "綁定手機號"; + /// "他的主頁" + @override + String get his_homepage => "他的主頁"; + /// "她的主頁" + @override + String get her_homepage => "她的主頁"; + /// "微信支付" + @override + String get wechat_pay => "微信支付"; + /// "facebook支付" + @override + String get facebook_pay => "facebook支付"; + /// "google支付" + @override + String get google_pay => "google支付"; + /// "支付成功" + @override + String get payment_successful => "支付成功"; + /// "設置提款金額" + @override + String get set_amount => "設置提款金額"; + /// "請輸入H幣個數" + @override + String get enter_amount => "請輸入H幣個數"; + /// "可提現" + @override + String get can_withdraw => "可提現"; + /// "語言設置" + @override + String get language_set => "語言設置"; + /// "用戶協議" + @override + String get user_agreement => "用戶協議"; + /// "續費" + @override + String get renewal_fee => "續費"; + /// "立即開通" + @override + String get open_immediately => "立即開通"; + /// "總計" + @override + String get total => "總計"; + /// "半 個 月" + @override + String get half_month => "半 個 月"; + /// "/s1 個 月" + @override + String get month2 => "/s1 個 月"; + /// "取消屏蔽" + @override + String get cancel_shield => "取消屏蔽"; + /// "黑名單" + @override + String get blacklist2 => "黑名單"; + /// "(會員可延長時間達6秒)" + @override + String get longTime => "(會員可延長時間達6秒)"; + /// "按住屏幕查看" + @override + String get longClick => "按住屏幕查看"; + /// "請先結束正在生效的節目" + @override + String get stop_program => "請先結束正在生效的節目"; + /// "男士不能收藏男士" + @override + String get not_love => "男士不能收藏男士"; + /// "女士不能收藏女士" + @override + String get not_love2 => "女士不能收藏女士"; + /// "女士可以免費發布" + @override + String get women_free => "女士可以免費發布"; + /// "他還沒有上傳照片" + @override + String get not_up_man => "他還沒有上傳照片"; + /// "她還沒有上傳照片" + @override + String get not_up_women => "她還沒有上傳照片"; + /// "請勿通過平台進行不法交易,如被舉報核實將作封號處理" + @override + String get not_illage => "請勿通過平台進行不法交易,如被舉報核實將作封號處理"; + /// "已報名" + @override + String get alreay_join => "已報名"; + /// "確定刪除這張照片嗎" + @override + String get sure_delete => "確定刪除這張照片嗎"; + /// "馬上填寫" + @override + String get white_now => "馬上填寫"; + /// "你還沒有填寫個人介紹,吸引人的個人介紹對約會成功影響很大哦" + @override + String get personal => "你還沒有填寫個人介紹,吸引人的個人介紹對約會成功影響很大哦"; + /// "成功" + @override + String get success => "成功"; + /// "失敗" + @override + String get fail => "失敗"; + /// "只有認證用戶才可以設置紅包照片" + @override + String get moneyPageTip => "只有認證用戶才可以設置紅包照片"; + /// "你已報名,如果對方覺得合適將會聯繫你" + @override + String get alreadyJoin => "你已報名,如果對方覺得合適將會聯繫你"; + /// "違規警告" + @override + String get waring => "違規警告"; + /// "尊重用戶隱私,請勿截圖。如有下次,將禁止你查看其他用戶照片" + @override + String get userPravicy => "尊重用戶隱私,請勿截圖。如有下次,將禁止你查看其他用戶照片"; + /// "約會時間已經過期了,請修改" + @override + String get outTime => "約會時間已經過期了,請修改"; + /// "審核中" + @override + String get reviewing => "審核中"; + /// "審核成功" + @override + String get reviewed => "審核成功"; + /// "審核失敗" + @override + String get reviewedFail => "審核失敗"; + /// "用戶需要先綁定銀行卡才可以提現" + @override + String get needCard => "用戶需要先綁定銀行卡才可以提現"; + /// "女士不能評論女士的動態" + @override + String get women_not_d => "女士不能評論女士的動態"; + /// "男士不能評論男士的動態" + @override + String get man_not_d => "男士不能評論男士的動態"; + /// "有照片才能吸引女士哦" + @override + String get have_picture => "有照片才能吸引女士哦"; + /// "上滑取消發送" + @override + String get up_cancle => "上滑取消發送"; + /// "消息不能為空" + @override + String get msg_not => "消息不能為空"; + /// "此功能需要授予錄音權限" + @override + String get need_record => "此功能需要授予錄音權限"; + /// "正在下載視頻文件" + @override + String get downloading_video => "正在下載視頻文件"; + /// "請重新輸入問題序號" + @override + String get reinput => "請重新輸入問題序號"; + /// "你的動態被用戶匿名舉報,經系統核實已將該動態刪除,請勿再進行違規操作" + @override + String get dy_delete => "你的動態被用戶匿名舉報,經系統核實已將該動態刪除,請勿再進行違規操作"; + /// "你的節目被用戶匿名舉報,經系統核實已將該節目刪除,請勿再進行違規操作" + @override + String get pro_delete => "你的節目被用戶匿名舉報,經系統核實已將該節目刪除,請勿再進行違規操作"; + /// "你的評論被用戶匿名舉報,經系統核實已將該評論刪除,請勿再進行違規操作" + @override + String get con_delete => "你的評論被用戶匿名舉報,經系統核實已將該評論刪除,請勿再進行違規操作"; + /// "經匿名用戶舉報,系統核實你近期存在違規行為,已將你近期收到H幣進行返還。如有下次,將進行賬號凍結" + @override + String get coin_returen => "經匿名用戶舉報,系統核實你近期存在違規行為,已將你近期收到H幣進行返還。如有下次,將進行賬號凍結"; + /// "通話中禁止出現色情淫穢等違法行為,一經發現將做封號處理" + @override + String get voicing => "通話中禁止出現色情淫穢等違法行為,一經發現將做封號處理"; + /// "客服" + @override + String get help => "客服"; + /// "人工翻譯開啟" + @override + String get translate_on => "人工翻譯開啟"; + /// "人工翻譯關閉" + @override + String get translate_off => "人工翻譯關閉"; + /// "消耗/s1 H幣將續費為SVIP" + @override + String get becomeSvip => "消耗/s1 H幣將續費為SVIP"; + /// "svip權限可開啟" + @override + String get need_svip => "svip權限可開啟"; + /// "SVIP無法續費為VIP" + @override + String get cannot_vip => "SVIP無法續費為VIP"; + /// "您已離線,無法發送和接收消息" + @override + String get offline => "您已離線,無法發送和接收消息"; + /// "賬號在其他設備登錄,您已離線" + @override + String get otherLogin => "賬號在其他設備登錄,您已離線"; + /// "暫時沒有新消息" + @override + String get no_new => "暫時沒有新消息"; + /// "翻譯完畢" + @override + String get over => "翻譯完畢"; + /// "確定要對此條翻譯進行差評麼?" + @override + String get bad_ev => "確定要對此條翻譯進行差評麼?"; + /// "聊的更爽" + @override + String get right5 => "聊的更爽"; + /// "用的更爽" + @override + String get right6 => "用的更爽"; + /// "小哥哥" + @override + String get man_vi => "小哥哥"; + /// "小姐姐" + @override + String get women_vi => "小姐姐"; + /// "為了提高服務效率,如果下面有您的問題,請直接回复序號數字哦!" + @override + String get kf_tips => "為了提高服務效率,如果下面有您的問題,請直接回复序號數字哦!"; + /// "已拒絕" + @override + String get rejected => "已拒絕"; + /// "你消費了/s1H幣購買會員" + @override + String get buy_vip => "你消費了/s1H幣購買會員"; + /// "你消費了/s1H幣發布動態節目" + @override + String get buy_program => "你消費了/s1H幣發布動態節目"; + /// "你的H幣提現申請已處理,已轉賬/s1到你的賬號,請查收" + @override + String get del_add_money => "你的H幣提現申請已處理,已轉賬/s1到你的賬號,請查收"; + /// "你申請提現的/s1H幣正在審批中" + @override + String get adding_money => "你申請提現的/s1H幣正在審批中"; + /// "免費享受翻譯專員實時翻譯" + @override + String get free_translate => "免費享受翻譯專員實時翻譯"; + /// "專享客服為你服務" + @override + String get personalTraff => "專享客服為你服務"; + /// "人工翻譯中..." + @override + String get ManTranslate => "人工翻譯中..."; + /// "機器翻譯中..." + @override + String get robotTranslate => "機器翻譯中..."; + /// "人工翻譯完畢" + @override + String get translated => "人工翻譯完畢"; + /// "健康交流,請勿廣播低俗內容,一經發現將作刪除處理" + @override + String get delete_progarm => "健康交流,請勿廣播低俗內容,一經發現將作刪除處理"; + /// "定位權限未開啟" + @override + String get open_location => "定位權限未開啟"; + /// "請在手機設置中開啟定位權限以獲得其他用戶距離" + @override + String get get_location => "請在手機設置中開啟定位權限以獲得其他用戶距離"; + /// "再按一次退出" + @override + String get confirm_exit => "再按一次退出"; + /// "每天/s1次機會發布免費廣播" + @override + String get free_program => "每天/s1次機會發布免費廣播"; + /// "圖片" + @override + String get picture => "圖片"; + /// "相機" + @override + String get camera => "相機"; + /// "視頻" + @override + String get video => "視頻"; + /// "紅包" + @override + String get red_money => "紅包"; + /// "粘貼" + @override + String get stick => "粘貼"; + /// "按住說話" + @override + String get press_say => "按住說話"; + /// "/s1領取了你的紅包" + @override + String get get_money => "/s1領取了你的紅包"; + /// "你領取了/s1的紅包" + @override + String get you_get_money => "你領取了/s1的紅包"; + /// "/s1的紅包" + @override + String get ones_money => "/s1的紅包"; + /// "紅包已過期" + @override + String get money_over => "紅包已過期"; + /// "下載文件失敗" + @override + String get downloading_fail => "下載文件失敗"; + /// "正在下載視頻文件" + @override + String get downloading => "正在下載視頻文件"; + /// "未領取的紅包,將於24小時後發起退款" + @override + String get back_money => "未領取的紅包,將於24小時後發起退款"; + /// "紅包不存在" + @override + String get no_money => "紅包不存在"; + /// "紅包已領取" + @override + String get already_money => "紅包已領取"; + /// "已過期,已退到賬戶" + @override + String get back_user => "已過期,已退到賬戶"; + /// "等待對方領取" + @override + String get waiting_user => "等待對方領取"; + /// "對方已領取" + @override + String get other_get => "對方已領取"; + /// "小小意思,拿去浪吧" + @override + String get little => "小小意思,拿去浪吧"; + /// "塞錢進紅包" + @override + String get put_money => "塞錢進紅包"; + /// "金額" + @override + String get mount => "金額"; + /// "已過期" + @override + String get over_time => "已過期"; + /// "已領取" + @override + String get has_get => "已領取"; + /// "暫時沒有禮物" + @override + String get no_gift => "暫時沒有禮物"; + /// "打賞禮物" + @override + String get sent_gift => "打賞禮物"; + /// "填寫成功可以獲得/s1H幣,綁定後無法修改" + @override + String get fill_tips => "填寫成功可以獲得/s1H幣,綁定後無法修改"; + /// "綁定邀請碼" + @override + String get bind_code => "綁定邀請碼"; + /// "邀請碼" + @override + String get invide_code => "邀請碼"; + /// "確認刪除" + @override + String get confirm_delete => "確認刪除"; + /// "您已經評價過了" + @override + String get has_eva => "您已經評價過了"; + /// "開" + @override + String get open => "開"; + /// "語音" + @override + String get voice => "語音"; + /// "鬆開發送" + @override + String get release_send => "鬆開發送"; + /// "錄音時間過短" + @override + String get time_little => "錄音時間過短"; + /// "對方不在線,無法連麥" + @override + String get not_online => "對方不在線,無法連麥"; + /// "你給/s1發送了/s2H幣的紅包" + @override + String get give_red_money => "你給/s1發送了/s2H幣的紅包"; + /// "你領取了/s1的/s2H幣的紅包" + @override + String get get_red_money => "你領取了/s1的/s2H幣的紅包"; + /// "你打賞了/s1/s2H幣" + @override + String get give_other_money => "你打賞了/s1/s2H幣"; + /// "你獲得了/s1的/s2H幣的打賞" + @override + String get get_other_money => "你獲得了/s1的/s2H幣的打賞"; + /// "超級會員" + @override + String get svip => "超級會員"; + /// "推薦" + @override + String get recommend => "推薦"; + /// "你付費了(/s2H幣)查看/s1的紅包照片" + @override + String get paid_you4 => "你付費了(/s2H幣)查看/s1的紅包照片"; + /// "你付費了(/s2H幣)查看/s1的相冊" + @override + String get paid_you5 => "你付費了(/s2H幣)查看/s1的相冊"; + /// "你付費解鎖了/s1的全部資料" + @override + String get paid_you6 => "你付費解鎖了/s1的全部資料"; + /// "hiAPP許可及服務協議" + @override + String get UG_LINE0 => "hiAPP許可及服務協議"; + /// "[首部及導言]" + @override + String get UG_LINE1 => "[首部及導言]"; + /// "前海遊龍科技有限公司(以下簡稱“Qianhai Youlong Technology Co., Ltd.”)在此特別提醒用戶認真閱讀、充分理解本《服務協議》(下稱《協議》)一用戶應認真閱讀、充分理解本《協議》中各條款,包括免除或者限制Qianhai Youlong Technology Co., Ltd.責任的免責條款及對用戶的權利限制條款。請您審慎閱讀並選擇接受或不接受本《協議》(未成年人應在法定監護人陪同下閱讀)。除非您接受本《協議》所有條款,否則您無權註冊、登錄或使用本協議所涉相關服務。您的註冊、登錄、使用等行為將視為對本《協議》的接受,並同意接受本《協議》各項條款的約束。" + @override + String get UG_LINE2 => "前海遊龍科技有限公司(以下簡稱“Qianhai Youlong Technology Co., Ltd.”)在此特別提醒用戶認真閱讀、充分理解本《服務協議》(下稱《協議》)一用戶應認真閱讀、充分理解本《協議》中各條款,包括免除或者限制Qianhai Youlong Technology Co., Ltd.責任的免責條款及對用戶的權利限制條款。請您審慎閱讀並選擇接受或不接受本《協議》(未成年人應在法定監護人陪同下閱讀)。除非您接受本《協議》所有條款,否則您無權註冊、登錄或使用本協議所涉相關服務。您的註冊、登錄、使用等行為將視為對本《協議》的接受,並同意接受本《協議》各項條款的約束。"; + /// "本《協議》是您(下稱“用戶”與Qianhai Youlong Technology Co., Ltd.之間關於用戶註冊、登錄、使用“hi服務所訂立的協議。本《協議》描述Qianhai Youlong Technology Co., Ltd.與用戶之間關於“hi服務相關方面的權利義務。“用戶”是指註冊、登錄、使用、瀏覽本服務的個人或組織。您對本協議的接受即受全部條款的約束,包括接受Qianhai Youlong Technology Co., Ltd.對任意服務條款隨時所做的任何修改。本《協議》可由Qianhai Youlong Technology Co., Ltd.隨時更新,更新後的協議條款一旦公佈即代替原來的協議條款,恕不再另行通知,用戶可在本APP查閱最新版協議條款。在Qianhai Youlong Technology Co., Ltd.修改《協議》條款後,如果用戶不接受修改後的條款,請立即停止使用Qianhai Youlong Technology Co., Ltd.提供的服務,用戶繼續使用Qianhai Youlong Technology Co., Ltd.提供的服務將被視為已接受了修改後的協議。" + @override + String get UG_LINE3 => "本《協議》是您(下稱“用戶”與Qianhai Youlong Technology Co., Ltd.之間關於用戶註冊、登錄、使用“hi服務所訂立的協議。本《協議》描述Qianhai Youlong Technology Co., Ltd.與用戶之間關於“hi服務相關方面的權利義務。“用戶”是指註冊、登錄、使用、瀏覽本服務的個人或組織。您對本協議的接受即受全部條款的約束,包括接受Qianhai Youlong Technology Co., Ltd.對任意服務條款隨時所做的任何修改。本《協議》可由Qianhai Youlong Technology Co., Ltd.隨時更新,更新後的協議條款一旦公佈即代替原來的協議條款,恕不再另行通知,用戶可在本APP查閱最新版協議條款。在Qianhai Youlong Technology Co., Ltd.修改《協議》條款後,如果用戶不接受修改後的條款,請立即停止使用Qianhai Youlong Technology Co., Ltd.提供的服務,用戶繼續使用Qianhai Youlong Technology Co., Ltd.提供的服務將被視為已接受了修改後的協議。"; + /// "一、使用規則" + @override + String get UG_LINE4 => "一、使用規則"; + /// "1、用戶充分了解並同意,僅為用戶提供信息分享、傳送及獲取的平台,用戶必須為自己註冊帳號下的一切行為負責,包括但不限於您所傳送的任何內容以及由此產生的任何結果。" + @override + String get UG_LINE5 => "1、用戶充分了解並同意,僅為用戶提供信息分享、傳送及獲取的平台,用戶必須為自己註冊帳號下的一切行為負責,包括但不限於您所傳送的任何內容以及由此產生的任何結果。"; + /// "2、用戶在服務中或通過服務所傳送的任何內容並不反映Qianhai Youlong Technology Co., Ltd.的觀點或政策,Qianhai Youlong Technology Co., Ltd.對此不承擔任何責任。" + @override + String get UG_LINE6 => "2、用戶在服務中或通過服務所傳送的任何內容並不反映Qianhai Youlong Technology Co., Ltd.的觀點或政策,Qianhai Youlong Technology Co., Ltd.對此不承擔任何責任。"; + /// "3、用戶充分了解並同意,是一個基於用戶關係網的社交信息瀏覽產品,用戶須對在上的註冊信息的真實性、合法性、有效性承擔全部責任,用戶不得冒充他人;不得利用他人的名義傳播任何信息;不得惡意使用註冊帳號導致其他用戶誤認;否則Qianhai Youlong Technology Co., Ltd.有權立即停止提供服務,收回帳號並由用戶獨自承擔由此而產生的一切法律責任。" + @override + String get UG_LINE7 => "3、用戶充分了解並同意,是一個基於用戶關係網的社交信息瀏覽產品,用戶須對在上的註冊信息的真實性、合法性、有效性承擔全部責任,用戶不得冒充他人;不得利用他人的名義傳播任何信息;不得惡意使用註冊帳號導致其他用戶誤認;否則Qianhai Youlong Technology Co., Ltd.有權立即停止提供服務,收回帳號並由用戶獨自承擔由此而產生的一切法律責任。"; + /// "4、用戶須對在上所傳送信息的真實性、合法性、無害性、有效性等全權負責,與用戶所傳播的信息相關的任何法律責任由用戶自行承擔,與Qianhai Youlong Technology Co., Ltd.無關。" + @override + String get UG_LINE8 => "4、用戶須對在上所傳送信息的真實性、合法性、無害性、有效性等全權負責,與用戶所傳播的信息相關的任何法律責任由用戶自行承擔,與Qianhai Youlong Technology Co., Ltd.無關。"; + /// "5、Qianhai Youlong Technology Co., Ltd.保留因業務發展需要,單方面對本服務的全部或部分服務內容在任何時候不經任何通知的情況下變更、暫停、限制、終止或撤銷服務的權利,用戶需承擔此風險。" + @override + String get UG_LINE9 => "5、Qianhai Youlong Technology Co., Ltd.保留因業務發展需要,單方面對本服務的全部或部分服務內容在任何時候不經任何通知的情況下變更、暫停、限制、終止或撤銷服務的權利,用戶需承擔此風險。"; + /// "6、提供的服務中可能包括廣告,用戶同意在使用過程中顯示和第三方供應商、合作夥伴提供的廣告。" + @override + String get UG_LINE10 => "6、提供的服務中可能包括廣告,用戶同意在使用過程中顯示和第三方供應商、合作夥伴提供的廣告。"; + /// "7、用戶不得利用或服務製作、上載、複製、發送如下內容:" + @override + String get UG_LINE11 => "7、用戶不得利用或服務製作、上載、複製、發送如下內容:"; + /// "(1 )反對憲法所確定的基本原則的;" + @override + String get UG_LINE12 => "(1 )反對憲法所確定的基本原則的;"; + /// "(2)危害國家安全,洩露國家秘密,顛覆國家政權,破壞國家統一-的;" + @override + String get UG_LINE13 => "(2)危害國家安全,洩露國家秘密,顛覆國家政權,破壞國家統一-的;"; + /// "(3)損害國家榮譽和利益的;" + @override + String get UG_LINE14 => "(3)損害國家榮譽和利益的;"; + /// "(4)煽動民族仇恨、民族歧視,破壞民族團結的;" + @override + String get UG_LINE15 => "(4)煽動民族仇恨、民族歧視,破壞民族團結的;"; + /// "(5)破壞國家宗教政策,宣揚邪教和封建迷信的;" + @override + String get UG_LINE16 => "(5)破壞國家宗教政策,宣揚邪教和封建迷信的;"; + /// "(6)散佈謠言,擾亂社會秩序,破壞社會穩定的;" + @override + String get UG_LINE17 => "(6)散佈謠言,擾亂社會秩序,破壞社會穩定的;"; + /// "(7)散佈淫穢、色情、賭博、暴力、兇殺、恐怖或者教唆犯罪的;" + @override + String get UG_LINE18 => "(7)散佈淫穢、色情、賭博、暴力、兇殺、恐怖或者教唆犯罪的;"; + /// "(8)侮辱或者誹謗他人,侵害他人合法權益的;" + @override + String get UG_LINE19 => "(8)侮辱或者誹謗他人,侵害他人合法權益的;"; + /// "(9)含有法律、行政法規禁止的其他內容的信息。" + @override + String get UG_LINE20 => "(9)含有法律、行政法規禁止的其他內容的信息。"; + /// "8、Qianhai Youlong Technology Co., Ltd.可依其合理判斷,對違反有關法律法規或本協議約定;或侵犯、妨害、威脅任何人權利或安全的內容,或者假冒他人的行為,Qianhai Youlong Technology Co., Ltd.有權依法停止傳輸任何前述內容,並有權依其自行判斷對違反本條款的任何人士採取適當的法律行動,包括但不限於從服務中刪除具有違法性、侵權性、不當性等內容,終止違反者的成員資格,阻止其使用全部或部分服務,並且依據法律法規保存有關信息並向有關部門報告等。" + @override + String get UG_LINE21 => "8、Qianhai Youlong Technology Co., Ltd.可依其合理判斷,對違反有關法律法規或本協議約定;或侵犯、妨害、威脅任何人權利或安全的內容,或者假冒他人的行為,Qianhai Youlong Technology Co., Ltd.有權依法停止傳輸任何前述內容,並有權依其自行判斷對違反本條款的任何人士採取適當的法律行動,包括但不限於從服務中刪除具有違法性、侵權性、不當性等內容,終止違反者的成員資格,阻止其使用全部或部分服務,並且依據法律法規保存有關信息並向有關部門報告等。"; + /// "9、用戶權利及義務:" + @override + String get UG_LINE22 => "9、用戶權利及義務:"; + /// "(1 )Qianhai Youlong Technology Co., Ltd.帳號的所有權歸Qianhai Youlong Technology Co., Ltd.所有,用戶完成申請註冊手續後,獲得帳號的使用權,該使用權屬於初始申請註冊人,禁止贈與、借用、租用、轉讓或售賣。 Qianhai Youlong Technology Co., Ltd.因經營需要,有權回收用戶的帳號,並有權使用用戶照片、視頻、語音等進行產品宣傳活動。" + @override + String get UG_LINE23 => "(1 )Qianhai Youlong Technology Co., Ltd.帳號的所有權歸Qianhai Youlong Technology Co., Ltd.所有,用戶完成申請註冊手續後,獲得帳號的使用權,該使用權屬於初始申請註冊人,禁止贈與、借用、租用、轉讓或售賣。 Qianhai Youlong Technology Co., Ltd.因經營需要,有權回收用戶的帳號,並有權使用用戶照片、視頻、語音等進行產品宣傳活動。"; + /// "(2)用戶有權更改、刪除在Qianhai Youlong Technology Co., Ltd.上的個人資料、註冊信息及傳送內容等,但需注意,刪除有關信息的同時也會刪除任何您儲存在系統中的文字和圖片。用戶需承擔該風險。" + @override + String get UG_LINE24 => "(2)用戶有權更改、刪除在Qianhai Youlong Technology Co., Ltd.上的個人資料、註冊信息及傳送內容等,但需注意,刪除有關信息的同時也會刪除任何您儲存在系統中的文字和圖片。用戶需承擔該風險。"; + /// "(3)用戶有責任妥善保管註冊帳號信息及帳號密碼的安全,用戶需要對註冊帳號以及密碼下的行為承擔法律責任。用戶同意在任何情況下不使用其他成員的帳號或密碼。在您懷疑他人在使用您的帳號或密碼時,您同意立即通知Qianhai Youlong Technology Co., Ltd.。" + @override + String get UG_LINE25 => "(3)用戶有責任妥善保管註冊帳號信息及帳號密碼的安全,用戶需要對註冊帳號以及密碼下的行為承擔法律責任。用戶同意在任何情況下不使用其他成員的帳號或密碼。在您懷疑他人在使用您的帳號或密碼時,您同意立即通知Qianhai Youlong Technology Co., Ltd.。"; + /// "(4)用戶應遵守本協議的各項條款,正確、適當地使用本服務,如因用戶違反本協議中的任何條款,Qianhai Youlong Technology Co., Ltd.有權依據協議終止對違約用戶Qianhai Youlong Technology Co., Ltd.帳號提供服務。同時,Qianhai Youlong Technology Co., Ltd.保留在任何時候收回Qianhai Youlong Technology Co., Ltd.帳號、用戶名的權利。" + @override + String get UG_LINE26 => "(4)用戶應遵守本協議的各項條款,正確、適當地使用本服務,如因用戶違反本協議中的任何條款,Qianhai Youlong Technology Co., Ltd.有權依據協議終止對違約用戶Qianhai Youlong Technology Co., Ltd.帳號提供服務。同時,Qianhai Youlong Technology Co., Ltd.保留在任何時候收回Qianhai Youlong Technology Co., Ltd.帳號、用戶名的權利。"; + /// "(5)如果用戶有自己的常用英文帳號,那麼用戶有優先將該英文帳號註冊為帳號的權利,但是如果用戶在服務上線後一段時間內沒有註冊帳號,或者用戶雖然註冊了微信帳號,但是並不是使用該英文帳號作為微信帳號的,視為用戶放棄了將該英文帳號註冊為微信帳號的權利,Qianhai Youlong Technology Co., Ltd.有權將該英文帳號回收並分配給其他用戶使用,以免造成資源浪費,由此帶來問題均由用戶自行承擔。" + @override + String get UG_LINE27 => "(5)如果用戶有自己的常用英文帳號,那麼用戶有優先將該英文帳號註冊為帳號的權利,但是如果用戶在服務上線後一段時間內沒有註冊帳號,或者用戶雖然註冊了微信帳號,但是並不是使用該英文帳號作為微信帳號的,視為用戶放棄了將該英文帳號註冊為微信帳號的權利,Qianhai Youlong Technology Co., Ltd.有權將該英文帳號回收並分配給其他用戶使用,以免造成資源浪費,由此帶來問題均由用戶自行承擔。"; + /// "(6)用戶註冊帳號後如果長期不登錄該帳號,Qianhai Youlong Technology Co., Ltd.有權回收該帳號,以免造成資源浪費,由此帶來問題均由用戶自行承擔。" + @override + String get UG_LINE28 => "(6)用戶註冊帳號後如果長期不登錄該帳號,Qianhai Youlong Technology Co., Ltd.有權回收該帳號,以免造成資源浪費,由此帶來問題均由用戶自行承擔。"; + /// "(7)用戶發生糾紛可使用舉報功能維護用戶平台權益,若收到用戶舉報反饋,被舉報用戶有義務主動告知或配合客服人員核實情況,舉報內容核實屬實,面具公園有權對用戶警告、限制賬號使用功能等方式約束用戶違規行為,嚴重違規者hi有權直接凍結賬號,且賬戶內餘額不返還。如果賬號被凍結需申訴,用戶可聯繫客服 。" + @override + String get UG_LINE29 => "(7)用戶發生糾紛可使用舉報功能維護用戶平台權益,若收到用戶舉報反饋,被舉報用戶有義務主動告知或配合客服人員核實情況,舉報內容核實屬實,面具公園有權對用戶警告、限制賬號使用功能等方式約束用戶違規行為,嚴重違規者hi有權直接凍結賬號,且賬戶內餘額不返還。如果賬號被凍結需申訴,用戶可聯繫客服 。"; + /// "二、隱私保護" + @override + String get UG_LINE30 => "二、隱私保護"; + /// "用戶同意個人隱私信息是指那些能夠對用戶進行個人辨識或涉及個人通信的信息,包括下列信息:用戶真實姓名,手機號碼,微信賬號,facebook賬號,IP地址。而非個人隱私信息是指用戶對本服務的操作狀態以及使用習慣等一些明確且客觀反映在Qianhai Youlong Technology Co., Ltd.服務器端的基本記錄信息和其他一切個人隱私信息範圍外的普通信息;以及用戶同意公開的上述隱私信息。尊重用戶個人隱私信息的私有性是Qianhai Youlong Technology Co., Ltd.的一貫制度,Qianhai Youlong Technology Co., Ltd.將會採取合理的措施保護用戶的個人隱私信息,除法律或有法律賦予權限的政府部門要求或用戶同意等原因外,Qianhai Youlong Technology Co., Ltd.未經用戶同意不向除合作單位以外的第三方公開、透露用戶個人隱私信息。但是,用戶在註冊時選擇同意,或用戶與Qianhai Youlong Technology Co., Ltd.及合作單位之間就用戶個人隱私信息公開或使用另有約定的除外,同時用戶應自行承擔因此可能產生的任何風險,Qianhai Youlong Technology Co., Ltd.對此不予負責。同時,為了運營和改善Qianhai Youlong Technology Co., Ltd.的技術和服務,Qianhai Youlong Technology Co., Ltd.將可能會自行收集使用或向第三方提供用戶的非個人隱私信息,這將有助於Qianhai Youlong Technology Co., Ltd.向用戶提供更好的用戶體驗和提高Qianhai Youlong Technology Co., Ltd.的服務質量。 Qianhai Youlong Technology Co., Ltd.收集數據是根據用戶與Qianhai Youlong Technology Co., Ltd.的互動和用戶所做出的選擇,包括用戶的隱私設置以及用戶使用的產品和功能。 Qianhai Youlong Technology Co., Ltd.收集的數據可能包括SDK/API/JS代碼版本、IP地址、平台、時間戳、應用標識符、應用程序版本、應用分發渠道、獨立設備標識符、iOS廣告標識符(IDFA)、 安卓廣告主標識符、網卡(MAC) 地址、國際移動設備識別碼(IMEI)、設備型號、終端製造廠商、終端設備操作系統版本、會話啟動/停止時間、語言所在地、時區和網絡狀態(WiFi等)、硬盤、 CPU和電池使用情況等。這將有助於Qianhai Youlong Technology Co., Ltd.開展內部數據分析和研究,第三方SDK統計服務,改善Qianhai Youlong Technology Co., Ltd.的產品或服務。為確保用戶身份真實性,向用戶提供更好的安全保障,用戶需提交的身份信息或面部特徵等生物識別信息(均屬於個人敏感信息)來完成具體產品服務所需或必要的真人認證。 .上 述信息將僅用於核實用戶身份的真實性。用戶提供的.上述信息,將在用戶使用本服務期間持續授權Qianhai Youlong Technology Co., Ltd.使用。在用戶註銷賬號時,Qianhai Youlong Technology Co., Ltd.將停止使用。上述信息將存儲於中華人民共和國境內。如需跨境傳輸,Qianhai Youlong Technology Co., Ltd.將會單獨徵得用戶的授權同意。 App用戶真實性認證需要用戶提供能證實用戶身份真實性的部分資料。相關資料只用做平台審核不會披露給任何其他用戶或用於商業用途,僅法律或有關部門要求介入除外。" + @override + String get UG_LINE31 => "用戶同意個人隱私信息是指那些能夠對用戶進行個人辨識或涉及個人通信的信息,包括下列信息:用戶真實姓名,手機號碼,微信賬號,facebook賬號,IP地址。而非個人隱私信息是指用戶對本服務的操作狀態以及使用習慣等一些明確且客觀反映在Qianhai Youlong Technology Co., Ltd.服務器端的基本記錄信息和其他一切個人隱私信息範圍外的普通信息;以及用戶同意公開的上述隱私信息。尊重用戶個人隱私信息的私有性是Qianhai Youlong Technology Co., Ltd.的一貫制度,Qianhai Youlong Technology Co., Ltd.將會採取合理的措施保護用戶的個人隱私信息,除法律或有法律賦予權限的政府部門要求或用戶同意等原因外,Qianhai Youlong Technology Co., Ltd.未經用戶同意不向除合作單位以外的第三方公開、透露用戶個人隱私信息。但是,用戶在註冊時選擇同意,或用戶與Qianhai Youlong Technology Co., Ltd.及合作單位之間就用戶個人隱私信息公開或使用另有約定的除外,同時用戶應自行承擔因此可能產生的任何風險,Qianhai Youlong Technology Co., Ltd.對此不予負責。同時,為了運營和改善Qianhai Youlong Technology Co., Ltd.的技術和服務,Qianhai Youlong Technology Co., Ltd.將可能會自行收集使用或向第三方提供用戶的非個人隱私信息,這將有助於Qianhai Youlong Technology Co., Ltd.向用戶提供更好的用戶體驗和提高Qianhai Youlong Technology Co., Ltd.的服務質量。 Qianhai Youlong Technology Co., Ltd.收集數據是根據用戶與Qianhai Youlong Technology Co., Ltd.的互動和用戶所做出的選擇,包括用戶的隱私設置以及用戶使用的產品和功能。 Qianhai Youlong Technology Co., Ltd.收集的數據可能包括SDK/API/JS代碼版本、IP地址、平台、時間戳、應用標識符、應用程序版本、應用分發渠道、獨立設備標識符、iOS廣告標識符(IDFA)、 安卓廣告主標識符、網卡(MAC) 地址、國際移動設備識別碼(IMEI)、設備型號、終端製造廠商、終端設備操作系統版本、會話啟動/停止時間、語言所在地、時區和網絡狀態(WiFi等)、硬盤、 CPU和電池使用情況等。這將有助於Qianhai Youlong Technology Co., Ltd.開展內部數據分析和研究,第三方SDK統計服務,改善Qianhai Youlong Technology Co., Ltd.的產品或服務。為確保用戶身份真實性,向用戶提供更好的安全保障,用戶需提交的身份信息或面部特徵等生物識別信息(均屬於個人敏感信息)來完成具體產品服務所需或必要的真人認證。 .上 述信息將僅用於核實用戶身份的真實性。用戶提供的.上述信息,將在用戶使用本服務期間持續授權Qianhai Youlong Technology Co., Ltd.使用。在用戶註銷賬號時,Qianhai Youlong Technology Co., Ltd.將停止使用。上述信息將存儲於中華人民共和國境內。如需跨境傳輸,Qianhai Youlong Technology Co., Ltd.將會單獨徵得用戶的授權同意。 App用戶真實性認證需要用戶提供能證實用戶身份真實性的部分資料。相關資料只用做平台審核不會披露給任何其他用戶或用於商業用途,僅法律或有關部門要求介入除外。"; + /// "三、Qianhai Youlong Technology Co., Ltd.商標信息" + @override + String get UG_LINE32 => "三、Qianhai Youlong Technology Co., Ltd.商標信息"; + /// "Qianhai Youlong Technology Co., Ltd.服務中所涉及的logo等圖形、文字或其組成,以及其他Qianhai Youlong Technology Co., Ltd.標誌及產品、服務名稱,均為Qianhai Youlong Technology Co., Ltd.之商標(以下簡稱“Qianhai Youlong Technology Co., Ltd.標識”)。未經Qianhai Youlong Technology Co., Ltd.事先書面同意,用戶不得將Qianhai Youlong Technology Co., Ltd.標識以任何方式展示或使用或作其他處理,也不得向他人表明您有權展示、使用、或其他有權處理Qianhai Youlong Technology Co., Ltd.標識的行為。" + @override + String get UG_LINE33 => "Qianhai Youlong Technology Co., Ltd.服務中所涉及的logo等圖形、文字或其組成,以及其他Qianhai Youlong Technology Co., Ltd.標誌及產品、服務名稱,均為Qianhai Youlong Technology Co., Ltd.之商標(以下簡稱“Qianhai Youlong Technology Co., Ltd.標識”)。未經Qianhai Youlong Technology Co., Ltd.事先書面同意,用戶不得將Qianhai Youlong Technology Co., Ltd.標識以任何方式展示或使用或作其他處理,也不得向他人表明您有權展示、使用、或其他有權處理Qianhai Youlong Technology Co., Ltd.標識的行為。"; + /// "四、法律責任及免責" + @override + String get UG_LINE34 => "四、法律責任及免責"; + /// "1、用戶違反本《協議》或相關的服務條款的規定,導致或產生的任何第三方主張的任何索賠、要求或損失,包括合理的律師費,用戶同意賠償Qianhai Youlong Technology Co., Ltd.與合作公司、關聯公司,並使之免受損害。" + @override + String get UG_LINE35 => "1、用戶違反本《協議》或相關的服務條款的規定,導致或產生的任何第三方主張的任何索賠、要求或損失,包括合理的律師費,用戶同意賠償Qianhai Youlong Technology Co., Ltd.與合作公司、關聯公司,並使之免受損害。"; + /// "2、用戶因第三方如電信部門的通訊線路故障、技術問題、網絡、電腦故障、系統不穩定性及其他各種不可抗力原因而遭受的一切損失,Qianhai Youlong Technology Co., Ltd.及合作單位不承擔責任。" + @override + String get UG_LINE36 => "2、用戶因第三方如電信部門的通訊線路故障、技術問題、網絡、電腦故障、系統不穩定性及其他各種不可抗力原因而遭受的一切損失,Qianhai Youlong Technology Co., Ltd.及合作單位不承擔責任。"; + /// "3、因技術故障等不可抗事件影響到服務的正常運行的,Qianhai Youlong Technology Co., Ltd.及合作單位承諾在第一時間內與相關單位配合,及時處理進行修復,但用戶因此而遭受的一切損失,Qianhai Youlong Technology Co., Ltd.及合作單位不承擔責任。" + @override + String get UG_LINE37 => "3、因技術故障等不可抗事件影響到服務的正常運行的,Qianhai Youlong Technology Co., Ltd.及合作單位承諾在第一時間內與相關單位配合,及時處理進行修復,但用戶因此而遭受的一切損失,Qianhai Youlong Technology Co., Ltd.及合作單位不承擔責任。"; + /// "4、本服務同大多數互聯網服務一樣,受包括但不限於用戶原因、網絡服務質量、社會環境等因素的差異影響,可能受到各種安全問題的侵擾,如他人利用用戶的資料,造成現實生活中的騷擾;用戶下載安裝的其它軟件或訪問的其他網站中含有“特洛伊木馬”等病毒,威脅到用戶的計算機信息和數據的安全,繼而影響本服務的正常使用等等。用戶應加強信息安全及使用者資料的保護意識,要注意加強密碼保護,以免遭致損失和騷擾。" + @override + String get UG_LINE38 => "4、本服務同大多數互聯網服務一樣,受包括但不限於用戶原因、網絡服務質量、社會環境等因素的差異影響,可能受到各種安全問題的侵擾,如他人利用用戶的資料,造成現實生活中的騷擾;用戶下載安裝的其它軟件或訪問的其他網站中含有“特洛伊木馬”等病毒,威脅到用戶的計算機信息和數據的安全,繼而影響本服務的正常使用等等。用戶應加強信息安全及使用者資料的保護意識,要注意加強密碼保護,以免遭致損失和騷擾。"; + /// "5、用戶須明白,使用本服務因涉及Internet服務,可能會受到各個環節不穩定因素的影響。因此,本服務存在因不可抗力、計算機病毒或黑客攻擊、系統不穩定、用戶所在位置、用戶關機以及其他任何技術、互聯網絡、通信線路原因等造成的服務中斷或不能滿足用戶要求的風險。用戶須承擔以上風險,Qianhai Youlong Technology Co., Ltd.不作擔保。對因此導致用戶不能發送和接受閱讀信息、或接發錯信息,Qianhai Youlong Technology Co., Ltd.不承擔任何責任。" + @override + String get UG_LINE39 => "5、用戶須明白,使用本服務因涉及Internet服務,可能會受到各個環節不穩定因素的影響。因此,本服務存在因不可抗力、計算機病毒或黑客攻擊、系統不穩定、用戶所在位置、用戶關機以及其他任何技術、互聯網絡、通信線路原因等造成的服務中斷或不能滿足用戶要求的風險。用戶須承擔以上風險,Qianhai Youlong Technology Co., Ltd.不作擔保。對因此導致用戶不能發送和接受閱讀信息、或接發錯信息,Qianhai Youlong Technology Co., Ltd.不承擔任何責任。"; + /// "6、用戶須明白,在使用本服務過程中存在有來自,任何他人的包括威脅性的、誹謗性的、令人反感的或非法的內容或行為或對他人權利的侵犯(包括知識產權)的匿名或冒名的信息的風險,用戶須承擔以上風險,Qianhai Youlong Technology Co., Ltd.和合作公司對本服務不作任何類型的擔保,不論是明確的或隱含的,包括所有有關信息真實性、適商性、適於某一特定用途、所有權和非侵權性的默示擔保和條件,對因此導致任何因用戶不正當或非法使用服務產生的直接、間接、偶然、特殊及後續的損害,不承擔任何責任。" + @override + String get UG_LINE40 => "6、用戶須明白,在使用本服務過程中存在有來自,任何他人的包括威脅性的、誹謗性的、令人反感的或非法的內容或行為或對他人權利的侵犯(包括知識產權)的匿名或冒名的信息的風險,用戶須承擔以上風險,Qianhai Youlong Technology Co., Ltd.和合作公司對本服務不作任何類型的擔保,不論是明確的或隱含的,包括所有有關信息真實性、適商性、適於某一特定用途、所有權和非侵權性的默示擔保和條件,對因此導致任何因用戶不正當或非法使用服務產生的直接、間接、偶然、特殊及後續的損害,不承擔任何責任。"; + /// "7、Qianhai Youlong Technology Co., Ltd.定義的信息內容包括:文字、軟件、聲音、相片、錄像、圖表;在廣告中全部內容;Qianhai Youlong Technology Co., Ltd.為用戶提供的商業信息,所有這些內容受版權、商標權、和其它知識產權和所有權法律的保護。所以,用戶只能在Qianhai Youlong Technology Co., Ltd.和廣告商授權下才能使用這些內容,而不能擅自複制、修改、編纂這.些內容、或創造與內容有關的衍生產品。" + @override + String get UG_LINE41 => "7、Qianhai Youlong Technology Co., Ltd.定義的信息內容包括:文字、軟件、聲音、相片、錄像、圖表;在廣告中全部內容;Qianhai Youlong Technology Co., Ltd.為用戶提供的商業信息,所有這些內容受版權、商標權、和其它知識產權和所有權法律的保護。所以,用戶只能在Qianhai Youlong Technology Co., Ltd.和廣告商授權下才能使用這些內容,而不能擅自複制、修改、編纂這.些內容、或創造與內容有關的衍生產品。"; + /// "8、在任何情況下,Qianhai Youlong Technology Co., Ltd.均不對任何間接性、後果性、懲罰性、偶然性、特殊性或刑罰性的損害,包括因用戶使用服務而遭受的利潤損失,承擔責任(即使已被告知該等損失的可能性亦然)。儘管本協議中可能含有相悖的規定,Qianhai Youlong Technology Co., Ltd.對您承擔的全部責任,無論因何原因或何種行為方式,始終不超過您在成員期內因使用服務而支付給Qianhai Youlong Technology Co., Ltd.的費用。" + @override + String get UG_LINE42 => "8、在任何情況下,Qianhai Youlong Technology Co., Ltd.均不對任何間接性、後果性、懲罰性、偶然性、特殊性或刑罰性的損害,包括因用戶使用服務而遭受的利潤損失,承擔責任(即使已被告知該等損失的可能性亦然)。儘管本協議中可能含有相悖的規定,Qianhai Youlong Technology Co., Ltd.對您承擔的全部責任,無論因何原因或何種行為方式,始終不超過您在成員期內因使用服務而支付給Qianhai Youlong Technology Co., Ltd.的費用。"; + /// "五、會員條款" + @override + String get UG_LINE43 => "五、會員條款"; + /// "1、hi會員平等享有會員的權利,同時應遵守Qianhai Youlong Technology Co., Ltd.的各項規範、規則,包括但不限於本服務條款和《用戶協議》。" + @override + String get UG_LINE44 => "1、hi會員平等享有會員的權利,同時應遵守Qianhai Youlong Technology Co., Ltd.的各項規範、規則,包括但不限於本服務條款和《用戶協議》。"; + /// "2、因違反Qianhai Youlong Technology Co., Ltd.《用戶協議》而導致會員服務被暫停使用的相關損失,由用戶自行承擔。" + @override + String get UG_LINE45 => "2、因違反Qianhai Youlong Technology Co., Ltd.《用戶協議》而導致會員服務被暫停使用的相關損失,由用戶自行承擔。"; + /// "3、會員在會員資格有效期內可以享受hi會員的各項增值服務。" + @override + String get UG_LINE46 => "3、會員在會員資格有效期內可以享受hi會員的各項增值服務。"; + /// "4、如會員在會員資格有效期內主動終止或取消會員資格,Qianhai Youlong Technology Co., Ltd.不負責退還與該會員剩餘會員資格有效期對應的服務費用。" + @override + String get UG_LINE47 => "4、如會員在會員資格有效期內主動終止或取消會員資格,Qianhai Youlong Technology Co., Ltd.不負責退還與該會員剩餘會員資格有效期對應的服務費用。"; + /// "5、會員自行承擔在hi中傳送、發布信息及使用hi免費服務或收費服務的法律責任,會員使用hi服務,包括免費服務與收費服務的行為,均應遵守各項法律法規、規章、規範性文件。" + @override + String get UG_LINE48 => "5、會員自行承擔在hi中傳送、發布信息及使用hi免費服務或收費服務的法律責任,會員使用hi服務,包括免費服務與收費服務的行為,均應遵守各項法律法規、規章、規範性文件。"; + /// "6、會員服務開通之後,不可進行轉讓或退訂。" + @override + String get UG_LINE49 => "6、會員服務開通之後,不可進行轉讓或退訂。"; + /// "7、因會員在使用Qianhai Youlong Technology Co., Ltd.免費服務或收費服務的過程中,存在違反法律法規的行為,Qianhai Youlong Technology Co., Ltd.有權取消該會員的會員資格而無須給予任何補償,且該會員須自行承擔全部責任。" + @override + String get UG_LINE50 => "7、因會員在使用Qianhai Youlong Technology Co., Ltd.免費服務或收費服務的過程中,存在違反法律法規的行為,Qianhai Youlong Technology Co., Ltd.有權取消該會員的會員資格而無須給予任何補償,且該會員須自行承擔全部責任。"; + /// "六、其他條款" + @override + String get UG_LINE51 => "六、其他條款"; + /// "1、Qianhai Youlong Technology Co., Ltd.鄭重提醒用戶注意本《協議》中免除Qianhai Youlong Technology Co., Ltd.責任和加重用戶義務的條款,請用戶仔細閱讀,自主考慮風險。未成年人應在法定監護人的陪同下閱讀本《協議》。以上各項條款內容的最終解釋權及修改權歸Qianhai Youlong Technology Co., Ltd.所有。" + @override + String get UG_LINE52 => "1、Qianhai Youlong Technology Co., Ltd.鄭重提醒用戶注意本《協議》中免除Qianhai Youlong Technology Co., Ltd.責任和加重用戶義務的條款,請用戶仔細閱讀,自主考慮風險。未成年人應在法定監護人的陪同下閱讀本《協議》。以上各項條款內容的最終解釋權及修改權歸Qianhai Youlong Technology Co., Ltd.所有。"; + /// "2、本《協議》所定的任何條款的部分或全部無效者,不影響其它條款的效力。" + @override + String get UG_LINE53 => "2、本《協議》所定的任何條款的部分或全部無效者,不影響其它條款的效力。"; + /// "3、本《協議》的解釋、效力及糾紛的解決,適用於中華人民共和國法律。若用戶和Qianhai Youlong Technology Co., Ltd.之間發生任何糾紛或爭議,首先應友好協商解決,協商不成的,用戶在此完全同意將糾紛或爭議提交Qianhai Youlong Technology Co., Ltd.住所地的人民法院管轄。" + @override + String get UG_LINE54 => "3、本《協議》的解釋、效力及糾紛的解決,適用於中華人民共和國法律。若用戶和Qianhai Youlong Technology Co., Ltd.之間發生任何糾紛或爭議,首先應友好協商解決,協商不成的,用戶在此完全同意將糾紛或爭議提交Qianhai Youlong Technology Co., Ltd.住所地的人民法院管轄。"; + /// "4、本《協議》的版權由Qianhai Youlong Technology Co., Ltd.所有,Qianhai Youlong Technology Co., Ltd.保留一切解釋和修改權利。" + @override + String get UG_LINE55 => "4、本《協議》的版權由Qianhai Youlong Technology Co., Ltd.所有,Qianhai Youlong Technology Co., Ltd.保留一切解釋和修改權利。"; + /// "前海遊龍科技有限公司" + @override + String get UG_LINE56 => "前海遊龍科技有限公司"; + /// "網絡異常" + @override + String get net_error => "網絡異常"; + /// "請輸入姓名" + @override + String get enter_name => "請輸入姓名"; + /// "譯" + @override + String get translate => "譯"; + /// "位置" + @override + String get locate => "位置"; + /// "按住錄音,鬆開發送" + @override + String get voice_tips => "按住錄音,鬆開發送"; + /// "解鎖" + @override + String get unlock => "解鎖"; + /// "請輸入聊天內容" + @override + String get input_content => "請輸入聊天內容"; + /// "連接中..." + @override + String get connecting => "連接中..."; + /// "登陸中..." + @override + String get logining => "登陸中..."; + /// "/s1拒絕了你的查看申請" + @override + String get reject_reply => "/s1拒絕了你的查看申請"; + /// "H幣進賬3天內沒人舉報你即可兌消(1:1000越南盾)" + @override + String get warning_text => "H幣進賬3天內沒人舉報你即可兌消(1:1000越南盾)"; + /// "輸入個數不大於/s1" + @override + String get more_big => "輸入個數不大於/s1"; + /// "輸入個數不小於/s1" + @override + String get little_min => "輸入個數不小於/s1"; + /// "/s1邀請你進行通話" + @override + String get voice_msg => "/s1邀請你進行通話"; + /// "你打賞了對方/s1個/s2" + @override + String get send_gift => "你打賞了對方/s1個/s2"; + /// "對方打賞了你/s1個/s2" + @override + String get receive_gift => "對方打賞了你/s1個/s2"; + /// "非會員不能報名" + @override + String get cannot_join => "非會員不能報名"; + /// "已退回" + @override + String get alreay_back => "已退回"; + /// "文件過大" + @override + String get video_more_big => "文件過大"; + /// "選擇所有" + @override + String get select_all => "選擇所有"; + /// "重新連接" + @override + String get re_connect => "重新連接"; + /// "鬆開發送,滑動取消" + @override + String get voice_tips2 => "鬆開發送,滑動取消"; + /// "國籍" + @override + String get country => "國籍"; + /// "有照片審核中" + @override + String get have_picture_view => "有照片審核中"; + /// "揚聲器播放" + @override + String get speaker_play => "揚聲器播放"; + /// "聽筒播放" + @override + String get handset_playback => "聽筒播放"; + /// "聽筒模式" + @override + String get play_model => "聽筒模式"; + /// "密碼過短" + @override + String get password_less => "密碼過短"; + /// "歲" + @override + String get years_old => "歲"; + /// "經匿名用戶舉報,系統核實你近期存在違規行為,請勿再進行違規操作。如有下次,將進行賬號凍結" + @override + String get coin_returen1 => "經匿名用戶舉報,系統核實你近期存在違規行為,請勿再進行違規操作。如有下次,將進行賬號凍結"; + /// "已經是最新版本" + @override + String get already_new => "已經是最新版本"; + /// "立即體驗" + @override + String get test_it => "立即體驗"; + /// "發現新版本" + @override + String get found_new => "發現新版本"; + /// "廣告" + @override + String get ad => "廣告"; + /// "關注" + @override + String get attention => "關注"; + /// "粉絲" + @override + String get fans => "粉絲"; + /// "/s1 申請查看我的資料頁" + @override + String get apply_see => "/s1 申請查看我的資料頁"; + /// "/s1 通過了我的查看請求" + @override + String get agree_apply => "/s1 通過了我的查看請求"; + /// "/s1 查看了我的紅包照片" + @override + String get see_redBag => "/s1 查看了我的紅包照片"; + /// "提醒" + @override + String get notice => "提醒"; + /// "請在手機設置中開啟通知權限以獲取消息通知" + @override + String get notice_open => "請在手機設置中開啟通知權限以獲取消息通知"; + /// "通知權限未開啟" + @override + String get open_notice => "通知權限未開啟"; + /// "未開啟通知權限,無法接收通知" + @override + String get not_open => "未開啟通知權限,無法接收通知"; + /// "你申請提現的的/s1H幣已被退回,請確認綁定賬戶是否正確" + @override + String get withdraw_fail => "你申請提現的的/s1H幣已被退回,請確認綁定賬戶是否正確"; + /// "動態" + @override + String get dynamics => "動態"; + /// "備註" + @override + String get Remark => "備註"; + /// "設置備註" + @override + String get setRemark => "設置備註"; + /// "/s1條評論" + @override + String get content_num => "/s1條評論"; + /// "積分兌換獲得/s1H幣" + @override + String get Redeem => "積分兌換獲得/s1H幣"; + /// "沒有訪問手機存儲權限" + @override + String get location_permission => "沒有訪問手機存儲權限"; + /// "沒有訪問攝像頭權限" + @override + String get camera_permission => "沒有訪問攝像頭權限"; + /// "沒有訪問相冊的權限" + @override + String get photo_permission => "沒有訪問相冊的權限"; + /// "沒有訪問麥克風的權限" + @override + String get video_permission => "沒有訪問麥克風的權限"; + /// "你發送的紅包已過期" + @override + String get your_redMoney_over => "你發送的紅包已過期"; + /// "對方發送的紅包已過期" + @override + String get other_redMoney_over => "對方發送的紅包已過期"; + /// "貌似出了點問題..." + @override + String get server_error_tips => "貌似出了點問題..."; + /// "表情" + @override + String get emoji => "表情"; + /// "今日簽到可領取/s1積分" + @override + String get today_score => "今日簽到可領取/s1積分"; + /// "1、每日簽到可領取積分,累計天數越多積分越高。\n2、積分可兌換H幣,兌換將消耗對應積分,請慎重兌換。\n3、每月最後一天將重置簽到,清零積分,請記得及時兌換。" + @override + String get sign_tips => "1、每日簽到可領取積分,累計天數越多積分越高。\n2、積分可兌換H幣,兌換將消耗對應積分,請慎重兌換。\n3、每月最後一天將重置簽到,清零積分,請記得及時兌換。"; + /// "簽到" + @override + String get sign_in => "簽到"; + /// "我的積分" + @override + String get my_score => "我的積分"; + /// "立即簽到" + @override + String get signin_now => "立即簽到"; + /// "已累積簽到/s1天" + @override + String get sign_in_day => "已累積簽到/s1天"; + /// "已兌換" + @override + String get have_get => "已兌換"; + /// "掃一掃" + @override + String get scan => "掃一掃"; + /// "我的二維碼" + @override + String get my_qr => "我的二維碼"; + /// "掃一掃,加好友" + @override + String get scan_and_add => "掃一掃,加好友"; + /// "高德地圖" + @override + String get amap => "高德地圖"; + /// "百度地圖" + @override + String get baidumap => "百度地圖"; + /// "谷歌地圖" + @override + String get googlemap => "谷歌地圖"; + /// "蘋果地圖" + @override + String get applemap => "蘋果地圖"; + /// "去開啟" + @override + String get go_open => "去開啟"; + /// "預覽" + @override + String get Preview => "預覽"; + /// "相冊" + @override + String get Photo_album => "相冊"; + /// "全部圖片" + @override + String get all_photo => "全部圖片"; + /// "您已經選擇了/s1張圖片" + @override + String get have_select => "您已經選擇了/s1張圖片"; + /// "加載中..." + @override + String get loading => "加載中..."; + /// "您有新的聊天消息" + @override + String get new_chat_msg => "您有新的聊天消息"; + /// "您有新的連麥消息" + @override + String get new_video_msg => "您有新的連麥消息"; + /// "/s1申請成為你的好友" + @override + String get apply_friends => "/s1申請成為你的好友"; + /// "/s1通過了你的好友請求" + @override + String get applyed_friends => "/s1通過了你的好友請求"; + /// "沒有訪問通訊錄的權限" + @override + String get contact_permission => "沒有訪問通訊錄的權限"; + /// "通訊錄" + @override + String get contact => "通訊錄"; + /// "搜索" + @override + String get search => "搜索"; + /// "添加通訊錄中的好友" + @override + String get contact_add => "添加通訊錄中的好友"; + /// "發現" + @override + String get find => "發現"; + /// "翻譯機器人" + @override + String get translate_robot => "翻譯機器人"; + /// "你好,我是翻譯機器人..." + @override + String get robot_hello => "你好,我是翻譯機器人..."; + /// "簡體中文" + @override + String get Simplified_Chinese => "簡體中文"; + /// "繁體中文" + @override + String get traditional_Chinese => "繁體中文"; + /// "英語" + @override + String get english => "英語"; + /// "越南語" + @override + String get Vietnamese => "越南語"; + /// "韓語" + @override + String get Korean => "韓語"; + /// "日語" + @override + String get Japanese => "日語"; + /// "添加好友" + @override + String get add_friends => "添加好友"; + /// "陌生人" + @override + String get stranger => "陌生人"; + /// "接收陌生人發送的消息" + @override + String get receive_stranger => "接收陌生人發送的消息"; + /// "簽到" + @override + String get signin => "簽到"; + /// "對方拒絕接收陌生人發送的消息,是否繼續解鎖全部資料。" + @override + String get stranger_close => "對方拒絕接收陌生人發送的消息,是否繼續解鎖全部資料。"; + /// "添加" + @override + String get add => "添加"; + /// "已添加" + @override + String get added => "已添加"; + /// "對方拒絕接收陌生人發送的消息。" + @override + String get stranger_close_tips => "對方拒絕接收陌生人發送的消息。"; + /// "翻譯失敗" + @override + String get translate_fail => "翻譯失敗"; + /// "請先上傳照片,再設置紅包照片。" + @override + String get no_photos => "請先上傳照片,再設置紅包照片。"; + /// "你上訴的評價:/s1上訴失敗。" + @override + String get successful_appeal1 => "你上訴的評價:/s1上訴失敗。"; + /// "添加成功,等待對方同意" + @override + String get add_success => "添加成功,等待對方同意"; + /// "他人代付" + @override + String get other_pay => "他人代付"; + /// "朋友驗證" + @override + String get friend_verification => "朋友驗證"; + /// "你已發送驗證申請,等對方通過" + @override + String get add_friends_tips => "你已發送驗證申請,等對方通過"; + /// "我是/s1" + @override + String get i_am => "我是/s1"; + /// "允許" + @override + String get agree => "允許"; + /// "\"Hibok\"需要您同意《隱私協議》方可使用" + @override + String get privacyAgreement => "\"Hibok\"需要您同意《隱私協議》方可使用"; + /// "隱私協議" + @override + String get privacy => "隱私協議"; + /// "Hibok!有人申請添加你為好友,看看是誰吧" + @override + String get notification_addfriend => "Hibok!有人申請添加你為好友,看看是誰吧"; + /// "面對面才可以加好友哦" + @override + String get distance_long => "面對面才可以加好友哦"; + /// "為了翻譯內容的準確性,請不要簡寫" + @override + String get chat_tips => "為了翻譯內容的準確性,請不要簡寫"; + /// "粉絲列表" + @override + String get fans_list => "粉絲列表"; + /// "功能內測中" + @override + String get system_not_open => "功能內測中"; + /// "iOS客戶端暫不支持提現,你可以使用安卓客戶端提現,或點擊下方按鈕進行提現" + @override + String get service_withdraw_tips => "iOS客戶端暫不支持提現,你可以使用安卓客戶端提現,或點擊下方按鈕進行提現"; + /// "點擊提現" + @override + String get withdraw_tips => "點擊提現"; + /// "添加成員" + @override + String get add_member => "添加成員"; + /// "刪除成員" + @override + String get delete_member => "刪除成員"; + /// "修改群名稱" + @override + String get change_group_name => "修改群名稱"; + /// "我在本群中的暱稱" + @override + String get my_group_nickname => "我在本群中的暱稱"; + /// "群聊" + @override + String get group_chat => "群聊"; + /// "創建群聊" + @override + String get create_group_chat => "創建群聊"; + /// "你需要發送驗證申請,等對方通過" + @override + String get added_friends_tips => "你需要發送驗證申請,等對方通過"; + /// "群聊名稱" + @override + String get group_chat_name => "群聊名稱"; + /// "在這裡可以設置你在這個群裡的暱稱,這個暱稱只會在此群內顯示" + @override + String get my_group_nickname_tips => "在這裡可以設置你在這個群裡的暱稱,這個暱稱只會在此群內顯示"; + /// "男神動態" + @override + String get man_gold => "男神動態"; + /// "女神動態" + @override + String get woman_gold => "女神動態"; + /// "選擇新群主" + @override + String get choose_group_owner => "選擇新群主"; + /// "群公告" + @override + String get group_announcement => "群公告"; + /// "聊天消息" + @override + String get chat_news => "聊天消息"; + /// "群二維碼" + @override + String get group_qr => "群二維碼"; + /// "群管理" + @override + String get group_setting => "群管理"; + /// "消息免打擾" + @override + String get close_news_notice => "消息免打擾"; + /// "置頂聊天" + @override + String get set_chat_top => "置頂聊天"; + /// "顯示群成員暱稱" + @override + String get show_group_member_name => "顯示群成員暱稱"; + /// "退出後不會通知群聊中其他成員,且不會再接收此群聊消息" + @override + String get quit_group_tips => "退出後不會通知群聊中其他成員,且不會再接收此群聊消息"; + /// "退出並刪除" + @override + String get quit_and_delete => "退出並刪除"; + /// "查看更多群成員" + @override + String get show_more_member => "查看更多群成員"; + /// "群聊邀請確認" + @override + String get group_invite => "群聊邀請確認"; + /// "群主管理權轉讓" + @override + String get change_group_owner => "群主管理權轉讓"; + /// "啟用後,群成員需群主確認才能邀請朋友進群。掃二維碼進群將同時停用" + @override + String get group_setting_tips => "啟用後,群成員需群主確認才能邀請朋友進群。掃二維碼進群將同時停用"; + /// "邀請詳情" + @override + String get invite_detail => "邀請詳情"; + /// "未命名" + @override + String get undefine_name => "未命名"; + /// "群二維碼名片" + @override + String get group_qr_code => "群二維碼名片"; + /// "該二維碼7天內(/s1月/s2日前)有效,重新進入將更新" + @override + String get group_qr_code_tips => "該二維碼7天內(/s1月/s2日前)有效,重新進入將更新"; + /// "女神熱度" + @override + String get Goddess_heat => "女神熱度"; + /// "累計收穫的禮物" + @override + String get Goddess_heat_tips => "累計收穫的禮物"; + /// "新朋友" + @override + String get new_friends => "新朋友"; + /// "三天前" + @override + String get before_three_day => "三天前"; + /// "近三天" + @override + String get after_three_day => "近三天"; + /// "清除聊天記錄" + @override + String get group_clean_chat_record => "清除聊天記錄"; + /// "查看" + @override + String get check => "查看"; + /// "請求添加你為好友" + @override + String get apply_fro_friends => "請求添加你為好友"; + /// "非會員不能提現" + @override + String get no_vip_cannot_withdraw => "非會員不能提現"; + /// "該用戶未認證,謹防被騙" + @override + String get not_true_woman => "該用戶未認證,謹防被騙"; + /// "加入群聊" + @override + String get join_group => "加入群聊"; + /// "使用Apple登錄" + @override + String get sign_in_apple => "使用Apple登錄"; + /// "只有群主才能編輯群公告" + @override + String get only_host => "只有群主才能編輯群公告"; + /// "你打賞了對方/s1個禮物" + @override + String get send_gift1 => "你打賞了對方/s1個禮物"; + /// "對方打賞了你/s1個禮物" + @override + String get receive_gift1 => "對方打賞了你/s1個禮物"; + /// "你已不在該群" + @override + String get not_in_group => "你已不在該群"; + /// "正在創建,請稍等" + @override + String get creating_group => "正在創建,請稍等"; + /// "條" + @override + String get article => "條"; + /// "該群已開啟進群驗證只能通過邀請進群" + @override + String get group_open_verification => "該群已開啟進群驗證只能通過邀請進群"; + /// "群成員" + @override + String get group_memeber => "群成員"; + /// "邀請/s1位朋友加入群聊" + @override + String get invite_members => "邀請/s1位朋友加入群聊"; + /// "共/s1人" + @override + String get total_members => "共/s1人"; + /// "二維碼已過期" + @override + String get qr_outtime => "二維碼已過期"; + /// "沒有該群信息" + @override + String get no_goupr_info => "沒有該群信息"; + /// "你邀請/s1加入了群聊" + @override + String get you_invite => "你邀請/s1加入了群聊"; + /// "你被/s1拉進了群聊" + @override + String get invite_you => "你被/s1拉進了群聊"; + /// " /s1 邀請 /s2 加入了群聊" + @override + String get invite_someone => " /s1 邀請 /s2 加入了群聊"; + /// "你" + @override + String get you => "你"; + /// " /s1 將 /s2 移出了群聊" + @override + String get delete_group => " /s1 將 /s2 移出了群聊"; + /// "你已成為新群主" + @override + String get you_group_owner => "你已成為新群主"; + /// "/s1已成為新群主" + @override + String get someone_group_owner => "/s1已成為新群主"; + /// "群名已更改為/s1" + @override + String get change_group_owner1 => "群名已更改為/s1"; + /// "群公告已更新" + @override + String get update_group_announce => "群公告已更新"; + /// "你通過掃描二維碼加入群聊" + @override + String get you_qr => "你通過掃描二維碼加入群聊"; + /// "/s1通過掃描二維碼加入群聊" + @override + String get others_qr => "/s1通過掃描二維碼加入群聊"; + /// "\"/s1\" 想邀請/s2位朋友加入群聊 \$去確認\$ " + @override + String get invite_confirm => "\"/s1\" 想邀請/s2位朋友加入群聊 \$去確認\$ "; + /// " \"/s1\" 想邀請\"/s2\" 加入群聊" + @override + String get want_invite_confirm => " \"/s1\" 想邀請\"/s2\" 加入群聊"; + /// "\"/s1\" 加入群聊 已確認" + @override + String get join_group_confirm => "\"/s1\" 加入群聊 已確認"; + /// "你被 /s1 拉進了群聊" + @override + String get you_invite_gourp => "你被 /s1 拉進了群聊"; + /// " \"/s1\" 加入群聊" + @override + String get someone_join_group => " \"/s1\" 加入群聊"; + /// "群主已開啟\"群聊邀請確認\",群成員需群主確認才能邀請朋友進群" + @override + String get group_setting_tips1 => "群主已開啟\"群聊邀請確認\",群成員需群主確認才能邀請朋友進群"; + /// "群主已恢復默認進群方式" + @override + String get group_setting_tips2 => "群主已恢復默認進群方式"; + /// "群成員已達上限" + @override + String get members_max => "群成員已達上限"; + /// "群數量已達上限" + @override + String get group_max => "群數量已達上限"; + /// "我的賬單" + @override + String get my_money_info => "我的賬單"; + /// "我的餘額" + @override + String get my_left_money => "我的餘額"; + /// "H幣可通過充值或兌換方式獲得,無法進行提現" + @override + String get money_tips => "H幣可通過充值或兌換方式獲得,無法進行提現"; + /// "收入明細" + @override + String get get_money_detail => "收入明細"; + /// "Hibox收入" + @override + String get hibok_money => "Hibox收入"; + /// "兌換H幣" + @override + String get charge_h => "兌換H幣"; + /// "提款規則" + @override + String get charge_tips => "提款規則"; + /// "百變定位" + @override + String get splash_tips1 => "百變定位"; + /// "翻譯機器人" + @override + String get splash_tips2 => "翻譯機器人"; + /// "交友APP" + @override + String get splash_tips3 => "交友APP"; + /// "百變女神,選你所愛" + @override + String get splash_tips_content1 => "百變女神,選你所愛"; + /// "語音互動一起聊" + @override + String get splash_tips_content2 => "語音互動一起聊"; + /// "解決語言問題" + @override + String get splash_tips_content3 => "解決語言問題"; + /// "立即體驗" + @override + String get splash_go => "立即體驗"; + /// "你通過收入兌換了/s1H幣" + @override + String get change_h_coin => "你通過收入兌換了/s1H幣"; + /// "您的申述成功,系統已退款" + @override + String get Representation_succes => "您的申述成功,系統已退款"; + /// "系統贈送" + @override + String get system_give => "系統贈送"; + /// "您的提款申請失敗,已退回" + @override + String get exchange_fail => "您的提款申請失敗,已退回"; + /// "通過Hibox收入兌換/s1H幣" + @override + String get hibok_exchange => "通過Hibox收入兌換/s1H幣"; + /// "成功綁定代理優惠碼" + @override + String get bind_code_success => "成功綁定代理優惠碼"; + /// "您消耗了/s1H幣進行人工翻譯" + @override + String get translate_money => "您消耗了/s1H幣進行人工翻譯"; + /// "系統取消退回" + @override + String get system_back => "系統取消退回"; + /// "你打賞了對方" + @override + String get you_give => "你打賞了對方"; + /// "對方打賞了你" + @override + String get you_get => "對方打賞了你"; + /// "兑换数目(单位K)" + @override + String get enter_num_qian => "兑换数目(单位K)"; + /// "提现数目(单位K)" + @override + String get enter_num_qian1 => "提现数目(单位K)"; + /// "翻譯券" + @override + String get daily_translate_voucher => "翻譯券"; + /// "通知消息" + @override + String get msg_notice => "通知消息"; + /// "選擇提醒的人" + @override + String get select_notice_people => "選擇提醒的人"; + /// "查找手機號" + @override + String get search_phone => "查找手機號"; + /// "用戶不存在" + @override + String get not_have_user => "用戶不存在"; + /// "你不能添加自己" + @override + String get not_add_Myself => "你不能添加自己"; + /// "對方已拉黑了你" + @override + String get you_are_blaklisted => "對方已拉黑了你"; + /// "確定恢復已被焚毀的照片嗎?\n(已經看過的用戶可以再看一次)" + @override + String get confrim_recovery => "確定恢復已被焚毀的照片嗎?\n(已經看過的用戶可以再看一次)"; + /// "發送到" + @override + String get send_to => "發送到"; + + @override + TextDirection get textDirection => TextDirection.ltr; +} + +class _I18n_zh_CN extends _I18n_zh_HK { + const _I18n_zh_CN(); + + /// "Hi公园" + @override + String get appName => "Hi公园"; + /// "登录" + @override + String get login => "登录"; + /// "注册" + @override + String get registration => "注册"; + /// "其他登录" + @override + String get other_login => "其他登录"; + /// "账号" + @override + String get account => "账号"; + /// "请输入账号" + @override + String get enter_username => "请输入账号"; + /// "密码" + @override + String get password => "密码"; + /// "输入密码" + @override + String get enter_password => "输入密码"; + /// "忘记密码" + @override + String get forget_password => "忘记密码"; + /// "重置密码" + @override + String get reset_password => "重置密码"; + /// "手机号注册" + @override + String get number_registration => "手机号注册"; + /// "请输入手机号" + @override + String get enter_number => "请输入手机号"; + /// "验证码" + @override + String get code => "验证码"; + /// "请输入收到的验证码" + @override + String get enter_code => "请输入收到的验证码"; + /// "发送验证码" + @override + String get send_code => "发送验证码"; + /// "重新发送" + @override + String get send_again => "重新发送"; + /// "设置密码" + @override + String get set_password => "设置密码"; + /// "密码不少于6位" + @override + String get password_limit => "密码不少于6位"; + /// "请设置登录密码" + @override + String get set_password2 => "请设置登录密码"; + /// "下一步" + @override + String get next_step => "下一步"; + /// "点击进入表示你已阅读并同意《用户协议》" + @override + String get agreed_agreement => "点击进入表示你已阅读并同意《用户协议》"; + /// "请输入登录密码" + @override + String get enter_password2 => "请输入登录密码"; + /// "立即重置" + @override + String get reset_now => "立即重置"; + /// "选择性别" + @override + String get choose_gender => "选择性别"; + /// "你是..." + @override + String get who => "你是..."; + /// "确定" + @override + String get determine => "确定"; + /// "选择性别后无法修改" + @override + String get cannot_modified => "选择性别后无法修改"; + /// "提示" + @override + String get tip => "提示"; + /// "你即将完成注册,是否现在退出?" + @override + String get choose_quit => "你即将完成注册,是否现在退出?"; + /// "确认" + @override + String get confirm => "确认"; + /// "使用" + @override + String get use => "使用"; + /// "取消" + @override + String get cancel => "取消"; + /// "关闭" + @override + String get close => "关闭"; + /// "删除" + @override + String get delete => "删除"; + /// "算了" + @override + String get forget_it => "算了"; + /// "好的" + @override + String get ok => "好的"; + /// "注册后将不能修改性别,确定么?" + @override + String get choose_quit2 => "注册后将不能修改性别,确定么?"; + /// "提示:你不能和同性别用户进行交流" + @override + String get tip_content => "提示:你不能和同性别用户进行交流"; + /// "欢迎" + @override + String get welcome => "欢迎"; + /// "请填写邀请码" + @override + String get enter_incode => "请填写邀请码"; + /// "Hi仅向拥有邀请码的男士提供服务" + @override + String get must_incode => "Hi仅向拥有邀请码的男士提供服务"; + /// "你的邀请码" + @override + String get your_incode => "你的邀请码"; + /// "没有邀请码?你可以通过以下方式获取" + @override + String get how_get => "没有邀请码?你可以通过以下方式获取"; + /// "方式1" + @override + String get method1 => "方式1"; + /// "免费申请" + @override + String get free => "免费申请"; + /// "马上申请" + @override + String get apply_now => "马上申请"; + /// "查收邀请码" + @override + String get check_incode => "查收邀请码"; + /// "你需要填写一些个人信息,审核通过后回给你发送邀请码" + @override + String get so_get => "你需要填写一些个人信息,审核通过后回给你发送邀请码"; + /// "申请邀请码" + @override + String get apply_incode => "申请邀请码"; + /// "所在地" + @override + String get location => "所在地"; + /// "你所在的城市名称" + @override + String get cityname => "你所在的城市名称"; + /// "信息渠道" + @override + String get message_channel => "信息渠道"; + /// "你从哪里知道APP" + @override + String get how_know => "你从哪里知道APP"; + /// "微信号" + @override + String get wechat_number => "微信号"; + /// "你的微信号" + @override + String get your_wechat => "你的微信号"; + /// "facebook" + @override + String get facebook => "facebook"; + /// "你的脸书" + @override + String get your_facebook => "你的脸书"; + /// "提交申请" + @override + String get submit_application => "提交申请"; + /// "请输入所在城市" + @override + String get enter_city => "请输入所在城市"; + /// "请告诉我们你获取APP的信息渠道" + @override + String get so_know => "请告诉我们你获取APP的信息渠道"; + /// "请告诉我们你的社交账号" + @override + String get your_social => "请告诉我们你的社交账号"; + /// "我们将尽快处理你的申请。如果通过审核,你会在消息中心收到我们发放的邀请码" + @override + String get receive_incode => "我们将尽快处理你的申请。如果通过审核,你会在消息中心收到我们发放的邀请码"; + /// "邀请码还未发放,申请后请耐心等待!" + @override + String get wait_incode => "邀请码还未发放,申请后请耐心等待!"; + /// "邀请码申请成功!" + @override + String get successful_application1 => "邀请码申请成功!"; + /// "邀请码申请失败!" + @override + String get application_failed1 => "邀请码申请失败!"; + /// "复制成功" + @override + String get successful_copy => "复制成功"; + /// "方式2" + @override + String get method2 => "方式2"; + /// "加入会员" + @override + String get joinvip => "加入会员"; + /// "立即加入" + @override + String get join_now => "立即加入"; + /// "已加入" + @override + String get joined => "已加入"; + /// "加入会员可享受各种特权,包括无需邀请码注册" + @override + String get join_odds => "加入会员可享受各种特权,包括无需邀请码注册"; + /// "你还没有加入会员" + @override + String get not_joinvip => "你还没有加入会员"; + /// "加入会员后,即可不需要邀请码完成注册" + @override + String get join_after => "加入会员后,即可不需要邀请码完成注册"; + /// "邀请码验证通过" + @override + String get incode_passed => "邀请码验证通过"; + /// "欢迎加入!请勿把你的账号泄露给他人,一经发现登录异常,账户会被自动冻结。" + @override + String get welcome_join => "欢迎加入!请勿把你的账号泄露给他人,一经发现登录异常,账户会被自动冻结。"; + /// "会员中心" + @override + String get member_centre => "会员中心"; + /// "会员特权" + @override + String get members_privilege => "会员特权"; + /// "看的更多" + @override + String get see_more => "看的更多"; + /// "每天不限次数查看用户" + @override + String get unlimited_see => "每天不限次数查看用户"; + /// "看的更省" + @override + String get see_cheaper => "看的更省"; + /// "每天/s1次免费机会查看付费相册或者社交账号" + @override + String get free10 => "每天/s1次免费机会查看付费相册或者社交账号"; + /// "看的更久" + @override + String get see_longer => "看的更久"; + /// "查看阅后即焚照片的时间从2秒提升到/s1秒" + @override + String get towto6 => "查看阅后即焚照片的时间从2秒提升到/s1秒"; + /// "看的更爽" + @override + String get see_better => "看的更爽"; + /// "免费发布约会广播" + @override + String get free_release => "免费发布约会广播"; + /// "选择套餐" + @override + String get choose_price => "选择套餐"; + /// "支付方式" + @override + String get pay_method => "支付方式"; + /// "支付金额" + @override + String get pay_amount => "支付金额"; + /// "钱包余额不足" + @override + String get not_enough => "钱包余额不足"; + /// "确认支付" + @override + String get confirm_pay => "确认支付"; + /// "完善资料" + @override + String get complete_material => "完善资料"; + /// "基本资料" + @override + String get basic_information => "基本资料"; + /// "上传头像" + @override + String get upload_avatar => "上传头像"; + /// "请选择" + @override + String get choose => "请选择"; + /// "请填写" + @override + String get fill_out => "请填写"; + /// "可以多选" + @override + String get choose_multiple => "可以多选"; + /// "选填" + @override + String get optional => "选填"; + /// "最少填写/s1个" + @override + String get least => "最少填写/s1个"; + /// "介绍一下自己" + @override + String get introduce_yourself => "介绍一下自己"; + /// "最多选择/s1个" + @override + String get most => "最多选择/s1个"; + /// "昵称" + @override + String get nickname => "昵称"; + /// "昵称只能1-20个字符" + @override + String get only1_8 => "昵称只能1-20个字符"; + /// "当前城市" + @override + String get Resident_city => "当前城市"; + /// "请选择当前城市" + @override + String get Please_select_a_resident_city => "请选择当前城市"; + /// "芹苴" + @override + String get City1 => "芹苴"; + /// "岘港" + @override + String get City2 => "岘港"; + /// "海防" + @override + String get City3 => "海防"; + /// "河内" + @override + String get City4 => "河内"; + /// "胡志明" + @override + String get City5 => "胡志明"; + /// "安江" + @override + String get City6 => "安江"; + /// "北江" + @override + String get City7 => "北江"; + /// "北件" + @override + String get City8 => "北件"; + /// "薄辽" + @override + String get City9 => "薄辽"; + /// "北宁" + @override + String get City10 => "北宁"; + /// "巴地头顿" + @override + String get City11 => "巴地头顿"; + /// "槟椥" + @override + String get City12 => "槟椥"; + /// "平定" + @override + String get City13 => "平定"; + /// "平阳" + @override + String get City14 => "平阳"; + /// "平福" + @override + String get City15 => "平福"; + /// "平顺" + @override + String get City16 => "平顺"; + /// "金瓯" + @override + String get City17 => "金瓯"; + /// "高平" + @override + String get City18 => "高平"; + /// "得乐" + @override + String get City19 => "得乐"; + /// "得农" + @override + String get City20 => "得农"; + /// "奠边" + @override + String get City21 => "奠边"; + /// "同奈" + @override + String get City22 => "同奈"; + /// "同塔" + @override + String get City23 => "同塔"; + /// "嘉莱" + @override + String get City24 => "嘉莱"; + /// "河江" + @override + String get City25 => "河江"; + /// "海阳" + @override + String get City26 => "海阳"; + /// "河南" + @override + String get City27 => "河南"; + /// "河静" + @override + String get City28 => "河静"; + /// "和平" + @override + String get City29 => "和平"; + /// "后江" + @override + String get City30 => "后江"; + /// "兴安" + @override + String get City31 => "兴安"; + /// "庆和" + @override + String get City32 => "庆和"; + /// "坚江" + @override + String get City33 => "坚江"; + /// "昆嵩" + @override + String get City34 => "昆嵩"; + /// "莱州" + @override + String get City35 => "莱州"; + /// "林同" + @override + String get City36 => "林同"; + /// "谅山" + @override + String get City37 => "谅山"; + /// "老街" + @override + String get City38 => "老街"; + /// "隆安" + @override + String get City39 => "隆安"; + /// "乂安" + @override + String get City40 => "乂安"; + /// "宁平" + @override + String get City41 => "宁平"; + /// "宁顺" + @override + String get City42 => "宁顺"; + /// "富寿" + @override + String get City43 => "富寿"; + /// "富安" + @override + String get City44 => "富安"; + /// "广平" + @override + String get City45 => "广平"; + /// "广南" + @override + String get City46 => "广南"; + /// "广义" + @override + String get City47 => "广义"; + /// "广宁" + @override + String get City48 => "广宁"; + /// "广治" + @override + String get City49 => "广治"; + /// "朔庄" + @override + String get City50 => "朔庄"; + /// "山罗" + @override + String get City51 => "山罗"; + /// "西宁" + @override + String get City52 => "西宁"; + /// "太平" + @override + String get City53 => "太平"; + /// "太原" + @override + String get City54 => "太原"; + /// "清化" + @override + String get City55 => "清化"; + /// "承天顺化" + @override + String get City56 => "承天顺化"; + /// "前江" + @override + String get City57 => "前江"; + /// "茶荣" + @override + String get City58 => "茶荣"; + /// "宣光" + @override + String get City59 => "宣光"; + /// "永隆" + @override + String get City60 => "永隆"; + /// "永富" + @override + String get City61 => "永富"; + /// "安沛" + @override + String get City62 => "安沛"; + /// "南定" + @override + String get City63 => "南定"; + /// "生日" + @override + String get birthday => "生日"; + /// "请选择生日" + @override + String get choose_birthday => "请选择生日"; + /// "年" + @override + String get year => "年"; + /// "月" + @override + String get month => "月"; + /// "日" + @override + String get day => "日"; + /// "时" + @override + String get hour => "时"; + /// "分" + @override + String get minute => "分"; + /// "秒" + @override + String get second => "秒"; + /// "刚刚" + @override + String get just => "刚刚"; + /// "/s1分钟前" + @override + String get minute_ago => "/s1分钟前"; + /// "/s1小时前" + @override + String get hour_ago => "/s1小时前"; + /// "/s1天前" + @override + String get day_ago => "/s1天前"; + /// "/s1周前" + @override + String get week_ago => "/s1周前"; + /// "/s1月前" + @override + String get month_ago => "/s1月前"; + /// "上午" + @override + String get morning => "上午"; + /// "中午" + @override + String get noon => "中午"; + /// "下午" + @override + String get afternoon => "下午"; + /// "晚上" + @override + String get night => "晚上"; + /// "一整天" + @override + String get all_day => "一整天"; + /// "昨天" + @override + String get yesterday => "昨天"; + /// "前天" + @override + String get two_yesterday => "前天"; + /// "通宵" + @override + String get overnight => "通宵"; + /// "个" + @override + String get one => "个"; + /// "十" + @override + String get ten => "十"; + /// "百" + @override + String get hundred => "百"; + /// "千" + @override + String get thousand => "千"; + /// "万" + @override + String get ten_thousand => "万"; + /// "白羊座" + @override + String get aries => "白羊座"; + /// "金牛座" + @override + String get taurus => "金牛座"; + /// "双子座" + @override + String get gemini => "双子座"; + /// "巨蟹座" + @override + String get cancer => "巨蟹座"; + /// "狮子座" + @override + String get leo => "狮子座"; + /// "处女座" + @override + String get virgo => "处女座"; + /// "天秤座" + @override + String get libra => "天秤座"; + /// "天蝎座" + @override + String get scorpio => "天蝎座"; + /// "射手座" + @override + String get sagittarius => "射手座"; + /// "摩羯座" + @override + String get capricorn => "摩羯座"; + /// "水瓶座" + @override + String get aquarius => "水瓶座"; + /// "双鱼座" + @override + String get pisces => "双鱼座"; + /// "星期一" + @override + String get monday => "星期一"; + /// "星期二" + @override + String get tuesday => "星期二"; + /// "星期三" + @override + String get wednesday => "星期三"; + /// "星期四" + @override + String get thursday => "星期四"; + /// "星期五" + @override + String get friday => "星期五"; + /// "星期六" + @override + String get saturday => "星期六"; + /// "星期天" + @override + String get sunday => "星期天"; + /// "职业" + @override + String get job => "职业"; + /// "请选择职业" + @override + String get choose_career => "请选择职业"; + /// "信息技术" + @override + String get career1 => "信息技术"; + /// "互联网" + @override + String get career2 => "互联网"; + /// "IT" + @override + String get career3 => "IT"; + /// "电信运营" + @override + String get career4 => "电信运营"; + /// "网络游戏" + @override + String get career5 => "网络游戏"; + /// "金融保险" + @override + String get career6 => "金融保险"; + /// "投资" + @override + String get career7 => "投资"; + /// "股票基金" + @override + String get career8 => "股票基金"; + /// "保险" + @override + String get career9 => "保险"; + /// "银行" + @override + String get career10 => "银行"; + /// "信托担保" + @override + String get career11 => "信托担保"; + /// "商业服务" + @override + String get career12 => "商业服务"; + /// "咨询" + @override + String get career13 => "咨询"; + /// "个体经营" + @override + String get career14 => "个体经营"; + /// "美容美发" + @override + String get career15 => "美容美发"; + /// "旅游" + @override + String get career16 => "旅游"; + /// "酒店餐饮" + @override + String get career17 => "酒店餐饮"; + /// "休闲娱乐" + @override + String get career18 => "休闲娱乐"; + /// "贸易" + @override + String get career19 => "贸易"; + /// "汽车" + @override + String get career20 => "汽车"; + /// "房地产" + @override + String get career21 => "房地产"; + /// "物业管理" + @override + String get career22 => "物业管理"; + /// "装修装潢" + @override + String get career23 => "装修装潢"; + /// "侦探" + @override + String get career24 => "侦探"; + /// "工程制造" + @override + String get career25 => "工程制造"; + /// "建筑" + @override + String get career26 => "建筑"; + /// "土木工程" + @override + String get career27 => "土木工程"; + /// "机械制造" + @override + String get career28 => "机械制造"; + /// "电子" + @override + String get career29 => "电子"; + /// "生物医学" + @override + String get career30 => "生物医学"; + /// "食品" + @override + String get career31 => "食品"; + /// "服装" + @override + String get career32 => "服装"; + /// "能源" + @override + String get career33 => "能源"; + /// "交通运输" + @override + String get career34 => "交通运输"; + /// "航空" + @override + String get career35 => "航空"; + /// "铁路" + @override + String get career36 => "铁路"; + /// "航运船舶" + @override + String get career37 => "航运船舶"; + /// "公共交通" + @override + String get career38 => "公共交通"; + /// "物流运输" + @override + String get career39 => "物流运输"; + /// "文化传媒" + @override + String get career40 => "文化传媒"; + /// "媒体出版" + @override + String get career41 => "媒体出版"; + /// "设计" + @override + String get career42 => "设计"; + /// "文化传播" + @override + String get career43 => "文化传播"; + /// "广告创意" + @override + String get career44 => "广告创意"; + /// "动漫" + @override + String get career45 => "动漫"; + /// "公关会展" + @override + String get career46 => "公关会展"; + /// "摄影" + @override + String get career47 => "摄影"; + /// "娱乐体育" + @override + String get career48 => "娱乐体育"; + /// "影视" + @override + String get career49 => "影视"; + /// "运动体育" + @override + String get career50 => "运动体育"; + /// "音乐" + @override + String get career51 => "音乐"; + /// "模特" + @override + String get career52 => "模特"; + /// "公共事业" + @override + String get career53 => "公共事业"; + /// "医疗" + @override + String get career54 => "医疗"; + /// "法律" + @override + String get career55 => "法律"; + /// "教育" + @override + String get career56 => "教育"; + /// "政府机构" + @override + String get career57 => "政府机构"; + /// "公益" + @override + String get career58 => "公益"; + /// "学生" + @override + String get career59 => "学生"; + /// "无" + @override + String get career60 => "无"; + /// "节目" + @override + String get program => "节目"; + /// "请选择国籍" + @override + String get select_program => "请选择国籍"; + /// "健康运动" + @override + String get healthy_exercise => "健康运动"; + /// "夜蒲聚会" + @override + String get night_party => "夜蒲聚会"; + /// "我是吃货" + @override + String get gourmet_party => "我是吃货"; + /// "看电影" + @override + String get watch_movie => "看电影"; + /// "玩游戏" + @override + String get play_games => "玩游戏"; + /// "结伴旅行" + @override + String get travel_together => "结伴旅行"; + /// "连麦聊天" + @override + String get voice_chat => "连麦聊天"; + /// "其他" + @override + String get other => "其他"; + /// "期望对象" + @override + String get expect_lover => "期望对象"; + /// "请选择期望对象" + @override + String get choose_lover => "请选择期望对象"; + /// "看脸" + @override + String get beautiful => "看脸"; + /// "土豪" + @override + String get rich => "土豪"; + /// "关爱我" + @override + String get care_me => "关爱我"; + /// "看感觉" + @override + String get look_feeling => "看感觉"; + /// "无所谓" + @override + String get doesnt_matter => "无所谓"; + /// "请至少填写一种社交账号" + @override + String get least_account => "请至少填写一种社交账号"; + /// "我的用户资料隐藏社交账号" + @override + String get hide_account1 => "我的用户资料隐藏社交账号"; + /// "更多信息" + @override + String get more_information => "更多信息"; + /// "身高" + @override + String get height => "身高"; + /// "体重" + @override + String get weight => "体重"; + /// "不显示" + @override + String get not_show => "不显示"; + /// "个人介绍" + @override + String get self_introduction => "个人介绍"; + /// "注册成功" + @override + String get registration_success1 => "注册成功"; + /// "确定退出么" + @override + String get exit => "确定退出么"; + /// "你还未完善个人信息,现在退出下次进入请用已注册账号直接登录" + @override + String get exit_registration => "你还未完善个人信息,现在退出下次进入请用已注册账号直接登录"; + /// "男士无法查看其他男士详情" + @override + String get cant_see => "男士无法查看其他男士详情"; + /// "女士无法查看其他女士详情" + @override + String get cant_see2 => "女士无法查看其他女士详情"; + /// "你今天还能查看/s1位女士" + @override + String get see_one => "你今天还能查看/s1位女士"; + /// "非会员用户每天只能查看15位女士" + @override + String get only_see => "非会员用户每天只能查看15位女士"; + /// "继续查看" + @override + String get continue_see => "继续查看"; + /// "用户已冻结" + @override + String get user_frozen => "用户已冻结"; + /// "请输入昵称/职业进行搜索" + @override + String get search_user => "请输入昵称/职业进行搜索"; + /// "附近" + @override + String get nearby => "附近"; + /// "会员" + @override + String get member => "会员"; + /// "新注册" + @override + String get new_registration => "新注册"; + /// "认证" + @override + String get authenticate => "认证"; + /// "在线" + @override + String get first_online => "在线"; + /// "未开启定位,无法计算与其他用户距离" + @override + String get not_positioned => "未开启定位,无法计算与其他用户距离"; + /// "未知" + @override + String get unknown => "未知"; + /// "保密" + @override + String get secrecy => "保密"; + /// "收藏" + @override + String get collection => "收藏"; + /// "取消收藏" + @override + String get cancel_collection => "取消收藏"; + /// "已取消收藏" + @override + String get canceled_collection => "已取消收藏"; + /// "加入喜欢" + @override + String get like => "加入喜欢"; + /// "已加入喜欢" + @override + String get added_like => "已加入喜欢"; + /// "已取消喜欢" + @override + String get canceled_like => "已取消喜欢"; + /// "拉黑" + @override + String get blacklist => "拉黑"; + /// "你们将无法再看到对方和对方的动态,确定吗" + @override + String get blacklist_choose => "你们将无法再看到对方和对方的动态,确定吗"; + /// "已加入黑名单" + @override + String get blacklisted => "已加入黑名单"; + /// "你已拉黑对方并拒收消息" + @override + String get reject_message => "你已拉黑对方并拒收消息"; + /// "移除黑名单" + @override + String get remove_blacklist => "移除黑名单"; + /// "已移除黑名单" + @override + String get blacklist_removed => "已移除黑名单"; + /// "你将对方移除黑名单并取消拒收消息" + @override + String get receive_message => "你将对方移除黑名单并取消拒收消息"; + /// "在线" + @override + String get online => "在线"; + /// "付费相册" + @override + String get paid_photo => "付费相册"; + /// "申请浏览" + @override + String get application_view => "申请浏览"; + /// "已通过" + @override + String get passed => "已通过"; + /// "公园" + @override + String get park => "公园"; + /// "电台" + @override + String get radio => "电台"; + /// "消息" + @override + String get news => "消息"; + /// "我" + @override + String get me => "我"; + /// "更多操作" + @override + String get more_operations => "更多操作"; + /// "匿名举报" + @override + String get anonymous_report => "匿名举报"; + /// "认证视频" + @override + String get certified_video => "认证视频"; + /// "她已通过视频认证真实性" + @override + String get passed_video => "她已通过视频认证真实性"; + /// "她还没认证身份真实性" + @override + String get not_video => "她还没认证身份真实性"; + /// "她正在发起约会哦" + @override + String get her_appointment => "她正在发起约会哦"; + /// "他通过付费加入" + @override + String get pay_join => "他通过付费加入"; + /// "他通过了身份安全审核" + @override + String get passed_review => "他通过了身份安全审核"; + /// "他通过资深用户/s1赠送的邀请码加入" + @override + String get invited_user => "他通过资深用户/s1赠送的邀请码加入"; + /// "他正在发起约会哦" + @override + String get his_appointment => "他正在发起约会哦"; + /// "她的动态" + @override + String get her_dynamics => "她的动态"; + /// "他的动态" + @override + String get his_dynamics => "他的动态"; + /// "她非常低调" + @override + String get low_key => "她非常低调"; + /// "他非常低调" + @override + String get low_key2 => "他非常低调"; + /// "她的相册" + @override + String get her_photo => "她的相册"; + /// "他的相册" + @override + String get his_photo => "他的相册"; + /// "他设置了相册锁" + @override + String get set_lock => "他设置了相册锁"; + /// "她设置了相册锁" + @override + String get set_lock2 => "她设置了相册锁"; + /// "解锁相册(/s1),会员免费" + @override + String get free_unlock => "解锁相册(/s1),会员免费"; + /// "解锁/s1的相册" + @override + String get unlock_user => "解锁/s1的相册"; + /// "付费解锁(/s1H币)" + @override + String get pay_unlock => "付费解锁(/s1H币)"; + /// "成为会员,免费解锁" + @override + String get become_member => "成为会员,免费解锁"; + /// "是否使用1次机会解锁/s1的相册" + @override + String get consumption_once => "是否使用1次机会解锁/s1的相册"; + /// "(你今天还有/s1次机会)" + @override + String get remaining_once => "(你今天还有/s1次机会)"; + /// "你今天的免费机会已用完,是否赠送/s1解锁/s2的全部资料" + @override + String get no_times => "你今天的免费机会已用完,是否赠送/s1解锁/s2的全部资料"; + /// "支付" + @override + String get pay => "支付"; + /// "他设置了限制,查看资料需要请求他的同意" + @override + String get view_user => "他设置了限制,查看资料需要请求他的同意"; + /// "她设置了限制,查看资料需要请求她的同意" + @override + String get view_user2 => "她设置了限制,查看资料需要请求她的同意"; + /// "申请查看需给对方发送一张你的照片。放心,你的照片会在对方长按屏幕查看的2秒后焚毁" + @override + String get need_photo => "申请查看需给对方发送一张你的照片。放心,你的照片会在对方长按屏幕查看的2秒后焚毁"; + /// "选择照片" + @override + String get choose_photo => "选择照片"; + /// "已发送申请,对方确认后你会收到消息提醒" + @override + String get send_application => "已发送申请,对方确认后你会收到消息提醒"; + /// "你还没进行认证" + @override + String get not_authenticate => "你还没进行认证"; + /// "认证你的真实性后,才能与他人互动" + @override + String get after_authenticate => "认证你的真实性后,才能与他人互动"; + /// "马上认证" + @override + String get authenticate_now => "马上认证"; + /// "阅后即焚" + @override + String get destroy_after => "阅后即焚"; + /// "已焚毁" + @override + String get destroyed => "已焚毁"; + /// "阅后即焚的红包照片" + @override + String get red_photo1 => "阅后即焚的红包照片"; + /// "请通过私聊向我索取" + @override + String get ask_me => "请通过私聊向我索取"; + /// "已填写,点击查看" + @override + String get filled_in => "已填写,点击查看"; + /// "解锁全部资料" + @override + String get unlock_information => "解锁全部资料"; + /// "使用1次免费解锁" + @override + String get unlock_choose => "使用1次免费解锁"; + /// "你的真实评价" + @override + String get your_evaluation => "你的真实评价"; + /// "她的真实评价" + @override + String get her_evaluation => "她的真实评价"; + /// "他的真实评价" + @override + String get his_evaluation => "他的真实评价"; + /// "评价" + @override + String get evaluate => "评价"; + /// "友好" + @override + String get friendly => "友好"; + /// "有趣" + @override + String get interesting => "有趣"; + /// "爽快" + @override + String get readily => "爽快"; + /// "耐心" + @override + String get patient => "耐心"; + /// "高冷" + @override + String get indifferent => "高冷"; + /// "爆脾气" + @override + String get bad_temper => "爆脾气"; + /// "礼貌" + @override + String get courtesy => "礼貌"; + /// "大方" + @override + String get generous => "大方"; + /// "口嗨" + @override + String get lie => "口嗨"; + /// "不友好" + @override + String get unfriendly => "不友好"; + /// "匿名评价" + @override + String get anonymous_evaluation => "匿名评价"; + /// "你还没约过她,无法评价" + @override + String get cant_evaluate => "你还没约过她,无法评价"; + /// "他还没约过你,无法评价" + @override + String get cant_evaluate2 => "他还没约过你,无法评价"; + /// "请提供相关截图,以便我们跟进核实" + @override + String get bad_evaluate => "请提供相关截图,以便我们跟进核实"; + /// "提交" + @override + String get submit => "提交"; + /// "评价成功" + @override + String get evaluation_success => "评价成功"; + /// "私聊" + @override + String get private_chat => "私聊"; + /// "关闭消息提醒" + @override + String get close_reminder => "关闭消息提醒"; + /// "关闭消息提醒成功" + @override + String get closed_reminder => "关闭消息提醒成功"; + /// "开启消息提醒" + @override + String get open_reminder => "开启消息提醒"; + /// "开启消息提醒成功" + @override + String get opened_reminder => "开启消息提醒成功"; + /// "她的社交账号" + @override + String get her_account => "她的社交账号"; + /// "他的社交账号" + @override + String get his_account => "他的社交账号"; + /// "复制" + @override + String get copy => "复制"; + /// "发送我的社交账号给她" + @override + String get send_account => "发送我的社交账号给她"; + /// "输入你的社交账号" + @override + String get enter_account => "输入你的社交账号"; + /// "比如:微信号abc" + @override + String get for_example => "比如:微信号abc"; + /// "发送给她" + @override + String get sent_she => "发送给她"; + /// "连麦" + @override + String get chat => "连麦"; + /// "对方关闭了连麦功能" + @override + String get cantt_voice => "对方关闭了连麦功能"; + /// "认证你的真实性后,才能主动连麦" + @override + String get authentication_voice => "认证你的真实性后,才能主动连麦"; + /// "正在请求连麦" + @override + String get requesting_voice => "正在请求连麦"; + /// "正在等待接听" + @override + String get waitting_answer => "正在等待接听"; + /// "接听" + @override + String get answer => "接听"; + /// "挂断" + @override + String get hang_up => "挂断"; + /// "连麦中" + @override + String get chatting => "连麦中"; + /// "免提" + @override + String get handsfree => "免提"; + /// "打赏" + @override + String get giving_gift => "打赏"; + /// "打赏成功" + @override + String get give_success => "打赏成功"; + /// "对方已打赏" + @override + String get others_gift => "对方已打赏"; + /// "你已打赏价值/s1H币的礼物" + @override + String get given_gift => "你已打赏价值/s1H币的礼物"; + /// "你已获赏/s1H币" + @override + String get earned_gift => "你已获赏/s1H币"; + /// "可用余额/s1" + @override + String get available_balance => "可用余额/s1"; + /// "充值" + @override + String get recharge => "充值"; + /// "赠送" + @override + String get give => "赠送"; + /// "抱歉,你的余额不足了" + @override + String get balance_insufficien => "抱歉,你的余额不足了"; + /// "请充值后再送礼物哦!" + @override + String get first_recharge => "请充值后再送礼物哦!"; + /// "本次连麦打赏/s1H币" + @override + String get give_coin => "本次连麦打赏/s1H币"; + /// "本次连麦获赏/s1H币" + @override + String get get_coin => "本次连麦获赏/s1H币"; + /// "本次连麦打赏/s1H币,获赏了/s2H币" + @override + String get give_get => "本次连麦打赏/s1H币,获赏了/s2H币"; + /// "连麦已结束,时长/s1" + @override + String get chat_over => "连麦已结束,时长/s1"; + /// "消息中心" + @override + String get message_center => "消息中心"; + /// "你可以在对方的用户详情页发起私聊" + @override + String get can_chat => "你可以在对方的用户详情页发起私聊"; + /// "聊天" + @override + String get text_chat => "聊天"; + /// "系统消息" + @override + String get system_information => "系统消息"; + /// "系统通知" + @override + String get system_notification => "系统通知"; + /// "你举报用户/s1的情况不属实,请提供更有效的证据后再次举报。谢谢!" + @override + String get report_failure => "你举报用户/s1的情况不属实,请提供更有效的证据后再次举报。谢谢!"; + /// "你举报用户/s1的情况属实,系统已对该用户进行处理" + @override + String get report_success => "你举报用户/s1的情况属实,系统已对该用户进行处理"; + /// "邀请码申请成功!邀请码【/s1】(点击可复制)" + @override + String get successful_application => "邀请码申请成功!邀请码【/s1】(点击可复制)"; + /// "邀请码申请成功,感谢你介绍靠谱的朋友!邀请码【/s1】(点击可复制)" + @override + String get successful_application2 => "邀请码申请成功,感谢你介绍靠谱的朋友!邀请码【/s1】(点击可复制)"; + /// "邀请码申请失败!很遗憾您的申请未能通过审核,请填写真实信息将有效的提高审核通过率" + @override + String get application_failed => "邀请码申请失败!很遗憾您的申请未能通过审核,请填写真实信息将有效的提高审核通过率"; + /// "【重要通知】:" + @override + String get important_notice => "【重要通知】:"; + /// "你的认证资料不符合要求,请修改后重新提交。" + @override + String get authentication_failed => "你的认证资料不符合要求,请修改后重新提交。"; + /// "1.请根据认证要求拍摄认证视频" + @override + String get request1 => "1.请根据认证要求拍摄认证视频"; + /// "2.请在相册上传五官清晰的正脸本人照片" + @override + String get request2 => "2.请在相册上传五官清晰的正脸本人照片"; + /// "恭喜,你的认证申请已通过审核" + @override + String get successful_authentication => "恭喜,你的认证申请已通过审核"; + /// "你新上传的照片没有通过审核,请根据要求重新上传" + @override + String get re_upload => "你新上传的照片没有通过审核,请根据要求重新上传"; + /// "恭喜,你新上传的照片已成功通过审核" + @override + String get upload_success => "恭喜,你新上传的照片已成功通过审核"; + /// "您的约会报名因违规被删除,多次违规或情节严重系统将对您账号进行限制甚至封号,请遵守谨记,谢谢配合" + @override + String get caveat => "您的约会报名因违规被删除,多次违规或情节严重系统将对您账号进行限制甚至封号,请遵守谨记,谢谢配合"; + /// "您的评论因违规被删除,多次违规或情节严重系统将对您账号进行限制甚至封号,请遵守谨记,谢谢配合" + @override + String get caveat2 => "您的评论因违规被删除,多次违规或情节严重系统将对您账号进行限制甚至封号,请遵守谨记,谢谢配合"; + /// "电台消息" + @override + String get radio_message => "电台消息"; + /// "暂时没有此类消息" + @override + String get no_message => "暂时没有此类消息"; + /// "/s1在/s2发布了一条约会消息,点击查看" + @override + String get dating_news => "/s1在/s2发布了一条约会消息,点击查看"; + /// "去看看" + @override + String get go_see => "去看看"; + /// "/s1赞了你的动态" + @override + String get thumbs_up => "/s1赞了你的动态"; + /// "/s1赞了你的约会节目" + @override + String get thumbs_up2 => "/s1赞了你的约会节目"; + /// "/s1评论了你的动态" + @override + String get comment1 => "/s1评论了你的动态"; + /// "/s1评论了你的约会节目" + @override + String get comment2 => "/s1评论了你的约会节目"; + /// "/s1回复了你的评论" + @override + String get replied_comment => "/s1回复了你的评论"; + /// "/s1报名了你的约会节目" + @override + String get signed_up => "/s1报名了你的约会节目"; + /// "你喜欢的用户/s1发布了一条约会,点击查看" + @override + String get favorite_user => "你喜欢的用户/s1发布了一条约会,点击查看"; + /// "你喜欢的用户/s1发布了一条动态,点击查看" + @override + String get favorite_user2 => "你喜欢的用户/s1发布了一条动态,点击查看"; + /// "钱包提醒" + @override + String get wallet_reminder => "钱包提醒"; + /// "/s1付费了(/s2H币)查看了你的红包照片" + @override + String get paid_you => "/s1付费了(/s2H币)查看了你的红包照片"; + /// "/s1付费了(/s2H币)查看了你的相册" + @override + String get paid_you2 => "/s1付费了(/s2H币)查看了你的相册"; + /// "/s1付费解锁了你的全部资料" + @override + String get paid_you3 => "/s1付费解锁了你的全部资料"; + /// "查看申请" + @override + String get view_application => "查看申请"; + /// "/s1请求查看你的详情页" + @override + String get view_application2 => "/s1请求查看你的详情页"; + /// "允许(有效期15天)" + @override + String get aging => "允许(有效期15天)"; + /// "拒绝" + @override + String get refuse => "拒绝"; + /// "已通过请求" + @override + String get passed_request => "已通过请求"; + /// "/s1已通过你的查看申请,有效期15天" + @override + String get l15_days => "/s1已通过你的查看申请,有效期15天"; + /// "评价通知" + @override + String get evaluation_notice => "评价通知"; + /// "已经约出/s1了吗?赶快评价一下她吧" + @override + String get rate_her => "已经约出/s1了吗?赶快评价一下她吧"; + /// "联系过你的女士用户(匿名)对你进行了评价:/s1" + @override + String get received_evaluation => "联系过你的女士用户(匿名)对你进行了评价:/s1"; + /// "联系过你的男士用户(匿名)对你进行了评价:/s1" + @override + String get received_evaluation2 => "联系过你的男士用户(匿名)对你进行了评价:/s1"; + /// "如果评价不属实,你可申请上述,我们会进行核实" + @override + String get application_appeal => "如果评价不属实,你可申请上述,我们会进行核实"; + /// "我要上诉" + @override + String get appeal => "我要上诉"; + /// "已申请上诉" + @override + String get appealed => "已申请上诉"; + /// "我们会尽快核实情况,并通过站内信告诉你处理结果" + @override + String get waiting_results => "我们会尽快核实情况,并通过站内信告诉你处理结果"; + /// "你上诉的评价:/s1上诉成功,我们将为你撤销此评价。" + @override + String get successful_appeal => "你上诉的评价:/s1上诉成功,我们将为你撤销此评价。"; + /// "社交账号" + @override + String get social_account => "社交账号"; + /// "/s1向你发送了他的社交账号" + @override + String get get_account => "/s1向你发送了他的社交账号"; + /// "编辑资料" + @override + String get edit_information => "编辑资料"; + /// "保存" + @override + String get save => "保存"; + /// "你通过了身份安全核实" + @override + String get passed_verification1 => "你通过了身份安全核实"; + /// "你通过资深用户/s1的邀请码加入" + @override + String get by_code => "你通过资深用户/s1的邀请码加入"; + /// "你通过付费加入" + @override + String get by_paying => "你通过付费加入"; + /// "你已通过视频认证身份真实性" + @override + String get passed_verification => "你已通过视频认证身份真实性"; + /// "你还没有认证身份真实性" + @override + String get not_certified => "你还没有认证身份真实性"; + /// "我们正在认证你的真实性" + @override + String get verificating => "我们正在认证你的真实性"; + /// "经过认证的女生更受欢迎哦" + @override + String get real_girl => "经过认证的女生更受欢迎哦"; + /// "认证中" + @override + String get certificating => "认证中"; + /// "待重新上传视频" + @override + String get re_upload2 => "待重新上传视频"; + /// "更新认证" + @override + String get update_certification => "更新认证"; + /// "升级会员尊享特权" + @override + String get enjoy_privileges => "升级会员尊享特权"; + /// "/s1到期" + @override + String get expires => "/s1到期"; + /// "钱包" + @override + String get wallet => "钱包"; + /// "隐私" + @override + String get setting => "隐私"; + /// "我的动态" + @override + String get my_dynamic => "我的动态"; + /// "我的相册" + @override + String get my_album => "我的相册"; + /// "上传我的第一张照片" + @override + String get first_photo => "上传我的第一张照片"; + /// "有照片才能吸引男士哦" + @override + String get no_photo => "有照片才能吸引男士哦"; + /// "上传照片" + @override + String get upload_photos => "上传照片"; + /// "上传视频" + @override + String get upload_video => "上传视频"; + /// "上传照片" + @override + String get upload => "上传照片"; + /// "设置红包照片" + @override + String get set_photo => "设置红包照片"; + /// "长按拖动可对照片排序" + @override + String get photo_order => "长按拖动可对照片排序"; + /// "我的评价" + @override + String get my_evaluation => "我的评价"; + /// "我的节目" + @override + String get my_show => "我的节目"; + /// "我喜欢的" + @override + String get i_like => "我喜欢的"; + /// "你喜欢的女士会显示这里" + @override + String get your_favorite => "你喜欢的女士会显示这里"; + /// "你喜欢的男士会显示这里" + @override + String get your_favorite2 => "你喜欢的男士会显示这里"; + /// "没有数据" + @override + String get no_data => "没有数据"; + /// "历史访客" + @override + String get historical_visitor => "历史访客"; + /// "有/s1个人看过你" + @override + String get visit_you => "有/s1个人看过你"; + /// "已有/s1个人焚毁了你的照片" + @override + String get visit_photo => "已有/s1个人焚毁了你的照片"; + /// "一键恢复" + @override + String get recovery_photo => "一键恢复"; + /// "设置" + @override + String get setting2 => "设置"; + /// "帮朋友申请邀请码" + @override + String get apply_code => "帮朋友申请邀请码"; + /// "申请邀请码是免费的,我们会根据你的历史消费来评估是否发放邀请码。为维持公园的氛围,请一定把邀请码赠与靠谱的朋友" + @override + String get issue_choose => "申请邀请码是免费的,我们会根据你的历史消费来评估是否发放邀请码。为维持公园的氛围,请一定把邀请码赠与靠谱的朋友"; + /// "成功递交申请" + @override + String get successfully_submit => "成功递交申请"; + /// "分享APP给朋友" + @override + String get share_app => "分享APP给朋友"; + /// "有问题需要帮助" + @override + String get need_help => "有问题需要帮助"; + /// "联系客服" + @override + String get need_help2 => "联系客服"; + /// "为了提高服务效率,如果下面有您的问题,请直接回复序号数字哦!" + @override + String get need_help3 => "为了提高服务效率,如果下面有您的问题,请直接回复序号数字哦!"; + /// "【1】账号被冻结是什么原因?" + @override + String get question1 => "【1】账号被冻结是什么原因?"; + /// "出现下述任意一种情况,账号都会被冻结:①骗子②中介③骚扰广告④多人举报⑤已有其他账号⑥多次发布违规电台广播无视警告⑦用户自己要求注销" + @override + String get answer1 => "出现下述任意一种情况,账号都会被冻结:①骗子②中介③骚扰广告④多人举报⑤已有其他账号⑥多次发布违规电台广播无视警告⑦用户自己要求注销"; + /// "【2】钱包现金什么时候才能提现?" + @override + String get question2 => "【2】钱包现金什么时候才能提现?"; + /// "所有收益会直接进入到钱包,提现需要三天(按收取时间计算开始),三天后收取的金额将会进入到钱包,金额>=10元即可提现" + @override + String get answer2 => "所有收益会直接进入到钱包,提现需要三天(按收取时间计算开始),三天后收取的金额将会进入到钱包,金额>=10元即可提现"; + /// "【3】我发出的红包怎么没有显示?" + @override + String get question3 => "【3】我发出的红包怎么没有显示?"; + /// "可能是网络原因导致。放心,这种情况对方无法领取你的红包,红包将在24小时后自动退还到你的支付渠道" + @override + String get answer3 => "可能是网络原因导致。放心,这种情况对方无法领取你的红包,红包将在24小时后自动退还到你的支付渠道"; + /// "【4】提现需要多久到账?" + @override + String get question4 => "【4】提现需要多久到账?"; + /// "提交提现申请后两个工作日内到账。温馨提示:提现时请确认账号无误!" + @override + String get answer4 => "提交提现申请后两个工作日内到账。温馨提示:提现时请确认账号无误!"; + /// "【5】如何匿名举报其他用户/电台广播内容?" + @override + String get question5 => "【5】如何匿名举报其他用户/电台广播内容?"; + /// "进入对方详情页或选择某条电台广播,点击右上角选择【匿名举报】,请填写相关举报信息即可对其发起举报。" + @override + String get answer5 => "进入对方详情页或选择某条电台广播,点击右上角选择【匿名举报】,请填写相关举报信息即可对其发起举报。"; + /// "【6】如何成为认证用户?" + @override + String get question6 => "【6】如何成为认证用户?"; + /// "认证通过需满足以下要求:①个人资料填写有效社交账号②相册至少上传一张本人清晰的正脸照③在认证页面查看验证码,在纸上写上昵称+验证码④拿着这张纸,与你的正脸合拍一段视频,点击上传认证视频" + @override + String get answer6 => "认证通过需满足以下要求:①个人资料填写有效社交账号②相册至少上传一张本人清晰的正脸照③在认证页面查看验证码,在纸上写上昵称+验证码④拿着这张纸,与你的正脸合拍一段视频,点击上传认证视频"; + /// "【7】认证的视频可以不公开吗?" + @override + String get question7 => "【7】认证的视频可以不公开吗?"; + /// "可以在设置里选择是否公开:用户中心-点击认证视频-左下角'将认证视频显示在我的详情页'" + @override + String get answer7 => "可以在设置里选择是否公开:用户中心-点击认证视频-左下角'将认证视频显示在我的详情页'"; + /// "【8】如何避免认证被取消?" + @override + String get question8 => "【8】如何避免认证被取消?"; + /// "相册至少有一张被标记为本人的照片" + @override + String get answer8 => "相册至少有一张被标记为本人的照片"; + /// "【9】电台广播被删除是什么原因?" + @override + String get question9 => "【9】电台广播被删除是什么原因?"; + /// "电台广播不能发布敏感图,敏感词,包括但不限于暗示或明示性词语,不能发布个人信息(包括头像,昵称,联系方式),违规电台广播将被删除" + @override + String get answer9 => "电台广播不能发布敏感图,敏感词,包括但不限于暗示或明示性词语,不能发布个人信息(包括头像,昵称,联系方式),违规电台广播将被删除"; + /// "【10】如何注销账号?" + @override + String get question10 => "【10】如何注销账号?"; + /// "注销账号将无法登录APP,以后再想使用服务则需要重新注册,请谨慎考虑。如果你仍然决定注销账号,请回复序号【12】联系客服" + @override + String get answer10 => "注销账号将无法登录APP,以后再想使用服务则需要重新注册,请谨慎考虑。如果你仍然决定注销账号,请回复序号【12】联系客服"; + /// "【11】忘记密码怎么办?" + @override + String get question11 => "【11】忘记密码怎么办?"; + /// "通过手机号码注册或者绑定手机号码的用户,可以通过登录页面右上角的“忘记密码”功能重置密码。未绑定用户请先绑定手机号,再设置新的登录密码" + @override + String get answer11 => "通过手机号码注册或者绑定手机号码的用户,可以通过登录页面右上角的“忘记密码”功能重置密码。未绑定用户请先绑定手机号,再设置新的登录密码"; + /// "【12】其他问题/转接人工客服" + @override + String get question12 => "【12】其他问题/转接人工客服"; + /// "你好,请问有什么问题可以帮你?请描述你的问题(客服上班时间为每天8:00-次日02:00,由于咨询人数较多,你可能需要等待回复)" + @override + String get answer12 => "你好,请问有什么问题可以帮你?请描述你的问题(客服上班时间为每天8:00-次日02:00,由于咨询人数较多,你可能需要等待回复)"; + /// "认证中心" + @override + String get certification_center => "认证中心"; + /// "认证视频拍摄方式示例" + @override + String get for_example2 => "认证视频拍摄方式示例"; + /// "认证条件" + @override + String get certification_conditions => "认证条件"; + /// "1.个人形象良好" + @override + String get conditions1 => "1.个人形象良好"; + /// "2.相册中至少上传一张本人照片" + @override + String get conditions2 => "2.相册中至少上传一张本人照片"; + /// "认证方式" + @override + String get verification_method => "认证方式"; + /// "1.取一张纸,写上你的昵称和以下验证码:" + @override + String get method3 => "1.取一张纸,写上你的昵称和以下验证码:"; + /// "2.拿着这张纸,与你的正脸合拍一段视频(3~15秒)" + @override + String get method4 => "2.拿着这张纸,与你的正脸合拍一段视频(3~15秒)"; + /// "上传认证视频" + @override + String get upload_video2 => "上传认证视频"; + /// "认证成功后,你的头像会带有real标志" + @override + String get after_authentication => "认证成功后,你的头像会带有real标志"; + /// "将认证视频显示在我的详情页" + @override + String get show_video => "将认证视频显示在我的详情页"; + /// "已上传的认证视频" + @override + String get uploaded_video => "已上传的认证视频"; + /// "审核中(24小时内)" + @override + String get under_review => "审核中(24小时内)"; + /// "认证状态" + @override + String get certification_status => "认证状态"; + /// "你已通过认证" + @override + String get certified => "你已通过认证"; + /// "认证待重提" + @override + String get wait_resubmitted => "认证待重提"; + /// "您的认证视频不符合要求,原因是:" + @override + String get reason_failure => "您的认证视频不符合要求,原因是:"; + /// "请根据认证要求拍摄认证视频" + @override + String get claim => "请根据认证要求拍摄认证视频"; + /// "请在相册上传清晰展示五官的正脸本人照片" + @override + String get claim2 => "请在相册上传清晰展示五官的正脸本人照片"; + /// "重新上传认证视频" + @override + String get re_upload_video => "重新上传认证视频"; + /// "更新上传认证视频" + @override + String get update_video => "更新上传认证视频"; + /// "H币" + @override + String get mask_coin => "H币"; + /// "你可以通过充值或者开麦等途径获得H币。" + @override + String get get_way => "你可以通过充值或者开麦等途径获得H币。"; + /// "H币可用于使用连麦服务,并且在连麦时进行打赏。" + @override + String get coin_use => "H币可用于使用连麦服务,并且在连麦时进行打赏。"; + /// "H币总额" + @override + String get coin_total => "H币总额"; + /// "可兑消" + @override + String get can_redeemed => "可兑消"; + /// "/s1账号" + @override + String get who_account => "/s1账号"; + /// "绑定/s1账号" + @override + String get bind_account => "绑定/s1账号"; + /// "你的/s1账号" + @override + String get your_account => "你的/s1账号"; + /// "你通过充值获得了/s1H币" + @override + String get get_coin2 => "你通过充值获得了/s1H币"; + /// "/s1查看了你的社交账号" + @override + String get viewed_your => "/s1查看了你的社交账号"; + /// "/s1赠送了礼物:1个/s2" + @override + String get give_gift => "/s1赠送了礼物:1个/s2"; + /// "+/s1H币" + @override + String get add_coin => "+/s1H币"; + /// "你赠送了1个/s1给/s2" + @override + String get give_one => "你赠送了1个/s1给/s2"; + /// "-/s1H币" + @override + String get less_coin => "-/s1H币"; + /// "提现" + @override + String get exchange_cash => "提现"; + /// "提现申请" + @override + String get withdrawal_application => "提现申请"; + /// "你有/s1枚H币可兑换成/s2,兑换后剩余/s3枚H币。确定申请兑换吗?" + @override + String get redeem_choose => "你有/s1枚H币可兑换成/s2,兑换后剩余/s3枚H币。确定申请兑换吗?"; + /// "提现申请已提交" + @override + String get application_submitted => "提现申请已提交"; + /// "我们将在2个工作日内处理,有疑问可咨询客服" + @override + String get working_days => "我们将在2个工作日内处理,有疑问可咨询客服"; + /// "现金" + @override + String get cash => "现金"; + /// "每当你再聊天页面收到红包,红包金额都会进入这里。金额进账后3天内没人举报你即可提现,提现将收取5%手续费" + @override + String get handling_fee => "每当你再聊天页面收到红包,红包金额都会进入这里。金额进账后3天内没人举报你即可提现,提现将收取5%手续费"; + /// "账户总额" + @override + String get total_account => "账户总额"; + /// "金额不足,无法兑消" + @override + String get cannot_redeemed => "金额不足,无法兑消"; + /// "兑消成功" + @override + String get successful_redemption => "兑消成功"; + /// "你的账户总额为/s1元,本次可提现/s2元,确定申请提现吗?" + @override + String get redeem_choose2 => "你的账户总额为/s1元,本次可提现/s2元,确定申请提现吗?"; + /// "个人详情" + @override + String get personal_details => "个人详情"; + /// "公开(推荐)" + @override + String get public => "公开(推荐)"; + /// "相册付费查看" + @override + String get paid_album => "相册付费查看"; + /// "他人必须付费才能查看你的相册,费用由你定,这可能会降低你的访问量" + @override + String get must_pay => "他人必须付费才能查看你的相册,费用由你定,这可能会降低你的访问量"; + /// "设置查看金额" + @override + String get set_amount1 => "设置查看金额"; + /// "请先上传照片,再设置付费相册" + @override + String get first_upload => "请先上传照片,再设置付费相册"; + /// "查看前需通过我验证" + @override + String get need_permission => "查看前需通过我验证"; + /// "他人必须发照片让你验证身份后才能浏览你的主页,确定吗?" + @override + String get permission_choose => "他人必须发照片让你验证身份后才能浏览你的主页,确定吗?"; + /// "在附近的人列表隐藏我" + @override + String get hide_me => "在附近的人列表隐藏我"; + /// "对他人隐藏我的距离" + @override + String get hide_distance => "对他人隐藏我的距离"; + /// "对他人隐藏我的社交账号" + @override + String get hide_account => "对他人隐藏我的社交账号"; + /// "连麦控制" + @override + String get chat_setting => "连麦控制"; + /// "允许有私聊权限的人对我发起连麦" + @override + String get chat_me => "允许有私聊权限的人对我发起连麦"; + /// "保存成功" + @override + String get successfully_saved => "保存成功"; + /// "你还没有发布过动态" + @override + String get on_dynamic => "你还没有发布过动态"; + /// "发布动态" + @override + String get release_dynamics => "发布动态"; + /// "动态详情" + @override + String get dynamic_details => "动态详情"; + /// "发布" + @override + String get release => "发布"; + /// "我发布的" + @override + String get i_posted => "我发布的"; + /// "删除动态" + @override + String get delete_dynamic => "删除动态"; + /// "确定要删除这条动态吗?" + @override + String get delete_choose => "确定要删除这条动态吗?"; + /// "发布于/s1" + @override + String get posted_on => "发布于/s1"; + /// "赞" + @override + String get thumbs_up3 => "赞"; + /// "已经赞过了" + @override + String get already_praised => "已经赞过了"; + /// "评论" + @override + String get comment => "评论"; + /// "发送" + @override + String get send => "发送"; + /// "评论已关闭" + @override + String get comment_closed => "评论已关闭"; + /// "只有发布者能看见你的评论" + @override + String get your_comment => "只有发布者能看见你的评论"; + /// "大家都能看见你的评论" + @override + String get everyone_comment => "大家都能看见你的评论"; + /// "禁止评论" + @override + String get prohibit_comments => "禁止评论"; + /// "已禁止评论" + @override + String get comments_disabled => "已禁止评论"; + /// "开放评论" + @override + String get open_comments => "开放评论"; + /// "已开放评论" + @override + String get already_open => "已开放评论"; + /// "回复" + @override + String get reply => "回复"; + /// "举报" + @override + String get report => "举报"; + /// "确定举报这条评论吗?" + @override + String get report_choose => "确定举报这条评论吗?"; + /// "举报成功,我们会尽快处理" + @override + String get successful_report => "举报成功,我们会尽快处理"; + /// "删除成功" + @override + String get successfully_deleted => "删除成功"; + /// "谈吐文明的人更受欢迎,请勿发布低俗、色情交易、或曝光他人隐私的内容" + @override + String get please_civilization => "谈吐文明的人更受欢迎,请勿发布低俗、色情交易、或曝光他人隐私的内容"; + /// "对同性别用户隐藏" + @override + String get same_sex => "对同性别用户隐藏"; + /// "会员免费,非会员需/s1H币" + @override + String get member_free => "会员免费,非会员需/s1H币"; + /// "已认证女士免费3次,之后需要支付/s1H币" + @override + String get certified_free => "已认证女士免费3次,之后需要支付/s1H币"; + /// "请输入文字内容或选择图片" + @override + String get enter_something => "请输入文字内容或选择图片"; + /// "付费发布(/s1H币)" + @override + String get raid_release => "付费发布(/s1H币)"; + /// "成为会员,免费发布" + @override + String get become_member2 => "成为会员,免费发布"; + /// "马上认证,免费发布" + @override + String get now_certification => "马上认证,免费发布"; + /// "发布成功" + @override + String get successfully_released => "发布成功"; + /// "你还没有发布过节目" + @override + String get no_program => "你还没有发布过节目"; + /// "节目详情" + @override + String get program_details => "节目详情"; + /// "节目主题" + @override + String get program_theme => "节目主题"; + /// "点击选择" + @override + String get click_select => "点击选择"; + /// "城市" + @override + String get city => "城市"; + /// "选择城市" + @override + String get select_city => "选择城市"; + /// "时间" + @override + String get time => "时间"; + /// "选择日期" + @override + String get select_date => "选择日期"; + /// "选择时间" + @override + String get select_time => "选择时间"; + /// "不限时间" + @override + String get unlimited_time => "不限时间"; + /// "补充说明" + @override + String get supplementary_explanation => "补充说明"; + /// "配图" + @override + String get image => "配图"; + /// "删除节目" + @override + String get delete_program => "删除节目"; + /// "确定要删除这条节目吗?" + @override + String get delete_choose2 => "确定要删除这条节目吗?"; + /// "请选择节目主题" + @override + String get please_choose => "请选择节目主题"; + /// "请选择期望对象" + @override + String get please_choose2 => "请选择期望对象"; + /// "请选择城市" + @override + String get please_choose3 => "请选择城市"; + /// "请选择日期" + @override + String get please_choose4 => "请选择日期"; + /// "请选择时间" + @override + String get please_choose5 => "请选择时间"; + /// "发布节目" + @override + String get release_program => "发布节目"; + /// "报名" + @override + String get sign_up => "报名"; + /// "结束报名" + @override + String get end_registration => "结束报名"; + /// "确定结束约会吗?" + @override + String get end_choose => "确定结束约会吗?"; + /// "联系她" + @override + String get contact_her => "联系她"; + /// "私聊他" + @override + String get talk_him => "私聊他"; + /// "确定举报这条报名信息吗?" + @override + String get report_choose2 => "确定举报这条报名信息吗?"; + /// "发布时间" + @override + String get release_time => "发布时间"; + /// "活动时间" + @override + String get activity_time => "活动时间"; + /// "不限性别" + @override + String get any_sex => "不限性别"; + /// "只看女士" + @override + String get look_women => "只看女士"; + /// "只看男士" + @override + String get look_men => "只看男士"; + /// "不限地区" + @override + String get unlimited_area => "不限地区"; + /// "该节目已删除" + @override + String get program_deleted => "该节目已删除"; + /// "非会员不能评论" + @override + String get cant_comment => "非会员不能评论"; + /// "我要报名" + @override + String get sign_up2 => "我要报名"; + /// "报名需要发送你的正脸照片(只有对方能看到)" + @override + String get need_photo2 => "报名需要发送你的正脸照片(只有对方能看到)"; + /// "报名成功,如果对方觉得合适将会联系你" + @override + String get registration_success => "报名成功,如果对方觉得合适将会联系你"; + /// "已结束" + @override + String get has_ended => "已结束"; + /// "男士不能报名男士的节目" + @override + String get men_cant => "男士不能报名男士的节目"; + /// "女士不能报名女士的节目" + @override + String get ms_cant => "女士不能报名女士的节目"; + /// "男士不能评论男士的节目" + @override + String get men_cant2 => "男士不能评论男士的节目"; + /// "女士不能评论女士的节目" + @override + String get ms_cant2 => "女士不能评论女士的节目"; + /// "消息推送、修改密码" + @override + String get message_push => "消息推送、修改密码"; + /// "手机号码" + @override + String get phone_number => "手机号码"; + /// "绑定手机号" + @override + String get bind_phone1 => "绑定手机号"; + /// "绑定手机号,让你的账户更安全" + @override + String get more_safer => "绑定手机号,让你的账户更安全"; + /// "你想修改绑定的手机号码吗?" + @override + String get modify_choose => "你想修改绑定的手机号码吗?"; + /// "修改密码" + @override + String get change_password => "修改密码"; + /// "用户需要先绑定手机号码才可以设置登录密码" + @override + String get first_bind => "用户需要先绑定手机号码才可以设置登录密码"; + /// "原密码" + @override + String get old_password => "原密码"; + /// "请输入当前登录密码" + @override + String get current_password => "请输入当前登录密码"; + /// "新密码" + @override + String get new_password => "新密码"; + /// "请设置新密码,不少于6位" + @override + String get set_new => "请设置新密码,不少于6位"; + /// "清除图片缓存" + @override + String get clear_cache => "清除图片缓存"; + /// "清除成功" + @override + String get cleared_successfully => "清除成功"; + /// "用户使用协议" + @override + String get user_agreement1 => "用户使用协议"; + /// "退出登录" + @override + String get sign_out => "退出登录"; + /// "确定退出账号么?" + @override + String get out_choose => "确定退出账号么?"; + /// "推送设置" + @override + String get push_settings => "推送设置"; + /// "权限已被拒绝" + @override + String get permission_denied => "权限已被拒绝"; + /// "消息推送设置" + @override + String get push_setting2 => "消息推送设置"; + /// "私聊消息" + @override + String get private_chat2 => "私聊消息"; + /// "有新的约会" + @override + String get new_date => "有新的约会"; + /// "有女士通过了我的查看请求" + @override + String get passed_request2 => "有女士通过了我的查看请求"; + /// "有男士申请查看我的资料页" + @override + String get men_view => "有男士申请查看我的资料页"; + /// "有男士查看我的社交账号" + @override + String get men_view2 => "有男士查看我的社交账号"; + /// "有男士查看我的红包照片" + @override + String get men_view3 => "有男士查看我的红包照片"; + /// "有已查看资料的男士给我发送社交账号" + @override + String get men_view4 => "有已查看资料的男士给我发送社交账号"; + /// "邀请码申请成功" + @override + String get applied_successfully => "邀请码申请成功"; + /// "打开后将推送相应消息类型" + @override + String get after_open => "打开后将推送相应消息类型"; + /// "如果你在最近3天曾向她/他支付过费用,我们核实举报后,系统将自动向你退回消费金额" + @override + String get if_something => "如果你在最近3天曾向她/他支付过费用,我们核实举报后,系统将自动向你退回消费金额"; + /// "发广告" + @override + String get advertise => "发广告"; + /// "虚假照片" + @override + String get false_photo => "虚假照片"; + /// "色情低俗" + @override + String get erotic_vulgarity => "色情低俗"; + /// "骚扰谩骂" + @override + String get harassment => "骚扰谩骂"; + /// "她是骗子" + @override + String get she_liar => "她是骗子"; + /// "他是骗子" + @override + String get he_liar => "他是骗子"; + /// "请提供相关截图,以便我们跟进核实" + @override + String get provide_screenshots => "请提供相关截图,以便我们跟进核实"; + /// "请描述详情(100字内)" + @override + String get describe_details => "请描述详情(100字内)"; + /// "请选择举报原因" + @override + String get report_reason => "请选择举报原因"; + /// "举报成功" + @override + String get report_success2 => "举报成功"; + /// "修改成功" + @override + String get successfully_modified => "修改成功"; + /// "男生" + @override + String get boy => "男生"; + /// "女生" + @override + String get girl => "女生"; + /// "已申请" + @override + String get already_applied => "已申请"; + /// "查看报名" + @override + String get view_registration => "查看报名"; + /// "展开" + @override + String get expand => "展开"; + /// "收起" + @override + String get collapse => "收起"; + /// "申请通知" + @override + String get application_notice => "申请通知"; + /// "有用户同意你的申请" + @override + String get agrees_application => "有用户同意你的申请"; + /// "红包照片" + @override + String get red_photo => "红包照片"; + /// "请勿上传非法裸露低俗的照片/视频,严重者将封号" + @override + String get dont => "请勿上传非法裸露低俗的照片/视频,严重者将封号"; + /// "当前版本" + @override + String get current_version => "当前版本"; + /// "绑定银行卡" + @override + String get bank_card => "绑定银行卡"; + /// "请选择开户行" + @override + String get choose_bank => "请选择开户行"; + /// "请输入银行卡号" + @override + String get bank_number => "请输入银行卡号"; + /// "请输入证件号" + @override + String get id_number => "请输入证件号"; + /// "姓名" + @override + String get name => "姓名"; + /// "银行卡号" + @override + String get bank_number2 => "银行卡号"; + /// "证件号" + @override + String get license_number => "证件号"; + /// "绑定手机号" + @override + String get bind_phone => "绑定手机号"; + /// "他的主页" + @override + String get his_homepage => "他的主页"; + /// "她的主页" + @override + String get her_homepage => "她的主页"; + /// "微信支付" + @override + String get wechat_pay => "微信支付"; + /// "facebook支付" + @override + String get facebook_pay => "facebook支付"; + /// "google支付" + @override + String get google_pay => "google支付"; + /// "支付成功" + @override + String get payment_successful => "支付成功"; + /// "设置提款金额" + @override + String get set_amount => "设置提款金额"; + /// "请输入H币个数" + @override + String get enter_amount => "请输入H币个数"; + /// "可提现" + @override + String get can_withdraw => "可提现"; + /// "语言设置" + @override + String get language_set => "语言设置"; + /// "用户协议" + @override + String get user_agreement => "用户协议"; + /// "续费" + @override + String get renewal_fee => "续费"; + /// "立即开通" + @override + String get open_immediately => "立即开通"; + /// "总计" + @override + String get total => "总计"; + /// "半个月" + @override + String get half_month => "半个月"; + /// "/s1个月" + @override + String get month2 => "/s1个月"; + /// "取消屏蔽" + @override + String get cancel_shield => "取消屏蔽"; + /// "黑名单" + @override + String get blacklist2 => "黑名单"; + /// "(会员可延长时间达6秒)" + @override + String get longTime => "(会员可延长时间达6秒)"; + /// "按住屏幕查看" + @override + String get longClick => "按住屏幕查看"; + /// "请先结束正在生效的节目" + @override + String get stop_program => "请先结束正在生效的节目"; + /// "男士不能收藏男士" + @override + String get not_love => "男士不能收藏男士"; + /// "女士不能收藏女士" + @override + String get not_love2 => "女士不能收藏女士"; + /// "女神可以免费发布" + @override + String get women_free => "女神可以免费发布"; + /// "他还没有上传照片" + @override + String get not_up_man => "他还没有上传照片"; + /// "她还没有上传照片" + @override + String get not_up_women => "她还没有上传照片"; + /// "请勿通过平台进行不法交易,如被举报核实将作封号处理" + @override + String get not_illage => "请勿通过平台进行不法交易,如被举报核实将作封号处理"; + /// "已报名" + @override + String get alreay_join => "已报名"; + /// "确定删除这张照片吗" + @override + String get sure_delete => "确定删除这张照片吗"; + /// "马上填写" + @override + String get white_now => "马上填写"; + /// "你还没有填写个人介绍,吸引人的个人介绍对约会成功影响很大哦" + @override + String get personal => "你还没有填写个人介绍,吸引人的个人介绍对约会成功影响很大哦"; + /// "成功" + @override + String get success => "成功"; + /// "失败" + @override + String get fail => "失败"; + /// "只有认证用户才可以设置红包照片" + @override + String get moneyPageTip => "只有认证用户才可以设置红包照片"; + /// "你已报名,如果对方觉得合适将会联系你" + @override + String get alreadyJoin => "你已报名,如果对方觉得合适将会联系你"; + /// "违规警告" + @override + String get waring => "违规警告"; + /// "尊重用户隐私,请勿截图。如有下次,将禁止你查看其他用户照片" + @override + String get userPravicy => "尊重用户隐私,请勿截图。如有下次,将禁止你查看其他用户照片"; + /// "约会时间已经过期了,请修改" + @override + String get outTime => "约会时间已经过期了,请修改"; + /// "审核中" + @override + String get reviewing => "审核中"; + /// "审核成功" + @override + String get reviewed => "审核成功"; + /// "审核失败" + @override + String get reviewedFail => "审核失败"; + /// "用户需要先绑定银行卡才可以提现" + @override + String get needCard => "用户需要先绑定银行卡才可以提现"; + /// "女士不能评论女士的动态" + @override + String get women_not_d => "女士不能评论女士的动态"; + /// "男士不能评论男士的动态" + @override + String get man_not_d => "男士不能评论男士的动态"; + /// "有照片才能吸引女士哦" + @override + String get have_picture => "有照片才能吸引女士哦"; + /// "上滑取消发送" + @override + String get up_cancle => "上滑取消发送"; + /// "消息不能为空" + @override + String get msg_not => "消息不能为空"; + /// "此功能需要授予录音权限" + @override + String get need_record => "此功能需要授予录音权限"; + /// "正在下载视频文件" + @override + String get downloading_video => "正在下载视频文件"; + /// "请重新输入问题序号" + @override + String get reinput => "请重新输入问题序号"; + /// "你的动态被用户匿名举报,经系统核实已将该动态删除,请勿再进行违规操作" + @override + String get dy_delete => "你的动态被用户匿名举报,经系统核实已将该动态删除,请勿再进行违规操作"; + /// "你的节目被用户匿名举报,经系统核实已将该节目删除,请勿再进行违规操作" + @override + String get pro_delete => "你的节目被用户匿名举报,经系统核实已将该节目删除,请勿再进行违规操作"; + /// "你的评论被用户匿名举报,经系统核实已将该评论删除,请勿再进行违规操作" + @override + String get con_delete => "你的评论被用户匿名举报,经系统核实已将该评论删除,请勿再进行违规操作"; + /// "经匿名用户举报,系统核实你近期存在违规行为,已将你近期收到H币进行返还。如有下次,将进行账号冻结" + @override + String get coin_returen => "经匿名用户举报,系统核实你近期存在违规行为,已将你近期收到H币进行返还。如有下次,将进行账号冻结"; + /// "通话中禁止出现色情淫秽等违法行为,一经发现将做封号处理" + @override + String get voicing => "通话中禁止出现色情淫秽等违法行为,一经发现将做封号处理"; + /// "客服" + @override + String get help => "客服"; + /// "人工翻译开启" + @override + String get translate_on => "人工翻译开启"; + /// "人工翻译关闭" + @override + String get translate_off => "人工翻译关闭"; + /// "消耗/s1 H币将续费为SVIP" + @override + String get becomeSvip => "消耗/s1 H币将续费为SVIP"; + /// "svip权限可开启" + @override + String get need_svip => "svip权限可开启"; + /// "SVIP无法续费为VIP" + @override + String get cannot_vip => "SVIP无法续费为VIP"; + /// "您已离线,无法发送和接收消息" + @override + String get offline => "您已离线,无法发送和接收消息"; + /// "账号在其他设备登录,您已离线" + @override + String get otherLogin => "账号在其他设备登录,您已离线"; + /// "暂时没有新消息" + @override + String get no_new => "暂时没有新消息"; + /// "翻译完毕" + @override + String get over => "翻译完毕"; + /// "确定要对此条翻译进行差评么?" + @override + String get bad_ev => "确定要对此条翻译进行差评么?"; + /// "聊的更爽" + @override + String get right5 => "聊的更爽"; + /// "用的更爽" + @override + String get right6 => "用的更爽"; + /// "小哥哥" + @override + String get man_vi => "小哥哥"; + /// "小姐姐" + @override + String get women_vi => "小姐姐"; + /// "为了提高服务效率,如果下面有您的问题,请直接回复序号数字哦!" + @override + String get kf_tips => "为了提高服务效率,如果下面有您的问题,请直接回复序号数字哦!"; + /// "已拒绝" + @override + String get rejected => "已拒绝"; + /// "你消费了/s1H币购买会员" + @override + String get buy_vip => "你消费了/s1H币购买会员"; + /// "你消费了/s1H币发布动态节目" + @override + String get buy_program => "你消费了/s1H币发布动态节目"; + /// "你的H币提现申请已处理,已转账/s1到你的银行卡账号,请查收" + @override + String get del_add_money => "你的H币提现申请已处理,已转账/s1到你的银行卡账号,请查收"; + /// "你申请提现的/s1H币正在审批中" + @override + String get adding_money => "你申请提现的/s1H币正在审批中"; + /// "免费享受翻译专员实时翻译" + @override + String get free_translate => "免费享受翻译专员实时翻译"; + /// "专享客服为你服务" + @override + String get personalTraff => "专享客服为你服务"; + /// "人工翻译中..." + @override + String get ManTranslate => "人工翻译中..."; + /// "机器翻译中..." + @override + String get robotTranslate => "机器翻译中..."; + /// "人工翻译完毕" + @override + String get translated => "人工翻译完毕"; + /// "健康交流,请勿广播低俗内容,一经发现将作删除处理" + @override + String get delete_progarm => "健康交流,请勿广播低俗内容,一经发现将作删除处理"; + /// "定位权限未开启" + @override + String get open_location => "定位权限未开启"; + /// "请在手机设置中开启定位权限以获得其他用户距离" + @override + String get get_location => "请在手机设置中开启定位权限以获得其他用户距离"; + /// "再按一次退出" + @override + String get confirm_exit => "再按一次退出"; + /// "每天/s1次机会发布免费广播" + @override + String get free_program => "每天/s1次机会发布免费广播"; + /// "图片" + @override + String get picture => "图片"; + /// "相机" + @override + String get camera => "相机"; + /// "视频" + @override + String get video => "视频"; + /// "红包" + @override + String get red_money => "红包"; + /// "粘贴" + @override + String get stick => "粘贴"; + /// "按住说话" + @override + String get press_say => "按住说话"; + /// "/s1领取了你的红包" + @override + String get get_money => "/s1领取了你的红包"; + /// "你领取了/s1的红包" + @override + String get you_get_money => "你领取了/s1的红包"; + /// "/s1的红包" + @override + String get ones_money => "/s1的红包"; + /// "红包已过期" + @override + String get money_over => "红包已过期"; + /// "下载文件失败" + @override + String get downloading_fail => "下载文件失败"; + /// "正在下载视频文件" + @override + String get downloading => "正在下载视频文件"; + /// "未领取的红包,将于24小时后发起退款" + @override + String get back_money => "未领取的红包,将于24小时后发起退款"; + /// "红包不存在" + @override + String get no_money => "红包不存在"; + /// "红包已领取" + @override + String get already_money => "红包已领取"; + /// "已过期,已退到账户" + @override + String get back_user => "已过期,已退到账户"; + /// "等待对方领取" + @override + String get waiting_user => "等待对方领取"; + /// "对方已领取" + @override + String get other_get => "对方已领取"; + /// "小小意思,拿去浪吧" + @override + String get little => "小小意思,拿去浪吧"; + /// "塞钱进红包" + @override + String get put_money => "塞钱进红包"; + /// "金额" + @override + String get mount => "金额"; + /// "已过期" + @override + String get over_time => "已过期"; + /// "已领取" + @override + String get has_get => "已领取"; + /// "暂时没有礼物" + @override + String get no_gift => "暂时没有礼物"; + /// "打赏礼物" + @override + String get sent_gift => "打赏礼物"; + /// "填写成功可以获得/s1H币,绑定后无法修改" + @override + String get fill_tips => "填写成功可以获得/s1H币,绑定后无法修改"; + /// "绑定邀请码" + @override + String get bind_code => "绑定邀请码"; + /// "邀请码" + @override + String get invide_code => "邀请码"; + /// "确认删除" + @override + String get confirm_delete => "确认删除"; + /// "您已经评价过了" + @override + String get has_eva => "您已经评价过了"; + /// "开" + @override + String get open => "开"; + /// "语音" + @override + String get voice => "语音"; + /// "松开发送" + @override + String get release_send => "松开发送"; + /// "录音时间过短" + @override + String get time_little => "录音时间过短"; + /// "对方不在线,无法连麦" + @override + String get not_online => "对方不在线,无法连麦"; + /// "你给/s1发送了/s2H币的红包" + @override + String get give_red_money => "你给/s1发送了/s2H币的红包"; + /// "你领取了/s1的/s2H币的红包" + @override + String get get_red_money => "你领取了/s1的/s2H币的红包"; + /// "你打赏了/s1/s2H币" + @override + String get give_other_money => "你打赏了/s1/s2H币"; + /// "你获得了/s1的/s2H币的打赏" + @override + String get get_other_money => "你获得了/s1的/s2H币的打赏"; + /// "超级会员" + @override + String get svip => "超级会员"; + /// "推荐" + @override + String get recommend => "推荐"; + /// "你付费了(/s2H币)查看/s1的红包照片" + @override + String get paid_you4 => "你付费了(/s2H币)查看/s1的红包照片"; + /// "你付费了(/s2H币)查看/s1的相册" + @override + String get paid_you5 => "你付费了(/s2H币)查看/s1的相册"; + /// "你付费解锁了/s1的全部资料" + @override + String get paid_you6 => "你付费解锁了/s1的全部资料"; + /// "hiAPP许可及服务协议" + @override + String get UG_LINE0 => "hiAPP许可及服务协议"; + /// "[首部及导言]" + @override + String get UG_LINE1 => "[首部及导言]"; + /// "前海游龙科技有限公司(以下简称“Qianhai Youlong Technology Co., Ltd.”)在此特别提醒用户认真阅读、充分理解本《服务协议》(下称 《协议》)一用户 应认真阅读、充分理解本《协议》中各条款,包括免除或者限制Qianhai Youlong Technology Co., Ltd.责任的免责条款及对用户的权利限制条款。请您审慎阅读并选择接受或不接受本《协议》(未成年人应在法定监护人陪同下阅读)。除非您接受本《协议》所有条款,否则您无权注册、登录或使用本协议所涉相关服务。您的注册、登录、使用等行为将视为对本《协议》的接受,并同意接受本《协议》各项条款的约束。" + @override + String get UG_LINE2 => "前海游龙科技有限公司(以下简称“Qianhai Youlong Technology Co., Ltd.”)在此特别提醒用户认真阅读、充分理解本《服务协议》(下称 《协议》)一用户 应认真阅读、充分理解本《协议》中各条款,包括免除或者限制Qianhai Youlong Technology Co., Ltd.责任的免责条款及对用户的权利限制条款。请您审慎阅读并选择接受或不接受本《协议》(未成年人应在法定监护人陪同下阅读)。除非您接受本《协议》所有条款,否则您无权注册、登录或使用本协议所涉相关服务。您的注册、登录、使用等行为将视为对本《协议》的接受,并同意接受本《协议》各项条款的约束。"; + /// "本《协议》是您(下称“用户”与Qianhai Youlong Technology Co., Ltd.之间关于用户注册、登录、使用“hi服务所订立的协议。本《协议》描述Qianhai Youlong Technology Co., Ltd.与用户之间关于“hi服务相关方面的权利义务。“用户”是指注册、登录、使用、浏览本服务的个人或组织。您对本协议的接受即受全部条款的约束,包括接受Qianhai Youlong Technology Co., Ltd.对任意服务条款随时所做的任何修改。本《协议》可由Qianhai Youlong Technology Co., Ltd.随时更新,更新后的协议条款一旦公布即代替原来的协议条款,恕不再另行通知,用户可在本APP查阅最新版协议条款。在Qianhai Youlong Technology Co., Ltd.修改《协议》条款后,如果用户不接受修改后的条款,请立即停止使用Qianhai Youlong Technology Co., Ltd.提供的服务,用户继续使用Qianhai Youlong Technology Co., Ltd.提供的服务将被视为已接受了修改后的协议。" + @override + String get UG_LINE3 => "本《协议》是您(下称“用户”与Qianhai Youlong Technology Co., Ltd.之间关于用户注册、登录、使用“hi服务所订立的协议。本《协议》描述Qianhai Youlong Technology Co., Ltd.与用户之间关于“hi服务相关方面的权利义务。“用户”是指注册、登录、使用、浏览本服务的个人或组织。您对本协议的接受即受全部条款的约束,包括接受Qianhai Youlong Technology Co., Ltd.对任意服务条款随时所做的任何修改。本《协议》可由Qianhai Youlong Technology Co., Ltd.随时更新,更新后的协议条款一旦公布即代替原来的协议条款,恕不再另行通知,用户可在本APP查阅最新版协议条款。在Qianhai Youlong Technology Co., Ltd.修改《协议》条款后,如果用户不接受修改后的条款,请立即停止使用Qianhai Youlong Technology Co., Ltd.提供的服务,用户继续使用Qianhai Youlong Technology Co., Ltd.提供的服务将被视为已接受了修改后的协议。"; + /// "一、使用规则" + @override + String get UG_LINE4 => "一、使用规则"; + /// "1、用户充分了解并同意,仅为用户提供信息分享、传送及获取的平台,用户必须为自己注册帐号下的一切行为负责,包括但不限于您所传送的任何内容以及由此产生的任何结果。" + @override + String get UG_LINE5 => "1、用户充分了解并同意,仅为用户提供信息分享、传送及获取的平台,用户必须为自己注册帐号下的一切行为负责,包括但不限于您所传送的任何内容以及由此产生的任何结果。"; + /// "2、用户在服务中或通过服务所传送的任何内容并不反映Qianhai Youlong Technology Co., Ltd.的观点或政策,Qianhai Youlong Technology Co., Ltd.对此不承担任何责任。" + @override + String get UG_LINE6 => "2、用户在服务中或通过服务所传送的任何内容并不反映Qianhai Youlong Technology Co., Ltd.的观点或政策,Qianhai Youlong Technology Co., Ltd.对此不承担任何责任。"; + /// "3、用户充分了解并同意,是一个基于用户关系网的社交信息浏览产品,用户须对在上的注册信息的真实性、合法性、有效性承担全部责任,用户不得冒充他人;不得利用他人的名义传播任何信息;不得恶意使用注册帐号导致其他用户误认;否则Qianhai Youlong Technology Co., Ltd.有权立即停止提供服务,收回帐号并由用户独自承担由此而产生的一切法律责任。" + @override + String get UG_LINE7 => "3、用户充分了解并同意,是一个基于用户关系网的社交信息浏览产品,用户须对在上的注册信息的真实性、合法性、有效性承担全部责任,用户不得冒充他人;不得利用他人的名义传播任何信息;不得恶意使用注册帐号导致其他用户误认;否则Qianhai Youlong Technology Co., Ltd.有权立即停止提供服务,收回帐号并由用户独自承担由此而产生的一切法律责任。"; + /// "4、用户须对在上所传送信息的真实性、合法性、无害性、有效性等全权负责,与用户所传播的信息相关的任何法律责任由用户自行承担,与Qianhai Youlong Technology Co., Ltd.无关。" + @override + String get UG_LINE8 => "4、用户须对在上所传送信息的真实性、合法性、无害性、有效性等全权负责,与用户所传播的信息相关的任何法律责任由用户自行承担,与Qianhai Youlong Technology Co., Ltd.无关。"; + /// "5、Qianhai Youlong Technology Co., Ltd.保留因业务发展需要,单方面对本服务的全部或部分服务内容在任何时候不经任何通知的情况下变更、暂停、限制、终止或撤销服务的权利,用户需承担此风险。" + @override + String get UG_LINE9 => "5、Qianhai Youlong Technology Co., Ltd.保留因业务发展需要,单方面对本服务的全部或部分服务内容在任何时候不经任何通知的情况下变更、暂停、限制、终止或撤销服务的权利,用户需承担此风险。"; + /// "6、提供的服务中可能包括广告,用户同意在使用过程中显示和第三方供应商、合作伙伴提供的广告。" + @override + String get UG_LINE10 => "6、提供的服务中可能包括广告,用户同意在使用过程中显示和第三方供应商、合作伙伴提供的广告。"; + /// "7、用户不得利用或服务制作、上载、复制、发送如下内容:" + @override + String get UG_LINE11 => "7、用户不得利用或服务制作、上载、复制、发送如下内容:"; + /// "(1 )反对宪法所确定的基本原则的;" + @override + String get UG_LINE12 => "(1 )反对宪法所确定的基本原则的;"; + /// "(2)危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家统一-的;" + @override + String get UG_LINE13 => "(2)危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家统一-的;"; + /// "(3)损害国家荣誉和利益的;" + @override + String get UG_LINE14 => "(3)损害国家荣誉和利益的;"; + /// "(4)煽动民族仇恨、民族歧视,破坏民族团结的;" + @override + String get UG_LINE15 => "(4)煽动民族仇恨、民族歧视,破坏民族团结的;"; + /// "(5)破坏国家宗教政策,宣扬邪教和封建迷信的;" + @override + String get UG_LINE16 => "(5)破坏国家宗教政策,宣扬邪教和封建迷信的;"; + /// "(6)散布谣言,扰乱社会秩序,破坏社会稳定的;" + @override + String get UG_LINE17 => "(6)散布谣言,扰乱社会秩序,破坏社会稳定的;"; + /// "(7)散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;" + @override + String get UG_LINE18 => "(7)散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;"; + /// "(8)侮辱或者诽谤他人,侵害他人合法权益的;" + @override + String get UG_LINE19 => "(8)侮辱或者诽谤他人,侵害他人合法权益的;"; + /// "(9)含有法律、行政法规禁止的其他内容的信息。" + @override + String get UG_LINE20 => "(9)含有法律、行政法规禁止的其他内容的信息。"; + /// "8、Qianhai Youlong Technology Co., Ltd.可依其合理判断,对违反有关法律法规或本协议约定;或侵犯、妨害、威胁任何人权利或安全的内容,或者假冒他人的行为,Qianhai Youlong Technology Co., Ltd.有权依法停止传输任何前述内容,并有权依其自行判断对违反本条款的任何人士采取适当的法律行动,包括但不限于从服务中删除具有违法性、侵权性、不当性等内容,终止违反者的成员资格,阻止其使用全部或部分服务,并且依据法律法规保存有关信息并向有关部门报告等。" + @override + String get UG_LINE21 => "8、Qianhai Youlong Technology Co., Ltd.可依其合理判断,对违反有关法律法规或本协议约定;或侵犯、妨害、威胁任何人权利或安全的内容,或者假冒他人的行为,Qianhai Youlong Technology Co., Ltd.有权依法停止传输任何前述内容,并有权依其自行判断对违反本条款的任何人士采取适当的法律行动,包括但不限于从服务中删除具有违法性、侵权性、不当性等内容,终止违反者的成员资格,阻止其使用全部或部分服务,并且依据法律法规保存有关信息并向有关部门报告等。"; + /// "9、用户权利及义务:" + @override + String get UG_LINE22 => "9、用户权利及义务:"; + /// "(1 )Qianhai Youlong Technology Co., Ltd.帐号的所有权归Qianhai Youlong Technology Co., Ltd.所有,用户完成申请注册手续后,获得帐号的使用权,该使用权属于初始申请注册人,禁止赠与、借用、租用、转让或售卖。Qianhai Youlong Technology Co., Ltd.因经营需要,有权回收用户的帐号,并有权使用用户照片、视频、语音等进行产品宣传活动。" + @override + String get UG_LINE23 => "(1 )Qianhai Youlong Technology Co., Ltd.帐号的所有权归Qianhai Youlong Technology Co., Ltd.所有,用户完成申请注册手续后,获得帐号的使用权,该使用权属于初始申请注册人,禁止赠与、借用、租用、转让或售卖。Qianhai Youlong Technology Co., Ltd.因经营需要,有权回收用户的帐号,并有权使用用户照片、视频、语音等进行产品宣传活动。"; + /// "(2)用户有权更改、删除在Qianhai Youlong Technology Co., Ltd..上的个人资料、注册信息及传送内容等,但需注意,删除有关信息的同时也会删除任何您储存在系统中的文字和图片。用户需承担该风险。" + @override + String get UG_LINE24 => "(2)用户有权更改、删除在Qianhai Youlong Technology Co., Ltd..上的个人资料、注册信息及传送内容等,但需注意,删除有关信息的同时也会删除任何您储存在系统中的文字和图片。用户需承担该风险。"; + /// "(3)用户有责任妥善保管注册帐号信息及帐号密码的安全,用户需要对注册帐号以及密码下的行为承担法律责任。用户同意在任何情况下不使用其他成员的帐号或密码。在您怀疑他人在使用您的帐号或密码时,您同意立即通知Qianhai Youlong Technology Co., Ltd.。" + @override + String get UG_LINE25 => "(3)用户有责任妥善保管注册帐号信息及帐号密码的安全,用户需要对注册帐号以及密码下的行为承担法律责任。用户同意在任何情况下不使用其他成员的帐号或密码。在您怀疑他人在使用您的帐号或密码时,您同意立即通知Qianhai Youlong Technology Co., Ltd.。"; + /// "(4)用户应遵守本协议的各项条款,正确、适当地使用本服务,如因用户违反本协议中的任何条款,Qianhai Youlong Technology Co., Ltd.有权依据协议终止对违约用户Qianhai Youlong Technology Co., Ltd.帐号提供服务。同时,Qianhai Youlong Technology Co., Ltd.保留在任何时候收回Qianhai Youlong Technology Co., Ltd.帐号、用户名的权利。" + @override + String get UG_LINE26 => "(4)用户应遵守本协议的各项条款,正确、适当地使用本服务,如因用户违反本协议中的任何条款,Qianhai Youlong Technology Co., Ltd.有权依据协议终止对违约用户Qianhai Youlong Technology Co., Ltd.帐号提供服务。同时,Qianhai Youlong Technology Co., Ltd.保留在任何时候收回Qianhai Youlong Technology Co., Ltd.帐号、用户名的权利。"; + /// "(5)如果用户有自己的常用英文帐号,那么用户有优先将该英文帐号注册为帐号的权利,但是如果用户在服务上线后一段时间内没有注册帐号,或者用户虽然注册了微信帐号,但是并不是使用该英文帐号作为微信帐号的,视为用户放弃了将该英文帐号注册为微信帐号的权利,Qianhai Youlong Technology Co., Ltd.有权将该英文帐号回收并分配给其他用户使用,以免造成资源浪费,由此带来问题均由用户自行承担。" + @override + String get UG_LINE27 => "(5)如果用户有自己的常用英文帐号,那么用户有优先将该英文帐号注册为帐号的权利,但是如果用户在服务上线后一段时间内没有注册帐号,或者用户虽然注册了微信帐号,但是并不是使用该英文帐号作为微信帐号的,视为用户放弃了将该英文帐号注册为微信帐号的权利,Qianhai Youlong Technology Co., Ltd.有权将该英文帐号回收并分配给其他用户使用,以免造成资源浪费,由此带来问题均由用户自行承担。"; + /// "(6)用户注册帐号后如果长期不登录该帐号,Qianhai Youlong Technology Co., Ltd.有权回收该帐号,以免造成资源浪费,由此带来问题均由用户自行承担。" + @override + String get UG_LINE28 => "(6)用户注册帐号后如果长期不登录该帐号,Qianhai Youlong Technology Co., Ltd.有权回收该帐号,以免造成资源浪费,由此带来问题均由用户自行承担。"; + /// "(7)用户发生纠纷可使用举报功能维护用户平台权益,若收到用户举报反馈,被举报用户有义务主动告知或配合客服人员核实情况,举报内容核实属实,面具公园有权对用户警告、限制账号使用功能等方式约束用户违规行为,严重违规者hi有权直接冻结账号,且账户内余额不返还。如果账号被冻结需申诉,用户可联系客服 。" + @override + String get UG_LINE29 => "(7)用户发生纠纷可使用举报功能维护用户平台权益,若收到用户举报反馈,被举报用户有义务主动告知或配合客服人员核实情况,举报内容核实属实,面具公园有权对用户警告、限制账号使用功能等方式约束用户违规行为,严重违规者hi有权直接冻结账号,且账户内余额不返还。如果账号被冻结需申诉,用户可联系客服 。"; + /// "二、隐私保护" + @override + String get UG_LINE30 => "二、隐私保护"; + /// "用户同意个人隐私信息是指那些能够对用户进行个人辨识或涉及个人通信的信息,包括下列信息:用户真实姓名,手机号码,微信账号,facebook账号,IP地址。而非个人隐私信息是指用户对本服务的操作状态以及使用习惯等一些明确且客观反映在Qianhai Youlong Technology Co., Ltd.服务器端的基本记录信息和其他一切个人隐私信息范围外的普通信息;以及用户同意公开的上述隐私信息。尊重用户个人隐私信息的私有性是Qianhai Youlong Technology Co., Ltd.的一贯制度,Qianhai Youlong Technology Co., Ltd.将会采取合理的措施保护用户的个人隐私信息,除法律或有法律赋予权限的政府部门要求或用户同意等原因外,Qianhai Youlong Technology Co., Ltd.未经用户同意不向除合作单位以外的第三方公开、透露用户个人隐私信息。但是,用户在注册时选择同意,或用户与Qianhai Youlong Technology Co., Ltd.及合作单位之间就用户个人隐私信息公开或使用另有约定的除外,同时用户应自行承担因此可能产生的任何风险,Qianhai Youlong Technology Co., Ltd.对此不予负责。同时,为了运营和改善Qianhai Youlong Technology Co., Ltd.的技术和服务,Qianhai Youlong Technology Co., Ltd.将可能会自行收集使用或向第三方提供用户的非个人隐私信息,这将有助于Qianhai Youlong Technology Co., Ltd.向用户提供更好的用户体验和提高Qianhai Youlong Technology Co., Ltd.的服务质量。Qianhai Youlong Technology Co., Ltd.收集数据是根据用户与Qianhai Youlong Technology Co., Ltd.的互动和用户所做出的选择,包括用户的隐私设置以及用户使用的产品和功能。Qianhai Youlong Technology Co., Ltd.收集的数据可能包括SDK/API/JS代码版本、IP地址、平台、时间戳、应用标识符、应用程序版本、应用分发渠道、独立设备标识符、iOS广告标识符(IDFA)、 安卓广告主标识符、网卡(MAC) 地址、国际移动设备识别码(IMEI)、设备型号、终端制造厂商、终端设备操作系统版本、会话启动/停止时间、语言所在地、时区和网络状态(WiFi等)、 硬盘、 CPU和电池使用情况等。这将有助于Qianhai Youlong Technology Co., Ltd.开展内部数据分析和研究,第三方SDK统计服务,改善Qianhai Youlong Technology Co., Ltd.的产品或服务。为确保用户身份真实性,向用户提供更好的安全保障,用户需提交的身份信息或面部特征等生物识别信息(均属于个人敏感信息)来完成具体产品服务所需或必要的真人认证。.上 述信息将仅用于核实用户身份的真实性。用户提供的.上述信息,将在用户使用本服务期间持续授权Qianhai Youlong Technology Co., Ltd.使用。在用户注销账号时,Qianhai Youlong Technology Co., Ltd.将停止使用。上述信息将存储于中华人民共和国境内。如需跨境传输,Qianhai Youlong Technology Co., Ltd.将会单独征得用户的授权同意。App用户真实性认证需要用户提供能证实用户身份真实性的部分资料。相关资料只用做平台审核不会披露给任何其他用户或用于商业用途,仅法律或有关部门要求介入除外。" + @override + String get UG_LINE31 => "用户同意个人隐私信息是指那些能够对用户进行个人辨识或涉及个人通信的信息,包括下列信息:用户真实姓名,手机号码,微信账号,facebook账号,IP地址。而非个人隐私信息是指用户对本服务的操作状态以及使用习惯等一些明确且客观反映在Qianhai Youlong Technology Co., Ltd.服务器端的基本记录信息和其他一切个人隐私信息范围外的普通信息;以及用户同意公开的上述隐私信息。尊重用户个人隐私信息的私有性是Qianhai Youlong Technology Co., Ltd.的一贯制度,Qianhai Youlong Technology Co., Ltd.将会采取合理的措施保护用户的个人隐私信息,除法律或有法律赋予权限的政府部门要求或用户同意等原因外,Qianhai Youlong Technology Co., Ltd.未经用户同意不向除合作单位以外的第三方公开、透露用户个人隐私信息。但是,用户在注册时选择同意,或用户与Qianhai Youlong Technology Co., Ltd.及合作单位之间就用户个人隐私信息公开或使用另有约定的除外,同时用户应自行承担因此可能产生的任何风险,Qianhai Youlong Technology Co., Ltd.对此不予负责。同时,为了运营和改善Qianhai Youlong Technology Co., Ltd.的技术和服务,Qianhai Youlong Technology Co., Ltd.将可能会自行收集使用或向第三方提供用户的非个人隐私信息,这将有助于Qianhai Youlong Technology Co., Ltd.向用户提供更好的用户体验和提高Qianhai Youlong Technology Co., Ltd.的服务质量。Qianhai Youlong Technology Co., Ltd.收集数据是根据用户与Qianhai Youlong Technology Co., Ltd.的互动和用户所做出的选择,包括用户的隐私设置以及用户使用的产品和功能。Qianhai Youlong Technology Co., Ltd.收集的数据可能包括SDK/API/JS代码版本、IP地址、平台、时间戳、应用标识符、应用程序版本、应用分发渠道、独立设备标识符、iOS广告标识符(IDFA)、 安卓广告主标识符、网卡(MAC) 地址、国际移动设备识别码(IMEI)、设备型号、终端制造厂商、终端设备操作系统版本、会话启动/停止时间、语言所在地、时区和网络状态(WiFi等)、 硬盘、 CPU和电池使用情况等。这将有助于Qianhai Youlong Technology Co., Ltd.开展内部数据分析和研究,第三方SDK统计服务,改善Qianhai Youlong Technology Co., Ltd.的产品或服务。为确保用户身份真实性,向用户提供更好的安全保障,用户需提交的身份信息或面部特征等生物识别信息(均属于个人敏感信息)来完成具体产品服务所需或必要的真人认证。.上 述信息将仅用于核实用户身份的真实性。用户提供的.上述信息,将在用户使用本服务期间持续授权Qianhai Youlong Technology Co., Ltd.使用。在用户注销账号时,Qianhai Youlong Technology Co., Ltd.将停止使用。上述信息将存储于中华人民共和国境内。如需跨境传输,Qianhai Youlong Technology Co., Ltd.将会单独征得用户的授权同意。App用户真实性认证需要用户提供能证实用户身份真实性的部分资料。相关资料只用做平台审核不会披露给任何其他用户或用于商业用途,仅法律或有关部门要求介入除外。"; + /// "三、Qianhai Youlong Technology Co., Ltd.商标信息" + @override + String get UG_LINE32 => "三、Qianhai Youlong Technology Co., Ltd.商标信息"; + /// "Qianhai Youlong Technology Co., Ltd.服务中所涉及的logo等图形、文字或其组成,以及其他Qianhai Youlong Technology Co., Ltd.标志及产品、服务名称,均为Qianhai Youlong Technology Co., Ltd.之商标(以下简称“Qianhai Youlong Technology Co., Ltd.标识”)。未经Qianhai Youlong Technology Co., Ltd.事先书面同意,用户不得将Qianhai Youlong Technology Co., Ltd.标识以任何方式展示或使用或作其他处理,也不得向他人表明您有权展示、使用、或其他有权处理Qianhai Youlong Technology Co., Ltd.标识的行为。" + @override + String get UG_LINE33 => "Qianhai Youlong Technology Co., Ltd.服务中所涉及的logo等图形、文字或其组成,以及其他Qianhai Youlong Technology Co., Ltd.标志及产品、服务名称,均为Qianhai Youlong Technology Co., Ltd.之商标(以下简称“Qianhai Youlong Technology Co., Ltd.标识”)。未经Qianhai Youlong Technology Co., Ltd.事先书面同意,用户不得将Qianhai Youlong Technology Co., Ltd.标识以任何方式展示或使用或作其他处理,也不得向他人表明您有权展示、使用、或其他有权处理Qianhai Youlong Technology Co., Ltd.标识的行为。"; + /// "四、法律责任及免责" + @override + String get UG_LINE34 => "四、法律责任及免责"; + /// "1、用户违反本《协议》或相关的服务条款的规定,导致或产生的任何第三方主张的任何索赔、要求或损失,包括合理的律师费,用户同意赔偿Qianhai Youlong Technology Co., Ltd.与合作公司、关联公司,并使之免受损害。" + @override + String get UG_LINE35 => "1、用户违反本《协议》或相关的服务条款的规定,导致或产生的任何第三方主张的任何索赔、要求或损失,包括合理的律师费,用户同意赔偿Qianhai Youlong Technology Co., Ltd.与合作公司、关联公司,并使之免受损害。"; + /// "2、用户因第三方如电信部门的通讯线路故障、技术问题、网络、电脑故障、系统不稳定性及其他各种不可抗力原因而遭受的一切损失,Qianhai Youlong Technology Co., Ltd.及合作单位不承担责任。" + @override + String get UG_LINE36 => "2、用户因第三方如电信部门的通讯线路故障、技术问题、网络、电脑故障、系统不稳定性及其他各种不可抗力原因而遭受的一切损失,Qianhai Youlong Technology Co., Ltd.及合作单位不承担责任。"; + /// "3、因技术故障等不可抗事件影响到服务的正常运行的,Qianhai Youlong Technology Co., Ltd.及合作单位承诺在第一时间内与相关单位配合,及时处理进行修复,但用户因此而遭受的一切损失,Qianhai Youlong Technology Co., Ltd.及合作单位不承担责任。" + @override + String get UG_LINE37 => "3、因技术故障等不可抗事件影响到服务的正常运行的,Qianhai Youlong Technology Co., Ltd.及合作单位承诺在第一时间内与相关单位配合,及时处理进行修复,但用户因此而遭受的一切损失,Qianhai Youlong Technology Co., Ltd.及合作单位不承担责任。"; + /// "4、本服务同大多数互联网服务一样,受包括但不限于用户原因、网络服务质量、社会环境等因素的差异影响,可能受到各种安全问题的侵扰,如他人利用用户的资料,造成现实生活中的骚扰;用户下载安装的其它软件或访问的其他网站中含有“特洛伊木马”等病毒,威胁到用户的计算机信息和数据的安全,继而影响本服务的正常使用等等。用户应加强信息安全及使用者资料的保护意识,要注意加强密码保护,以免遭致损失和骚扰。" + @override + String get UG_LINE38 => "4、本服务同大多数互联网服务一样,受包括但不限于用户原因、网络服务质量、社会环境等因素的差异影响,可能受到各种安全问题的侵扰,如他人利用用户的资料,造成现实生活中的骚扰;用户下载安装的其它软件或访问的其他网站中含有“特洛伊木马”等病毒,威胁到用户的计算机信息和数据的安全,继而影响本服务的正常使用等等。用户应加强信息安全及使用者资料的保护意识,要注意加强密码保护,以免遭致损失和骚扰。"; + /// "5、用户须明白,使用本服务因涉及Internet服务,可能会受到各个环节不稳定因素的影响。因此,本服务存在因不可抗力、计算机病毒或黑客攻击、系统不稳定、用户所在位置、用户关机以及其他任何技术、互联网络、通信线路原因等造成的服务中断或不能满足用户要求的风险。用户须承担以上风险,Qianhai Youlong Technology Co., Ltd.不作担保。对因此导致用户不能发送和接受阅读信息、或接发错信息,Qianhai Youlong Technology Co., Ltd.不承担任何责任。" + @override + String get UG_LINE39 => "5、用户须明白,使用本服务因涉及Internet服务,可能会受到各个环节不稳定因素的影响。因此,本服务存在因不可抗力、计算机病毒或黑客攻击、系统不稳定、用户所在位置、用户关机以及其他任何技术、互联网络、通信线路原因等造成的服务中断或不能满足用户要求的风险。用户须承担以上风险,Qianhai Youlong Technology Co., Ltd.不作担保。对因此导致用户不能发送和接受阅读信息、或接发错信息,Qianhai Youlong Technology Co., Ltd.不承担任何责任。"; + /// "6、用户须明白,在使用本服务过程中存在有来自,任何他人的包括威胁性的、诽谤性的、令人反感的或非法的内容或行为或对他人权利的侵犯(包括知识产权)的匿名或冒名的信息的风险,用户须承担以上风险,Qianhai Youlong Technology Co., Ltd.和合作公司对本服务不作任何类型的担保,不论是明确的或隐含的,包括所有有关信息真实性、适商性、适于某一特定用途、所有权和非侵权性的默示担保和条件,对因此导致任何因用户不正当或非法使用服务产生的直接、间接、偶然、特殊及后续的损害,不承担任何责任。" + @override + String get UG_LINE40 => "6、用户须明白,在使用本服务过程中存在有来自,任何他人的包括威胁性的、诽谤性的、令人反感的或非法的内容或行为或对他人权利的侵犯(包括知识产权)的匿名或冒名的信息的风险,用户须承担以上风险,Qianhai Youlong Technology Co., Ltd.和合作公司对本服务不作任何类型的担保,不论是明确的或隐含的,包括所有有关信息真实性、适商性、适于某一特定用途、所有权和非侵权性的默示担保和条件,对因此导致任何因用户不正当或非法使用服务产生的直接、间接、偶然、特殊及后续的损害,不承担任何责任。"; + /// "7、Qianhai Youlong Technology Co., Ltd.定义的信息内容包括:文字、软件、声音、相片、录像、图表;在广告中全部内容;Qianhai Youlong Technology Co., Ltd.为用户提供的商业信息,所有这些内容受版权、商标权、和其它知识产权和所有权法律的保护。所以,用户只能在Qianhai Youlong Technology Co., Ltd.和广告商授权下才能使用这些内容,而不能擅自复制、修改、编纂这.些内容、或创造与内容有关的衍生产品。" + @override + String get UG_LINE41 => "7、Qianhai Youlong Technology Co., Ltd.定义的信息内容包括:文字、软件、声音、相片、录像、图表;在广告中全部内容;Qianhai Youlong Technology Co., Ltd.为用户提供的商业信息,所有这些内容受版权、商标权、和其它知识产权和所有权法律的保护。所以,用户只能在Qianhai Youlong Technology Co., Ltd.和广告商授权下才能使用这些内容,而不能擅自复制、修改、编纂这.些内容、或创造与内容有关的衍生产品。"; + /// "8、在任何情况下,Qianhai Youlong Technology Co., Ltd.均不对任何间接性、后果性、惩罚性、偶然性、特殊性或刑罚性的损害,包括因用户使用服务而遭受的利润损失,承担责任(即使已被告知该等损失的可能性亦然)。 尽管本协议中可能含有相悖的规定,Qianhai Youlong Technology Co., Ltd.对您承担的全部责任,无论因何原因或何种行为方式,始终不超过您在成员期内因使用服务而支付给Qianhai Youlong Technology Co., Ltd.的费用。" + @override + String get UG_LINE42 => "8、在任何情况下,Qianhai Youlong Technology Co., Ltd.均不对任何间接性、后果性、惩罚性、偶然性、特殊性或刑罚性的损害,包括因用户使用服务而遭受的利润损失,承担责任(即使已被告知该等损失的可能性亦然)。 尽管本协议中可能含有相悖的规定,Qianhai Youlong Technology Co., Ltd.对您承担的全部责任,无论因何原因或何种行为方式,始终不超过您在成员期内因使用服务而支付给Qianhai Youlong Technology Co., Ltd.的费用。"; + /// "五、会员条款" + @override + String get UG_LINE43 => "五、会员条款"; + /// "1、hi会员平等享有会员的权利,同时应遵守Qianhai Youlong Technology Co., Ltd.的各项规范、规则,包括但不限于本服务条款和《用户协议》。" + @override + String get UG_LINE44 => "1、hi会员平等享有会员的权利,同时应遵守Qianhai Youlong Technology Co., Ltd.的各项规范、规则,包括但不限于本服务条款和《用户协议》。"; + /// "2、因违反Qianhai Youlong Technology Co., Ltd.《用户协议》而导致会员服务被暂停使用的相关损失,由用户自行承担。" + @override + String get UG_LINE45 => "2、因违反Qianhai Youlong Technology Co., Ltd.《用户协议》而导致会员服务被暂停使用的相关损失,由用户自行承担。"; + /// "3、会员在会员资格有效期内可以享受hi会员的各项增值服务。" + @override + String get UG_LINE46 => "3、会员在会员资格有效期内可以享受hi会员的各项增值服务。"; + /// "4、如会员在会员资格有效期内主动终止或取消会员资格,Qianhai Youlong Technology Co., Ltd.不负责退还与该会员剩余会员资格有效期对应的服务费用。" + @override + String get UG_LINE47 => "4、如会员在会员资格有效期内主动终止或取消会员资格,Qianhai Youlong Technology Co., Ltd.不负责退还与该会员剩余会员资格有效期对应的服务费用。"; + /// "5、会员自行承担在hi中传送、发布信息及使用hi免费服务或收费服务的法律责任,会员使用hi服务,包括免费服务与收费服务的行为,均应遵守各项法律法规、规章、规范性文件。" + @override + String get UG_LINE48 => "5、会员自行承担在hi中传送、发布信息及使用hi免费服务或收费服务的法律责任,会员使用hi服务,包括免费服务与收费服务的行为,均应遵守各项法律法规、规章、规范性文件。"; + /// "6、会员服务开通之后,不可进行转让或退订。" + @override + String get UG_LINE49 => "6、会员服务开通之后,不可进行转让或退订。"; + /// "7、因会员在使用Qianhai Youlong Technology Co., Ltd.免费服务或收费服务的过程中,存在违反法律法规的行为,Qianhai Youlong Technology Co., Ltd.有权取消该会员的会员资格而无须给予任何补偿,且该会员须自行承担全部责任。" + @override + String get UG_LINE50 => "7、因会员在使用Qianhai Youlong Technology Co., Ltd.免费服务或收费服务的过程中,存在违反法律法规的行为,Qianhai Youlong Technology Co., Ltd.有权取消该会员的会员资格而无须给予任何补偿,且该会员须自行承担全部责任。"; + /// "六、其他条款" + @override + String get UG_LINE51 => "六、其他条款"; + /// "1、Qianhai Youlong Technology Co., Ltd.郑重提醒用户注意本《协议》中免除Qianhai Youlong Technology Co., Ltd.责任和加重用户义务的条款,请用户仔细阅读,自主考虑风险。未成年人应在法定监护人的陪同下阅读本《协议》。以上各项条款内容的最终解释权及修改权归Qianhai Youlong Technology Co., Ltd.所有。" + @override + String get UG_LINE52 => "1、Qianhai Youlong Technology Co., Ltd.郑重提醒用户注意本《协议》中免除Qianhai Youlong Technology Co., Ltd.责任和加重用户义务的条款,请用户仔细阅读,自主考虑风险。未成年人应在法定监护人的陪同下阅读本《协议》。以上各项条款内容的最终解释权及修改权归Qianhai Youlong Technology Co., Ltd.所有。"; + /// "2、本《协议》所定的任何条款的部分或全部无效者,不影响其它条款的效力。" + @override + String get UG_LINE53 => "2、本《协议》所定的任何条款的部分或全部无效者,不影响其它条款的效力。"; + /// "3、本《协议》的解释、效力及纠纷的解决,适用于中华人民共和国法律。若用户和Qianhai Youlong Technology Co., Ltd.之间发生任何纠纷或争议,首先应友好协商解决,协商不成的,用户在此完全同意将纠纷或争议提交Qianhai Youlong Technology Co., Ltd.住所地的人民法院管辖。" + @override + String get UG_LINE54 => "3、本《协议》的解释、效力及纠纷的解决,适用于中华人民共和国法律。若用户和Qianhai Youlong Technology Co., Ltd.之间发生任何纠纷或争议,首先应友好协商解决,协商不成的,用户在此完全同意将纠纷或争议提交Qianhai Youlong Technology Co., Ltd.住所地的人民法院管辖。"; + /// "4、本《协议》的版权由Qianhai Youlong Technology Co., Ltd.所有,Qianhai Youlong Technology Co., Ltd.保留一切解释和修改权利。" + @override + String get UG_LINE55 => "4、本《协议》的版权由Qianhai Youlong Technology Co., Ltd.所有,Qianhai Youlong Technology Co., Ltd.保留一切解释和修改权利。"; + /// "前海游龙科技有限公司" + @override + String get UG_LINE56 => "前海游龙科技有限公司"; + /// "网络异常" + @override + String get net_error => "网络异常"; + /// "请输入姓名" + @override + String get enter_name => "请输入姓名"; + /// "译" + @override + String get translate => "译"; + /// "位置" + @override + String get locate => "位置"; + /// "按住录音,松开发送" + @override + String get voice_tips => "按住录音,松开发送"; + /// "解锁" + @override + String get unlock => "解锁"; + /// "请输入聊天内容" + @override + String get input_content => "请输入聊天内容"; + /// "连接中..." + @override + String get connecting => "连接中..."; + /// "登陆中..." + @override + String get logining => "登陆中..."; + /// "/s1拒绝了你的查看申请" + @override + String get reject_reply => "/s1拒绝了你的查看申请"; + /// "H币进账3天内没人举报你即可兑消(1:1000越南盾)" + @override + String get warning_text => "H币进账3天内没人举报你即可兑消(1:1000越南盾)"; + /// "输入个数不大于/s1" + @override + String get more_big => "输入个数不大于/s1"; + /// "输入个数不小于/s1" + @override + String get little_min => "输入个数不小于/s1"; + /// "/s1邀请你进行通话" + @override + String get voice_msg => "/s1邀请你进行通话"; + /// "你打赏了对方/s1个/s2" + @override + String get send_gift => "你打赏了对方/s1个/s2"; + /// "对方打赏了你/s1个/s2" + @override + String get receive_gift => "对方打赏了你/s1个/s2"; + /// "非会员不能报名" + @override + String get cannot_join => "非会员不能报名"; + /// "已退回" + @override + String get alreay_back => "已退回"; + /// "文件过大" + @override + String get video_more_big => "文件过大"; + /// "选择所有" + @override + String get select_all => "选择所有"; + /// "重新连接" + @override + String get re_connect => "重新连接"; + /// "松开发送,滑动取消" + @override + String get voice_tips2 => "松开发送,滑动取消"; + /// "国籍" + @override + String get country => "国籍"; + /// "有照片审核中" + @override + String get have_picture_view => "有照片审核中"; + /// "扬声器播放" + @override + String get speaker_play => "扬声器播放"; + /// "听筒播放" + @override + String get handset_playback => "听筒播放"; + /// "听筒模式" + @override + String get play_model => "听筒模式"; + /// "密码过短" + @override + String get password_less => "密码过短"; + /// "岁" + @override + String get years_old => "岁"; + /// "经匿名用户举报,系统核实你近期存在违规行为,请勿再进行违规操作。如有下次,将进行账号冻结" + @override + String get coin_returen1 => "经匿名用户举报,系统核实你近期存在违规行为,请勿再进行违规操作。如有下次,将进行账号冻结"; + /// "已经是最新版本" + @override + String get already_new => "已经是最新版本"; + /// "立即体验" + @override + String get test_it => "立即体验"; + /// "发现新版本" + @override + String get found_new => "发现新版本"; + /// "广告" + @override + String get ad => "广告"; + /// "关注" + @override + String get attention => "关注"; + /// "粉丝" + @override + String get fans => "粉丝"; + /// "/s1 申请查看我的资料页" + @override + String get apply_see => "/s1 申请查看我的资料页"; + /// "/s1 通过了我的查看请求" + @override + String get agree_apply => "/s1 通过了我的查看请求"; + /// "/s1 查看了我的红包照片" + @override + String get see_redBag => "/s1 查看了我的红包照片"; + /// "提醒" + @override + String get notice => "提醒"; + /// "请在手机设置中开启通知权限以获取消息通知" + @override + String get notice_open => "请在手机设置中开启通知权限以获取消息通知"; + /// "通知权限未开启" + @override + String get open_notice => "通知权限未开启"; + /// "未开启通知权限,无法接收通知" + @override + String get not_open => "未开启通知权限,无法接收通知"; + /// "你申请提现的的/s1H币已被退回,请确认绑定账户是否正确" + @override + String get withdraw_fail => "你申请提现的的/s1H币已被退回,请确认绑定账户是否正确"; + /// "动态" + @override + String get dynamics => "动态"; + /// "备注" + @override + String get Remark => "备注"; + /// "设置备注" + @override + String get setRemark => "设置备注"; + /// "/s1条评论" + @override + String get content_num => "/s1条评论"; + /// "积分兑换获得/s1H币" + @override + String get Redeem => "积分兑换获得/s1H币"; + /// "没有访问手机存储权限" + @override + String get location_permission => "没有访问手机存储权限"; + /// "没有访问摄像头权限" + @override + String get camera_permission => "没有访问摄像头权限"; + /// "没有访问相册的权限" + @override + String get photo_permission => "没有访问相册的权限"; + /// "没有访问麦克风的权限" + @override + String get video_permission => "没有访问麦克风的权限"; + /// "你发送的红包已过期" + @override + String get your_redMoney_over => "你发送的红包已过期"; + /// "对方发送的红包已过期" + @override + String get other_redMoney_over => "对方发送的红包已过期"; + /// "貌似出了点问题..." + @override + String get server_error_tips => "貌似出了点问题..."; + /// "表情" + @override + String get emoji => "表情"; + /// "今日签到可领取/s1积分" + @override + String get today_score => "今日签到可领取/s1积分"; + /// "1、每日签到可领取积分,累计天数越多积分越高。\n2、积分可兑换H币,兑换将消耗对应积分,请慎重兑换。\n3、每月最后一天将重置签到,清零积分,请记得及时兑换。" + @override + String get sign_tips => "1、每日签到可领取积分,累计天数越多积分越高。\n2、积分可兑换H币,兑换将消耗对应积分,请慎重兑换。\n3、每月最后一天将重置签到,清零积分,请记得及时兑换。"; + /// "签到" + @override + String get sign_in => "签到"; + /// "我的积分" + @override + String get my_score => "我的积分"; + /// "立即签到" + @override + String get signin_now => "立即签到"; + /// "已累积签到/s1天" + @override + String get sign_in_day => "已累积签到/s1天"; + /// "已兑换" + @override + String get have_get => "已兑换"; + /// "扫一扫" + @override + String get scan => "扫一扫"; + /// "我的二维码" + @override + String get my_qr => "我的二维码"; + /// "扫一扫,加好友" + @override + String get scan_and_add => "扫一扫,加好友"; + /// "高德地图" + @override + String get amap => "高德地图"; + /// "百度地图" + @override + String get baidumap => "百度地图"; + /// "谷歌地图" + @override + String get googlemap => "谷歌地图"; + /// "苹果地图" + @override + String get applemap => "苹果地图"; + /// "去开启" + @override + String get go_open => "去开启"; + /// "预览" + @override + String get Preview => "预览"; + /// "相册" + @override + String get Photo_album => "相册"; + /// "全部图片" + @override + String get all_photo => "全部图片"; + /// "您已经选择了/s1张图片" + @override + String get have_select => "您已经选择了/s1张图片"; + /// "加载中..." + @override + String get loading => "加载中..."; + /// "您有新的聊天消息" + @override + String get new_chat_msg => "您有新的聊天消息"; + /// "您有新的连麦消息" + @override + String get new_video_msg => "您有新的连麦消息"; + /// "/s1申请成为你的好友" + @override + String get apply_friends => "/s1申请成为你的好友"; + /// "/s1通过了你的好友请求" + @override + String get applyed_friends => "/s1通过了你的好友请求"; + /// "没有访问通讯录的权限" + @override + String get contact_permission => "没有访问通讯录的权限"; + /// "通讯录" + @override + String get contact => "通讯录"; + /// "搜索" + @override + String get search => "搜索"; + /// "添加通讯录中的好友" + @override + String get contact_add => "添加通讯录中的好友"; + /// "发现" + @override + String get find => "发现"; + /// "翻译机器人" + @override + String get translate_robot => "翻译机器人"; + /// "你好,我是翻译机器人..." + @override + String get robot_hello => "你好,我是翻译机器人..."; + /// "简体中文" + @override + String get Simplified_Chinese => "简体中文"; + /// "繁体中文" + @override + String get traditional_Chinese => "繁体中文"; + /// "英语" + @override + String get english => "英语"; + /// "越南语" + @override + String get Vietnamese => "越南语"; + /// "韩语" + @override + String get Korean => "韩语"; + /// "日语" + @override + String get Japanese => "日语"; + /// "添加好友" + @override + String get add_friends => "添加好友"; + /// "陌生人" + @override + String get stranger => "陌生人"; + /// "接收陌生人发送的消息" + @override + String get receive_stranger => "接收陌生人发送的消息"; + /// "签到" + @override + String get signin => "签到"; + /// "对方拒绝接收陌生人发送的消息,是否继续解锁全部资料。" + @override + String get stranger_close => "对方拒绝接收陌生人发送的消息,是否继续解锁全部资料。"; + /// "添加" + @override + String get add => "添加"; + /// "已添加" + @override + String get added => "已添加"; + /// "对方拒绝接收陌生人发送的消息。" + @override + String get stranger_close_tips => "对方拒绝接收陌生人发送的消息。"; + /// "翻译失败" + @override + String get translate_fail => "翻译失败"; + /// "请先上传照片,再设置红包照片。" + @override + String get no_photos => "请先上传照片,再设置红包照片。"; + /// "你上诉的评价:/s1上诉失败。" + @override + String get successful_appeal1 => "你上诉的评价:/s1上诉失败。"; + /// "添加成功,等待对方同意" + @override + String get add_success => "添加成功,等待对方同意"; + /// "他人代付" + @override + String get other_pay => "他人代付"; + /// "朋友验证" + @override + String get friend_verification => "朋友验证"; + /// "你已发送验证申请,等对方通过" + @override + String get add_friends_tips => "你已发送验证申请,等对方通过"; + /// "我是/s1" + @override + String get i_am => "我是/s1"; + /// "允许" + @override + String get agree => "允许"; + /// "\"Hibok\"需要您同意《隐私协议》方可使用" + @override + String get privacyAgreement => "\"Hibok\"需要您同意《隐私协议》方可使用"; + /// "隐私协议" + @override + String get privacy => "隐私协议"; + /// "Hibok!有人申请添加你为好友,看看是谁吧" + @override + String get notification_addfriend => "Hibok!有人申请添加你为好友,看看是谁吧"; + /// "面对面才可以加好友哦" + @override + String get distance_long => "面对面才可以加好友哦"; + /// "为了翻译内容的准确性,请不要简写" + @override + String get chat_tips => "为了翻译内容的准确性,请不要简写"; + /// "粉丝列表" + @override + String get fans_list => "粉丝列表"; + /// "功能内测中" + @override + String get system_not_open => "功能内测中"; + /// "iOS客户端暂不支持提现,你可以使用安卓客户端提现,或点击下方按钮进行提现" + @override + String get service_withdraw_tips => "iOS客户端暂不支持提现,你可以使用安卓客户端提现,或点击下方按钮进行提现"; + /// "点击提现" + @override + String get withdraw_tips => "点击提现"; + /// "添加成员" + @override + String get add_member => "添加成员"; + /// "删除成员" + @override + String get delete_member => "删除成员"; + /// "修改群名称" + @override + String get change_group_name => "修改群名称"; + /// "我在本群中的昵称" + @override + String get my_group_nickname => "我在本群中的昵称"; + /// "群聊" + @override + String get group_chat => "群聊"; + /// "创建群聊" + @override + String get create_group_chat => "创建群聊"; + /// "你需要发送验证申请,等对方通过" + @override + String get added_friends_tips => "你需要发送验证申请,等对方通过"; + /// "群聊名称" + @override + String get group_chat_name => "群聊名称"; + /// "在这里可以设置你在这个群里的昵称,这个昵称只会在此群内显示" + @override + String get my_group_nickname_tips => "在这里可以设置你在这个群里的昵称,这个昵称只会在此群内显示"; + /// "男神动态" + @override + String get man_gold => "男神动态"; + /// "女神动态" + @override + String get woman_gold => "女神动态"; + /// "选择新群主" + @override + String get choose_group_owner => "选择新群主"; + /// "群公告" + @override + String get group_announcement => "群公告"; + /// "聊天消息" + @override + String get chat_news => "聊天消息"; + /// "群二维码" + @override + String get group_qr => "群二维码"; + /// "群管理" + @override + String get group_setting => "群管理"; + /// "消息免打扰" + @override + String get close_news_notice => "消息免打扰"; + /// "置顶聊天" + @override + String get set_chat_top => "置顶聊天"; + /// "显示群成员昵称" + @override + String get show_group_member_name => "显示群成员昵称"; + /// "退出后不会通知群聊中其他成员,且不会再接收此群聊消息" + @override + String get quit_group_tips => "退出后不会通知群聊中其他成员,且不会再接收此群聊消息"; + /// "退出并删除" + @override + String get quit_and_delete => "退出并删除"; + /// "查看更多群成员" + @override + String get show_more_member => "查看更多群成员"; + /// "群聊邀请确认" + @override + String get group_invite => "群聊邀请确认"; + /// "群主管理权转让" + @override + String get change_group_owner => "群主管理权转让"; + /// "启用后,群成员需群主确认才能邀请朋友进群。扫二维码进群将同时停用" + @override + String get group_setting_tips => "启用后,群成员需群主确认才能邀请朋友进群。扫二维码进群将同时停用"; + /// "邀请详情" + @override + String get invite_detail => "邀请详情"; + /// "未命名" + @override + String get undefine_name => "未命名"; + /// "群二维码名片" + @override + String get group_qr_code => "群二维码名片"; + /// "该二维码7天内(/s1月/s2日前)有效,重新进入将更新" + @override + String get group_qr_code_tips => "该二维码7天内(/s1月/s2日前)有效,重新进入将更新"; + /// "女神热度" + @override + String get Goddess_heat => "女神热度"; + /// "累计收获的礼物" + @override + String get Goddess_heat_tips => "累计收获的礼物"; + /// "新朋友" + @override + String get new_friends => "新朋友"; + /// "三天前" + @override + String get before_three_day => "三天前"; + /// "近三天" + @override + String get after_three_day => "近三天"; + /// "清除聊天记录" + @override + String get group_clean_chat_record => "清除聊天记录"; + /// "查看" + @override + String get check => "查看"; + /// "请求添加你为好友" + @override + String get apply_fro_friends => "请求添加你为好友"; + /// "非会员不能提现" + @override + String get no_vip_cannot_withdraw => "非会员不能提现"; + /// "该用户未认证,谨防被骗" + @override + String get not_true_woman => "该用户未认证,谨防被骗"; + /// "加入群聊" + @override + String get join_group => "加入群聊"; + /// "通过Apple登录" + @override + String get sign_in_apple => "通过Apple登录"; + /// "只有群主才能编辑群公告" + @override + String get only_host => "只有群主才能编辑群公告"; + /// "你打赏了对方/s1个礼物" + @override + String get send_gift1 => "你打赏了对方/s1个礼物"; + /// "对方打赏了你/s1个礼物" + @override + String get receive_gift1 => "对方打赏了你/s1个礼物"; + /// "你已不在该群" + @override + String get not_in_group => "你已不在该群"; + /// "正在创建,请稍等" + @override + String get creating_group => "正在创建,请稍等"; + /// "条" + @override + String get article => "条"; + /// "该群已开启进群验证只能通过邀请进群" + @override + String get group_open_verification => "该群已开启进群验证只能通过邀请进群"; + /// "群成员" + @override + String get group_memeber => "群成员"; + /// "邀请/s1位朋友加入群聊" + @override + String get invite_members => "邀请/s1位朋友加入群聊"; + /// "共/s1人" + @override + String get total_members => "共/s1人"; + /// "二维码已过期" + @override + String get qr_outtime => "二维码已过期"; + /// "没有该群信息" + @override + String get no_goupr_info => "没有该群信息"; + /// "你邀请/s1加入了群聊" + @override + String get you_invite => "你邀请/s1加入了群聊"; + /// "你被/s1拉进了群聊" + @override + String get invite_you => "你被/s1拉进了群聊"; + /// " /s1 邀请 /s2 加入了群聊" + @override + String get invite_someone => " /s1 邀请 /s2 加入了群聊"; + /// "你" + @override + String get you => "你"; + /// " /s1 将 /s2 移出了群聊" + @override + String get delete_group => " /s1 将 /s2 移出了群聊"; + /// "你已成为新群主" + @override + String get you_group_owner => "你已成为新群主"; + /// "/s1已成为新群主" + @override + String get someone_group_owner => "/s1已成为新群主"; + /// "群名已更改为/s1" + @override + String get change_group_owner1 => "群名已更改为/s1"; + /// "群公告已更新" + @override + String get update_group_announce => "群公告已更新"; + /// "你通过扫描二维码加入群聊" + @override + String get you_qr => "你通过扫描二维码加入群聊"; + /// "/s1通过扫描二维码加入群聊" + @override + String get others_qr => "/s1通过扫描二维码加入群聊"; + /// "\"/s1\" 想邀请/s2位朋友加入群聊 \$去确认\$ " + @override + String get invite_confirm => "\"/s1\" 想邀请/s2位朋友加入群聊 \$去确认\$ "; + /// " \"/s1\" 想邀请\"/s2\" 加入群聊 " + @override + String get want_invite_confirm => " \"/s1\" 想邀请\"/s2\" 加入群聊 "; + /// "\"/s1\" 加入群聊 已确认" + @override + String get join_group_confirm => "\"/s1\" 加入群聊 已确认"; + /// "你被 /s1 拉进了群聊 " + @override + String get you_invite_gourp => "你被 /s1 拉进了群聊 "; + /// " \"/s1\" 加入群聊 " + @override + String get someone_join_group => " \"/s1\" 加入群聊 "; + /// "群主已开启\"群聊邀请确认\",群成员需群主确认才能邀请朋友进群" + @override + String get group_setting_tips1 => "群主已开启\"群聊邀请确认\",群成员需群主确认才能邀请朋友进群"; + /// "群主已恢复默认进群方式" + @override + String get group_setting_tips2 => "群主已恢复默认进群方式"; + /// "群成员已达上限" + @override + String get members_max => "群成员已达上限"; + /// "群数量已达上限" + @override + String get group_max => "群数量已达上限"; + /// "我的账单" + @override + String get my_money_info => "我的账单"; + /// "我的余额" + @override + String get my_left_money => "我的余额"; + /// "H币可通过充值或兑换方式获得,无法进行提现" + @override + String get money_tips => "H币可通过充值或兑换方式获得,无法进行提现"; + /// "收入明细" + @override + String get get_money_detail => "收入明细"; + /// "Hibox收入" + @override + String get hibok_money => "Hibox收入"; + /// "兑换H币" + @override + String get charge_h => "兑换H币"; + /// "提款规则" + @override + String get charge_tips => "提款规则"; + /// "百变定位" + @override + String get splash_tips1 => "百变定位"; + /// "翻译机器人" + @override + String get splash_tips2 => "翻译机器人"; + /// "交友APP" + @override + String get splash_tips3 => "交友APP"; + /// "百变女神,选你所爱" + @override + String get splash_tips_content1 => "百变女神,选你所爱"; + /// "语音互动一起聊" + @override + String get splash_tips_content2 => "语音互动一起聊"; + /// "解决语言问题" + @override + String get splash_tips_content3 => "解决语言问题"; + /// "立即体验" + @override + String get splash_go => "立即体验"; + /// "你通过收入兑换了/s1H币" + @override + String get change_h_coin => "你通过收入兑换了/s1H币"; + /// "您的申述成功,系统已退款" + @override + String get Representation_succes => "您的申述成功,系统已退款"; + /// "系统赠送" + @override + String get system_give => "系统赠送"; + /// "您的提款申请失败,已退回" + @override + String get exchange_fail => "您的提款申请失败,已退回"; + /// "通过Hibox收入兑换/s1H币" + @override + String get hibok_exchange => "通过Hibox收入兑换/s1H币"; + /// "成功绑定代理优惠码" + @override + String get bind_code_success => "成功绑定代理优惠码"; + /// "您消耗了/s1H币进行人工翻译" + @override + String get translate_money => "您消耗了/s1H币进行人工翻译"; + /// "系统取消退回" + @override + String get system_back => "系统取消退回"; + /// "你打赏了对方" + @override + String get you_give => "你打赏了对方"; + /// "对方打赏了你" + @override + String get you_get => "对方打赏了你"; + /// "兑换数量(单位K)" + @override + String get enter_num_qian => "兑换数量(单位K)"; + /// "提现数量(单位K)" + @override + String get enter_num_qian1 => "提现数量(单位K)"; + /// "翻译券" + @override + String get daily_translate_voucher => "翻译券"; + /// "通知消息" + @override + String get msg_notice => "通知消息"; + /// "选择提醒的人" + @override + String get select_notice_people => "选择提醒的人"; + /// "查找手机号" + @override + String get search_phone => "查找手机号"; + /// "用户不存在" + @override + String get not_have_user => "用户不存在"; + /// "你不能添加自己" + @override + String get not_add_Myself => "你不能添加自己"; + /// "对方已拉黑了你" + @override + String get you_are_blaklisted => "对方已拉黑了你"; + /// "确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)" + @override + String get confrim_recovery => "确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)"; + /// "发送到" + @override + String get send_to => "发送到"; + + @override + TextDirection get textDirection => TextDirection.ltr; +} + +class _I18n_ko_KR extends I18n { + const _I18n_ko_KR(); + + /// " 흔호 공원" + @override + String get appName => " 흔호 공원"; + /// "로그인" + @override + String get login => "로그인"; + /// "회원가입" + @override + String get registration => "회원가입"; + /// "기타 로그인" + @override + String get other_login => "기타 로그인"; + /// "아이디 " + @override + String get account => "아이디 "; + /// "아이디 입력하세요" + @override + String get enter_username => "아이디 입력하세요"; + /// "암호 " + @override + String get password => "암호 "; + /// "암호 입력하세요" + @override + String get enter_password => "암호 입력하세요"; + /// "암호 찾기" + @override + String get forget_password => "암호 찾기"; + /// "암호 재설정하기 " + @override + String get reset_password => "암호 재설정하기 "; + /// "휴대폰 번호 등록" + @override + String get number_registration => "휴대폰 번호 등록"; + /// "휴대폰 번호 입력하세요" + @override + String get enter_number => "휴대폰 번호 입력하세요"; + /// "검증 코드" + @override + String get code => "검증 코드"; + /// "받은 인증 코드 입력하세요" + @override + String get enter_code => "받은 인증 코드 입력하세요"; + /// "인증 코드 보내기" + @override + String get send_code => "인증 코드 보내기"; + /// "다시 보내기 " + @override + String get send_again => "다시 보내기 "; + /// "암호 설정" + @override + String get set_password => "암호 설정"; + /// "암호 6짜리이상 설정하세요" + @override + String get password_limit => "암호 6짜리이상 설정하세요"; + /// "로그인 암호 설정하세요" + @override + String get set_password2 => "로그인 암호 설정하세요"; + /// "다음 단계" + @override + String get next_step => "다음 단계"; + /// "가입 버튼을 누르면《사용자 협의》을 읽고 동의함" + @override + String get agreed_agreement => "가입 버튼을 누르면《사용자 협의》을 읽고 동의함"; + /// "로그인 암호 입력하세요" + @override + String get enter_password2 => "로그인 암호 입력하세요"; + /// "바로 재설정하기" + @override + String get reset_now => "바로 재설정하기"; + /// "성별 선택" + @override + String get choose_gender => "성별 선택"; + /// "누구..." + @override + String get who => "누구..."; + /// "확정" + @override + String get determine => "확정"; + /// "성별을 선택한후에 수정할 수 없음" + @override + String get cannot_modified => "성별을 선택한후에 수정할 수 없음"; + /// "힌트" + @override + String get tip => "힌트"; + /// "바로 회원가입이나 탈퇴 여부?" + @override + String get choose_quit => "바로 회원가입이나 탈퇴 여부?"; + /// "확인" + @override + String get confirm => "확인"; + /// "사용" + @override + String get use => "사용"; + /// "취소" + @override + String get cancel => "취소"; + /// "닫다" + @override + String get close => "닫다"; + /// "삭제" + @override + String get delete => "삭제"; + /// "안합니다" + @override + String get forget_it => "안합니다"; + /// "좋습니다" + @override + String get ok => "좋습니다"; + /// "등록한후에 성별 변경 할수 없습니다 .확인하시겠요?" + @override + String get choose_quit2 => "등록한후에 성별 변경 할수 없습니다 .확인하시겠요?"; + /// "힌트: 당신은 동성별 사용자와 얘기할 수 없음" + @override + String get tip_content => "힌트: 당신은 동성별 사용자와 얘기할 수 없음"; + /// "환영합니다" + @override + String get welcome => "환영합니다"; + /// "초대 번호를 입력하세요" + @override + String get enter_incode => "초대 번호를 입력하세요"; + /// "흔호 초대번호 갖은 남자만 서비스 제공함" + @override + String get must_incode => "흔호 초대번호 갖은 남자만 서비스 제공함"; + /// "당신의 초대번호 " + @override + String get your_incode => "당신의 초대번호 "; + /// "초대 코드 없습니까? 다음 방식으로 받을 수 있습니다" + @override + String get how_get => "초대 코드 없습니까? 다음 방식으로 받을 수 있습니다"; + /// "방식 1 " + @override + String get method1 => "방식 1 "; + /// "공짜 신청" + @override + String get free => "공짜 신청"; + /// "바로 신청" + @override + String get apply_now => "바로 신청"; + /// "초대번호 받음" + @override + String get check_incode => "초대번호 받음"; + /// "개인 정보를 작성해서 심사 통과 후 다시 요청 코드를 보내 드립니다" + @override + String get so_get => "개인 정보를 작성해서 심사 통과 후 다시 요청 코드를 보내 드립니다"; + /// "초대번호 신청하다" + @override + String get apply_incode => "초대번호 신청하다"; + /// "소재지" + @override + String get location => "소재지"; + /// "도시 " + @override + String get cityname => "도시 "; + /// "정보 경로" + @override + String get message_channel => "정보 경로"; + /// "앱을 어디서 알게 되셨어요?" + @override + String get how_know => "앱을 어디서 알게 되셨어요?"; + /// "Wechat 아이디 " + @override + String get wechat_number => "Wechat 아이디 "; + /// "당신의 Wechat 아이다 " + @override + String get your_wechat => "당신의 Wechat 아이다 "; + /// "페이스북" + @override + String get facebook => "페이스북"; + /// "당신의 페이스북 " + @override + String get your_facebook => "당신의 페이스북 "; + /// "신청을 제출하다" + @override + String get submit_application => "신청을 제출하다"; + /// "도시명 입력하세요" + @override + String get enter_city => "도시명 입력하세요"; + /// "앱을 받을수 있는 경로를 알려 주세요" + @override + String get so_know => "앱을 받을수 있는 경로를 알려 주세요"; + /// "사교 아이디 알려주세요" + @override + String get your_social => "사교 아이디 알려주세요"; + /// "당신의 신청를 최대한 빨리 처리해 드리겠습니다. 심사 통과후 고객센터에서 코드 번호를 받을수 있습니다" + @override + String get receive_incode => "당신의 신청를 최대한 빨리 처리해 드리겠습니다. 심사 통과후 고객센터에서 코드 번호를 받을수 있습니다"; + /// "초대 번호는 아직 발급되지 않았으니 조금만 기다려 주십시오" + @override + String get wait_incode => "초대 번호는 아직 발급되지 않았으니 조금만 기다려 주십시오"; + /// "신청 성공" + @override + String get successful_application1 => "신청 성공"; + /// "검토 실패" + @override + String get application_failed1 => "검토 실패"; + /// "복사 성공" + @override + String get successful_copy => "복사 성공"; + /// "방식 2" + @override + String get method2 => "방식 2"; + /// "회원 가입" + @override + String get joinvip => "회원 가입"; + /// "바로 가입" + @override + String get join_now => "바로 가입"; + /// "가입 되었다" + @override + String get joined => "가입 되었다"; + /// "회원 가입 은 각종 특권 을 갖을 수 있다,요청번호 필요 없는 등록 포함" + @override + String get join_odds => "회원 가입 은 각종 특권 을 갖을 수 있다,요청번호 필요 없는 등록 포함"; + /// "당신 아직 회원 아니였습니다" + @override + String get not_joinvip => "당신 아직 회원 아니였습니다"; + /// "회원 가입 후 코드 번호 없어도 등록 됩니다" + @override + String get join_after => "회원 가입 후 코드 번호 없어도 등록 됩니다"; + /// "초대번호 인증 통과" + @override + String get incode_passed => "초대번호 인증 통과"; + /// "가입을 환영하다!당신의 계좌번호를 다른 사람에게 알려주지 마시오,로그인 이상을 발견하면 아이디가 자동으로 동결된다" + @override + String get welcome_join => "가입을 환영하다!당신의 계좌번호를 다른 사람에게 알려주지 마시오,로그인 이상을 발견하면 아이디가 자동으로 동결된다"; + /// "고객센터" + @override + String get member_centre => "고객센터"; + /// "회원특권" + @override + String get members_privilege => "회원특권"; + /// "더 많은 보기 " + @override + String get see_more => "더 많은 보기 "; + /// "사용자를 하루에 무제한으로 조회" + @override + String get unlimited_see => "사용자를 하루에 무제한으로 조회"; + /// "더 싸게 볼 수 있습니다" + @override + String get see_cheaper => "더 싸게 볼 수 있습니다"; + /// "매일/s1차 무료 기회 유료앨범이랑 사교 아이디 볼수 있다" + @override + String get free10 => "매일/s1차 무료 기회 유료앨범이랑 사교 아이디 볼수 있다"; + /// "더 오래 볼 수 있음" + @override + String get see_longer => "더 오래 볼 수 있음"; + /// " 보고 바로 간 사진의 시간을 2초에서 /s1초로 올리기" + @override + String get towto6 => " 보고 바로 간 사진의 시간을 2초에서 /s1초로 올리기"; + /// "더 즐겁게 보다" + @override + String get see_better => "더 즐겁게 보다"; + /// "무료 데이트 방송 " + @override + String get free_release => "무료 데이트 방송 "; + /// "세트 선택" + @override + String get choose_price => "세트 선택"; + /// "지불 방식" + @override + String get pay_method => "지불 방식"; + /// "지불 금액" + @override + String get pay_amount => "지불 금액"; + /// "지갑 잔액이 부족하다" + @override + String get not_enough => "지갑 잔액이 부족하다"; + /// "지불 확인" + @override + String get confirm_pay => "지불 확인"; + /// "정보 작성" + @override + String get complete_material => "정보 작성"; + /// "기본 정보" + @override + String get basic_information => "기본 정보"; + /// "이미지 작성" + @override + String get upload_avatar => "이미지 작성"; + /// "선택하세요" + @override + String get choose => "선택하세요"; + /// "써 주세요" + @override + String get fill_out => "써 주세요"; + /// "많이 선택할 수 있다" + @override + String get choose_multiple => "많이 선택할 수 있다"; + /// "고르다" + @override + String get optional => "고르다"; + /// "최소 작성 s1" + @override + String get least => "최소 작성 s1"; + /// "자기 소개 좀 해 주세요" + @override + String get introduce_yourself => "자기 소개 좀 해 주세요"; + /// "최다/s1 선택" + @override + String get most => "최다/s1 선택"; + /// "닉네임" + @override + String get nickname => "닉네임"; + /// "닉네임은 1-20 글짜만 가능합니다" + @override + String get only1_8 => "닉네임은 1-20 글짜만 가능합니다"; + /// "현재 도시" + @override + String get Resident_city => "현재 도시"; + /// "현재 도시를 선택하십시오" + @override + String get Please_select_a_resident_city => "현재 도시를 선택하십시오"; + /// "칸토" + @override + String get City1 => "칸토"; + /// "다낭" + @override + String get City2 => "다낭"; + /// "하이퐁" + @override + String get City3 => "하이퐁"; + /// "하내 " + @override + String get City4 => "하내 "; + /// "호치민" + @override + String get City5 => "호치민"; + /// "안강" + @override + String get City6 => "안강"; + /// "북강" + @override + String get City7 => "북강"; + /// "북건" + @override + String get City8 => "북건"; + /// "볼리 아오" + @override + String get City9 => "볼리 아오"; + /// "북닝" + @override + String get City10 => "북닝"; + /// "바디 붕타우" + @override + String get City11 => "바디 붕타우"; + /// "빈랑" + @override + String get City12 => "빈랑"; + /// "평정" + @override + String get City13 => "평정"; + /// "평약" + @override + String get City14 => "평약"; + /// "평복" + @override + String get City15 => "평복"; + /// "평순 " + @override + String get City16 => "평순 "; + /// "김오" + @override + String get City17 => "김오"; + /// "고평" + @override + String get City18 => "고평"; + /// "더락" + @override + String get City19 => "더락"; + /// "더농" + @override + String get City20 => "더농"; + /// "모비안" + @override + String get City21 => "모비안"; + /// "동내 " + @override + String get City22 => "동내 "; + /// "동타" + @override + String get City23 => "동타"; + /// "가래" + @override + String get City24 => "가래"; + /// "하강" + @override + String get City25 => "하강"; + /// "해양" + @override + String get City26 => "해양"; + /// "하남" + @override + String get City27 => "하남"; + /// "하정" + @override + String get City28 => "하정"; + /// "하평" + @override + String get City29 => "하평"; + /// "후강" + @override + String get City30 => "후강"; + /// "흥안" + @override + String get City31 => "흥안"; + /// "경하" + @override + String get City32 => "경하"; + /// "견강" + @override + String get City33 => "견강"; + /// "쿤호" + @override + String get City34 => "쿤호"; + /// "라이저우" + @override + String get City35 => "라이저우"; + /// "린동" + @override + String get City36 => "린동"; + /// "령산" + @override + String get City37 => "령산"; + /// "노가" + @override + String get City38 => "노가"; + /// "롱안 " + @override + String get City39 => "롱안 "; + /// "루안" + @override + String get City40 => "루안"; + /// "닝평" + @override + String get City41 => "닝평"; + /// "닝순" + @override + String get City42 => "닝순"; + /// "부수" + @override + String get City43 => "부수"; + /// "부안" + @override + String get City44 => "부안"; + /// "광평 " + @override + String get City45 => "광평 "; + /// "광남" + @override + String get City46 => "광남"; + /// "광의" + @override + String get City47 => "광의"; + /// "광닝" + @override + String get City48 => "광닝"; + /// "광지" + @override + String get City49 => "광지"; + /// "수장" + @override + String get City50 => "수장"; + /// "산라" + @override + String get City51 => "산라"; + /// "서닝" + @override + String get City52 => "서닝"; + /// "태평" + @override + String get City53 => "태평"; + /// "태원" + @override + String get City54 => "태원"; + /// "청화" + @override + String get City55 => "청화"; + /// "승천순화" + @override + String get City56 => "승천순화"; + /// "전강" + @override + String get City57 => "전강"; + /// "차영" + @override + String get City58 => "차영"; + /// "선광" + @override + String get City59 => "선광"; + /// "영롱" + @override + String get City60 => "영롱"; + /// "영부" + @override + String get City61 => "영부"; + /// "안폐" + @override + String get City62 => "안폐"; + /// "남정" + @override + String get City63 => "남정"; + /// "새일" + @override + String get birthday => "새일"; + /// "생일날짜 선택" + @override + String get choose_birthday => "생일날짜 선택"; + /// "년" + @override + String get year => "년"; + /// "월" + @override + String get month => "월"; + /// "일" + @override + String get day => "일"; + /// "시 " + @override + String get hour => "시 "; + /// "분" + @override + String get minute => "분"; + /// "초" + @override + String get second => "초"; + /// "방금" + @override + String get just => "방금"; + /// "/s1 분 전" + @override + String get minute_ago => "/s1 분 전"; + /// "/s1 시간 전" + @override + String get hour_ago => "/s1 시간 전"; + /// "/s1일 전" + @override + String get day_ago => "/s1일 전"; + /// "/s1 주전" + @override + String get week_ago => "/s1 주전"; + /// "s1 달 전" + @override + String get month_ago => "s1 달 전"; + /// "오전 " + @override + String get morning => "오전 "; + /// "점심" + @override + String get noon => "점심"; + /// "오후" + @override + String get afternoon => "오후"; + /// "저녁" + @override + String get night => "저녁"; + /// "하루종일" + @override + String get all_day => "하루종일"; + /// "어제 " + @override + String get yesterday => "어제 "; + /// "그저께" + @override + String get two_yesterday => "그저께"; + /// "밤새" + @override + String get overnight => "밤새"; + /// "개 " + @override + String get one => "개 "; + /// "십" + @override + String get ten => "십"; + /// "백" + @override + String get hundred => "백"; + /// "천" + @override + String get thousand => "천"; + /// "만" + @override + String get ten_thousand => "만"; + /// "양자리" + @override + String get aries => "양자리"; + /// "황소자리" + @override + String get taurus => "황소자리"; + /// "쌍둥이자리" + @override + String get gemini => "쌍둥이자리"; + /// "게자리" + @override + String get cancer => "게자리"; + /// "사자자리" + @override + String get leo => "사자자리"; + /// "처녀자리" + @override + String get virgo => "처녀자리"; + /// "천칭자리" + @override + String get libra => "천칭자리"; + /// "전갈자리" + @override + String get scorpio => "전갈자리"; + /// "사수자리" + @override + String get sagittarius => "사수자리"; + /// "염소자리" + @override + String get capricorn => "염소자리"; + /// "물병자리" + @override + String get aquarius => "물병자리"; + /// "물고기자리" + @override + String get pisces => "물고기자리"; + /// "월요일" + @override + String get monday => "월요일"; + /// "화요일" + @override + String get tuesday => "화요일"; + /// "수요일" + @override + String get wednesday => "수요일"; + /// "목요일" + @override + String get thursday => "목요일"; + /// "금요일" + @override + String get friday => "금요일"; + /// "토요일" + @override + String get saturday => "토요일"; + /// "일요일" + @override + String get sunday => "일요일"; + /// "직업" + @override + String get job => "직업"; + /// "직업 선택" + @override + String get choose_career => "직업 선택"; + /// "정보 기술" + @override + String get career1 => "정보 기술"; + /// "인터넷" + @override + String get career2 => "인터넷"; + /// "IT" + @override + String get career3 => "IT"; + /// "통신 운영" + @override + String get career4 => "통신 운영"; + /// "네트워크 게임" + @override + String get career5 => "네트워크 게임"; + /// "금용 보험" + @override + String get career6 => "금용 보험"; + /// "투자 " + @override + String get career7 => "투자 "; + /// "주식 기금" + @override + String get career8 => "주식 기금"; + /// "보험" + @override + String get career9 => "보험"; + /// "은행" + @override + String get career10 => "은행"; + /// "신탁 담보" + @override + String get career11 => "신탁 담보"; + /// "상업 서비스" + @override + String get career12 => "상업 서비스"; + /// "컨설팅" + @override + String get career13 => "컨설팅"; + /// "자영업자" + @override + String get career14 => "자영업자"; + /// "미용 미발" + @override + String get career15 => "미용 미발"; + /// "여행" + @override + String get career16 => "여행"; + /// "호텔,식당" + @override + String get career17 => "호텔,식당"; + /// "레저 오락" + @override + String get career18 => "레저 오락"; + /// "무역" + @override + String get career19 => "무역"; + /// "자동차 " + @override + String get career20 => "자동차 "; + /// "부동산" + @override + String get career21 => "부동산"; + /// "부동산 관리" + @override + String get career22 => "부동산 관리"; + /// "인테리어" + @override + String get career23 => "인테리어"; + /// "탐정" + @override + String get career24 => "탐정"; + /// "공사 제조" + @override + String get career25 => "공사 제조"; + /// "건설" + @override + String get career26 => "건설"; + /// "토목공사 " + @override + String get career27 => "토목공사 "; + /// "기계제조" + @override + String get career28 => "기계제조"; + /// "전자" + @override + String get career29 => "전자"; + /// "생물의학" + @override + String get career30 => "생물의학"; + /// "식품" + @override + String get career31 => "식품"; + /// "복장" + @override + String get career32 => "복장"; + /// "에너지" + @override + String get career33 => "에너지"; + /// "교통운송" + @override + String get career34 => "교통운송"; + /// "항공" + @override + String get career35 => "항공"; + /// "철도" + @override + String get career36 => "철도"; + /// "운수선박" + @override + String get career37 => "운수선박"; + /// "대중교통" + @override + String get career38 => "대중교통"; + /// "물류 수송" + @override + String get career39 => "물류 수송"; + /// "문화 미디어" + @override + String get career40 => "문화 미디어"; + /// "미디어 출판" + @override + String get career41 => "미디어 출판"; + /// "디자인" + @override + String get career42 => "디자인"; + /// "문화 전파" + @override + String get career43 => "문화 전파"; + /// "광고창의" + @override + String get career44 => "광고창의"; + /// "만화" + @override + String get career45 => "만화"; + /// "홍보 전시회" + @override + String get career46 => "홍보 전시회"; + /// "촬영" + @override + String get career47 => "촬영"; + /// "오락 체육" + @override + String get career48 => "오락 체육"; + /// "영화" + @override + String get career49 => "영화"; + /// "스포츠" + @override + String get career50 => "스포츠"; + /// "음악" + @override + String get career51 => "음악"; + /// "모델" + @override + String get career52 => "모델"; + /// "공공사업" + @override + String get career53 => "공공사업"; + /// "의료" + @override + String get career54 => "의료"; + /// "법률" + @override + String get career55 => "법률"; + /// "교육" + @override + String get career56 => "교육"; + /// "정부 기관" + @override + String get career57 => "정부 기관"; + /// "공공 복지" + @override + String get career58 => "공공 복지"; + /// "학생" + @override + String get career59 => "학생"; + /// "무" + @override + String get career60 => "무"; + /// "프로그램" + @override + String get program => "프로그램"; + /// "국적을 선택하십시오" + @override + String get select_program => "국적을 선택하십시오"; + /// "건강 스포츠" + @override + String get healthy_exercise => "건강 스포츠"; + /// "나이트 파티" + @override + String get night_party => "나이트 파티"; + /// "음식" + @override + String get gourmet_party => "음식"; + /// "영화감상" + @override + String get watch_movie => "영화감상"; + /// "게임을 하다" + @override + String get play_games => "게임을 하다"; + /// "동반 여행" + @override + String get travel_together => "동반 여행"; + /// "음성 채팅" + @override + String get voice_chat => "음성 채팅"; + /// "기타" + @override + String get other => "기타"; + /// "이상형" + @override + String get expect_lover => "이상형"; + /// "이상형 선택" + @override + String get choose_lover => "이상형 선택"; + /// "외모" + @override + String get beautiful => "외모"; + /// "부자" + @override + String get rich => "부자"; + /// "자상함" + @override + String get care_me => "자상함"; + /// "첫인상" + @override + String get look_feeling => "첫인상"; + /// "상관 없습니다" + @override + String get doesnt_matter => "상관 없습니다"; + /// "사교 아이디를 최소 한개 적어 주세요" + @override + String get least_account => "사교 아이디를 최소 한개 적어 주세요"; + /// "소셜 계정 숨기기" + @override + String get hide_account1 => "소셜 계정 숨기기"; + /// "더 많은 정보" + @override + String get more_information => "더 많은 정보"; + /// "키" + @override + String get height => "키"; + /// "체중" + @override + String get weight => "체중"; + /// "표시하지 않음" + @override + String get not_show => "표시하지 않음"; + /// "개인소개" + @override + String get self_introduction => "개인소개"; + /// "등록 성공" + @override + String get registration_success1 => "등록 성공"; + /// "탈퇴 확정하세요?" + @override + String get exit => "탈퇴 확정하세요?"; + /// "개인 정보를 완전하게 작성하지 못했습니다. 지금은 종료하십시오. 다음에 등록 된 아이다로 직접 로그인하십시오" + @override + String get exit_registration => "개인 정보를 완전하게 작성하지 못했습니다. 지금은 종료하십시오. 다음에 등록 된 아이다로 직접 로그인하십시오"; + /// "남자는 다른 남자 사용자 정보 볼 수 없다" + @override + String get cant_see => "남자는 다른 남자 사용자 정보 볼 수 없다"; + /// "여자는 다른 여자 사용자 정보 볼 수 없다" + @override + String get cant_see2 => "여자는 다른 여자 사용자 정보 볼 수 없다"; + /// "당신은 오늘에 /S1명 여자 볼 수 있다" + @override + String get see_one => "당신은 오늘에 /S1명 여자 볼 수 있다"; + /// "비회원은 하루에 15명 여자 사용자만 볼 수 있다" + @override + String get only_see => "비회원은 하루에 15명 여자 사용자만 볼 수 있다"; + /// "계속 보기" + @override + String get continue_see => "계속 보기"; + /// "아이디 동결되였다" + @override + String get user_frozen => "아이디 동결되였다"; + /// "닉네임/직업으로 검색" + @override + String get search_user => "닉네임/직업으로 검색"; + /// "근처" + @override + String get nearby => "근처"; + /// "회원" + @override + String get member => "회원"; + /// "새 등록" + @override + String get new_registration => "새 등록"; + /// "인증" + @override + String get authenticate => "인증"; + /// "온라인" + @override + String get first_online => "온라인"; + /// "포지셔닝이 켜져 있지 않아서 다른 사용자와 거리를 계산할 수 없음" + @override + String get not_positioned => "포지셔닝이 켜져 있지 않아서 다른 사용자와 거리를 계산할 수 없음"; + /// "미지" + @override + String get unknown => "미지"; + /// "비밀" + @override + String get secrecy => "비밀"; + /// "수장 " + @override + String get collection => "수장 "; + /// "수장 취소" + @override + String get cancel_collection => "수장 취소"; + /// "수장 취소되였다" + @override + String get canceled_collection => "수장 취소되였다"; + /// "좋아요" + @override + String get like => "좋아요"; + /// "좋아한 것을 가입했다" + @override + String get added_like => "좋아한 것을 가입했다"; + /// "좋아한 것을 취소했다" + @override + String get canceled_like => "좋아한 것을 취소했다"; + /// "블랙리스트" + @override + String get blacklist => "블랙리스트"; + /// "더 이상 서로와 동적을 볼 수 없습니다. 확실합니까?" + @override + String get blacklist_choose => "더 이상 서로와 동적을 볼 수 없습니다. 확실합니까?"; + /// "블랙리스트에 가입했다" + @override + String get blacklisted => "블랙리스트에 가입했다"; + /// "상대방을 블랙리스트에 추가하고 상대방의 메시지 수신을 거부했다" + @override + String get reject_message => "상대방을 블랙리스트에 추가하고 상대방의 메시지 수신을 거부했다"; + /// "블랙리스트 삭제" + @override + String get remove_blacklist => "블랙리스트 삭제"; + /// "블랙리스트 제거" + @override + String get blacklist_removed => "블랙리스트 제거"; + /// "상대방을 블랙리스트를 제거하고 소식을 거부한거도 취소했다" + @override + String get receive_message => "상대방을 블랙리스트를 제거하고 소식을 거부한거도 취소했다"; + /// "온라인" + @override + String get online => "온라인"; + /// "유료앨범" + @override + String get paid_photo => "유료앨범"; + /// "보기 신청" + @override + String get application_view => "보기 신청"; + /// "통과했다" + @override + String get passed => "통과했다"; + /// "공원" + @override + String get park => "공원"; + /// "라디오 방송" + @override + String get radio => "라디오 방송"; + /// "소식" + @override + String get news => "소식"; + /// "나" + @override + String get me => "나"; + /// "더 많은 조작" + @override + String get more_operations => "더 많은 조작"; + /// "익명신고" + @override + String get anonymous_report => "익명신고"; + /// "인증영상" + @override + String get certified_video => "인증영상"; + /// "이미 영상을 통해 진실성을 인증했다" + @override + String get passed_video => "이미 영상을 통해 진실성을 인증했다"; + /// "아직 신분의 진실성을 인증하지 않았다" + @override + String get not_video => "아직 신분의 진실성을 인증하지 않았다"; + /// "그녀가 데이트를 신청했어요" + @override + String get her_appointment => "그녀가 데이트를 신청했어요"; + /// "그는 유료로 가입했습니다" + @override + String get pay_join => "그는 유료로 가입했습니다"; + /// "신분 안전 심사를 통과했다" + @override + String get passed_review => "신분 안전 심사를 통과했다"; + /// "그는 경력많은 사용자/s1 증정 초대 번호로 가입한다" + @override + String get invited_user => "그는 경력많은 사용자/s1 증정 초대 번호로 가입한다"; + /// "그는 데이트를 신청했어요" + @override + String get his_appointment => "그는 데이트를 신청했어요"; + /// "그녀의 동태" + @override + String get her_dynamics => "그녀의 동태"; + /// "그의 동태" + @override + String get his_dynamics => "그의 동태"; + /// "그녀는 매우 겸손하다 " + @override + String get low_key => "그녀는 매우 겸손하다 "; + /// "그는 매우 겸손하다 " + @override + String get low_key2 => "그는 매우 겸손하다 "; + /// "그녀의 앨범" + @override + String get her_photo => "그녀의 앨범"; + /// "그의 앨범" + @override + String get his_photo => "그의 앨범"; + /// "그는 앨범 자물쇠를 설치했다" + @override + String get set_lock => "그는 앨범 자물쇠를 설치했다"; + /// "그녀는 앨범 자물쇠를 설치했다" + @override + String get set_lock2 => "그녀는 앨범 자물쇠를 설치했다"; + /// "앨범 해제(/s1),회원 무료" + @override + String get free_unlock => "앨범 해제(/s1),회원 무료"; + /// "앨범 해제/s1" + @override + String get unlock_user => "앨범 해제/s1"; + /// "비용을 지불 해제(/s1H화폐)" + @override + String get pay_unlock => "비용을 지불 해제(/s1H화폐)"; + /// "회원을 되면 공짜 해제" + @override + String get become_member => "회원을 되면 공짜 해제"; + /// "한 번 기회 사용 해제/s1앨범 여부?" + @override + String get consumption_once => "한 번 기회 사용 해제/s1앨범 여부?"; + /// "(당신이 오늘에 아직/s1한 번 기회 있다.)" + @override + String get remaining_once => "(당신이 오늘에 아직/s1한 번 기회 있다.)"; + /// "당신이 오늘 공짜 기회 다 썼습니다. 증정/S1로 /s2 모두자료를 해제할시겠습니까?" + @override + String get no_times => "당신이 오늘 공짜 기회 다 썼습니다. 증정/S1로 /s2 모두자료를 해제할시겠습니까?"; + /// "지불" + @override + String get pay => "지불"; + /// "그는 제한을 설치하여 자료를 살펴보면 그의 동의를 요청해야 한다" + @override + String get view_user => "그는 제한을 설치하여 자료를 살펴보면 그의 동의를 요청해야 한다"; + /// "그녀는 제한을 설치하여 자료를 살펴보면 그의 동의를 요청해야 한다" + @override + String get view_user2 => "그녀는 제한을 설치하여 자료를 살펴보면 그의 동의를 요청해야 한다"; + /// "상대방에게 당신의 사진을 한 장 보내는 것을 신청합니다.걱정하지 마세요. 상대방이 스크린을 찍는 2초 후에 삭제할 거예요" + @override + String get need_photo => "상대방에게 당신의 사진을 한 장 보내는 것을 신청합니다.걱정하지 마세요. 상대방이 스크린을 찍는 2초 후에 삭제할 거예요"; + /// "사진 선택" + @override + String get choose_photo => "사진 선택"; + /// "신청 이미 발송했고 상대방이 확인한 후에 당신은 소식을 받겠습니다" + @override + String get send_application => "신청 이미 발송했고 상대방이 확인한 후에 당신은 소식을 받겠습니다"; + /// "당신이 아직 인증안 했습니다" + @override + String get not_authenticate => "당신이 아직 인증안 했습니다"; + /// "당신의 진실성을 인증한 후에다른 사람과 연락할 수 있다" + @override + String get after_authenticate => "당신의 진실성을 인증한 후에다른 사람과 연락할 수 있다"; + /// "바로 인증" + @override + String get authenticate_now => "바로 인증"; + /// "본 후에 바로 삭제" + @override + String get destroy_after => "본 후에 바로 삭제"; + /// "삭제됨" + @override + String get destroyed => "삭제됨"; + /// "보고 삭제한 빨간 봉투 사진" + @override + String get red_photo1 => "보고 삭제한 빨간 봉투 사진"; + /// "단독 체팅으로 나한데 요청해 주세요" + @override + String get ask_me => "단독 체팅으로 나한데 요청해 주세요"; + /// "작성끝, 클릭 보기" + @override + String get filled_in => "작성끝, 클릭 보기"; + /// "해제 모두 자료" + @override + String get unlock_information => "해제 모두 자료"; + /// "공짜 해제 한번 사용하다" + @override + String get unlock_choose => "공짜 해제 한번 사용하다"; + /// "당신의 진실 평가" + @override + String get your_evaluation => "당신의 진실 평가"; + /// "그녀의 진실 평가 " + @override + String get her_evaluation => "그녀의 진실 평가 "; + /// "그는 진실 평가 " + @override + String get his_evaluation => "그는 진실 평가 "; + /// "평가 " + @override + String get evaluate => "평가 "; + /// "친절하다 " + @override + String get friendly => "친절하다 "; + /// "재미는 성격" + @override + String get interesting => "재미는 성격"; + /// "상쾌하다" + @override + String get readily => "상쾌하다"; + /// "인내심" + @override + String get patient => "인내심"; + /// "퉁명하다" + @override + String get indifferent => "퉁명하다"; + /// "난폭한 성격" + @override + String get bad_temper => "난폭한 성격"; + /// "예의" + @override + String get courtesy => "예의"; + /// "대범하다 " + @override + String get generous => "대범하다 "; + /// "거짓말" + @override + String get lie => "거짓말"; + /// "불친절한다" + @override + String get unfriendly => "불친절한다"; + /// "무명평가 " + @override + String get anonymous_evaluation => "무명평가 "; + /// "그녀를 데이트 안했으니 평가 못 한다" + @override + String get cant_evaluate => "그녀를 데이트 안했으니 평가 못 한다"; + /// "그를 데이트 안했으니 평가 못 한다" + @override + String get cant_evaluate2 => "그를 데이트 안했으니 평가 못 한다"; + /// "우리가 따라가서 확인하기 위해 관련 캡처를 제공하십시오" + @override + String get bad_evaluate => "우리가 따라가서 확인하기 위해 관련 캡처를 제공하십시오"; + /// "제출" + @override + String get submit => "제출"; + /// "평가 성공" + @override + String get evaluation_success => "평가 성공"; + /// "단독 채팅" + @override + String get private_chat => "단독 채팅"; + /// "메시지 닫기" + @override + String get close_reminder => "메시지 닫기"; + /// "메시지 닫기 성공" + @override + String get closed_reminder => "메시지 닫기 성공"; + /// "메시지를 켜다" + @override + String get open_reminder => "메시지를 켜다"; + /// "메시지를 켜다 성공" + @override + String get opened_reminder => "메시지를 켜다 성공"; + /// "그녀의 사교 아이디" + @override + String get her_account => "그녀의 사교 아이디"; + /// "그의 사교 아이디" + @override + String get his_account => "그의 사교 아이디"; + /// "복제" + @override + String get copy => "복제"; + /// "내 사교 아이디를 보내기" + @override + String get send_account => "내 사교 아이디를 보내기"; + /// "당신의 사교 아이디 입력하세요" + @override + String get enter_account => "당신의 사교 아이디 입력하세요"; + /// "예하면:Wechat 아이다 abc" + @override + String get for_example => "예하면:Wechat 아이다 abc"; + /// "그녀에게 보내기 " + @override + String get sent_she => "그녀에게 보내기 "; + /// "음성 통화" + @override + String get chat => "음성 통화"; + /// "상대방이 인터넷 통화 기능을 꼈다" + @override + String get cantt_voice => "상대방이 인터넷 통화 기능을 꼈다"; + /// "당신의 진실성을 인증한 후에야, 주동적인 인터넷 통화를 할 수 있다" + @override + String get authentication_voice => "당신의 진실성을 인증한 후에야, 주동적인 인터넷 통화를 할 수 있다"; + /// "인터넷 통화를 신청하는 중이에요" + @override + String get requesting_voice => "인터넷 통화를 신청하는 중이에요"; + /// "대기 중" + @override + String get waitting_answer => "대기 중"; + /// "받기 " + @override + String get answer => "받기 "; + /// "끄기 " + @override + String get hang_up => "끄기 "; + /// "통화중 " + @override + String get chatting => "통화중 "; + /// "면제" + @override + String get handsfree => "면제"; + /// "상을 주기 " + @override + String get giving_gift => "상을 주기 "; + /// "상을 주는 게 성공하다" + @override + String get give_success => "상을 주는 게 성공하다"; + /// "상대방은 이미 상을 주었다" + @override + String get others_gift => "상대방은 이미 상을 주었다"; + /// "당신 가치/s1H 화폐 의선물을 주었다" + @override + String get given_gift => "당신 가치/s1H 화폐 의선물을 주었다"; + /// "당신은 가치/s1H 화폐 의선물을 받았다" + @override + String get earned_gift => "당신은 가치/s1H 화폐 의선물을 받았다"; + /// "사용 가능 잔액/s1" + @override + String get available_balance => "사용 가능 잔액/s1"; + /// "충전" + @override + String get recharge => "충전"; + /// "증정" + @override + String get give => "증정"; + /// "죄송합니다. 잔액이 부족합니다" + @override + String get balance_insufficien => "죄송합니다. 잔액이 부족합니다"; + /// "충전한 후에 선물을 증정하세요!" + @override + String get first_recharge => "충전한 후에 선물을 증정하세요!"; + /// "이번 통화 /s1H화폐 상을 주다" + @override + String get give_coin => "이번 통화 /s1H화폐 상을 주다"; + /// "이번 통화 /s1H화폐 상을 받다" + @override + String get get_coin => "이번 통화 /s1H화폐 상을 받다"; + /// "이번 통화 /s1H화폐 상을 주고 /s2H화폐 상을 받다" + @override + String get give_get => "이번 통화 /s1H화폐 상을 주고 /s2H화폐 상을 받다"; + /// "통화가 끝나다.통화시간 /s1" + @override + String get chat_over => "통화가 끝나다.통화시간 /s1"; + /// "소식센터" + @override + String get message_center => "소식센터"; + /// "당싱이 사용자 정보 페이지에서 개인 채팅을할 수 있습니다" + @override + String get can_chat => "당싱이 사용자 정보 페이지에서 개인 채팅을할 수 있습니다"; + /// "채팅" + @override + String get text_chat => "채팅"; + /// "시스템 메시지" + @override + String get system_information => "시스템 메시지"; + /// "시스템 알림" + @override + String get system_notification => "시스템 알림"; + /// "신고한 사용자/s1상황이 사실이 아니라서 더 확실한 증거를 제공한 후에 신고하세요.감사합니다!" + @override + String get report_failure => "신고한 사용자/s1상황이 사실이 아니라서 더 확실한 증거를 제공한 후에 신고하세요.감사합니다!"; + /// "신고한 사용자/s1가 상황이 사실이라서 시스템은 이미 이 사용자에 대한 처리하다" + @override + String get report_success => "신고한 사용자/s1가 상황이 사실이라서 시스템은 이미 이 사용자에 대한 처리하다"; + /// "초대 신청 성공 !초청 코드【/s1】( 클릭 복사 가능)" + @override + String get successful_application => "초대 신청 성공 !초청 코드【/s1】( 클릭 복사 가능)"; + /// "초청 코드 성공을 신청하다 ,믿을 만한 친구를 소개해 주셔서 감사합니다!초청 코드【/s1】(클릭 복사 가능).)" + @override + String get successful_application2 => "초청 코드 성공을 신청하다 ,믿을 만한 친구를 소개해 주셔서 감사합니다!초청 코드【/s1】(클릭 복사 가능).)"; + /// "초청 번호 신청실패한다! 당신의 신청은 심사를 통과하지 못해서 아쉽다 ,진실 정보 작성을 효과적 으로 심사 통과율 을 높일 것 이다" + @override + String get application_failed => "초청 번호 신청실패한다! 당신의 신청은 심사를 통과하지 못해서 아쉽다 ,진실 정보 작성을 효과적 으로 심사 통과율 을 높일 것 이다"; + /// "중요 소식:" + @override + String get important_notice => "중요 소식:"; + /// "당신의 인증 자료 요구에 부합되지 않는다 , 수정하고 다시 제출해 주세요" + @override + String get authentication_failed => "당신의 인증 자료 요구에 부합되지 않는다 , 수정하고 다시 제출해 주세요"; + /// "1.인증 조권을 따라서 인증 영상 찍어주세요" + @override + String get request1 => "1.인증 조권을 따라서 인증 영상 찍어주세요"; + /// "2.앨범에 이목구비 또렷한 얼굴 본인 사진 올려주세요" + @override + String get request2 => "2.앨범에 이목구비 또렷한 얼굴 본인 사진 올려주세요"; + /// "축하합니다, 당신의 인증 신청은 이미 심사를 통과했습니다" + @override + String get successful_authentication => "축하합니다, 당신의 인증 신청은 이미 심사를 통과했습니다"; + /// "당신이 새 올린 사진은 심사를 통과하지 않았으니 요구를 따라 다시 올려 주십시오" + @override + String get re_upload => "당신이 새 올린 사진은 심사를 통과하지 않았으니 요구를 따라 다시 올려 주십시오"; + /// "축하합니다.당신 새 올린 사진은 심사를 통과 성공했습니다" + @override + String get upload_success => "축하합니다.당신 새 올린 사진은 심사를 통과 성공했습니다"; + /// "데이트신청은 규칙 위반으로 삭제되었기 때문에, 여러 번 규칙 또는 플랜 심각한 시스템이 당신의 계좌에 대한 제한, 심지어는 봉호까지 지켜 주시기 바랍니다. 감사합니다" + @override + String get caveat => "데이트신청은 규칙 위반으로 삭제되었기 때문에, 여러 번 규칙 또는 플랜 심각한 시스템이 당신의 계좌에 대한 제한, 심지어는 봉호까지 지켜 주시기 바랍니다. 감사합니다"; + /// "당신의 평론은 규칙 위반으로 삭제되었기 때문에, 여러 번 규칙 또는 플랜 심각한 시스템이 당신의 계좌에 제한되어 있으며, 심지어 봉호를 준수해 주십시오. 감사합니다" + @override + String get caveat2 => "당신의 평론은 규칙 위반으로 삭제되었기 때문에, 여러 번 규칙 또는 플랜 심각한 시스템이 당신의 계좌에 제한되어 있으며, 심지어 봉호를 준수해 주십시오. 감사합니다"; + /// "방송 소식" + @override + String get radio_message => "방송 소식"; + /// " 소식 없다" + @override + String get no_message => " 소식 없다"; + /// "/s1가 /s2에게 데이트 소식을 발표하여 체크 를 클릭 하다" + @override + String get dating_news => "/s1가 /s2에게 데이트 소식을 발표하여 체크 를 클릭 하다"; + /// "가서 보기 " + @override + String get go_see => "가서 보기 "; + /// "/s1 당신의 동태를 칭찬했다" + @override + String get thumbs_up => "/s1 당신의 동태를 칭찬했다"; + /// " /s1 당신의데이트 프로그램을 칭찬했다" + @override + String get thumbs_up2 => " /s1 당신의데이트 프로그램을 칭찬했다"; + /// "/s1 당신의 동태를 평론했다" + @override + String get comment1 => "/s1 당신의 동태를 평론했다"; + /// "/s1 당신의 데이트 프로그램을평론했다" + @override + String get comment2 => "/s1 당신의 데이트 프로그램을평론했다"; + /// " /s1평론을 답장했다" + @override + String get replied_comment => " /s1평론을 답장했다"; + /// "/s1 당신의 데이트 프로그램 신청했다" + @override + String get signed_up => "/s1 당신의 데이트 프로그램 신청했다"; + /// "당신이 좋아하는 사용자 /s1 데이트를 발표하여 체크하기" + @override + String get favorite_user => "당신이 좋아하는 사용자 /s1 데이트를 발표하여 체크하기"; + /// "당신이 좋아하는 사용자/s1동태를 발표하여, 체크하기" + @override + String get favorite_user2 => "당신이 좋아하는 사용자/s1동태를 발표하여, 체크하기"; + /// "지갑 알람" + @override + String get wallet_reminder => "지갑 알람"; + /// "/s1 (/s2H화폐)비용을 지불하다 당신 빨간 봉투사진을 보았습니다" + @override + String get paid_you => "/s1 (/s2H화폐)비용을 지불하다 당신 빨간 봉투사진을 보았습니다"; + /// "/s1 (/s2H화폐)비용을 지불하다 당신의 앨범을 보았습니다" + @override + String get paid_you2 => "/s1 (/s2H화폐)비용을 지불하다 당신의 앨범을 보았습니다"; + /// "/s1비용을 지불하다 당신의 모두 자료를 보았습니다" + @override + String get paid_you3 => "/s1비용을 지불하다 당신의 모두 자료를 보았습니다"; + /// "보기 신청" + @override + String get view_application => "보기 신청"; + /// "/s1 자세한 페이지 보기 요청" + @override + String get view_application2 => "/s1 자세한 페이지 보기 요청"; + /// "허락(유한기간: 15일)" + @override + String get aging => "허락(유한기간: 15일)"; + /// "거절하다" + @override + String get refuse => "거절하다"; + /// "요청을 통관했다" + @override + String get passed_request => "요청을 통관했다"; + /// "/s1 이미 당신의 조사 신청을 통과하여 유효기간 15일" + @override + String get l15_days => "/s1 이미 당신의 조사 신청을 통과하여 유효기간 15일"; + /// " 평가통지" + @override + String get evaluation_notice => " 평가통지"; + /// "/s1이미 약속하셨어요?빨리 평가하세요" + @override + String get rate_her => "/s1이미 약속하셨어요?빨리 평가하세요"; + /// "연락떤 여자 사용자(익명)가 당신한테 평가를 했습니다. :/s1" + @override + String get received_evaluation => "연락떤 여자 사용자(익명)가 당신한테 평가를 했습니다. :/s1"; + /// "연락떤 남자사용자(익명)가 당신한테 평가를 했습니다. :/s1" + @override + String get received_evaluation2 => "연락떤 남자사용자(익명)가 당신한테 평가를 했습니다. :/s1"; + /// "만약 평가가 사실이 아니라면, 당신이 상술한 것을 신청할 수 있으니, 우리는 확인할 것이다" + @override + String get application_appeal => "만약 평가가 사실이 아니라면, 당신이 상술한 것을 신청할 수 있으니, 우리는 확인할 것이다"; + /// "상술하다" + @override + String get appeal => "상술하다"; + /// "상술을 신청했다" + @override + String get appealed => "상술을 신청했다"; + /// "우리는 최대한 빨리 상황을 확인할 것이며, 편지를 통해 당신에게 처리 결과를 알려 줄 것이다" + @override + String get waiting_results => "우리는 최대한 빨리 상황을 확인할 것이며, 편지를 통해 당신에게 처리 결과를 알려 줄 것이다"; + /// "상술 평가 :/s1 상술 성공하면 우리 는 당신의평가 를 철회 할 것이다" + @override + String get successful_appeal => "상술 평가 :/s1 상술 성공하면 우리 는 당신의평가 를 철회 할 것이다"; + /// "사교 아이디" + @override + String get social_account => "사교 아이디"; + /// "/s1에게 당신한테 사교 아이디 보냈다" + @override + String get get_account => "/s1에게 당신한테 사교 아이디 보냈다"; + /// "자료를 편집하다" + @override + String get edit_information => "자료를 편집하다"; + /// "보존" + @override + String get save => "보존"; + /// "당신이 신분 안전 인정을 통관했다" + @override + String get passed_verification1 => "당신이 신분 안전 인정을 통관했다"; + /// "경력 많은사용자/s1초대 코드로 통해서 가입하다" + @override + String get by_code => "경력 많은사용자/s1초대 코드로 통해서 가입하다"; + /// "비용을 지불으로 가입하다" + @override + String get by_paying => "비용을 지불으로 가입하다"; + /// "당신은 이미 영상을 통해서 신분의 진실성을 인증했다" + @override + String get passed_verification => "당신은 이미 영상을 통해서 신분의 진실성을 인증했다"; + /// "당신이 아직 신분의 진실성릉 인증 안했다" + @override + String get not_certified => "당신이 아직 신분의 진실성릉 인증 안했다"; + /// "저희 당신의 진실성을 인증하는 중이다" + @override + String get verificating => "저희 당신의 진실성을 인증하는 중이다"; + /// "인증을 통관했는 여자는 인기 더 많다" + @override + String get real_girl => "인증을 통관했는 여자는 인기 더 많다"; + /// "인증중" + @override + String get certificating => "인증중"; + /// "영상을 다시 올리겠습니다. " + @override + String get re_upload2 => "영상을 다시 올리겠습니다. "; + /// "업데이트 인증" + @override + String get update_certification => "업데이트 인증"; + /// "회원존을 업그레이드 하여 특권을 있다" + @override + String get enjoy_privileges => "회원존을 업그레이드 하여 특권을 있다"; + /// "/s1만료" + @override + String get expires => "/s1만료"; + /// "지갑" + @override + String get wallet => "지갑"; + /// "프라이버시" + @override + String get setting => "프라이버시"; + /// "나의 동태 " + @override + String get my_dynamic => "나의 동태 "; + /// "나의 앨범" + @override + String get my_album => "나의 앨범"; + /// "제 첫 번째 사진을 올리다" + @override + String get first_photo => "제 첫 번째 사진을 올리다"; + /// "사진이 있어야 남자를 사로잡을 수 있다" + @override + String get no_photo => "사진이 있어야 남자를 사로잡을 수 있다"; + /// "사진을 올리다" + @override + String get upload_photos => "사진을 올리다"; + /// "영상을 올리다" + @override + String get upload_video => "영상을 올리다"; + /// "사진 업로드" + @override + String get upload => "사진 업로드"; + /// "빨간 봉투 사진을 설치하다" + @override + String get set_photo => "빨간 봉투 사진을 설치하다"; + /// "화면을 누르고 끌면 사진을 정렬할 수 있다" + @override + String get photo_order => "화면을 누르고 끌면 사진을 정렬할 수 있다"; + /// "나의 평가 " + @override + String get my_evaluation => "나의 평가 "; + /// "나의프로그램" + @override + String get my_show => "나의프로그램"; + /// "제가 좋아하는 거" + @override + String get i_like => "제가 좋아하는 거"; + /// "당신이 좋아하는 여자가 여기 나타난다" + @override + String get your_favorite => "당신이 좋아하는 여자가 여기 나타난다"; + /// "당신이 좋아하는 남자가 여기 나타난다" + @override + String get your_favorite2 => "당신이 좋아하는 남자가 여기 나타난다"; + /// "데이터가 없습니다" + @override + String get no_data => "데이터가 없습니다"; + /// "역사 방문객" + @override + String get historical_visitor => "역사 방문객"; + /// "/s1 한 명이 당신을 본다" + @override + String get visit_you => "/s1 한 명이 당신을 본다"; + /// "누군가가/s1 당신의 사진을 삭제했다" + @override + String get visit_photo => "누군가가/s1 당신의 사진을 삭제했다"; + /// "단축 복구" + @override + String get recovery_photo => "단축 복구"; + /// "설치" + @override + String get setting2 => "설치"; + /// "친구대신 초대번호 신청하다" + @override + String get apply_code => "친구대신 초대번호 신청하다"; + /// "초청 번호는 무료입니다. 우리는 당신의 역사적 소비에 따라 초청번호를 발송할지 평가할 것입니다.공원의 분위기를 유지하기 위해서 꼭 초청번호를 믿고 믿을 만한 친구에게 증정해 주십시오" + @override + String get issue_choose => "초청 번호는 무료입니다. 우리는 당신의 역사적 소비에 따라 초청번호를 발송할지 평가할 것입니다.공원의 분위기를 유지하기 위해서 꼭 초청번호를 믿고 믿을 만한 친구에게 증정해 주십시오"; + /// "신청을 성공 제출했다" + @override + String get successfully_submit => "신청을 성공 제출했다"; + /// "앱을 친구에게 공유하다" + @override + String get share_app => "앱을 친구에게 공유하다"; + /// "질문이 있으니까 도움이 필요하다" + @override + String get need_help => "질문이 있으니까 도움이 필요하다"; + /// "고객을 연락하다" + @override + String get need_help2 => "고객을 연락하다"; + /// "서비스 효율을 높이기 위해서 아래에 문제가 있으면 숫자를 바로 답장하십시오!" + @override + String get need_help3 => "서비스 효율을 높이기 위해서 아래에 문제가 있으면 숫자를 바로 답장하십시오!"; + /// "【1】아이디 동결된 이유는 무엇입니까 ?" + @override + String get question1 => "【1】아이디 동결된 이유는 무엇입니까 ?"; + /// " 아래 여러 상황이 나타나면 아이다가 동결될 수 있다 :① 사기꾼 ② 중개 ③ 소란 광고 ④ 많은 사람들이 신고하다 ⑤ 이미 기타 아이디 있다 ⑥ 여러번 위반 방송국 방송의 경고를 무시했다 ⑦ 사용자 스스로 취소 요구" + @override + String get answer1 => " 아래 여러 상황이 나타나면 아이다가 동결될 수 있다 :① 사기꾼 ② 중개 ③ 소란 광고 ④ 많은 사람들이 신고하다 ⑤ 이미 기타 아이디 있다 ⑥ 여러번 위반 방송국 방송의 경고를 무시했다 ⑦ 사용자 스스로 취소 요구"; + /// "【2】 지갑에 현금은 언제 제시할 수 있습니까?" + @override + String get question2 => "【2】 지갑에 현금은 언제 제시할 수 있습니까?"; + /// "모든 수익은 지갑에 직접 들어가고, 현금을 꺼낸지 3일 걸린다(수취시간 계산에 따라 시작) , 사흘 후 받은 금액은 지갑, 금액 > = 10위안을 제시할 수 있다" + @override + String get answer2 => "모든 수익은 지갑에 직접 들어가고, 현금을 꺼낸지 3일 걸린다(수취시간 계산에 따라 시작) , 사흘 후 받은 금액은 지갑, 금액 > = 10위안을 제시할 수 있다"; + /// "【3】 내가 보낸 빨간 봉투는 왜 안 뜨다?" + @override + String get question3 => "【3】 내가 보낸 빨간 봉투는 왜 안 뜨다?"; + /// "인터넷 원인으로 인한 것 같다.안심해, 이런 상황에서 상대방이 당신의 돈을 받을 수 없어, 빨간 봉투는 24시간 후에 자동으로 당신의 지불 루트에 돌려줄 것이다" + @override + String get answer3 => "인터넷 원인으로 인한 것 같다.안심해, 이런 상황에서 상대방이 당신의 돈을 받을 수 없어, 빨간 봉투는 24시간 후에 자동으로 당신의 지불 루트에 돌려줄 것이다"; + /// "【4】 현금을 인출하려면 얼마나 걸립니까? " + @override + String get question4 => "【4】 현금을 인출하려면 얼마나 걸립니까? "; + /// "현금 인출 신청후 두 업무일 내에 장부를 제출하다 . 훈훈한 힌트: 현금 계좌번호 확인하세요 ! " + @override + String get answer4 => "현금 인출 신청후 두 업무일 내에 장부를 제출하다 . 훈훈한 힌트: 현금 계좌번호 확인하세요 ! "; + /// "【5】 어떻게 익명 신고 기타 사용자/라디오 내용을 할수 있겠어요 ?" + @override + String get question5 => "【5】 어떻게 익명 신고 기타 사용자/라디오 내용을 할수 있겠어요 ?"; + /// "상대방의 자세한 페이지에 들어가거나 어떤 라디오 를 선택하여 오른쪽 위 각 선택 을 클릭 (익명 신고서), 관련 제보 메시지 를 기입하면 제보할 수 있다" + @override + String get answer5 => "상대방의 자세한 페이지에 들어가거나 어떤 라디오 를 선택하여 오른쪽 위 각 선택 을 클릭 (익명 신고서), 관련 제보 메시지 를 기입하면 제보할 수 있다"; + /// "【6】어떻게 인증 사용자 될 수 있을까요?" + @override + String get question6 => "【6】어떻게 인증 사용자 될 수 있을까요?"; + /// "인증은 다음과 같은 요구를 충족시켜야 한다 :① 개인 자료는 유효 사교 아이디를 작성 하다 ②앨범 적어도 본인의 또렷한 정면사진 한 장 올려 주세요. ③인증 페이지 검증 코드 보기, 종이에 닉네임+검증 코드 ④ 이 종이를 들고 당신의 정면과 동영상을 맞추고 인증 영상을 업로드하는 것을 클릭하여 클릭하다" + @override + String get answer6 => "인증은 다음과 같은 요구를 충족시켜야 한다 :① 개인 자료는 유효 사교 아이디를 작성 하다 ②앨범 적어도 본인의 또렷한 정면사진 한 장 올려 주세요. ③인증 페이지 검증 코드 보기, 종이에 닉네임+검증 코드 ④ 이 종이를 들고 당신의 정면과 동영상을 맞추고 인증 영상을 업로드하는 것을 클릭하여 클릭하다"; + /// "【7】인증 영상은 공개 안 해도 돼요?" + @override + String get question7 => "【7】인증 영상은 공개 안 해도 돼요?"; + /// "설정에서 공개 여부: 사용자 중심 - 인증 동영상을 클릭 - 왼쪽 밑 구석'인증 영상을 내 자세한 페이지에 표시할 수 있다.'" + @override + String get answer7 => "설정에서 공개 여부: 사용자 중심 - 인증 동영상을 클릭 - 왼쪽 밑 구석'인증 영상을 내 자세한 페이지에 표시할 수 있다.'"; + /// "【8】인증 취소를 피하는 방법?" + @override + String get question8 => "【8】인증 취소를 피하는 방법?"; + /// " 앨범에 적어도본인 사진으로 표기된 사진이 한 장 있다" + @override + String get answer8 => " 앨범에 적어도본인 사진으로 표기된 사진이 한 장 있다"; + /// "【9】 라디오 방송 삭제의 원인?" + @override + String get question9 => "【9】 라디오 방송 삭제의 원인?"; + /// "라디오 방송에 민감한 도를 발표하지 못하고 예민한 단어는 암시나 명시적인 단어에 한정되지 않고 개인정보 (포함 프로필, 닉네임, 연락처) 를 발포할 수 없다. 방송은 삭제될 것이다" + @override + String get answer9 => "라디오 방송에 민감한 도를 발표하지 못하고 예민한 단어는 암시나 명시적인 단어에 한정되지 않고 개인정보 (포함 프로필, 닉네임, 연락처) 를 발포할 수 없다. 방송은 삭제될 것이다"; + /// "【10】어떻게 아이디를 취소합니까?" + @override + String get question10 => "【10】어떻게 아이디를 취소합니까?"; + /// "아이디를 취소한후에 APP 에서 로그인할 수 없습니다. 앞으로 서비스를 사용하려면 다시 아이디 만들어야 합니다. 신중히 고려하십시오.만약 당신이아이디를 취소를 결정한다면 ,번호【12】고객직원이랑 연락 주세요 " + @override + String get answer10 => "아이디를 취소한후에 APP 에서 로그인할 수 없습니다. 앞으로 서비스를 사용하려면 다시 아이디 만들어야 합니다. 신중히 고려하십시오.만약 당신이아이디를 취소를 결정한다면 ,번호【12】고객직원이랑 연락 주세요 "; + /// "【11】암호 잊으면 어떡해요?" + @override + String get question11 => "【11】암호 잊으면 어떡해요?"; + /// "핸드폰 번호를 통해서 등록하거나 핸드폰 번호를 바인든사용자 , 로그인 페이지 오른쪽 모서리를 통과할 수 있습니다. “ 암호 잊기 ” 기능 암호 초기화 . 사용자 납치되지 않음 핸드폰 번호를 묶어주세요. , 새 로그인 암호 다시 설정하다" + @override + String get answer11 => "핸드폰 번호를 통해서 등록하거나 핸드폰 번호를 바인든사용자 , 로그인 페이지 오른쪽 모서리를 통과할 수 있습니다. “ 암호 잊기 ” 기능 암호 초기화 . 사용자 납치되지 않음 핸드폰 번호를 묶어주세요. , 새 로그인 암호 다시 설정하다"; + /// "【12】기타 질문 / 수동 고객 서비스 이전" + @override + String get question12 => "【12】기타 질문 / 수동 고객 서비스 이전"; + /// "안녕하십니까?당신의 문제를 말해 주십시오 ( 고객지원 근무 시간은 매일 8:00-다음날 02:00, 상담 고객이 많아서, 답변을 기다려야 할 수도 있다. )" + @override + String get answer12 => "안녕하십니까?당신의 문제를 말해 주십시오 ( 고객지원 근무 시간은 매일 8:00-다음날 02:00, 상담 고객이 많아서, 답변을 기다려야 할 수도 있다. )"; + /// "인증 센터" + @override + String get certification_center => "인증 센터"; + /// " 인증 영상 촬영 방식 실례" + @override + String get for_example2 => " 인증 영상 촬영 방식 실례"; + /// " 인증 조건" + @override + String get certification_conditions => " 인증 조건"; + /// "1.개인 이미지 양호" + @override + String get conditions1 => "1.개인 이미지 양호"; + /// "2.앨범 적어도 본인 사진 한장 올리다" + @override + String get conditions2 => "2.앨범 적어도 본인 사진 한장 올리다"; + /// "인증 방식" + @override + String get verification_method => "인증 방식"; + /// "1.종이 한 장에 당신의 닉네임과 이하 검증 코드를 쓰세요" + @override + String get method3 => "1.종이 한 장에 당신의 닉네임과 이하 검증 코드를 쓰세요"; + /// "2.이 종이 가지고 당신의 정면과 영상 찍으세요.(3~15초)" + @override + String get method4 => "2.이 종이 가지고 당신의 정면과 영상 찍으세요.(3~15초)"; + /// "인증 영상 올리다" + @override + String get upload_video2 => "인증 영상 올리다"; + /// "인증 성공한 후에 당신의 프로필은 real 로고를 표시하고 있다" + @override + String get after_authentication => "인증 성공한 후에 당신의 프로필은 real 로고를 표시하고 있다"; + /// "인증 영상을 내 자세한 페이지에 표시하세요" + @override + String get show_video => "인증 영상을 내 자세한 페이지에 표시하세요"; + /// "인증 영상 올린다" + @override + String get uploaded_video => "인증 영상 올린다"; + /// "심사중(24 시간 내에))" + @override + String get under_review => "심사중(24 시간 내에))"; + /// " 인증 상태" + @override + String get certification_status => " 인증 상태"; + /// "당신은 인증 통과했다" + @override + String get certified => "당신은 인증 통과했다"; + /// "인증은 다시 꺼내야 한다" + @override + String get wait_resubmitted => "인증은 다시 꺼내야 한다"; + /// "당신의 인증 영상은 요구에 맞지 않습니다. 원인은:" + @override + String get reason_failure => "당신의 인증 영상은 요구에 맞지 않습니다. 원인은:"; + /// "인증 요구를 따라 인증 영상 찍어주세요" + @override + String get claim => "인증 요구를 따라 인증 영상 찍어주세요"; + /// "앨범에 이목구비 정면 본인 사진을 또렷하게 올려주세요" + @override + String get claim2 => "앨범에 이목구비 정면 본인 사진을 또렷하게 올려주세요"; + /// "다시 인증 영상 올리세요" + @override + String get re_upload_video => "다시 인증 영상 올리세요"; + /// "인증 영상 업데이트" + @override + String get update_video => "인증 영상 업데이트"; + /// "H 화폐 " + @override + String get mask_coin => "H 화폐 "; + /// "당신은 충전가치나 밀 개설 등의 경로를 통해 H 화폐를 받을 수 있다" + @override + String get get_way => "당신은 충전가치나 밀 개설 등의 경로를 통해 H 화폐를 받을 수 있다"; + /// "H화는 음성 통화 및 보상에 사용할 수 있습니다." + @override + String get coin_use => "H화는 음성 통화 및 보상에 사용할 수 있습니다."; + /// " H 화폐 총액" + @override + String get coin_total => " H 화폐 총액"; + /// "환전 가능" + @override + String get can_redeemed => "환전 가능"; + /// "/s1 아이디" + @override + String get who_account => "/s1 아이디"; + /// "/s1 아이디 연동" + @override + String get bind_account => "/s1 아이디 연동"; + /// "당신의 /s1 아이디 " + @override + String get your_account => "당신의 /s1 아이디 "; + /// "당신이 총지를 통해서 /s1H 화폐 받았다" + @override + String get get_coin2 => "당신이 총지를 통해서 /s1H 화폐 받았다"; + /// "/s1 당신의 사교 아이디 보았다" + @override + String get viewed_your => "/s1 당신의 사교 아이디 보았다"; + /// "/s1가 /s2 한 개 증정했다" + @override + String get give_gift => "/s1가 /s2 한 개 증정했다"; + /// "+/s1H 화폐 " + @override + String get add_coin => "+/s1H 화폐 "; + /// "당신이 /s2에게 /s1 한 개 증정했다" + @override + String get give_one => "당신이 /s2에게 /s1 한 개 증정했다"; + /// "-/s1H 화폐 " + @override + String get less_coin => "-/s1H 화폐 "; + /// "현금을 제시하다" + @override + String get exchange_cash => "현금을 제시하다"; + /// "출금 신청" + @override + String get withdrawal_application => "출금 신청"; + /// "당신의/s1H화폐 환전 가능 /s2, 태환 후 잉여 /s3H화폐. 환전신청 확실합니까" + @override + String get redeem_choose => "당신의/s1H화폐 환전 가능 /s2, 태환 후 잉여 /s3H화폐. 환전신청 확실합니까"; + /// "출금 신청을 보냈다" + @override + String get application_submitted => "출금 신청을 보냈다"; + /// "저희가 두 업무일 내에 처리할 것이며, 의문이 있으면 고객센터직원이랑 상담을 할 수 있다" + @override + String get working_days => "저희가 두 업무일 내에 처리할 것이며, 의문이 있으면 고객센터직원이랑 상담을 할 수 있다"; + /// "현금" + @override + String get cash => "현금"; + /// "당신이 채팅 페이지에 돈봉투를 받을 때마다 돈봉투 금액이 여기에 들어갑니다.금액이 입금된 후 3일 이내에 아무도 신고하지 않으면 현금을 인출할 수 있으며, 현금 인출은 5%의 수수료를 받게 됩니다" + @override + String get handling_fee => "당신이 채팅 페이지에 돈봉투를 받을 때마다 돈봉투 금액이 여기에 들어갑니다.금액이 입금된 후 3일 이내에 아무도 신고하지 않으면 현금을 인출할 수 있으며, 현금 인출은 5%의 수수료를 받게 됩니다"; + /// "계좌총액" + @override + String get total_account => "계좌총액"; + /// "금액이 부족하여, 환불할 수 없다" + @override + String get cannot_redeemed => "금액이 부족하여, 환불할 수 없다"; + /// "환불을 성공한다" + @override + String get successful_redemption => "환불을 성공한다"; + /// "당신의 계좌 총액은 /s1위안입니다.이번에 현금을 인출할 수 있습니다./s2위안입니다.확실하세요?" + @override + String get redeem_choose2 => "당신의 계좌 총액은 /s1위안입니다.이번에 현금을 인출할 수 있습니다./s2위안입니다.확실하세요?"; + /// "개인 상세" + @override + String get personal_details => "개인 상세"; + /// " 공개 (추천)" + @override + String get public => " 공개 (추천)"; + /// "앨범 유료 보기" + @override + String get paid_album => "앨범 유료 보기"; + /// "다른 사람은 반드시 비용을 지불해야만 당신의 앨범을 볼 수 있고, 비용은 당신이 정하는데, 이것은 당신의 방문량을 낮출 수 있다" + @override + String get must_pay => "다른 사람은 반드시 비용을 지불해야만 당신의 앨범을 볼 수 있고, 비용은 당신이 정하는데, 이것은 당신의 방문량을 낮출 수 있다"; + /// "보기 금액 설정" + @override + String get set_amount1 => "보기 금액 설정"; + /// "먼저 사진을 올리고 유료 앨범을 설정하십시오" + @override + String get first_upload => "먼저 사진을 올리고 유료 앨범을 설정하십시오"; + /// "보기 전에 내 검증을 통과해야 합니다" + @override + String get need_permission => "보기 전에 내 검증을 통과해야 합니다"; + /// "다른 사람은 반드시 사진을 보내서 당신이 신분을 검증한 후에야 당신의 홈페이지를 볼 수 있게 해야 합니다, 확실합니까?" + @override + String get permission_choose => "다른 사람은 반드시 사진을 보내서 당신이 신분을 검증한 후에야 당신의 홈페이지를 볼 수 있게 해야 합니다, 확실합니까?"; + /// "주변 사람들 목록에서 나를 숨 깁니다" + @override + String get hide_me => "주변 사람들 목록에서 나를 숨 깁니다"; + /// "다른 사람에게 나의 거리를 숨기다" + @override + String get hide_distance => "다른 사람에게 나의 거리를 숨기다"; + /// "다른 사람에게 내 사교 아이디를 숨기다" + @override + String get hide_account => "다른 사람에게 내 사교 아이디를 숨기다"; + /// "통화 제어" + @override + String get chat_setting => "통화 제어"; + /// "사적인 대화를 나눌 권한이 있는 사람이 나에게 통화를 일으키도록 허락하다" + @override + String get chat_me => "사적인 대화를 나눌 권한이 있는 사람이 나에게 통화를 일으키도록 허락하다"; + /// "저장 성공" + @override + String get successfully_saved => "저장 성공"; + /// "당신은 아직 동태를 발표한 적이 없다" + @override + String get on_dynamic => "당신은 아직 동태를 발표한 적이 없다"; + /// "동태를 발표하다" + @override + String get release_dynamics => "동태를 발표하다"; + /// "동태 상세" + @override + String get dynamic_details => "동태 상세"; + /// "발표하다" + @override + String get release => "발표하다"; + /// "제가 발표한 거" + @override + String get i_posted => "제가 발표한 거"; + /// "동태를 삭제하다" + @override + String get delete_dynamic => "동태를 삭제하다"; + /// "이 동태를 삭제하시겠습니까?" + @override + String get delete_choose => "이 동태를 삭제하시겠습니까?"; + /// "/s1를 발표하다" + @override + String get posted_on => "/s1를 발표하다"; + /// "좋아요" + @override + String get thumbs_up3 => "좋아요"; + /// "이미 좋아했니다" + @override + String get already_praised => "이미 좋아했니다"; + /// "댓글" + @override + String get comment => "댓글"; + /// "보내기 " + @override + String get send => "보내기 "; + /// "댓글을 닫혔습니다" + @override + String get comment_closed => "댓글을 닫혔습니다"; + /// "발표자만 당신의 댓글을 볼 수 있습니다" + @override + String get your_comment => "발표자만 당신의 댓글을 볼 수 있습니다"; + /// "모두 사람 당신의 댓글을 볼 수 있다" + @override + String get everyone_comment => "모두 사람 당신의 댓글을 볼 수 있다"; + /// "댓글 금지" + @override + String get prohibit_comments => "댓글 금지"; + /// "댓글을 금지했다" + @override + String get comments_disabled => "댓글을 금지했다"; + /// "댓글 개방" + @override + String get open_comments => "댓글 개방"; + /// "댓글 개방했다" + @override + String get already_open => "댓글 개방했다"; + /// "대답하다" + @override + String get reply => "대답하다"; + /// "신고하다" + @override + String get report => "신고하다"; + /// "이 댓글을 신고하는 것이 확실합니까?" + @override + String get report_choose => "이 댓글을 신고하는 것이 확실합니까?"; + /// "신고를 성공했으니 최대한 빨리 처리해 드리겠습니다" + @override + String get successful_report => "신고를 성공했으니 최대한 빨리 처리해 드리겠습니다"; + /// "삭제 성공" + @override + String get successfully_deleted => "삭제 성공"; + /// "말투가 교양 있는 사람이 더 인기가 있으니, 저속하고 야한 거래를 발표하거나, 기타 사람의 프라이버시 내용을 폭로하지 마시오" + @override + String get please_civilization => "말투가 교양 있는 사람이 더 인기가 있으니, 저속하고 야한 거래를 발표하거나, 기타 사람의 프라이버시 내용을 폭로하지 마시오"; + /// "동일한 성별의 사용자에 대해 숨김" + @override + String get same_sex => "동일한 성별의 사용자에 대해 숨김"; + /// " 회원은 무료, 비회원은 /s1H화폐 지불을 해야 한다" + @override + String get member_free => " 회원은 무료, 비회원은 /s1H화폐 지불을 해야 한다"; + /// "인증했는여사3회 무료이며, 그후에는 /s1H화폐 지불이 필요합니다" + @override + String get certified_free => "인증했는여사3회 무료이며, 그후에는 /s1H화폐 지불이 필요합니다"; + /// "문자 내용을 입력하거나 사진을 선택하십시오" + @override + String get enter_something => "문자 내용을 입력하거나 사진을 선택하십시오"; + /// "유료 발표(/s1H화폐)" + @override + String get raid_release => "유료 발표(/s1H화폐)"; + /// "회원이 되다 , 무료 발표" + @override + String get become_member2 => "회원이 되다 , 무료 발표"; + /// "즉시 인증 ,무료 발표" + @override + String get now_certification => "즉시 인증 ,무료 발표"; + /// "발표 성공" + @override + String get successfully_released => "발표 성공"; + /// "당신은 아직 프로그램을 발표한 적이 없어요" + @override + String get no_program => "당신은 아직 프로그램을 발표한 적이 없어요"; + /// "프로그램 상세" + @override + String get program_details => "프로그램 상세"; + /// "프로그램 주제" + @override + String get program_theme => "프로그램 주제"; + /// "클릭하여 선택" + @override + String get click_select => "클릭하여 선택"; + /// "도시 " + @override + String get city => "도시 "; + /// "도시 선택" + @override + String get select_city => "도시 선택"; + /// "시간 " + @override + String get time => "시간 "; + /// "날짜 선택" + @override + String get select_date => "날짜 선택"; + /// "시간 선택" + @override + String get select_time => "시간 선택"; + /// "시간 제한 없음" + @override + String get unlimited_time => "시간 제한 없음"; + /// "보충 설명" + @override + String get supplementary_explanation => "보충 설명"; + /// "배치도" + @override + String get image => "배치도"; + /// " 프로그램 삭제" + @override + String get delete_program => " 프로그램 삭제"; + /// "이 프로그램을 삭제하시겠습니까?" + @override + String get delete_choose2 => "이 프로그램을 삭제하시겠습니까?"; + /// "프로그램 주제를 선택하십시오" + @override + String get please_choose => "프로그램 주제를 선택하십시오"; + /// "원하는 이상형을 선택하십시오" + @override + String get please_choose2 => "원하는 이상형을 선택하십시오"; + /// "도시를 선택하세요" + @override + String get please_choose3 => "도시를 선택하세요"; + /// "날짜를 선택하십시오" + @override + String get please_choose4 => "날짜를 선택하십시오"; + /// "시간을 선택하세요" + @override + String get please_choose5 => "시간을 선택하세요"; + /// "프로그램을 발표하다" + @override + String get release_program => "프로그램을 발표하다"; + /// "신청하다" + @override + String get sign_up => "신청하다"; + /// "신청을 마치다" + @override + String get end_registration => "신청을 마치다"; + /// "데이트를 끝내는 게 확실해요?" + @override + String get end_choose => "데이트를 끝내는 게 확실해요?"; + /// "그녀를 연락하다" + @override + String get contact_her => "그녀를 연락하다"; + /// "단독 채팅하다" + @override + String get talk_him => "단독 채팅하다"; + /// "이 신청을 신고하시겠습니까?" + @override + String get report_choose2 => "이 신청을 신고하시겠습니까?"; + /// "발표 시간" + @override + String get release_time => "발표 시간"; + /// "활동 시간" + @override + String get activity_time => "활동 시간"; + /// "성별에 제한이 없다" + @override + String get any_sex => "성별에 제한이 없다"; + /// "여자만 보기" + @override + String get look_women => "여자만 보기"; + /// "남자만 보기" + @override + String get look_men => "남자만 보기"; + /// "지역 제한이 없다" + @override + String get unlimited_area => "지역 제한이 없다"; + /// "이 프로그램은 이미 삭제되었다" + @override + String get program_deleted => "이 프로그램은 이미 삭제되었다"; + /// "비회원 댓글할 수 없다" + @override + String get cant_comment => "비회원 댓글할 수 없다"; + /// "신청하다" + @override + String get sign_up2 => "신청하다"; + /// "신청하려면 당신의 정면 사진을 보내야 합니다(상대방만 볼 수 있음)" + @override + String get need_photo2 => "신청하려면 당신의 정면 사진을 보내야 합니다(상대방만 볼 수 있음)"; + /// "신청이 성공적으로 이루어졌는데, 상대방이 적절하다고 생각되면 연락드리겠습니다" + @override + String get registration_success => "신청이 성공적으로 이루어졌는데, 상대방이 적절하다고 생각되면 연락드리겠습니다"; + /// "이미 마치다" + @override + String get has_ended => "이미 마치다"; + /// "남자은 남자의 프로그램에 신청을 할 수 없다" + @override + String get men_cant => "남자은 남자의 프로그램에 신청을 할 수 없다"; + /// "여자은 여자의 프로그램에 신청을 할 수 없다" + @override + String get ms_cant => "여자은 여자의 프로그램에 신청을 할 수 없다"; + /// "남자은 남자의 프로그램에 댓글을 할 수 없다" + @override + String get men_cant2 => "남자은 남자의 프로그램에 댓글을 할 수 없다"; + /// "여자은 여자의 프로그램에 댓글을 할 수 없다" + @override + String get ms_cant2 => "여자은 여자의 프로그램에 댓글을 할 수 없다"; + /// "소식이 추송한다,암호 수정" + @override + String get message_push => "소식이 추송한다,암호 수정"; + /// "전화번호 " + @override + String get phone_number => "전화번호 "; + /// "핸드폰 번호를 묶다" + @override + String get bind_phone1 => "핸드폰 번호를 묶다"; + /// "휴대폰 번호를 묶어서 당신의 계좌를 더 안전하게 만들어요" + @override + String get more_safer => "휴대폰 번호를 묶어서 당신의 계좌를 더 안전하게 만들어요"; + /// "묶은 휴대폰 번호를 수정하고 싶으세요" + @override + String get modify_choose => "묶은 휴대폰 번호를 수정하고 싶으세요"; + /// "암호 수정 " + @override + String get change_password => "암호 수정 "; + /// "사용자는 먼저 휴대폰 번호를 묶어야 로그인 암호를 설정할 수 있습니다" + @override + String get first_bind => "사용자는 먼저 휴대폰 번호를 묶어야 로그인 암호를 설정할 수 있습니다"; + /// "기본 암호" + @override + String get old_password => "기본 암호"; + /// "현재 로그인 암호를 입력하십시오" + @override + String get current_password => "현재 로그인 암호를 입력하십시오"; + /// "새 암호" + @override + String get new_password => "새 암호"; + /// "6자리보다 많은 새 암호를 설정하십시오" + @override + String get set_new => "6자리보다 많은 새 암호를 설정하십시오"; + /// "사진 캐시 지우기" + @override + String get clear_cache => "사진 캐시 지우기"; + /// "제거 성공" + @override + String get cleared_successfully => "제거 성공"; + /// "사용자 협의" + @override + String get user_agreement1 => "사용자 협의"; + /// "로그아웃" + @override + String get sign_out => "로그아웃"; + /// "로그아웃 계정이 확정되었습니까?" + @override + String get out_choose => "로그아웃 계정이 확정되었습니까?"; + /// "추송 설정" + @override + String get push_settings => "추송 설정"; + /// "권한이 거절되었습니다" + @override + String get permission_denied => "권한이 거절되었습니다"; + /// "소식을 추송기 설정" + @override + String get push_setting2 => "소식을 추송기 설정"; + /// "단독 채팅 소식" + @override + String get private_chat2 => "단독 채팅 소식"; + /// "새 데이트" + @override + String get new_date => "새 데이트"; + /// "어떤 여자가 나의 관찰 요청을 통과하였다" + @override + String get passed_request2 => "어떤 여자가 나의 관찰 요청을 통과하였다"; + /// "내 자료 페이지를 볼남자분이 신청하셨어요" + @override + String get men_view => "내 자료 페이지를 볼남자분이 신청하셨어요"; + /// "내 사교 아이디을 볼남자분이 있어요" + @override + String get men_view2 => "내 사교 아이디을 볼남자분이 있어요"; + /// "내 빨간봉투 사진을 본 남자분이 있어요" + @override + String get men_view3 => "내 빨간봉투 사진을 본 남자분이 있어요"; + /// "이미 자료를 본남자분이 나에게 사교 아이디를 보내 줬어요" + @override + String get men_view4 => "이미 자료를 본남자분이 나에게 사교 아이디를 보내 줬어요"; + /// "요청 코드 신청을 성공했다" + @override + String get applied_successfully => "요청 코드 신청을 성공했다"; + /// "열기 후 응답 메시지 형식 보내다" + @override + String get after_open => "열기 후 응답 메시지 형식 보내다"; + /// "만약 당신이 최근 3일 동안 그녀/그에게 비용을 지불한 적이 있다면, 우리가 제보를 심사한 후에, 시스템은 자동적으로 당신에게 소비 금액을 반송할 것입니다" + @override + String get if_something => "만약 당신이 최근 3일 동안 그녀/그에게 비용을 지불한 적이 있다면, 우리가 제보를 심사한 후에, 시스템은 자동적으로 당신에게 소비 금액을 반송할 것입니다"; + /// "광고하다" + @override + String get advertise => "광고하다"; + /// "허위 사진" + @override + String get false_photo => "허위 사진"; + /// "색정적이고 저속하다" + @override + String get erotic_vulgarity => "색정적이고 저속하다"; + /// "소란을 피우고 욕설을 퍼붓다" + @override + String get harassment => "소란을 피우고 욕설을 퍼붓다"; + /// "그녀는 사기꾼이다" + @override + String get she_liar => "그녀는 사기꾼이다"; + /// "그는 사기꾼이다" + @override + String get he_liar => "그는 사기꾼이다"; + /// "우리가 확인에 따를 수 있도록 관련 캡처를 제공하십시오" + @override + String get provide_screenshots => "우리가 확인에 따를 수 있도록 관련 캡처를 제공하십시오"; + /// "자세한 내용을 묘사하십시오(200자 이내)" + @override + String get describe_details => "자세한 내용을 묘사하십시오(200자 이내)"; + /// "신고의 원인을 선택하세요" + @override + String get report_reason => "신고의 원인을 선택하세요"; + /// "신고가 성공했다" + @override + String get report_success2 => "신고가 성공했다"; + /// "수정 성공" + @override + String get successfully_modified => "수정 성공"; + /// "남자 " + @override + String get boy => "남자 "; + /// "여자" + @override + String get girl => "여자"; + /// "신청했다" + @override + String get already_applied => "신청했다"; + /// "신청 보기 " + @override + String get view_registration => "신청 보기 "; + /// "펼치다" + @override + String get expand => "펼치다"; + /// "닫다" + @override + String get collapse => "닫다"; + /// "소식 신청 " + @override + String get application_notice => "소식 신청 "; + /// "당신의 신청에 동의하는 사용자가 있습니다" + @override + String get agrees_application => "당신의 신청에 동의하는 사용자가 있습니다"; + /// "빨간봉투 사진" + @override + String get red_photo => "빨간봉투 사진"; + /// "불법노출 저속한 사진/동영상을 올리지 마십시오, 심각한 경우 아이디 차단됩니다" + @override + String get dont => "불법노출 저속한 사진/동영상을 올리지 마십시오, 심각한 경우 아이디 차단됩니다"; + /// "현재 버전" + @override + String get current_version => "현재 버전"; + /// "은행 카드를 묶다" + @override + String get bank_card => "은행 카드를 묶다"; + /// "계좌의개설한 은행을 선택하십시오" + @override + String get choose_bank => "계좌의개설한 은행을 선택하십시오"; + /// "은행 카드 번호 입력하세요" + @override + String get bank_number => "은행 카드 번호 입력하세요"; + /// "증건 번호 입력하세요" + @override + String get id_number => "증건 번호 입력하세요"; + /// "성명 " + @override + String get name => "성명 "; + /// "은행 카드 번호 " + @override + String get bank_number2 => "은행 카드 번호 "; + /// "증건 번호 " + @override + String get license_number => "증건 번호 "; + /// "묶은 전화번호 " + @override + String get bind_phone => "묶은 전화번호 "; + /// "그의 홈페이지" + @override + String get his_homepage => "그의 홈페이지"; + /// "그녀의 홈페이지" + @override + String get her_homepage => "그녀의 홈페이지"; + /// "Wechat 지불" + @override + String get wechat_pay => "Wechat 지불"; + /// "facebook 지불" + @override + String get facebook_pay => "facebook 지불"; + /// "google 지불" + @override + String get google_pay => "google 지불"; + /// "지불 성공" + @override + String get payment_successful => "지불 성공"; + /// "인출 금액 설정" + @override + String get set_amount => "인출 금액 설정"; + /// "H 코인의 수를 입력하십시오" + @override + String get enter_amount => "H 코인의 수를 입력하십시오"; + /// "인출 가능하다" + @override + String get can_withdraw => "인출 가능하다"; + /// "음성 설정 " + @override + String get language_set => "음성 설정 "; + /// "사용자 협의 " + @override + String get user_agreement => "사용자 협의 "; + /// "속비" + @override + String get renewal_fee => "속비"; + /// "즉시 개통" + @override + String get open_immediately => "즉시 개통"; + /// "합계" + @override + String get total => "합계"; + /// "반 개월" + @override + String get half_month => "반 개월"; + /// " /s1 개월 " + @override + String get month2 => " /s1 개월 "; + /// "차단 취소" + @override + String get cancel_shield => "차단 취소"; + /// "블랙리스트" + @override + String get blacklist2 => "블랙리스트"; + /// "(회원이 6초까지 연장 가능)" + @override + String get longTime => "(회원이 6초까지 연장 가능)"; + /// "화면을 눌러 보기" + @override + String get longClick => "화면을 눌러 보기"; + /// "발효 중인 프로그램을 먼저 종료하세요" + @override + String get stop_program => "발효 중인 프로그램을 먼저 종료하세요"; + /// "남자은 남자를 소장할 수 없다" + @override + String get not_love => "남자은 남자를 소장할 수 없다"; + /// "여자은 여자를 소장할 수 없다" + @override + String get not_love2 => "여자은 여자를 소장할 수 없다"; + /// "여신은 무료 발표할 수 있다" + @override + String get women_free => "여신은 무료 발표할 수 있다"; + /// "그는 아직 사진을 올리지 않았다" + @override + String get not_up_man => "그는 아직 사진을 올리지 않았다"; + /// "그녀는 아직 사진을 올리지 않았다" + @override + String get not_up_women => "그녀는 아직 사진을 올리지 않았다"; + /// "请플랫폼을 통해 불법 거래를 하지 마십시오. 신고 상황이 사실이면 아이디 차단됩니다" + @override + String get not_illage => "请플랫폼을 통해 불법 거래를 하지 마십시오. 신고 상황이 사실이면 아이디 차단됩니다"; + /// "신청했다" + @override + String get alreay_join => "신청했다"; + /// "이 사진 삭제할 건 확실하세요?" + @override + String get sure_delete => "이 사진 삭제할 건 확실하세요?"; + /// "즉시 입력하다" + @override + String get white_now => "즉시 입력하다"; + /// "당신은 아직 개인소개를 작성하지 않았는데, 사람을 끄는 개인소개는 데이트 성공에 큰 영향을 많다" + @override + String get personal => "당신은 아직 개인소개를 작성하지 않았는데, 사람을 끄는 개인소개는 데이트 성공에 큰 영향을 많다"; + /// "성공" + @override + String get success => "성공"; + /// "실패" + @override + String get fail => "실패"; + /// "인증된 사용자만 빨간봉투 사진을 설정할 수 있음" + @override + String get moneyPageTip => "인증된 사용자만 빨간봉투 사진을 설정할 수 있음"; + /// "당신은 이미 신청을 했는데, 상대방이 적합하다고 느끼면 연락할 것이다" + @override + String get alreadyJoin => "당신은 이미 신청을 했는데, 상대방이 적합하다고 느끼면 연락할 것이다"; + /// "반칙 경고" + @override + String get waring => "반칙 경고"; + /// "사용자의 프라이버시를 존중하며 캡처하지 마십시오.다음에 있으면, 당신이 다른 사용자의 사진을 보는 것을 금지할 것이다" + @override + String get userPravicy => "사용자의 프라이버시를 존중하며 캡처하지 마십시오.다음에 있으면, 당신이 다른 사용자의 사진을 보는 것을 금지할 것이다"; + /// "약속시간이 지났으니 수정해주세요" + @override + String get outTime => "약속시간이 지났으니 수정해주세요"; + /// "심사중 " + @override + String get reviewing => "심사중 "; + /// "심사 성공" + @override + String get reviewed => "심사 성공"; + /// "심사 실패" + @override + String get reviewedFail => "심사 실패"; + /// "사용자는 먼저 은행 카드를 묶어야 현금을 인출할 수 있다" + @override + String get needCard => "사용자는 먼저 은행 카드를 묶어야 현금을 인출할 수 있다"; + /// "여자는 여성의 동태를 댓글할 수 없다" + @override + String get women_not_d => "여자는 여성의 동태를 댓글할 수 없다"; + /// "남자는 남자의 동태를 댓글할 수 없다" + @override + String get man_not_d => "남자는 남자의 동태를 댓글할 수 없다"; + /// "사진이 있어야 여자를 끌어들일 수 있어요" + @override + String get have_picture => "사진이 있어야 여자를 끌어들일 수 있어요"; + /// "업로드 전송 취소 " + @override + String get up_cancle => "업로드 전송 취소 "; + /// "소식을 비워둘 수 없다" + @override + String get msg_not => "소식을 비워둘 수 없다"; + /// "이 기능은 녹음 권한을 부여해야 합니다" + @override + String get need_record => "이 기능은 녹음 권한을 부여해야 합니다"; + /// "동영상 파일을 다운로드하는 중이다" + @override + String get downloading_video => "동영상 파일을 다운로드하는 중이다"; + /// "문제 번호를 다시 입력하십시오" + @override + String get reinput => "문제 번호를 다시 입력하십시오"; + /// "당신의 동태는 사용자에게 익명으로 신고되어 시스템을 확인하고 이 동태를 삭제하고 다시는 규칙을 위반한 조작을 하지 마시오" + @override + String get dy_delete => "당신의 동태는 사용자에게 익명으로 신고되어 시스템을 확인하고 이 동태를 삭제하고 다시는 규칙을 위반한 조작을 하지 마시오"; + /// "당신의 프로그램은 사용자에게 익명으로 신고되어 시스템을 확인하여 이미 이 프로그램을 삭제하였다 , 다시는 규칙을 위반한 조작을 하지 마시오" + @override + String get pro_delete => "당신의 프로그램은 사용자에게 익명으로 신고되어 시스템을 확인하여 이미 이 프로그램을 삭제하였다 , 다시는 규칙을 위반한 조작을 하지 마시오"; + /// "당신의 평론은 사용자 익명에 의해 신고되어 시스템이 확인되어 이 평론을 삭제했습니다 , 다시는 규칙을 위반한 조작을 하지 마시오 " + @override + String get con_delete => "당신의 평론은 사용자 익명에 의해 신고되어 시스템이 확인되어 이 평론을 삭제했습니다 , 다시는 규칙을 위반한 조작을 하지 마시오 "; + /// "익명 사용자 신고를 거쳐 시스템에 당신은 최근에 불법 행위가 존재하고 있음을 확인하다 , 이미 당신 최근의H 화폐로 반환했다. 다음에 또 있으면 계좌가 동결될 것이다" + @override + String get coin_returen => "익명 사용자 신고를 거쳐 시스템에 당신은 최근에 불법 행위가 존재하고 있음을 확인하다 , 이미 당신 최근의H 화폐로 반환했다. 다음에 또 있으면 계좌가 동결될 것이다"; + /// "통화중에 음란물 및 음란물과 같은 불법 행위는 금지됩니다.발견하면 아이디 영구성 참겨 처리하다" + @override + String get voicing => "통화중에 음란물 및 음란물과 같은 불법 행위는 금지됩니다.발견하면 아이디 영구성 참겨 처리하다"; + /// "고객 서비스" + @override + String get help => "고객 서비스"; + /// "인공 번역 개시" + @override + String get translate_on => "인공 번역 개시"; + /// "인공 번역 폐쇄" + @override + String get translate_off => "인공 번역 폐쇄"; + /// "/s1 H 화폐를 쓰고 충전하며, SVIP된다" + @override + String get becomeSvip => "/s1 H 화폐를 쓰고 충전하며, SVIP된다"; + /// "svip 권한 개시 가능다" + @override + String get need_svip => "svip 권한 개시 가능다"; + /// "SVIP 는 VIP 로 속비할 수 없습니다" + @override + String get cannot_vip => "SVIP 는 VIP 로 속비할 수 없습니다"; + /// "연결 안돼서 소식 못 보내고 못 받다" + @override + String get offline => "연결 안돼서 소식 못 보내고 못 받다"; + /// "아이디가 다른 장비에 로그인되어 있습니다. 탈출했다" + @override + String get otherLogin => "아이디가 다른 장비에 로그인되어 있습니다. 탈출했다"; + /// "아직 새 소식 없다" + @override + String get no_new => "아직 새 소식 없다"; + /// "번역 완료" + @override + String get over => "번역 완료"; + /// "이 번역을 안 좋은 평가 하시겠습니까?" + @override + String get bad_ev => "이 번역을 안 좋은 평가 하시겠습니까?"; + /// "더 재밌게 얘기하다" + @override + String get right5 => "더 재밌게 얘기하다"; + /// "더 즐겁게 쓰다" + @override + String get right6 => "더 즐겁게 쓰다"; + /// "오빠" + @override + String get man_vi => "오빠"; + /// "누나" + @override + String get women_vi => "누나"; + /// "서비스 효율을 높이기 위해서 문제가 있으면 숫자를 바로 답장하십시오!" + @override + String get kf_tips => "서비스 효율을 높이기 위해서 문제가 있으면 숫자를 바로 답장하십시오!"; + /// "거절했다" + @override + String get rejected => "거절했다"; + /// "당신은/s1H화폐 회원 구매" + @override + String get buy_vip => "당신은/s1H화폐 회원 구매"; + /// "/s1H 화폐 게시동적 프로그램을 구매했다" + @override + String get buy_program => "/s1H 화폐 게시동적 프로그램을 구매했다"; + /// "당신이H 화폐 인출 신청은 이미 처리되었으니, 이미 이체되었다. /s1 당신의 은행 통장에 도착하니, 알아봐 주십시오. " + @override + String get del_add_money => "당신이H 화폐 인출 신청은 이미 처리되었으니, 이미 이체되었다. /s1 당신의 은행 통장에 도착하니, 알아봐 주십시오. "; + /// "당신이 추출한/s1H화폐를 신청하고 있다" + @override + String get adding_money => "당신이 추출한/s1H화폐를 신청하고 있다"; + /// "무료 전문번역사 즐시 번역" + @override + String get free_translate => "무료 전문번역사 즐시 번역"; + /// "고객서비스를 전문적으로 드리다" + @override + String get personalTraff => "고객서비스를 전문적으로 드리다"; + /// "인공 번역 중…" + @override + String get ManTranslate => "인공 번역 중…"; + /// "기계 번역 중…" + @override + String get robotTranslate => "기계 번역 중…"; + /// "인공 번역 완료" + @override + String get translated => "인공 번역 완료"; + /// "건강 교류, 저속한 내용을 방송하지 말고, 발견하면 삭제 처리가 될 것이다" + @override + String get delete_progarm => "건강 교류, 저속한 내용을 방송하지 말고, 발견하면 삭제 처리가 될 것이다"; + /// "위치 권한을 열리지 않다" + @override + String get open_location => "위치 권한을 열리지 않다"; + /// "휴댚폰 설정에서 위치 권한을 설치하여 다른 사용자와 거리를 알수 있다" + @override + String get get_location => "휴댚폰 설정에서 위치 권한을 설치하여 다른 사용자와 거리를 알수 있다"; + /// "한번 더 누르면 탈출다" + @override + String get confirm_exit => "한번 더 누르면 탈출다"; + /// "하루에 /s1번 기회 공짜 방송" + @override + String get free_program => "하루에 /s1번 기회 공짜 방송"; + /// "사진" + @override + String get picture => "사진"; + /// "카메라" + @override + String get camera => "카메라"; + /// "영상" + @override + String get video => "영상"; + /// "빨간봉투" + @override + String get red_money => "빨간봉투"; + /// "붙이다" + @override + String get stick => "붙이다"; + /// "키 를 누르고 말하다" + @override + String get press_say => "키 를 누르고 말하다"; + /// "/s1님이 당신의 빨간 봉투을 받았다" + @override + String get get_money => "/s1님이 당신의 빨간 봉투을 받았다"; + /// "/s1의빨간 봉투를 받았다" + @override + String get you_get_money => "/s1의빨간 봉투를 받았다"; + /// "/s1 빨간 봉투" + @override + String get ones_money => "/s1 빨간 봉투"; + /// "빨간 봉투가 기한 지났다" + @override + String get money_over => "빨간 봉투가 기한 지났다"; + /// "영상 파일 다운로드 실패" + @override + String get downloading_fail => "영상 파일 다운로드 실패"; + /// "영상 파일 다운로드 중" + @override + String get downloading => "영상 파일 다운로드 중"; + /// "아직 받지 않은 빨간 봉투,2 4시간 후에 환불할 예정입니다" + @override + String get back_money => "아직 받지 않은 빨간 봉투,2 4시간 후에 환불할 예정입니다"; + /// "빨간 봉투 없다" + @override + String get no_money => "빨간 봉투 없다"; + /// "빨간 봉투을 받았다" + @override + String get already_money => "빨간 봉투을 받았다"; + /// "기한 시간 지났으니 다시 당신의계좌로 환불되었다" + @override + String get back_user => "기한 시간 지났으니 다시 당신의계좌로 환불되었다"; + /// "상대방이 받기를 기다리다" + @override + String get waiting_user => "상대방이 받기를 기다리다"; + /// "상대방이 이미 받았다" + @override + String get other_get => "상대방이 이미 받았다"; + /// "작은 생각, 파도를 타고" + @override + String get little => "작은 생각, 파도를 타고"; + /// "돈을 빨간 봉투에 넣다" + @override + String get put_money => "돈을 빨간 봉투에 넣다"; + /// "금액" + @override + String get mount => "금액"; + /// "기한 지났다" + @override + String get over_time => "기한 지났다"; + /// "이미 받았다" + @override + String get has_get => "이미 받았다"; + /// "아직 선물 없다" + @override + String get no_gift => "아직 선물 없다"; + /// "상을 주기" + @override + String get sent_gift => "상을 주기"; + /// "작성에 성공하면 /s1H 화폐를 받을 수 있으며, 연동한 후에수정할 수 없습니다" + @override + String get fill_tips => "작성에 성공하면 /s1H 화폐를 받을 수 있으며, 연동한 후에수정할 수 없습니다"; + /// "초대 번호연동" + @override + String get bind_code => "초대 번호연동"; + /// "초대 번호" + @override + String get invide_code => "초대 번호"; + /// "확인 삭제" + @override + String get confirm_delete => "확인 삭제"; + /// "당신이 이미 평가했습나다" + @override + String get has_eva => "당신이 이미 평가했습나다"; + /// "오픈" + @override + String get open => "오픈"; + /// "음성" + @override + String get voice => "음성"; + /// "손을 놓으면 발송하다" + @override + String get release_send => "손을 놓으면 발송하다"; + /// "녹음시간 너무 짧다" + @override + String get time_little => "녹음시간 너무 짧다"; + /// "상대방이 온라인 하지 않아서 통화할 수 없다" + @override + String get not_online => "상대방이 온라인 하지 않아서 통화할 수 없다"; + /// "당신이 /s1에게 /s2H 화폐 빨간 봉투를 보냈다" + @override + String get give_red_money => "당신이 /s1에게 /s2H 화폐 빨간 봉투를 보냈다"; + /// "당신이 /s1준 /s2H 화폐 빨간 봉투 받았다" + @override + String get get_red_money => "당신이 /s1준 /s2H 화폐 빨간 봉투 받았다"; + /// "당신이 /s1에게 /s2H화폐상을 줬다" + @override + String get give_other_money => "당신이 /s1에게 /s2H화폐상을 줬다"; + /// " 당신이 /S1의 /s2H 화폐상 받았다" + @override + String get get_other_money => " 당신이 /S1의 /s2H 화폐상 받았다"; + /// "슈퍼 회원" + @override + String get svip => "슈퍼 회원"; + /// "추천" + @override + String get recommend => "추천"; + /// "당신이(/s2H)비용을 지불했습니다/s1의 빨간 봉투 사진을 보기" + @override + String get paid_you4 => "당신이(/s2H)비용을 지불했습니다/s1의 빨간 봉투 사진을 보기"; + /// "당신이(/s2H)비용을 지불했습니다/s1의 사진을 보기" + @override + String get paid_you5 => "당신이(/s2H)비용을 지불했습니다/s1의 사진을 보기"; + /// "당신이 /s1무두 자료 해제를 지불했다" + @override + String get paid_you6 => "당신이 /s1무두 자료 해제를 지불했다"; + /// "흔호 앱 허락및 서비스 협의" + @override + String get UG_LINE0 => "흔호 앱 허락및 서비스 협의"; + /// "[제1부 및 안내]" + @override + String get UG_LINE1 => "[제1부 및 안내]"; + /// "Qianhai Youlong Technology Co., Ltd(하명“Qianhai Youlong Technology Co., Ltd.”) 에서 사용자에게 자세하게 읽고 충분히 이해할 것 을 일깨워 준다 본《 서비스 협의》( 하명 《 협의 >》)사용자는 자세하게 읽고, 본 《협의》의 각 조항을 충분히 이해해야 한다. 면제 또는 제한 포함 Qianhai Youlong Technology Co., Ltd. 책임의 면책 조항 및 사용자에 대한 권리 제한 조항. 신중하게 읽고 받아들이거나 본 협의를 받아들이지 않는 것을 선택하십시오 (미성년자는 법정 보호자가 함께 읽으십시오). 이 협의 모든 조항을 받아들이지 않으면 등록, 로그인할 권리가 없습니다. 이 협의에 관한 서비스를 사용할 수 없습니다. 귀하의 등록,사용 등은 본 협의에 대한 받아들이고, 이 《 협의 》 각 조항의 구속에 동의할 것이다. " + @override + String get UG_LINE2 => "Qianhai Youlong Technology Co., Ltd(하명“Qianhai Youlong Technology Co., Ltd.”) 에서 사용자에게 자세하게 읽고 충분히 이해할 것 을 일깨워 준다 본《 서비스 협의》( 하명 《 협의 >》)사용자는 자세하게 읽고, 본 《협의》의 각 조항을 충분히 이해해야 한다. 면제 또는 제한 포함 Qianhai Youlong Technology Co., Ltd. 책임의 면책 조항 및 사용자에 대한 권리 제한 조항. 신중하게 읽고 받아들이거나 본 협의를 받아들이지 않는 것을 선택하십시오 (미성년자는 법정 보호자가 함께 읽으십시오). 이 협의 모든 조항을 받아들이지 않으면 등록, 로그인할 권리가 없습니다. 이 협의에 관한 서비스를 사용할 수 없습니다. 귀하의 등록,사용 등은 본 협의에 대한 받아들이고, 이 《 협의 》 각 조항의 구속에 동의할 것이다. "; + /// "본 '협의'는 귀하(이하 '사용자'라 함)와 Qianhai Youlong Technology Co., Ltd. 간에 사용자 등록, 로그인, 이용'흔호 서비스에 관해 수립된 프로토콜입니다.본 '합의'는 Qianhai Youlong Technology Co., Ltd.와 사용자 사이의 'Hibok 서비스 관련 권리 의무'에 대해 기술합니다.\"사용자\"는 본 서비스를 등록, 로그인, 사용, 브라우징하는 개인 또는 조직을 의미합니다.본 협약에 대한 귀하의 수락 즉, 전체 조항에 의해 구속되며, 임의 서비스 약관에 대해 Qianhai Youlong Technology Co., Ltd.가 언제든지 할 수 있는 어떠한 수정도 수용하는 것을 포함합니다.본 《합의》는 Qianhai Youlong Technology Co., Ltd.가 수시로 갱신할 수 있으며, 갱신 후 합의 조항이 공표되는 즉시 원래의 합의 조항을 대체하므로 더 이상 별도로 통지하지 않고, 사용자는 본 APP에서 최신 버전의 합의 조항을 열람할 수 있습니다.Qianhai Youlong Technology Co., Ltd.에서 프로토콜 조항이 수정된 후 사용자가 수정된 조항을 수락하지 않을 경우, Qianhai Youlong Technology Co., Ltd.가 제공한 서비스를 사용 중지하고 사용자가 계속해서 Qianhai Youlong Technology Co., Ltd.가 제공한 서비스를 받은 것으로 간주됩니다" + @override + String get UG_LINE3 => "본 '협의'는 귀하(이하 '사용자'라 함)와 Qianhai Youlong Technology Co., Ltd. 간에 사용자 등록, 로그인, 이용'흔호 서비스에 관해 수립된 프로토콜입니다.본 '합의'는 Qianhai Youlong Technology Co., Ltd.와 사용자 사이의 'Hibok 서비스 관련 권리 의무'에 대해 기술합니다.\"사용자\"는 본 서비스를 등록, 로그인, 사용, 브라우징하는 개인 또는 조직을 의미합니다.본 협약에 대한 귀하의 수락 즉, 전체 조항에 의해 구속되며, 임의 서비스 약관에 대해 Qianhai Youlong Technology Co., Ltd.가 언제든지 할 수 있는 어떠한 수정도 수용하는 것을 포함합니다.본 《합의》는 Qianhai Youlong Technology Co., Ltd.가 수시로 갱신할 수 있으며, 갱신 후 합의 조항이 공표되는 즉시 원래의 합의 조항을 대체하므로 더 이상 별도로 통지하지 않고, 사용자는 본 APP에서 최신 버전의 합의 조항을 열람할 수 있습니다.Qianhai Youlong Technology Co., Ltd.에서 프로토콜 조항이 수정된 후 사용자가 수정된 조항을 수락하지 않을 경우, Qianhai Youlong Technology Co., Ltd.가 제공한 서비스를 사용 중지하고 사용자가 계속해서 Qianhai Youlong Technology Co., Ltd.가 제공한 서비스를 받은 것으로 간주됩니다"; + /// "一、사용 규칙" + @override + String get UG_LINE4 => "一、사용 규칙"; + /// "1、사용자가 충분히 알고 동의하는 것은 오직 사용자가 정보를 공유, 전송 및 획득할 수 있는 플랫폼을 제공하는 것 뿐이며, 사용자는 자신이 계정을 등록한 아래의 모든 행위에 책임을 져야 하며, 그러나 당신이 전송한 어떤 콘텐츠는 물론 그로 인해 발생하는 어떤 결과도 포함됩니다" + @override + String get UG_LINE5 => "1、사용자가 충분히 알고 동의하는 것은 오직 사용자가 정보를 공유, 전송 및 획득할 수 있는 플랫폼을 제공하는 것 뿐이며, 사용자는 자신이 계정을 등록한 아래의 모든 행위에 책임을 져야 하며, 그러나 당신이 전송한 어떤 콘텐츠는 물론 그로 인해 발생하는 어떤 결과도 포함됩니다"; + /// "2、사용자가 서비스 중이거나 서비스로 전송되는 어떠한 내용도 Qianhai Youlong Technology Co., Ltd.의 관점이나 정책을 반영하지 않으며, Qianhai Youlong Technology Co., Ltd.는 이에 대해 어떠한 책임도 지지 않습니다" + @override + String get UG_LINE6 => "2、사용자가 서비스 중이거나 서비스로 전송되는 어떠한 내용도 Qianhai Youlong Technology Co., Ltd.의 관점이나 정책을 반영하지 않으며, Qianhai Youlong Technology Co., Ltd.는 이에 대해 어떠한 책임도 지지 않습니다"; + /// "3、사용자가 충분히 알고 동의하면, 사용자 관계망에 기반한 소셜 정보 뷰 제품이며, 사용자는 위에 있는 등록 정보의 진실성, 적법성, 유효성에 대해 모든 책임을 져야 하며, 사용자는 다른 사람의 이름을 사칭하여 어떠한 정보를 전파해서는 안 된다" + @override + String get UG_LINE7 => "3、사용자가 충분히 알고 동의하면, 사용자 관계망에 기반한 소셜 정보 뷰 제품이며, 사용자는 위에 있는 등록 정보의 진실성, 적법성, 유효성에 대해 모든 책임을 져야 하며, 사용자는 다른 사람의 이름을 사칭하여 어떠한 정보를 전파해서는 안 된다"; + /// "4、사용자는 위에서 전송한 정보의 진실성, 적법성, 무해성, 유효성 등에 대해 전적으로 책임을 져야 하며, 사용자가 전파하는 정보와 관련된 어떠한 법적 책임은 사용자 스스로가 져야 하며, Qianhai Youlong Technology Co., Ltd.와는 관련이 없다" + @override + String get UG_LINE8 => "4、사용자는 위에서 전송한 정보의 진실성, 적법성, 무해성, 유효성 등에 대해 전적으로 책임을 져야 하며, 사용자가 전파하는 정보와 관련된 어떠한 법적 책임은 사용자 스스로가 져야 하며, Qianhai Youlong Technology Co., Ltd.와는 관련이 없다"; + /// "5、 Qianhai Youlong Technology Co., Ltd. 보류는 업무 발전의 필요에 따라 일방적으로 본 서비스의 전부 또는 일부에 대해 어떠한 통지도 없이 서비스를 변경, 일시 중지, 제한, 종료 또는 철회할 수 있는 권리를 사용자가 부담해야 합니다" + @override + String get UG_LINE9 => "5、 Qianhai Youlong Technology Co., Ltd. 보류는 업무 발전의 필요에 따라 일방적으로 본 서비스의 전부 또는 일부에 대해 어떠한 통지도 없이 서비스를 변경, 일시 중지, 제한, 종료 또는 철회할 수 있는 권리를 사용자가 부담해야 합니다"; + /// "6、제공되는 서비스에는 광고가 포함될 수 있으며 사용자는 사용 중 제3자 공급업체, 파트너가 제공하는 광고와 함께 표시하기로 동의합니다" + @override + String get UG_LINE10 => "6、제공되는 서비스에는 광고가 포함될 수 있으며 사용자는 사용 중 제3자 공급업체, 파트너가 제공하는 광고와 함께 표시하기로 동의합니다"; + /// "7、사용자는 다음과 같은 내용을 작성, 업로드, 복사, 전송하거나 서비스를 이용할 수 없습니다:" + @override + String get UG_LINE11 => "7、사용자는 다음과 같은 내용을 작성, 업로드, 복사, 전송하거나 서비스를 이용할 수 없습니다:"; + /// "(1 )헌법 의 확정 된 기본 원칙 에 반대 하다.;" + @override + String get UG_LINE12 => "(1 )헌법 의 확정 된 기본 원칙 에 반대 하다.;"; + /// "(2)국가 의 안전 을 해치고 국가 의 비밀 을 유출 하여 국가 정권 을 전복시키다 ,국가 통일 파괴;" + @override + String get UG_LINE13 => "(2)국가 의 안전 을 해치고 국가 의 비밀 을 유출 하여 국가 정권 을 전복시키다 ,국가 통일 파괴;"; + /// "(3)국가의 명예와 이익을 해치다;" + @override + String get UG_LINE14 => "(3)국가의 명예와 이익을 해치다;"; + /// "(4)민족 적개심, 민족 차별을 선동하여 민족 단결을 파괴하다;" + @override + String get UG_LINE15 => "(4)민족 적개심, 민족 차별을 선동하여 민족 단결을 파괴하다;"; + /// "(5)국가 종교 정책을 파괴하고 사교와 봉건 미신을 선양하다;" + @override + String get UG_LINE16 => "(5)국가 종교 정책을 파괴하고 사교와 봉건 미신을 선양하다;"; + /// "(6)헛소문을 퍼뜨려 사회 질서를 어지럽히고, 사회 안정을 파괴하다;" + @override + String get UG_LINE17 => "(6)헛소문을 퍼뜨려 사회 질서를 어지럽히고, 사회 안정을 파괴하다;"; + /// "(7)음란, 포르노, 도박, 폭력, 살인, 공포 또는 범죄를 교사하다;" + @override + String get UG_LINE18 => "(7)음란, 포르노, 도박, 폭력, 살인, 공포 또는 범죄를 교사하다;"; + /// "(8)다른 사람을 모욕하거나 비방하며, 타인의 합법적 권익을 침해하다;" + @override + String get UG_LINE19 => "(8)다른 사람을 모욕하거나 비방하며, 타인의 합법적 권익을 침해하다;"; + /// "(9)법과 행정 법규가 금지하는 기타 내용을 포함한 정보" + @override + String get UG_LINE20 => "(9)법과 행정 법규가 금지하는 기타 내용을 포함한 정보"; + /// "8、Qianhai Youlong Technology Co., Ltd.는 그 합리적인 판단에 따라, 관련된 법률적 법규나 본 협약의 약속을 위반하거나, 침해하거나, 그 누구의 권리나 안전을 저해하거나, 위협할 수 있는 내용을 위반하거나, 타인의 행위를 허위로 하는 경우, Qianhai Youlong Technology Co., Ltd.는 합리적으로 판단한다. 위반자 의 멤버 자격 을 종지할 수 없다, 모든 또는 일부 서비스를 막고 법률 법규에 근거하여 관련 정보를 보존하고 관련 부서에 보고하는 등" + @override + String get UG_LINE21 => "8、Qianhai Youlong Technology Co., Ltd.는 그 합리적인 판단에 따라, 관련된 법률적 법규나 본 협약의 약속을 위반하거나, 침해하거나, 그 누구의 권리나 안전을 저해하거나, 위협할 수 있는 내용을 위반하거나, 타인의 행위를 허위로 하는 경우, Qianhai Youlong Technology Co., Ltd.는 합리적으로 판단한다. 위반자 의 멤버 자격 을 종지할 수 없다, 모든 또는 일부 서비스를 막고 법률 법규에 근거하여 관련 정보를 보존하고 관련 부서에 보고하는 등"; + /// "9、사용자 권리 및 의무:" + @override + String get UG_LINE22 => "9、사용자 권리 및 의무:"; + /// "(1 )Qianhai Youlong Technology Co., Ltd. 아이디의 소유권은 Qianhai Youlong Technology Co., Ltd.에게 있으며, 사용자는 등록 요청을 완료한 후 계정의 사용권을 얻게 되며, 이 사용권은 초기 신청 등록인에 속하며, 증여, 차용, 대여 또는 대여를 금지합니다.Qianhai Youlong Technology Co., Ltd.는 운영상 필요에 따라 사용자의 계정을 회수하고 사용자 사진, 동영상, 음성 등을 사용하여 제품 홍보 활동을 할 수 있는 권한을 가지고 있습니다" + @override + String get UG_LINE23 => "(1 )Qianhai Youlong Technology Co., Ltd. 아이디의 소유권은 Qianhai Youlong Technology Co., Ltd.에게 있으며, 사용자는 등록 요청을 완료한 후 계정의 사용권을 얻게 되며, 이 사용권은 초기 신청 등록인에 속하며, 증여, 차용, 대여 또는 대여를 금지합니다.Qianhai Youlong Technology Co., Ltd.는 운영상 필요에 따라 사용자의 계정을 회수하고 사용자 사진, 동영상, 음성 등을 사용하여 제품 홍보 활동을 할 수 있는 권한을 가지고 있습니다"; + /// "(2)사용자는 Qianhai Youlong Technology Co., Ltd..에 있는 개인 자료, 등록 정보 및 전송 내용 등을 변경, 삭제할 권한이 있지만, 해당 정보를 삭제하는 동시에 귀하가 시스템에 저장한 어떤 문자와 그림도 삭제할 수 있다는 점에 유의해야 합니다.사용자가 이 위험을 부담해야 합니다" + @override + String get UG_LINE24 => "(2)사용자는 Qianhai Youlong Technology Co., Ltd..에 있는 개인 자료, 등록 정보 및 전송 내용 등을 변경, 삭제할 권한이 있지만, 해당 정보를 삭제하는 동시에 귀하가 시스템에 저장한 어떤 문자와 그림도 삭제할 수 있다는 점에 유의해야 합니다.사용자가 이 위험을 부담해야 합니다"; + /// "(3)사용자는 등록 계정 정보 및 계정 암호의 보안을 적절하게 보관해야 할 책임이 있으며, 사용자는 등록 계정 그리고 암호 하의 행위에 대해 법적 책임을 져야 합니다.사용자는 어떤 경우에도 다른 구성원의 계정이나 암호를 사용하지 않기로 동의합니다.다른 사람이 당신의 계정이나 비밀번호를 사용하고 있다고 의심했을 때, 당신은 Qianhai Youlong Technology Co., Ltd.에게 즉시 통지하는 것에 동의합니다" + @override + String get UG_LINE25 => "(3)사용자는 등록 계정 정보 및 계정 암호의 보안을 적절하게 보관해야 할 책임이 있으며, 사용자는 등록 계정 그리고 암호 하의 행위에 대해 법적 책임을 져야 합니다.사용자는 어떤 경우에도 다른 구성원의 계정이나 암호를 사용하지 않기로 동의합니다.다른 사람이 당신의 계정이나 비밀번호를 사용하고 있다고 의심했을 때, 당신은 Qianhai Youlong Technology Co., Ltd.에게 즉시 통지하는 것에 동의합니다"; + /// "(4)사용자는 본 협약의 각 조항을 준수하여 본 서비스를 정확하고 적절하게 이용해야 하며, 사용자가 본 협약의 어떤 조항을 위반하였을 경우 Qianhai Youlong Technology Co., Ltd.는 협약에 의거하여 위약 사용자 Qianhai Youlong Technology Co., Ltd. 계정에 대한 서비스를 중지할 권리가 있습니다.아울러 Qianhai Youlong Technology Co., Ltd.는 언제든지 Qianhai Youlong Technology Co., Ltd. 계정, 사용자 이름을 회수할 권리를 보유합니다" + @override + String get UG_LINE26 => "(4)사용자는 본 협약의 각 조항을 준수하여 본 서비스를 정확하고 적절하게 이용해야 하며, 사용자가 본 협약의 어떤 조항을 위반하였을 경우 Qianhai Youlong Technology Co., Ltd.는 협약에 의거하여 위약 사용자 Qianhai Youlong Technology Co., Ltd. 계정에 대한 서비스를 중지할 권리가 있습니다.아울러 Qianhai Youlong Technology Co., Ltd.는 언제든지 Qianhai Youlong Technology Co., Ltd. 계정, 사용자 이름을 회수할 권리를 보유합니다"; + /// "(5)사용자가 자신의 상용 영문 계정을 가지고 있다면, 사용자는 이 영문 계정을 우선적으로 계정으로 등록할 권리가 있지만, 사용자가 서비스에 접속한 후 일정 기간 동안 계정을 등록하지 않았거나, 사용자가 위신 계정으로 등록할 권리가 있지만, 이 영문 계정을 사용하는 것은 아닙니다. 낭비를 초래하지 않도록 이 계정을 회수할 권한이 있으며, 이로 인한 문제는 사용자 스스로 부담합니다" + @override + String get UG_LINE27 => "(5)사용자가 자신의 상용 영문 계정을 가지고 있다면, 사용자는 이 영문 계정을 우선적으로 계정으로 등록할 권리가 있지만, 사용자가 서비스에 접속한 후 일정 기간 동안 계정을 등록하지 않았거나, 사용자가 위신 계정으로 등록할 권리가 있지만, 이 영문 계정을 사용하는 것은 아닙니다. 낭비를 초래하지 않도록 이 계정을 회수할 권한이 있으며, 이로 인한 문제는 사용자 스스로 부담합니다"; + /// "(6)사용자가 계정을 등록한 후 장기간 이 계정에 로그인하지 않으면 Qianhai Youlong Technology Co., Ltd.는 리소스 낭비를 초래하지 않도록 이 계정을 회수할 권한이 있으며, 이로 인한 문제는 사용자 스스로 부담합니다" + @override + String get UG_LINE28 => "(6)사용자가 계정을 등록한 후 장기간 이 계정에 로그인하지 않으면 Qianhai Youlong Technology Co., Ltd.는 리소스 낭비를 초래하지 않도록 이 계정을 회수할 권한이 있으며, 이로 인한 문제는 사용자 스스로 부담합니다"; + /// "(7)사용자 가 발생 한 분쟁 은 고발 기능 유지 사용자 플랫폼 권익 을 사용 할 수 있으며, 만약 사용자 가 신고하여 피드백 을 받을 수 있다면 , 사용자 에게 자발적 으로 알려 주거나 고객 에게 협조 할 의무 가 있다 , 신고 내용 확인 사실이 사실인지, 마스크 공원은 사용자 경고, 계좌 사용 기능 제한 등 사용자 위칙 행위를 구속할 권리가 있다 , 엄중위권자 데이트는 계좌를 직접 동결할 권리가 있고 계좌의 잔액은 반환하지 않는다.계좌가 동결되면, 고객은 고객에게 연락할 수 있다" + @override + String get UG_LINE29 => "(7)사용자 가 발생 한 분쟁 은 고발 기능 유지 사용자 플랫폼 권익 을 사용 할 수 있으며, 만약 사용자 가 신고하여 피드백 을 받을 수 있다면 , 사용자 에게 자발적 으로 알려 주거나 고객 에게 협조 할 의무 가 있다 , 신고 내용 확인 사실이 사실인지, 마스크 공원은 사용자 경고, 계좌 사용 기능 제한 등 사용자 위칙 행위를 구속할 권리가 있다 , 엄중위권자 데이트는 계좌를 직접 동결할 권리가 있고 계좌의 잔액은 반환하지 않는다.계좌가 동결되면, 고객은 고객에게 연락할 수 있다"; + /// "二、프라이버시 보호" + @override + String get UG_LINE30 => "二、프라이버시 보호"; + /// "사용자 동의 개인 프라이버시 정보는 사용자를 개인 식별하거나 개인 통신을 할 수 있는 정보를 말하며 다음을 포함한다. 사용자의 실제 이름, 휴대폰 번호, 위챗 계정, 페이스북 계정, IP 주소.비개인 프라이버시 정보란 본 서비스에 대한 사용자의 조작 상태 및 사용 습관과 같은 일부 명확하고 객관적으로 Qianhai Youlong Technology Co., Ltd. 서버단에 반영되는 기본 기록 정보와 기타 모든 개인의 프라이버시 정보의 범위 밖의 일반 정보를 의미하며, 또한 이용자가 공개에 동의한다.이용자 개인의 프라이버시 정보의 사유성을 존중하는 것은 Qianhai Youlong Technology Co., Ltd.의 일관된 제도이며, Qianhai Youlong Technology Co., Ltd.는 이용자의 개인 프라이버시 정보 보호, 법률 또는 법률에 의한 권한 부여에 관한 정부부처의 요청 또는 사용자의 합리적인 조치를 강구하지 아니한다.그러나, 사용자가 등록할 때 동의를 선택하거나, 사용자와 Qianhai Youlong Technology Co., Ltd. 및 제휴 단위 간에 사용자의 개인 프라이버시 정보의 공개나 별도의 약정이 있는 예외를 사용하면서 사용자는 이로 인해 발생할 수 있는 어떠한 위험도 스스로 부담해야 한다.아울러 Qianhai Youlong Technology Co., Ltd.의 기술 및 서비스를 운영 및 개선하기 위해 Qianhai Youlong Technology Co., Ltd.는 사용자의 비개인 프라이버시 정보를 자체 수집하여 사용하거나 제3자에게 제공하는 데 도움이 될 수 있으며, 이는 Qianhai Youlong Technology Co., Ltd. Limited 사용자들에게 더 나은 서비스를 제공하는 데 도움이 될 것이다.Qianhai Youlong Technology Co., Ltd. 데이터 수집은 사용자와 Qianhai Youlong Technology Co., Ltd.의 인터렉션과 사용자의 선택에 따라 사용자의 프라이버시 설정 그리고 사용자가 사용하는 제품과 기능을 포함한다.Qianhai Youlong Technology Co., Ltd.가 수집한 데이터는 SDK/API/JS 코드 버전, IP 주소, 플랫폼, 타임스탬프, 애플리케이션 식별자, 애플리케이션 배포 채널, 독립 디바이스 식별자, iOS 광고를 포함할 수 있습니다.이는 Qianhai Youlong Technology Co., Ltd.가 내부 데이터 분석과 연구, 제3자 SDK 통계 서비스를 전개하고 Qianhai Youlong Technology Co., Ltd.의 제품 또는 서비스를 개선하는 데 도움이 될 것입니다.사용자의 신원 진실성을 확보하고 사용자에게 더 나은 안전 보장을 제공하기 위해 사용자가 제출해야 하는 신원 정보나 안면 특징과 같은 생체 인식 정보(모두 개인 민감한 정보)는 구체적인 제품 서비스를 완료하는 데 필요하거나 필요한 실제 사용자의 인증에만 사용될 것입니다.사용자가 제공한 . 상기 정보는 사용자가 본 서비스를 사용하는 동안 Qianhai Youlong Technology Co., Ltd.에게 지속적으로 권한을 부여합니다.사용자가 계정을 해지할 때 Qianhai Youlong Technology Co., Ltd.가 사용 중지됩니다.상술한 정보는 중화인민공화국 경내에 저장될 것이다.크로스오버 전송이 필요한 경우, Qianhai Youlong Technology Co., Ltd.는 사용자의 라이선스 동의를 별도로 구합니다.App 사용자 진정성 인증에는 사용자의 신원을 확인할 수 있는 일부 자료가 필요합니다.관련 자료는 플랫폼 심사만을 사용하여 어떠한 다른 사용자에게 공개되거나 상업적 용도로 사용되지 않으며, 법률 또는 관련 부서의 개입 요청만 제외됩니다" + @override + String get UG_LINE31 => "사용자 동의 개인 프라이버시 정보는 사용자를 개인 식별하거나 개인 통신을 할 수 있는 정보를 말하며 다음을 포함한다. 사용자의 실제 이름, 휴대폰 번호, 위챗 계정, 페이스북 계정, IP 주소.비개인 프라이버시 정보란 본 서비스에 대한 사용자의 조작 상태 및 사용 습관과 같은 일부 명확하고 객관적으로 Qianhai Youlong Technology Co., Ltd. 서버단에 반영되는 기본 기록 정보와 기타 모든 개인의 프라이버시 정보의 범위 밖의 일반 정보를 의미하며, 또한 이용자가 공개에 동의한다.이용자 개인의 프라이버시 정보의 사유성을 존중하는 것은 Qianhai Youlong Technology Co., Ltd.의 일관된 제도이며, Qianhai Youlong Technology Co., Ltd.는 이용자의 개인 프라이버시 정보 보호, 법률 또는 법률에 의한 권한 부여에 관한 정부부처의 요청 또는 사용자의 합리적인 조치를 강구하지 아니한다.그러나, 사용자가 등록할 때 동의를 선택하거나, 사용자와 Qianhai Youlong Technology Co., Ltd. 및 제휴 단위 간에 사용자의 개인 프라이버시 정보의 공개나 별도의 약정이 있는 예외를 사용하면서 사용자는 이로 인해 발생할 수 있는 어떠한 위험도 스스로 부담해야 한다.아울러 Qianhai Youlong Technology Co., Ltd.의 기술 및 서비스를 운영 및 개선하기 위해 Qianhai Youlong Technology Co., Ltd.는 사용자의 비개인 프라이버시 정보를 자체 수집하여 사용하거나 제3자에게 제공하는 데 도움이 될 수 있으며, 이는 Qianhai Youlong Technology Co., Ltd. Limited 사용자들에게 더 나은 서비스를 제공하는 데 도움이 될 것이다.Qianhai Youlong Technology Co., Ltd. 데이터 수집은 사용자와 Qianhai Youlong Technology Co., Ltd.의 인터렉션과 사용자의 선택에 따라 사용자의 프라이버시 설정 그리고 사용자가 사용하는 제품과 기능을 포함한다.Qianhai Youlong Technology Co., Ltd.가 수집한 데이터는 SDK/API/JS 코드 버전, IP 주소, 플랫폼, 타임스탬프, 애플리케이션 식별자, 애플리케이션 배포 채널, 독립 디바이스 식별자, iOS 광고를 포함할 수 있습니다.이는 Qianhai Youlong Technology Co., Ltd.가 내부 데이터 분석과 연구, 제3자 SDK 통계 서비스를 전개하고 Qianhai Youlong Technology Co., Ltd.의 제품 또는 서비스를 개선하는 데 도움이 될 것입니다.사용자의 신원 진실성을 확보하고 사용자에게 더 나은 안전 보장을 제공하기 위해 사용자가 제출해야 하는 신원 정보나 안면 특징과 같은 생체 인식 정보(모두 개인 민감한 정보)는 구체적인 제품 서비스를 완료하는 데 필요하거나 필요한 실제 사용자의 인증에만 사용될 것입니다.사용자가 제공한 . 상기 정보는 사용자가 본 서비스를 사용하는 동안 Qianhai Youlong Technology Co., Ltd.에게 지속적으로 권한을 부여합니다.사용자가 계정을 해지할 때 Qianhai Youlong Technology Co., Ltd.가 사용 중지됩니다.상술한 정보는 중화인민공화국 경내에 저장될 것이다.크로스오버 전송이 필요한 경우, Qianhai Youlong Technology Co., Ltd.는 사용자의 라이선스 동의를 별도로 구합니다.App 사용자 진정성 인증에는 사용자의 신원을 확인할 수 있는 일부 자료가 필요합니다.관련 자료는 플랫폼 심사만을 사용하여 어떠한 다른 사용자에게 공개되거나 상업적 용도로 사용되지 않으며, 법률 또는 관련 부서의 개입 요청만 제외됩니다"; + /// "三、 Qianhai Youlong Technology Co., Ltd. 상업 로고 정보" + @override + String get UG_LINE32 => "三、 Qianhai Youlong Technology Co., Ltd. 상업 로고 정보"; + /// "Qianhai Youlong Technology Co., Ltd. 서비스에서 다루는 logo와 같은 그래픽, 문자 또는 그 구성, 그리고 기타 Qianhai Youlong Technology Co., Ltd. 로고 및 제품, 서비스 (이하 이름은 Qianhai Youlong Technology Co., Ltd.라는 상표입니다.)Qianhai Youlong Technology Co., Ltd.의 사전 서면 동의 없이, 사용자는 Qianhai Youlong Technology Co., Ltd. 표시를 어떤 방식으로든 보여지거나 사용하거나 다른 방법으로 처리하거나, 다른 사람에게 당신이 Cyhd를 전시, 사용할 권리가 있음을 나타내지 또는 기타 권한 있는 행위" + @override + String get UG_LINE33 => "Qianhai Youlong Technology Co., Ltd. 서비스에서 다루는 logo와 같은 그래픽, 문자 또는 그 구성, 그리고 기타 Qianhai Youlong Technology Co., Ltd. 로고 및 제품, 서비스 (이하 이름은 Qianhai Youlong Technology Co., Ltd.라는 상표입니다.)Qianhai Youlong Technology Co., Ltd.의 사전 서면 동의 없이, 사용자는 Qianhai Youlong Technology Co., Ltd. 표시를 어떤 방식으로든 보여지거나 사용하거나 다른 방법으로 처리하거나, 다른 사람에게 당신이 Cyhd를 전시, 사용할 권리가 있음을 나타내지 또는 기타 권한 있는 행위"; + /// "四、법적 책임 및 면책" + @override + String get UG_LINE34 => "四、법적 책임 및 면책"; + /// "1、사용자는 본 <합의> 또는 관련된 서비스 약관의 규정을 위반하여 발생하거나 발생한 어떠한 제3자가 주장하는 어떠한 클레임, 요청 또는 손해에 대해서도 합리적인 변호사비를 포함하여 Qianhai Youlong Technology Co., Ltd.와 협력사, 관련 회사를 배상하고 손해를 피하는데 동의합니다" + @override + String get UG_LINE35 => "1、사용자는 본 <합의> 또는 관련된 서비스 약관의 규정을 위반하여 발생하거나 발생한 어떠한 제3자가 주장하는 어떠한 클레임, 요청 또는 손해에 대해서도 합리적인 변호사비를 포함하여 Qianhai Youlong Technology Co., Ltd.와 협력사, 관련 회사를 배상하고 손해를 피하는데 동의합니다"; + /// "2、Qianhai Youlong Technology Co., Ltd.及合作单位不承担责任。사용자가 전기통신 부문과 같은 제3자의 통신회선 고장, 기술 문제, 네트워크, 컴퓨터 고장, 시스템 불안정성 및 기타 여러 가지 불가항력적인 이유로 입은 모든 손실에 대해 Qianhai Youlong Technology Co., Ltd. 및 협력 단위는 책임을 지지 않습니다" + @override + String get UG_LINE36 => "2、Qianhai Youlong Technology Co., Ltd.及合作单位不承担责任。사용자가 전기통신 부문과 같은 제3자의 통신회선 고장, 기술 문제, 네트워크, 컴퓨터 고장, 시스템 불안정성 및 기타 여러 가지 불가항력적인 이유로 입은 모든 손실에 대해 Qianhai Youlong Technology Co., Ltd. 및 협력 단위는 책임을 지지 않습니다"; + /// "3、기술적 고장과 같은 불가항적인 사건으로 서비스의 정상 운영에 영향을 미치는 경우, Qianhai Youlong Technology Co., Ltd. 및 협력 단위는 제1시간 이내에 해당 기관과 협조하여 적시에 처리하고 복구할 것을 약속하지만, 사용자가 이로 인해 입은 모든 손해, Qianhai Youlong Technology Co., Ltd.는 책임을 지지 않습니다" + @override + String get UG_LINE37 => "3、기술적 고장과 같은 불가항적인 사건으로 서비스의 정상 운영에 영향을 미치는 경우, Qianhai Youlong Technology Co., Ltd. 및 협력 단위는 제1시간 이내에 해당 기관과 협조하여 적시에 처리하고 복구할 것을 약속하지만, 사용자가 이로 인해 입은 모든 손해, Qianhai Youlong Technology Co., Ltd.는 책임을 지지 않습니다"; + /// "4、본 서비스는 대부분의 인터넷 서비스와 마찬가지로 이용자의 원인, 인터넷 서비스 품질, 사회 환경 등의 차이에 한정되지 않고, 타인이 이용자의 자료를 이용, 접속하는 경우, 이용자가 접속하는 경우, 이용자의 접속을 저해할 수 있다.이용자는 정보보안 및 이용자 자료의 보호의식을 강화해야 하며, 손해나 스토킹을 당하지 않도록 패스워드 보호 강화에 유의해야 한다" + @override + String get UG_LINE38 => "4、본 서비스는 대부분의 인터넷 서비스와 마찬가지로 이용자의 원인, 인터넷 서비스 품질, 사회 환경 등의 차이에 한정되지 않고, 타인이 이용자의 자료를 이용, 접속하는 경우, 이용자가 접속하는 경우, 이용자의 접속을 저해할 수 있다.이용자는 정보보안 및 이용자 자료의 보호의식을 강화해야 하며, 손해나 스토킹을 당하지 않도록 패스워드 보호 강화에 유의해야 한다"; + /// "5、사용자는 본 서비스 사용은 Internet 서비스에 관련된 것으로 인해 각 세션의 불안정한 요소에 의해 영향을 받을 수 있다는 것을 알아야 합니다.따라서 본 서비스는 불가항력, 컴퓨터 바이러스 또는 해킹, 시스템 불안정, 사용자의 위치, 사용자의 셧다운 그리고 기타 어떤 기술, 인터넷락, 통신회선 원인 등에 의한 서비스 중단 또는 사용자의 요구를 충족하지 못할 리스크가 있습니다.사용자는 위 위험을 감수해야 하며 Qianhai Youlong Technology Co., Ltd.는 보증하지 않습니다.이로 인해 사용자가 읽기 메시지를 보내고 받을 수 없게 되거나 잘못된 메시지를 수신하게 되는 것에 대해 Qianhai Youlong Technology Co., Ltd.는 어떠한 책임도 지지 않습니다" + @override + String get UG_LINE39 => "5、사용자는 본 서비스 사용은 Internet 서비스에 관련된 것으로 인해 각 세션의 불안정한 요소에 의해 영향을 받을 수 있다는 것을 알아야 합니다.따라서 본 서비스는 불가항력, 컴퓨터 바이러스 또는 해킹, 시스템 불안정, 사용자의 위치, 사용자의 셧다운 그리고 기타 어떤 기술, 인터넷락, 통신회선 원인 등에 의한 서비스 중단 또는 사용자의 요구를 충족하지 못할 리스크가 있습니다.사용자는 위 위험을 감수해야 하며 Qianhai Youlong Technology Co., Ltd.는 보증하지 않습니다.이로 인해 사용자가 읽기 메시지를 보내고 받을 수 없게 되거나 잘못된 메시지를 수신하게 되는 것에 대해 Qianhai Youlong Technology Co., Ltd.는 어떠한 책임도 지지 않습니다"; + /// "6、사용자 사용을 알아야 하는 과정에서 본 서비스에는 존재하고 타인의 어떠한 위협적인 비방성을 포함한 것이다.,,거슬린 내용이나 불법 행위나 타인에 대한 권리를 침해하거나()의 지적 재산권을 포함한 정보의 익명성 또는 위험에 대리 가입자 이상을 부담하고 협력사 리스크에 대한 본 Qianhai Youlong Technology Co., Ltd..어떠한 유형의 부당 업무와 상관 없이 명확한 담보나 숨은 정보를 포함, 모든 관계자성, 진실성에 적합하다 이제 특정 용도로 사용하고 있다.아닌 소유권과 특허 침해와 묵시적 담보에 대한 조건으로 이로 인해 부당한 어떠한 불법 이용자에 따른 서비스를 이용하거나 직간접적으로, 우연히, 특수한 피해 및 후속도 책임을 지지 않고 있다" + @override + String get UG_LINE40 => "6、사용자 사용을 알아야 하는 과정에서 본 서비스에는 존재하고 타인의 어떠한 위협적인 비방성을 포함한 것이다.,,거슬린 내용이나 불법 행위나 타인에 대한 권리를 침해하거나()의 지적 재산권을 포함한 정보의 익명성 또는 위험에 대리 가입자 이상을 부담하고 협력사 리스크에 대한 본 Qianhai Youlong Technology Co., Ltd..어떠한 유형의 부당 업무와 상관 없이 명확한 담보나 숨은 정보를 포함, 모든 관계자성, 진실성에 적합하다 이제 특정 용도로 사용하고 있다.아닌 소유권과 특허 침해와 묵시적 담보에 대한 조건으로 이로 인해 부당한 어떠한 불법 이용자에 따른 서비스를 이용하거나 직간접적으로, 우연히, 특수한 피해 및 후속도 책임을 지지 않고 있다"; + /// "7、Qianhai Youlong Technology Co., Ltd.가 정의하는 정보는 문자, 소프트웨어, 음성, 사진, 비디오, 그래프, 광고에서 전체 내용; Qianhai Youlong Technology Co., Ltd.가 사용자들에게 제공하는 상업적 정보, 기타 모든 것들을 저작권으로 보호한다.그래서 사용자는 Qianhai Youlong Technology Co., Ltd.와 광고주의 권한 하에서만 이러한 콘텐츠를 사용할 수 있으며, 이.약간의 내용을 무단으로 복사, 수정, 편찬하거나 콘텐츠와 관련된 파생상품을 창출할 수 없다" + @override + String get UG_LINE41 => "7、Qianhai Youlong Technology Co., Ltd.가 정의하는 정보는 문자, 소프트웨어, 음성, 사진, 비디오, 그래프, 광고에서 전체 내용; Qianhai Youlong Technology Co., Ltd.가 사용자들에게 제공하는 상업적 정보, 기타 모든 것들을 저작권으로 보호한다.그래서 사용자는 Qianhai Youlong Technology Co., Ltd.와 광고주의 권한 하에서만 이러한 콘텐츠를 사용할 수 있으며, 이.약간의 내용을 무단으로 복사, 수정, 편찬하거나 콘텐츠와 관련된 파생상품을 창출할 수 없다"; + /// "8、어떠한 경우에도 Qianhai Youlong Technology Co., Ltd.는 어떠한 간접성, 결과성, 징벌성, 우발적, 특수성 또는 형벌적 피해에 대하여 사용자의 서비스 이용으로 인한 이익손실을 포함하여 책임을 부담한다(예: 이미 고지되었다 하더라도). 본 협약에 상반되는 규정이 포함될 수 있음에도 불구하고, Qianhai Youlong Technology Co., Ltd.가 귀하에게 부과하는 모든 책임은 어떠한 이유로든, 어떤 행위 방식으로든 귀하가 멤버십 기간 동안 서비스를 이용함으로써 Qianhai Youlong Technology Co., Ltd.에게 지불한 비용을 초과하지 않습니다" + @override + String get UG_LINE42 => "8、어떠한 경우에도 Qianhai Youlong Technology Co., Ltd.는 어떠한 간접성, 결과성, 징벌성, 우발적, 특수성 또는 형벌적 피해에 대하여 사용자의 서비스 이용으로 인한 이익손실을 포함하여 책임을 부담한다(예: 이미 고지되었다 하더라도). 본 협약에 상반되는 규정이 포함될 수 있음에도 불구하고, Qianhai Youlong Technology Co., Ltd.가 귀하에게 부과하는 모든 책임은 어떠한 이유로든, 어떤 행위 방식으로든 귀하가 멤버십 기간 동안 서비스를 이용함으로써 Qianhai Youlong Technology Co., Ltd.에게 지불한 비용을 초과하지 않습니다"; + /// "五、회원 약관" + @override + String get UG_LINE43 => "五、회원 약관"; + /// "1、흔호 회원 평등로 회원 권리를 쓸 수 있으며, 또한 Qianhai Youlong Technology Co., Ltd. 의 각종 규범, 규칙을 지켜해야 하며, 이 서비스조항과 사용자협의에 제한되지 않는다" + @override + String get UG_LINE44 => "1、흔호 회원 평등로 회원 권리를 쓸 수 있으며, 또한 Qianhai Youlong Technology Co., Ltd. 의 각종 규범, 규칙을 지켜해야 하며, 이 서비스조항과 사용자협의에 제한되지 않는다"; + /// "2、Qianhai Youlong Technology Co., Ltd. < 사용자 협의 > 위반하면 회원 서비스 중단된 관련 손실은 사용자가 스스로 부담한다 " + @override + String get UG_LINE45 => "2、Qianhai Youlong Technology Co., Ltd. < 사용자 협의 > 위반하면 회원 서비스 중단된 관련 손실은 사용자가 스스로 부담한다 "; + /// "3、회원 은 회원 자격 유효 기간 내에 흔호 회원 의 각종 추가 서비스 를 쓸수 있다 " + @override + String get UG_LINE46 => "3、회원 은 회원 자격 유효 기간 내에 흔호 회원 의 각종 추가 서비스 를 쓸수 있다 "; + /// "4、회원 자격 유효기간 내에 회원 자격 정지나 취소, Qianhai Youlong Technology Co., Ltd. 는 회원 잉여 회원 자격 유효기간에 대한 서비스 비용을 반환하지 않습니다" + @override + String get UG_LINE47 => "4、회원 자격 유효기간 내에 회원 자격 정지나 취소, Qianhai Youlong Technology Co., Ltd. 는 회원 잉여 회원 자격 유효기간에 대한 서비스 비용을 반환하지 않습니다"; + /// "5、회원은 흔호중 전송이랑정보 및 흔호 무료 서비스 또는 요금 서비스를 이용한 법률 책임, 회원은 흔호 서비스, 무료 서비스와 요금 서비스를 포함하는 행위를 포함하여, 모든 법률 법규, 규범, 규범성 서류를 지켜해야 한다" + @override + String get UG_LINE48 => "5、회원은 흔호중 전송이랑정보 및 흔호 무료 서비스 또는 요금 서비스를 이용한 법률 책임, 회원은 흔호 서비스, 무료 서비스와 요금 서비스를 포함하는 행위를 포함하여, 모든 법률 법규, 규범, 규범성 서류를 지켜해야 한다"; + /// "6、회원 서비스가 개통된 후에는 양도 또는 취소를 할 수 없습니다" + @override + String get UG_LINE49 => "6、회원 서비스가 개통된 후에는 양도 또는 취소를 할 수 없습니다"; + /// "7、회원은 Qianhai Youlong Technology Co., Ltd. 무료 서비스 또는 유료 서비스를 이용하면서 법적 법규를 위반하는 행위가 있기 때문에, Qianhai Youlong Technology Co., Ltd.는 해당 회원의 자격을 취소할 권리가 있으며, 그에 대한 보상은 일체가 없이, 그리고 회원은 스스로 책임을 져야 한다" + @override + String get UG_LINE50 => "7、회원은 Qianhai Youlong Technology Co., Ltd. 무료 서비스 또는 유료 서비스를 이용하면서 법적 법규를 위반하는 행위가 있기 때문에, Qianhai Youlong Technology Co., Ltd.는 해당 회원의 자격을 취소할 권리가 있으며, 그에 대한 보상은 일체가 없이, 그리고 회원은 스스로 책임을 져야 한다"; + /// "六、기타 조항" + @override + String get UG_LINE51 => "六、기타 조항"; + /// "1、Qianhai Youlong Technology Co., Ltd. 사용자 주의본 협의에서 Qianhai Youlong Technology Co., Ltd. 책임과 사용자 의무를 강화하는 조항은 사용자가 자세히 읽으십시오. 자율적으로 위험을 고려합니다. 미성년자는 법정 보호자의 배동에서 본 《협의》를 읽어야 한다.이상 각종 조항 내용 의 최종 해석권 및 수정권 은 Qianhai Youlong Technology Co., Ltd. 소유" + @override + String get UG_LINE52 => "1、Qianhai Youlong Technology Co., Ltd. 사용자 주의본 협의에서 Qianhai Youlong Technology Co., Ltd. 책임과 사용자 의무를 강화하는 조항은 사용자가 자세히 읽으십시오. 자율적으로 위험을 고려합니다. 미성년자는 법정 보호자의 배동에서 본 《협의》를 읽어야 한다.이상 각종 조항 내용 의 최종 해석권 및 수정권 은 Qianhai Youlong Technology Co., Ltd. 소유"; + /// "2、본 《협의》 가 정한 무두 조항의 일부나 전부효자 는 다른 조항의 효력 에 영향을 하지 않는다" + @override + String get UG_LINE53 => "2、본 《협의》 가 정한 무두 조항의 일부나 전부효자 는 다른 조항의 효력 에 영향을 하지 않는다"; + /// "3、본 《협의》의 해석, 효력 및 분쟁의 해결, 중화인민공화국 법률에 적용된다. 사용자와 Qianhai Youlong Technology Co., Ltd. 사이의 어떤 분쟁이나 논란이 발생한다면 우선 우호적인 협상이 이루어지지 않는다면, 사용자는 분쟁이나 논란을 제기하거나 논란을 제기할 수 있는 Qianhai Youlong Technology Co., Ltd. 주소 인민법원 관할" + @override + String get UG_LINE54 => "3、본 《협의》의 해석, 효력 및 분쟁의 해결, 중화인민공화국 법률에 적용된다. 사용자와 Qianhai Youlong Technology Co., Ltd. 사이의 어떤 분쟁이나 논란이 발생한다면 우선 우호적인 협상이 이루어지지 않는다면, 사용자는 분쟁이나 논란을 제기하거나 논란을 제기할 수 있는 Qianhai Youlong Technology Co., Ltd. 주소 인민법원 관할"; + /// "4、본 <협의>'의 판권은 Qianhai Youlong Technology Co., Ltd. 모든 해석과 권리 수정이 보유합니다" + @override + String get UG_LINE55 => "4、본 <협의>'의 판권은 Qianhai Youlong Technology Co., Ltd. 모든 해석과 권리 수정이 보유합니다"; + /// "Qianhai Youlong Technology Co., Ltd." + @override + String get UG_LINE56 => "Qianhai Youlong Technology Co., Ltd."; + /// "네트워크 이상하다" + @override + String get net_error => "네트워크 이상하다"; + /// "이름을 입력하세요" + @override + String get enter_name => "이름을 입력하세요"; + /// "번역" + @override + String get translate => "번역"; + /// "위치 " + @override + String get locate => "위치 "; + /// "누르면 녹음하고 놓치면 보내다" + @override + String get voice_tips => "누르면 녹음하고 놓치면 보내다"; + /// "해제" + @override + String get unlock => "해제"; + /// "체팅내용 입력하세요" + @override + String get input_content => "체팅내용 입력하세요"; + /// "연결중…" + @override + String get connecting => "연결중…"; + /// "등록중…" + @override + String get logining => "등록중…"; + /// "/s1 당신의 보기 신청을 거절했다" + @override + String get reject_reply => "/s1 당신의 보기 신청을 거절했다"; + /// "H 돈을 입금한지 3일 안에서 아무도 신고하지 않으면 즉시 환전할 수 있다 (1:1000베트남 동)" + @override + String get warning_text => "H 돈을 입금한지 3일 안에서 아무도 신고하지 않으면 즉시 환전할 수 있다 (1:1000베트남 동)"; + /// "입력한 개수는 /s1 많으면 안된다" + @override + String get more_big => "입력한 개수는 /s1 많으면 안된다"; + /// "입력한 개수는 /s1 적으면 안된다" + @override + String get little_min => "입력한 개수는 /s1 적으면 안된다"; + /// "/s1 통화를 요청합니다" + @override + String get voice_msg => "/s1 통화를 요청합니다"; + /// "당신은 상대방에게 상을 주었다 /s1개 /s2" + @override + String get send_gift => "당신은 상대방에게 상을 주었다 /s1개 /s2"; + /// "상대방이 너에게 상을 주었다 /s1개 /s2" + @override + String get receive_gift => "상대방이 너에게 상을 주었다 /s1개 /s2"; + /// "비회원 신청 못한다" + @override + String get cannot_join => "비회원 신청 못한다"; + /// "반품했다" + @override + String get alreay_back => "반품했다"; + /// "파일이 너무 크다" + @override + String get video_more_big => "파일이 너무 크다"; + /// "무두 선택 " + @override + String get select_all => "무두 선택 "; + /// "다시 연결 " + @override + String get re_connect => "다시 연결 "; + /// "열히면 보내다, 슬라이딩으면 취소하다" + @override + String get voice_tips2 => "열히면 보내다, 슬라이딩으면 취소하다"; + /// "나라" + @override + String get country => "나라"; + /// "사진을 심사중" + @override + String get have_picture_view => "사진을 심사중"; + /// "스피커 방송" + @override + String get speaker_play => "스피커 방송"; + /// "수화기 방송" + @override + String get handset_playback => "수화기 방송"; + /// "수화기 모드" + @override + String get play_model => "수화기 모드"; + /// "암호가 너무 짧음" + @override + String get password_less => "암호가 너무 짧음"; + /// "나이" + @override + String get years_old => "나이"; + /// "익명의 사용자의 제보로,시스템은 당신이 최근 위반행위를 한 것을 확인하였으므로,더 이상 위반을 하지 마십시오.다음이 있는 경우 계정 동결 진행할것이다." + @override + String get coin_returen1 => "익명의 사용자의 제보로,시스템은 당신이 최근 위반행위를 한 것을 확인하였으므로,더 이상 위반을 하지 마십시오.다음이 있는 경우 계정 동결 진행할것이다."; + /// "이미 최신 버전입니다." + @override + String get already_new => "이미 최신 버전입니다."; + /// "즉시 체험" + @override + String get test_it => "즉시 체험"; + /// "새 버전이 발견됨" + @override + String get found_new => "새 버전이 발견됨"; + /// "광고" + @override + String get ad => "광고"; + /// "관심을 가지다" + @override + String get attention => "관심을 가지다"; + /// "팬" + @override + String get fans => "팬"; + /// "/s1 내 자료 페이지 보기 요청." + @override + String get apply_see => "/s1 내 자료 페이지 보기 요청."; + /// "/s1 내 보기 요청을 통과했다." + @override + String get agree_apply => "/s1 내 보기 요청을 통과했다."; + /// "/s1 내 돈봉투 사진을 봤습니다." + @override + String get see_redBag => "/s1 내 돈봉투 사진을 봤습니다."; + /// "상기" + @override + String get notice => "상기"; + /// "휴대폰 설정에서 알림을 받을 수 있도록 알림 권한을 켜십시오." + @override + String get notice_open => "휴대폰 설정에서 알림을 받을 수 있도록 알림 권한을 켜십시오."; + /// "알림 권한이 켜져 있지 않음" + @override + String get open_notice => "알림 권한이 켜져 있지 않음"; + /// "알림 권한이 켜져 있지 않아 알림을 수신할 수 없음" + @override + String get not_open => "알림 권한이 켜져 있지 않아 알림을 수신할 수 없음"; + /// "당신이 인출을 신청한/s1H달러가 반송되었으니, 계좌를 묶는 것이 올바른지 확인하세요." + @override + String get withdraw_fail => "당신이 인출을 신청한/s1H달러가 반송되었으니, 계좌를 묶는 것이 올바른지 확인하세요."; + /// "동태" + @override + String get dynamics => "동태"; + /// "비고" + @override + String get Remark => "비고"; + /// "비고 설치" + @override + String get setRemark => "비고 설치"; + /// "/s1 건 평론" + @override + String get content_num => "/s1 건 평론"; + /// "포인트 태환 획득/s1H화폐" + @override + String get Redeem => "포인트 태환 획득/s1H화폐"; + /// "모바일 저장을 방문 권한이 없음" + @override + String get location_permission => "모바일 저장을 방문 권한이 없음"; + /// "카메라 방문 권한이 없음" + @override + String get camera_permission => "카메라 방문 권한이 없음"; + /// "앨범 방문 권한이 없음" + @override + String get photo_permission => "앨범 방문 권한이 없음"; + /// "마이크를 방문 권한이 없음" + @override + String get video_permission => "마이크를 방문 권한이 없음"; + /// "당신이 보낸 돈봉투는 이미 기한이 지났다." + @override + String get your_redMoney_over => "당신이 보낸 돈봉투는 이미 기한이 지났다."; + /// "상대방이 보낸 돈봉투는 이미 기한이 지났다." + @override + String get other_redMoney_over => "상대방이 보낸 돈봉투는 이미 기한이 지났다."; + /// "뭔가 문제가 생긴 것 같은데…" + @override + String get server_error_tips => "뭔가 문제가 생긴 것 같은데…"; + /// "표정" + @override + String get emoji => "표정"; + /// "오늘 수령 가능/s1 적분에 서명합니다." + @override + String get today_score => "오늘 수령 가능/s1 적분에 서명합니다."; + /// "1. 매일 수령 가능한 포인트에 서명하고, 누적 일수가 많을수록 포인트가 높습니다. \n2.포인트는 H 화폐를 바꿀 수 있습니다. 포인트는 해당 포인트를 사용하므로 신중한 태환. \n3.매월 마지막 날 서명 초기화, 포인트가 적립, 잊지 말고 바로 교환하세요." + @override + String get sign_tips => "1. 매일 수령 가능한 포인트에 서명하고, 누적 일수가 많을수록 포인트가 높습니다. \n2.포인트는 H 화폐를 바꿀 수 있습니다. 포인트는 해당 포인트를 사용하므로 신중한 태환. \n3.매월 마지막 날 서명 초기화, 포인트가 적립, 잊지 말고 바로 교환하세요."; + /// "서명을 하다." + @override + String get sign_in => "서명을 하다."; + /// "내 포인트" + @override + String get my_score => "내 포인트"; + /// "즉시 서명하다." + @override + String get signin_now => "즉시 서명하다."; + /// "누적된 서명/s1일" + @override + String get sign_in_day => "누적된 서명/s1일"; + /// "기환" + @override + String get have_get => "기환"; + /// "스캔" + @override + String get scan => "스캔"; + /// "내 QR 코드" + @override + String get my_qr => "내 QR 코드"; + /// "스캔하고 친구 추가" + @override + String get scan_and_add => "스캔하고 친구 추가"; + /// "구다지도" + @override + String get amap => "구다지도"; + /// "바이두지도" + @override + String get baidumap => "바이두지도"; + /// "구글지도" + @override + String get googlemap => "구글지도"; + /// "애플지도" + @override + String get applemap => "애플지도"; + /// "열다" + @override + String get go_open => "열다"; + /// "미리 보기" + @override + String get Preview => "미리 보기"; + /// "앨범" + @override + String get Photo_album => "앨범"; + /// "모두 사진" + @override + String get all_photo => "모두 사진"; + /// "당신이 /s1 장 사진을 선택했습니다." + @override + String get have_select => "당신이 /s1 장 사진을 선택했습니다."; + /// "로드 중 …" + @override + String get loading => "로드 중 …"; + /// "새로운 채팅 메시지가 있습니다." + @override + String get new_chat_msg => "새로운 채팅 메시지가 있습니다."; + /// "새로운 통화 메시지가 있습니다." + @override + String get new_video_msg => "새로운 통화 메시지가 있습니다."; + /// "/s1친구 되기 신청" + @override + String get apply_friends => "/s1친구 되기 신청"; + /// "/s1은 당신의 친구 요청을 통과했습니다." + @override + String get applyed_friends => "/s1은 당신의 친구 요청을 통과했습니다."; + /// "통신록을 방문할 권한이 없습니다." + @override + String get contact_permission => "통신록을 방문할 권한이 없습니다."; + /// "통신록" + @override + String get contact => "통신록"; + /// "검색" + @override + String get search => "검색"; + /// "통신록의 친구 추가" + @override + String get contact_add => "통신록의 친구 추가"; + /// "발견" + @override + String get find => "발견"; + /// "번역 로봇" + @override + String get translate_robot => "번역 로봇"; + /// "안녕하세요, 번역로봇입니다…" + @override + String get robot_hello => "안녕하세요, 번역로봇입니다…"; + /// "중국어(간체 )" + @override + String get Simplified_Chinese => "중국어(간체 )"; + /// "중국어(번체)" + @override + String get traditional_Chinese => "중국어(번체)"; + /// "영어" + @override + String get english => "영어"; + /// "베드남어" + @override + String get Vietnamese => "베드남어"; + /// "한국어" + @override + String get Korean => "한국어"; + /// "일본어" + @override + String get Japanese => "일본어"; + /// "친구 추가" + @override + String get add_friends => "친구 추가"; + /// "모른 사람" + @override + String get stranger => "모른 사람"; + /// "모른 사람 보낸 메시지를 수신" + @override + String get receive_stranger => "모른 사람 보낸 메시지를 수신"; + /// "SignIn" + @override + String get signin => "SignIn"; + /// "상대방은 낯선 사람이 보낸 소식을 수신하기를 거부하며, 모든 자료를 계속 잠글지 여부를 결정합니다." + @override + String get stranger_close => "상대방은 낯선 사람이 보낸 소식을 수신하기를 거부하며, 모든 자료를 계속 잠글지 여부를 결정합니다."; + /// "추가하다." + @override + String get add => "추가하다."; + /// "추가했다." + @override + String get added => "추가했다."; + /// "상대방은 낯선 사람이 보낸 소식을 수신하기를 거부했다." + @override + String get stranger_close_tips => "상대방은 낯선 사람이 보낸 소식을 수신하기를 거부했다."; + /// "번역에 실패하다." + @override + String get translate_fail => "번역에 실패하다."; + /// "먼저 사진을 업로드하고 돈봉투 사진을 설정하십시오." + @override + String get no_photos => "먼저 사진을 업로드하고 돈봉투 사진을 설정하십시오."; + /// "당신 항소의 평가: /s1 항소에 실패했습니다." + @override + String get successful_appeal1 => "당신 항소의 평가: /s1 항소에 실패했습니다."; + /// "추가 성공, 상대방 동의 대기." + @override + String get add_success => "추가 성공, 상대방 동의 대기."; + /// "다른 사람이 대신 지불하다." + @override + String get other_pay => "다른 사람이 대신 지불하다."; + /// "친구 검증" + @override + String get friend_verification => "친구 검증"; + /// "당신은 이미 검증 신청을 보냈으니, 상대방이 통과할 때까지 기다려라." + @override + String get add_friends_tips => "당신은 이미 검증 신청을 보냈으니, 상대방이 통과할 때까지 기다려라."; + /// "나는/s1" + @override + String get i_am => "나는/s1"; + /// "허락" + @override + String get agree => "허락"; + /// "\"Hi\"는 당신이 <프라이버시 협약>에 동의해야 사용할 수 있다." + @override + String get privacyAgreement => "\"Hi\"는 당신이 <프라이버시 협약>에 동의해야 사용할 수 있다."; + /// "프라이버시 협약" + @override + String get privacy => "프라이버시 협약"; + /// "Hi! 누군가가 너를 친구로 추가하자고 신청했어. 누군지 보세요." + @override + String get notification_addfriend => "Hi! 누군가가 너를 친구로 추가하자고 신청했어. 누군지 보세요."; + /// "얼굴을 마주해야 친구를 추가할 수 있어요" + @override + String get distance_long => "얼굴을 마주해야 친구를 추가할 수 있어요"; + /// "번역 내용의 정확성을 위해서, 간단히 쓰지 마세요." + @override + String get chat_tips => "번역 내용의 정확성을 위해서, 간단히 쓰지 마세요."; + /// "팬 목록" + @override + String get fans_list => "팬 목록"; + /// "기능 내측 중" + @override + String get system_not_open => "기능 내측 중"; + /// "iOS 클라이언트는 현찰 인출을 당분간 지원하지 않으며, 당신은 안드로이드 클라이언트를 사용하여 현금을 인출하거나, 아래 버튼을 클릭하여 인출할 수 있다." + @override + String get service_withdraw_tips => "iOS 클라이언트는 현찰 인출을 당분간 지원하지 않으며, 당신은 안드로이드 클라이언트를 사용하여 현금을 인출하거나, 아래 버튼을 클릭하여 인출할 수 있다."; + /// "현금 인출 클릭" + @override + String get withdraw_tips => "현금 인출 클릭"; + /// "멤버 추가" + @override + String get add_member => "멤버 추가"; + /// "멤버 삭제" + @override + String get delete_member => "멤버 삭제"; + /// "그룹 이름 수정" + @override + String get change_group_name => "그룹 이름 수정"; + /// "이 그룹에 있는 내 닉네임" + @override + String get my_group_nickname => "이 그룹에 있는 내 닉네임"; + /// "그룹 채팅" + @override + String get group_chat => "그룹 채팅"; + /// "그룹 채팅 창건하다." + @override + String get create_group_chat => "그룹 채팅 창건하다."; + /// "너는 상대방이 통과할 때까지 검증 신청을 보내야 한다." + @override + String get added_friends_tips => "너는 상대방이 통과할 때까지 검증 신청을 보내야 한다."; + /// "그룹 채팅 미름" + @override + String get group_chat_name => "그룹 채팅 미름"; + /// "여기서는 당신이 이 그룹에 있는 닉네임을 설정할 수 있으며, 이 닉네임은 이 그룹에만 표시됩니다." + @override + String get my_group_nickname_tips => "여기서는 당신이 이 그룹에 있는 닉네임을 설정할 수 있으며, 이 닉네임은 이 그룹에만 표시됩니다."; + /// "남신 동태" + @override + String get man_gold => "남신 동태"; + /// "여신 동태" + @override + String get woman_gold => "여신 동태"; + /// "새 그롭 주인 선택" + @override + String get choose_group_owner => "새 그롭 주인 선택"; + /// "그롭 공고" + @override + String get group_announcement => "그롭 공고"; + /// "채팅 소식" + @override + String get chat_news => "채팅 소식"; + /// "그롭 코드" + @override + String get group_qr => "그롭 코드"; + /// "그롭 관리" + @override + String get group_setting => "그롭 관리"; + /// "메시지 알림 비활성화" + @override + String get close_news_notice => "메시지 알림 비활성화"; + /// "맨 위에 고정" + @override + String get set_chat_top => "맨 위에 고정"; + /// "그룹 멤버의 닉네임을 표시합니다" + @override + String get show_group_member_name => "그룹 멤버의 닉네임을 표시합니다"; + /// "탈퇴 후 그롭 채팅 중 다른 멤버에게 통보하지 않으며, 더 이상 이 그롭 채팅 소식을 받지 않는다." + @override + String get quit_group_tips => "탈퇴 후 그롭 채팅 중 다른 멤버에게 통보하지 않으며, 더 이상 이 그롭 채팅 소식을 받지 않는다."; + /// "삭제 후 종료" + @override + String get quit_and_delete => "삭제 후 종료"; + /// "멤버 더 보기 " + @override + String get show_more_member => "멤버 더 보기 "; + /// "그롭 채팅 요청 확인" + @override + String get group_invite => "그롭 채팅 요청 확인"; + /// "그롭 주인 관리권 양도" + @override + String get change_group_owner => "그롭 주인 관리권 양도"; + /// "부팅 후, 그룹 멤버는 그룹 소유자가 확인해야 친구를 그룹에 초대할 수 있습니다. 코드로 그롭 들어가는 것은 동시에 중지될 것이다." + @override + String get group_setting_tips => "부팅 후, 그룹 멤버는 그룹 소유자가 확인해야 친구를 그룹에 초대할 수 있습니다. 코드로 그롭 들어가는 것은 동시에 중지될 것이다."; + /// "요청 상세" + @override + String get invite_detail => "요청 상세"; + /// "이름 없다" + @override + String get undefine_name => "이름 없다"; + /// "그롭 코드 명함" + @override + String get group_qr_code => "그롭 코드 명함"; + /// "이 코드는 7일 이내(/s1월/s2일 전) 유효하며 재진입이 갱신됨" + @override + String get group_qr_code_tips => "이 코드는 7일 이내(/s1월/s2일 전) 유효하며 재진입이 갱신됨"; + /// "여신 인기" + @override + String get Goddess_heat => "여신 인기"; + /// "누적 수확의 선물" + @override + String get Goddess_heat_tips => "누적 수확의 선물"; + /// "새 친구" + @override + String get new_friends => "새 친구"; + /// "3일 전" + @override + String get before_three_day => "3일 전"; + /// "근 3일" + @override + String get after_three_day => "근 3일"; + /// "채팅 기록 지우기" + @override + String get group_clean_chat_record => "채팅 기록 지우기"; + /// "보기" + @override + String get check => "보기"; + /// "당신을 친구로 추가해 달라고 요청했습니다" + @override + String get apply_fro_friends => "당신을 친구로 추가해 달라고 요청했습니다"; + /// "비회원은 현금을 인출할 수 없다." + @override + String get no_vip_cannot_withdraw => "비회원은 현금을 인출할 수 없다."; + /// "이 사용자는 인증되지 않았으므로, 속지 않도록 주의한다." + @override + String get not_true_woman => "이 사용자는 인증되지 않았으므로, 속지 않도록 주의한다."; + /// "그롭 채팅 가입" + @override + String get join_group => "그롭 채팅 가입"; + /// "Apple로 등록" + @override + String get sign_in_apple => "Apple로 등록"; + /// "그룹 소유자만 그룹 게시를 편집할 수 있습니다." + @override + String get only_host => "그룹 소유자만 그룹 게시를 편집할 수 있습니다."; + /// "당신은 상대방에게/s1개의 선물을 주고 받았다" + @override + String get send_gift1 => "당신은 상대방에게/s1개의 선물을 주고 받았다"; + /// "상대방이 널/s 1개의 선물에 매겼어요." + @override + String get receive_gift1 => "상대방이 널/s 1개의 선물에 매겼어요."; + /// "당신은 이미 이 그롭에 있지 않다." + @override + String get not_in_group => "당신은 이미 이 그롭에 있지 않다."; + /// "만드는 중이니 잠시 기다려 주세요" + @override + String get creating_group => "만드는 중이니 잠시 기다려 주세요"; + /// "건" + @override + String get article => "건"; + /// "이 그롭은 이미 코드 검증을 시작했으며 요청을 통해서만 그롭에 들어갈 수 있습니다." + @override + String get group_open_verification => "이 그롭은 이미 코드 검증을 시작했으며 요청을 통해서만 그롭에 들어갈 수 있습니다."; + /// "그롭 멤버" + @override + String get group_memeber => "그롭 멤버"; + /// "초대/s1명의 친구를 그롭 채팅에 가입시키다" + @override + String get invite_members => "초대/s1명의 친구를 그롭 채팅에 가입시키다"; + /// "총/s1명" + @override + String get total_members => "총/s1명"; + /// "코드 유한기 지났다." + @override + String get qr_outtime => "코드 유한기 지났다."; + /// "이 그룹 메시지 없음" + @override + String get no_goupr_info => "이 그룹 메시지 없음"; + /// "당신이 /s1가 그롭 초청하여 그롭 채팅에 가입하게 했다." + @override + String get you_invite => "당신이 /s1가 그롭 초청하여 그롭 채팅에 가입하게 했다."; + /// "당신은 /s1에 의해 그롭 채팅에 끌려들어갔어요." + @override + String get invite_you => "당신은 /s1에 의해 그롭 채팅에 끌려들어갔어요."; + /// " /s1가 /s2를 그롭 초청하여 그롭 채팅에 가입하게 했다." + @override + String get invite_someone => " /s1가 /s2를 그롭 초청하여 그롭 채팅에 가입하게 했다."; + /// "당신" + @override + String get you => "당신"; + /// " /s1 를 /s2 그롭 채팅으로 나가 시켰다." + @override + String get delete_group => " /s1 를 /s2 그롭 채팅으로 나가 시켰다."; + /// "당신이 새 그롭 주인 되었다." + @override + String get you_group_owner => "당신이 새 그롭 주인 되었다."; + /// "/s1새 그롭 주인 되었다." + @override + String get someone_group_owner => "/s1새 그롭 주인 되었다."; + /// "그롭 이름은 /s1로 변경했다." + @override + String get change_group_owner1 => "그롭 이름은 /s1로 변경했다."; + /// "그롭 공지가 업데이트 되었습니다" + @override + String get update_group_announce => "그롭 공지가 업데이트 되었습니다"; + /// "당신은 스캔 코드를 통해 그롭 채팅에 가입한다." + @override + String get you_qr => "당신은 스캔 코드를 통해 그롭 채팅에 가입한다."; + /// "/s1스캔 코드를 통해 그롭 채팅에 가입한다." + @override + String get others_qr => "/s1스캔 코드를 통해 그롭 채팅에 가입한다."; + /// "\"/s1\" 초대/s2명 친구 그롭 가입하고 싶다. \$확인하세요.\$ " + @override + String get invite_confirm => "\"/s1\" 초대/s2명 친구 그롭 가입하고 싶다. \$확인하세요.\$ "; + /// " \"/s1\" 초데\"/s2\" 그롭 채팅 가입하고 싶다. " + @override + String get want_invite_confirm => " \"/s1\" 초데\"/s2\" 그롭 채팅 가입하고 싶다. "; + /// "\"/s1\" 그롭 채팅 가입 확인 되었다." + @override + String get join_group_confirm => "\"/s1\" 그롭 채팅 가입 확인 되었다."; + /// "당신은 /s1에 군담에 끌려들어갔다. " + @override + String get you_invite_gourp => "당신은 /s1에 군담에 끌려들어갔다. "; + /// " \"/s1\" 그롭 채팅 가입 " + @override + String get someone_join_group => " \"/s1\" 그롭 채팅 가입 "; + /// "그룹 소유자가 이미\"그룹 채팅 요청 확인\",을(를) 열어서, 그룹 멤버가 그룹 소유자가 확인해야 친구를 그룹에 초대할 수 있습니다." + @override + String get group_setting_tips1 => "그룹 소유자가 이미\"그룹 채팅 요청 확인\",을(를) 열어서, 그룹 멤버가 그룹 소유자가 확인해야 친구를 그룹에 초대할 수 있습니다."; + /// "그롭 소유자는 이미 암묵적인 그롭에 들어가는 방식을 회복하였다." + @override + String get group_setting_tips2 => "그롭 소유자는 이미 암묵적인 그롭에 들어가는 방식을 회복하였다."; + /// "그롭 멤버 더 추가할 수 없다." + @override + String get members_max => "그롭 멤버 더 추가할 수 없다."; + /// "그롭 수가 상한에 도달했습니다." + @override + String get group_max => "그롭 수가 상한에 도달했습니다."; + /// "내 계산서" + @override + String get my_money_info => "내 계산서"; + /// "내 잔고" + @override + String get my_left_money => "내 잔고"; + /// "H화폐는 충전이나 환전으로 얻을 수 있고 현금인출이 불가능합니다." + @override + String get money_tips => "H화폐는 충전이나 환전으로 얻을 수 있고 현금인출이 불가능합니다."; + /// "소득명세" + @override + String get get_money_detail => "소득명세"; + /// "Hibox소득" + @override + String get hibok_money => "Hibox소득"; + /// "H화폐 교환" + @override + String get charge_h => "H화폐 교환"; + /// "인출 규칙" + @override + String get charge_tips => "인출 규칙"; + /// "많은 편화 위치 改편리한 위치 변환" + @override + String get splash_tips1 => "많은 편화 위치 改편리한 위치 변환"; + /// "번역 로봇" + @override + String get splash_tips2 => "번역 로봇"; + /// "친구 사귀기 앱" + @override + String get splash_tips3 => "친구 사귀기 앱"; + /// "많은 편화 여신 改편리한 이성 변환" + @override + String get splash_tips_content1 => "많은 편화 여신 改편리한 이성 변환"; + /// "음성 인터랙티브" + @override + String get splash_tips_content2 => "음성 인터랙티브"; + /// "해결 언어 문제" + @override + String get splash_tips_content3 => "해결 언어 문제"; + /// "즉시 채험" + @override + String get splash_go => "즉시 채험"; + /// "당신은 수입에 통했고/s1H화폐 교환됐다." + @override + String get change_h_coin => "당신은 수입에 통했고/s1H화폐 교환됐다."; + /// "당신의 진술이 성공하여 시스템이 환불되었습니다." + @override + String get Representation_succes => "당신의 진술이 성공하여 시스템이 환불되었습니다."; + /// "시스템 증정" + @override + String get system_give => "시스템 증정"; + /// "당신의 인출 신청이 실패하여, 반송되었습니다." + @override + String get exchange_fail => "당신의 인출 신청이 실패하여, 반송되었습니다."; + /// "Hibox를 통해 환전/s1H화폐" + @override + String get hibok_exchange => "Hibox를 통해 환전/s1H화폐"; + /// "성공적으로 초대 코드를 묶음" + @override + String get bind_code_success => "성공적으로 초대 코드를 묶음"; + /// "당신은/s1H화폐를 소모해서 인공번역을 합니다." + @override + String get translate_money => "당신은/s1H화폐를 소모해서 인공번역을 합니다."; + /// "시스템 취소 반송" + @override + String get system_back => "시스템 취소 반송"; + /// "당신은 상대방에게 상을 주었다." + @override + String get you_give => "당신은 상대방에게 상을 주었다."; + /// "상대방이 당신에게 상을 주었다." + @override + String get you_get => "상대방이 당신에게 상을 주었다."; + /// "환전 금액(단위 K)" + @override + String get enter_num_qian => "환전 금액(단위 K)"; + /// "인출 금액(단위K)" + @override + String get enter_num_qian1 => "인출 금액(단위K)"; + /// "翻译券" + @override + String get daily_translate_voucher => "翻译券"; + /// "通知消息" + @override + String get msg_notice => "通知消息"; + /// "选择提醒的人" + @override + String get select_notice_people => "选择提醒的人"; + /// "查找手机号" + @override + String get search_phone => "查找手机号"; + /// "用户不存在" + @override + String get not_have_user => "用户不存在"; + /// "对方已拉黑了你" + @override + String get you_are_blaklisted => "对方已拉黑了你"; + /// "确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)" + @override + String get confrim_recovery => "确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)"; + /// "發送到" + @override + String get send_to => "發送到"; + + @override + TextDirection get textDirection => TextDirection.ltr; +} + +class _I18n_ja_JP extends I18n { + const _I18n_ja_JP(); + + /// " Hi公園" + @override + String get appName => " Hi公園"; + /// "登録" + @override + String get login => "登録"; + /// "新規取得" + @override + String get registration => "新規取得"; + /// "他の登録" + @override + String get other_login => "他の登録"; + /// "アカウント" + @override + String get account => "アカウント"; + /// "アカウントを入力してください" + @override + String get enter_username => "アカウントを入力してください"; + /// "パスワード" + @override + String get password => "パスワード"; + /// "パスワードを入力してください" + @override + String get enter_password => "パスワードを入力してください"; + /// "パスワードを忘れた" + @override + String get forget_password => "パスワードを忘れた"; + /// "パスワードをリセットする" + @override + String get reset_password => "パスワードをリセットする"; + /// "携帯番号で新規取得" + @override + String get number_registration => "携帯番号で新規取得"; + /// "携帯番号を入力してください" + @override + String get enter_number => "携帯番号を入力してください"; + /// "検証コード" + @override + String get code => "検証コード"; + /// "受け取った検証コードを入力してください" + @override + String get enter_code => "受け取った検証コードを入力してください"; + /// "検証コードを送信する" + @override + String get send_code => "検証コードを送信する"; + /// "再送する" + @override + String get send_again => "再送する"; + /// "パスワードを設定する" + @override + String get set_password => "パスワードを設定する"; + /// "パスワードは少なくても6桁に設定する" + @override + String get password_limit => "パスワードは少なくても6桁に設定する"; + /// "登録パスワードを設定してください" + @override + String get set_password2 => "登録パスワードを設定してください"; + /// "次へ" + @override + String get next_step => "次へ"; + /// "クリックすると、《ユーザー協議》を読んで同意したことになります" + @override + String get agreed_agreement => "クリックすると、《ユーザー協議》を読んで同意したことになります"; + /// "パスワードを入力してください" + @override + String get enter_password2 => "パスワードを入力してください"; + /// "すぐリセット" + @override + String get reset_now => "すぐリセット"; + /// "性別を選択" + @override + String get choose_gender => "性別を選択"; + /// "あなたは..." + @override + String get who => "あなたは..."; + /// "確定" + @override + String get determine => "確定"; + /// "性別を選択後変更できません" + @override + String get cannot_modified => "性別を選択後変更できません"; + /// "ヒント" + @override + String get tip => "ヒント"; + /// "あなたは間もなく新規取得完成しますが、今ログアウトしますか?" + @override + String get choose_quit => "あなたは間もなく新規取得完成しますが、今ログアウトしますか?"; + /// "確認" + @override + String get confirm => "確認"; + /// "使用" + @override + String get use => "使用"; + /// "キャンセル" + @override + String get cancel => "キャンセル"; + /// "閉じる" + @override + String get close => "閉じる"; + /// "削除" + @override + String get delete => "削除"; + /// "やめる" + @override + String get forget_it => "やめる"; + /// " OK " + @override + String get ok => " OK "; + /// "登録後に性別を変更することはできません、確定ですか?" + @override + String get choose_quit2 => "登録後に性別を変更することはできません、確定ですか?"; + /// "ヒント:同性別のユーザとのコミュニケーションすることができません" + @override + String get tip_content => "ヒント:同性別のユーザとのコミュニケーションすることができません"; + /// "ようこそ" + @override + String get welcome => "ようこそ"; + /// "招待コードを入力してください" + @override + String get enter_incode => "招待コードを入力してください"; + /// " Hiは招待コードを持つ男性のみにサービスを提供しています" + @override + String get must_incode => " Hiは招待コードを持つ男性のみにサービスを提供しています"; + /// "あなたの招待コード" + @override + String get your_incode => "あなたの招待コード"; + /// "招待コードがないですか?以下の方法で入手できます" + @override + String get how_get => "招待コードがないですか?以下の方法で入手できます"; + /// "方法1" + @override + String get method1 => "方法1"; + /// "無料申請" + @override + String get free => "無料申請"; + /// "すぐ申請" + @override + String get apply_now => "すぐ申請"; + /// "招待コードを査収してください" + @override + String get check_incode => "招待コードを査収してください"; + /// "個人情報を記入して、審査した後招待コードを送ります" + @override + String get so_get => "個人情報を記入して、審査した後招待コードを送ります"; + /// "招待コードを申請する" + @override + String get apply_incode => "招待コードを申請する"; + /// "所在地" + @override + String get location => "所在地"; + /// "あなたいる都市の名前" + @override + String get cityname => "あなたいる都市の名前"; + /// "情報ルート" + @override + String get message_channel => "情報ルート"; + /// "どこからこのAPPを知っていますか" + @override + String get how_know => "どこからこのAPPを知っていますか"; + /// "ウィーチャットID " + @override + String get wechat_number => "ウィーチャットID "; + /// "あなたのウィーチャットID " + @override + String get your_wechat => "あなたのウィーチャットID "; + /// "フェイスブック" + @override + String get facebook => "フェイスブック"; + /// "あなたのフェイスブック" + @override + String get your_facebook => "あなたのフェイスブック"; + /// "申請を提出します" + @override + String get submit_application => "申請を提出します"; + /// "あなたにいる都市を入力してください" + @override + String get enter_city => "あなたにいる都市を入力してください"; + /// " APPを獲得ルートを教えてください" + @override + String get so_know => " APPを獲得ルートを教えてください"; + /// "あなたのSNSアカウントを教えてください" + @override + String get your_social => "あなたのSNSアカウントを教えてください"; + /// "あなたの申請を出来るだけ早く処理します、もし審査に合格したらメッセージセンターで私たちが送った招待コードを受け取ります" + @override + String get receive_incode => "あなたの申請を出来るだけ早く処理します、もし審査に合格したらメッセージセンターで私たちが送った招待コードを受け取ります"; + /// "招待コードはまだ発行されていませんので、暫くお待ちください!" + @override + String get wait_incode => "招待コードはまだ発行されていませんので、暫くお待ちください!"; + /// "申し込み成功" + @override + String get successful_application1 => "申し込み成功"; + /// "レビューに失敗しました" + @override + String get application_failed1 => "レビューに失敗しました"; + /// "コピー成功" + @override + String get successful_copy => "コピー成功"; + /// "方法2" + @override + String get method2 => "方法2"; + /// " VIPになり" + @override + String get joinvip => " VIPになり"; + /// "すぐ加入する" + @override + String get join_now => "すぐ加入する"; + /// "加入しました" + @override + String get joined => "加入しました"; + /// " VIPになるとさまざまな特権があります、招待コードなしでの登録を含めます" + @override + String get join_odds => " VIPになるとさまざまな特権があります、招待コードなしでの登録を含めます"; + /// "あなたはまだVIPになっていません" + @override + String get not_joinvip => "あなたはまだVIPになっていません"; + /// " VIPになったら、招待コードなしで登録できます" + @override + String get join_after => " VIPになったら、招待コードなしで登録できます"; + /// "招待コードの認証をパスしました" + @override + String get incode_passed => "招待コードの認証をパスしました"; + /// "いらっしゃいませ、あなたのアカウントを他人に漏らさないでください。登録異常が発見されたら、アカウントは自動的に凍結されます" + @override + String get welcome_join => "いらっしゃいませ、あなたのアカウントを他人に漏らさないでください。登録異常が発見されたら、アカウントは自動的に凍結されます"; + /// " VIPセンター" + @override + String get member_centre => " VIPセンター"; + /// " VIP特権" + @override + String get members_privilege => " VIP特権"; + /// "もっと見える" + @override + String get see_more => "もっと見える"; + /// "毎日無制限でユーザを見えます" + @override + String get unlimited_see => "毎日無制限でユーザを見えます"; + /// "もっと節約で見る" + @override + String get see_cheaper => "もっと節約で見る"; + /// "毎日/s1回のチャンスで有料アルバム或いはSNSアカウントを閲覧できます" + @override + String get free10 => "毎日/s1回のチャンスで有料アルバム或いはSNSアカウントを閲覧できます"; + /// "もっと長く見えます" + @override + String get see_longer => "もっと長く見えます"; + /// "写真閲覧後焼却の時間が2秒から/s1に上げます" + @override + String get towto6 => "写真閲覧後焼却の時間が2秒から/s1に上げます"; + /// "もっと気持ち良く見える" + @override + String get see_better => "もっと気持ち良く見える"; + /// "デート放送無料発表" + @override + String get free_release => "デート放送無料発表"; + /// "コースを選択してください" + @override + String get choose_price => "コースを選択してください"; + /// "支払い方法" + @override + String get pay_method => "支払い方法"; + /// "支払い金額" + @override + String get pay_amount => "支払い金額"; + /// "残高が足りない" + @override + String get not_enough => "残高が足りない"; + /// "支払い確認" + @override + String get confirm_pay => "支払い確認"; + /// "資料を完備する" + @override + String get complete_material => "資料を完備する"; + /// "基本資料" + @override + String get basic_information => "基本資料"; + /// "アバターをアップロッド" + @override + String get upload_avatar => "アバターをアップロッド"; + /// "選択してください" + @override + String get choose => "選択してください"; + /// "入力してください" + @override + String get fill_out => "入力してください"; + /// "複数の選択肢" + @override + String get choose_multiple => "複数の選択肢"; + /// "オプショナル" + @override + String get optional => "オプショナル"; + /// "少なくても/sl個を入力してください" + @override + String get least => "少なくても/sl個を入力してください"; + /// "自己紹介してください" + @override + String get introduce_yourself => "自己紹介してください"; + /// "多くても/sl個を選んでください" + @override + String get most => "多くても/sl個を選んでください"; + /// "ニックネーム" + @override + String get nickname => "ニックネーム"; + /// "ニックネームは1~20文字のみです" + @override + String get only1_8 => "ニックネームは1~20文字のみです"; + /// "現在の都市" + @override + String get Resident_city => "現在の都市"; + /// "現在の都市を選択してください" + @override + String get Please_select_a_resident_city => "現在の都市を選択してください"; + /// "芹苴" + @override + String get City1 => "芹苴"; + /// "岘港" + @override + String get City2 => "岘港"; + /// "海防" + @override + String get City3 => "海防"; + /// "河内" + @override + String get City4 => "河内"; + /// "胡志明" + @override + String get City5 => "胡志明"; + /// "安江" + @override + String get City6 => "安江"; + /// "北江" + @override + String get City7 => "北江"; + /// "北件" + @override + String get City8 => "北件"; + /// "薄辽" + @override + String get City9 => "薄辽"; + /// "北宁" + @override + String get City10 => "北宁"; + /// "巴地头顿" + @override + String get City11 => "巴地头顿"; + /// "槟椥" + @override + String get City12 => "槟椥"; + /// "平定" + @override + String get City13 => "平定"; + /// "平陽" + @override + String get City14 => "平陽"; + /// "平福" + @override + String get City15 => "平福"; + /// "平順" + @override + String get City16 => "平順"; + /// "金瓯" + @override + String get City17 => "金瓯"; + /// "高平" + @override + String get City18 => "高平"; + /// "得楽" + @override + String get City19 => "得楽"; + /// "得农" + @override + String get City20 => "得农"; + /// "奠边" + @override + String get City21 => "奠边"; + /// "同奈" + @override + String get City22 => "同奈"; + /// "同塔" + @override + String get City23 => "同塔"; + /// "嘉莱" + @override + String get City24 => "嘉莱"; + /// "河江" + @override + String get City25 => "河江"; + /// "海陽" + @override + String get City26 => "海陽"; + /// "河南" + @override + String get City27 => "河南"; + /// "河静" + @override + String get City28 => "河静"; + /// "和平" + @override + String get City29 => "和平"; + /// "後江" + @override + String get City30 => "後江"; + /// "興安" + @override + String get City31 => "興安"; + /// "庆和" + @override + String get City32 => "庆和"; + /// "坚江" + @override + String get City33 => "坚江"; + /// "昆嵩" + @override + String get City34 => "昆嵩"; + /// "莱州" + @override + String get City35 => "莱州"; + /// "林同" + @override + String get City36 => "林同"; + /// "谅山" + @override + String get City37 => "谅山"; + /// "老街" + @override + String get City38 => "老街"; + /// "隆安" + @override + String get City39 => "隆安"; + /// "乂安" + @override + String get City40 => "乂安"; + /// "寧平" + @override + String get City41 => "寧平"; + /// "寧顺" + @override + String get City42 => "寧顺"; + /// "富寿" + @override + String get City43 => "富寿"; + /// "富安" + @override + String get City44 => "富安"; + /// "広平" + @override + String get City45 => "広平"; + /// "広南" + @override + String get City46 => "広南"; + /// "広義" + @override + String get City47 => "広義"; + /// "広寧" + @override + String get City48 => "広寧"; + /// "広治" + @override + String get City49 => "広治"; + /// "朔庄" + @override + String get City50 => "朔庄"; + /// "山羅" + @override + String get City51 => "山羅"; + /// "西寧" + @override + String get City52 => "西寧"; + /// "太平" + @override + String get City53 => "太平"; + /// "太原" + @override + String get City54 => "太原"; + /// "清化" + @override + String get City55 => "清化"; + /// "承天順化" + @override + String get City56 => "承天順化"; + /// "前江" + @override + String get City57 => "前江"; + /// "茶荣" + @override + String get City58 => "茶荣"; + /// "宣光" + @override + String get City59 => "宣光"; + /// "永隆" + @override + String get City60 => "永隆"; + /// "永富" + @override + String get City61 => "永富"; + /// "安沛" + @override + String get City62 => "安沛"; + /// "南定" + @override + String get City63 => "南定"; + /// "誕生日" + @override + String get birthday => "誕生日"; + /// "誕生日を選んでください" + @override + String get choose_birthday => "誕生日を選んでください"; + /// "年" + @override + String get year => "年"; + /// "月" + @override + String get month => "月"; + /// "日" + @override + String get day => "日"; + /// "時" + @override + String get hour => "時"; + /// "分" + @override + String get minute => "分"; + /// "秒" + @override + String get second => "秒"; + /// "たった今" + @override + String get just => "たった今"; + /// "/s1分前" + @override + String get minute_ago => "/s1分前"; + /// "/s1時間前" + @override + String get hour_ago => "/s1時間前"; + /// "/s1日前" + @override + String get day_ago => "/s1日前"; + /// "/s1週間前" + @override + String get week_ago => "/s1週間前"; + /// "/s1ヶ月前" + @override + String get month_ago => "/s1ヶ月前"; + /// "午前" + @override + String get morning => "午前"; + /// "昼ごろ" + @override + String get noon => "昼ごろ"; + /// "午後" + @override + String get afternoon => "午後"; + /// "夜" + @override + String get night => "夜"; + /// "一日中" + @override + String get all_day => "一日中"; + /// "昨日" + @override + String get yesterday => "昨日"; + /// "一昨日" + @override + String get two_yesterday => "一昨日"; + /// "徹夜" + @override + String get overnight => "徹夜"; + /// "一桁" + @override + String get one => "一桁"; + /// "十" + @override + String get ten => "十"; + /// "百" + @override + String get hundred => "百"; + /// "千" + @override + String get thousand => "千"; + /// "万" + @override + String get ten_thousand => "万"; + /// "おひつじ座" + @override + String get aries => "おひつじ座"; + /// "おうし座" + @override + String get taurus => "おうし座"; + /// "ふたご座" + @override + String get gemini => "ふたご座"; + /// "かに座" + @override + String get cancer => "かに座"; + /// "しし座" + @override + String get leo => "しし座"; + /// "おとめ座" + @override + String get virgo => "おとめ座"; + /// "てんびん座" + @override + String get libra => "てんびん座"; + /// "さそり座" + @override + String get scorpio => "さそり座"; + /// "いて座" + @override + String get sagittarius => "いて座"; + /// "やぎ座" + @override + String get capricorn => "やぎ座"; + /// "みずがめ座" + @override + String get aquarius => "みずがめ座"; + /// "うお座" + @override + String get pisces => "うお座"; + /// "月曜日" + @override + String get monday => "月曜日"; + /// "火曜日" + @override + String get tuesday => "火曜日"; + /// "水曜日" + @override + String get wednesday => "水曜日"; + /// "木曜日" + @override + String get thursday => "木曜日"; + /// "金曜日" + @override + String get friday => "金曜日"; + /// "土曜日" + @override + String get saturday => "土曜日"; + /// "日曜日" + @override + String get sunday => "日曜日"; + /// "職業" + @override + String get job => "職業"; + /// "職業を選択ください" + @override + String get choose_career => "職業を選択ください"; + /// "インフォメーション" + @override + String get career1 => "インフォメーション"; + /// "インターネット" + @override + String get career2 => "インターネット"; + /// " IT " + @override + String get career3 => " IT "; + /// "電信運行" + @override + String get career4 => "電信運行"; + /// "ネットゲーム" + @override + String get career5 => "ネットゲーム"; + /// "金融保険" + @override + String get career6 => "金融保険"; + /// "投資" + @override + String get career7 => "投資"; + /// "株式ファンド" + @override + String get career8 => "株式ファンド"; + /// "保険" + @override + String get career9 => "保険"; + /// "銀行" + @override + String get career10 => "銀行"; + /// "信託保証" + @override + String get career11 => "信託保証"; + /// "ビジネスサービス" + @override + String get career12 => "ビジネスサービス"; + /// "相談" + @override + String get career13 => "相談"; + /// "自営業" + @override + String get career14 => "自営業"; + /// "美容、美髪" + @override + String get career15 => "美容、美髪"; + /// "旅行" + @override + String get career16 => "旅行"; + /// "ホテル飲食" + @override + String get career17 => "ホテル飲食"; + /// "レクリエーション" + @override + String get career18 => "レクリエーション"; + /// "貿易" + @override + String get career19 => "貿易"; + /// "汽車" + @override + String get career20 => "汽車"; + /// "不動産" + @override + String get career21 => "不動産"; + /// "不動産管理" + @override + String get career22 => "不動産管理"; + /// "内装、表装" + @override + String get career23 => "内装、表装"; + /// "探偵" + @override + String get career24 => "探偵"; + /// "工程製造" + @override + String get career25 => "工程製造"; + /// "建築" + @override + String get career26 => "建築"; + /// "土木建築工事" + @override + String get career27 => "土木建築工事"; + /// "機械製造" + @override + String get career28 => "機械製造"; + /// "電子" + @override + String get career29 => "電子"; + /// "生物医学" + @override + String get career30 => "生物医学"; + /// "食品" + @override + String get career31 => "食品"; + /// "服装" + @override + String get career32 => "服装"; + /// "エネルギー" + @override + String get career33 => "エネルギー"; + /// "交通運輸" + @override + String get career34 => "交通運輸"; + /// "航空" + @override + String get career35 => "航空"; + /// "鉄道" + @override + String get career36 => "鉄道"; + /// "航运船舶" + @override + String get career37 => "航运船舶"; + /// "パブリック交通" + @override + String get career38 => "パブリック交通"; + /// "物流運輸" + @override + String get career39 => "物流運輸"; + /// "文化メディア" + @override + String get career40 => "文化メディア"; + /// "メディア出版" + @override + String get career41 => "メディア出版"; + /// "デザイン" + @override + String get career42 => "デザイン"; + /// "文化伝播" + @override + String get career43 => "文化伝播"; + /// "コマーシャルアイデア" + @override + String get career44 => "コマーシャルアイデア"; + /// "アニメ" + @override + String get career45 => "アニメ"; + /// "広報会議" + @override + String get career46 => "広報会議"; + /// "撮影" + @override + String get career47 => "撮影"; + /// "娯楽スポーツ" + @override + String get career48 => "娯楽スポーツ"; + /// "映画とテレビ" + @override + String get career49 => "映画とテレビ"; + /// "スポーツ" + @override + String get career50 => "スポーツ"; + /// "音楽" + @override + String get career51 => "音楽"; + /// "モデル" + @override + String get career52 => "モデル"; + /// "パブリック事業" + @override + String get career53 => "パブリック事業"; + /// "医療" + @override + String get career54 => "医療"; + /// "法律" + @override + String get career55 => "法律"; + /// "教育" + @override + String get career56 => "教育"; + /// "政府機関" + @override + String get career57 => "政府機関"; + /// "公益" + @override + String get career58 => "公益"; + /// "学生" + @override + String get career59 => "学生"; + /// "無" + @override + String get career60 => "無"; + /// "番組" + @override + String get program => "番組"; + /// "国籍を選択してください" + @override + String get select_program => "国籍を選択してください"; + /// "健康スポーツ" + @override + String get healthy_exercise => "健康スポーツ"; + /// "パーティー" + @override + String get night_party => "パーティー"; + /// "食べ物" + @override + String get gourmet_party => "食べ物"; + /// "映画を見る" + @override + String get watch_movie => "映画を見る"; + /// "ゲームを遊ぶ" + @override + String get play_games => "ゲームを遊ぶ"; + /// "旅行" + @override + String get travel_together => "旅行"; + /// "音声チャット" + @override + String get voice_chat => "音声チャット"; + /// "他" + @override + String get other => "他"; + /// "希望相手" + @override + String get expect_lover => "希望相手"; + /// "希望相手を選んでください" + @override + String get choose_lover => "希望相手を選んでください"; + /// "顔を見る" + @override + String get beautiful => "顔を見る"; + /// "お金持ち" + @override + String get rich => "お金持ち"; + /// "愛護をください" + @override + String get care_me => "愛護をください"; + /// "気持ちによる" + @override + String get look_feeling => "気持ちによる"; + /// "どうでもいい" + @override + String get doesnt_matter => "どうでもいい"; + /// "少なくとも一つのSNSアカウントを記入してください" + @override + String get least_account => "少なくとも一つのSNSアカウントを記入してください"; + /// "ソーシャルアカウントを非表示" + @override + String get hide_account1 => "ソーシャルアカウントを非表示"; + /// "詳細情報" + @override + String get more_information => "詳細情報"; + /// "身長" + @override + String get height => "身長"; + /// "体重" + @override + String get weight => "体重"; + /// "表示しません" + @override + String get not_show => "表示しません"; + /// "個人紹介" + @override + String get self_introduction => "個人紹介"; + /// "新規取得成功" + @override + String get registration_success1 => "新規取得成功"; + /// "ログアウトしますか" + @override + String get exit => "ログアウトしますか"; + /// "あなたの個人情報はまだ完備していません、今ログアウトしたら次入る時は登録済みのアカウントで直接ログインしてください" + @override + String get exit_registration => "あなたの個人情報はまだ完備していません、今ログアウトしたら次入る時は登録済みのアカウントで直接ログインしてください"; + /// "男性は男性の詳細情報を確認出来ません" + @override + String get cant_see => "男性は男性の詳細情報を確認出来ません"; + /// "女性は女性の詳細情報を確認出来ません" + @override + String get cant_see2 => "女性は女性の詳細情報を確認出来ません"; + /// "今日はまだ/s1人の女性情報が確認できます" + @override + String get see_one => "今日はまだ/s1人の女性情報が確認できます"; + /// "非VIPユーザーは毎日15人の女性情報しか見られません" + @override + String get only_see => "非VIPユーザーは毎日15人の女性情報しか見られません"; + /// "続き見る" + @override + String get continue_see => "続き見る"; + /// "ユーザーが凍結しました" + @override + String get user_frozen => "ユーザーが凍結しました"; + /// "ニックネームを入力ください/職業で検索します" + @override + String get search_user => "ニックネームを入力ください/職業で検索します"; + /// "近辺" + @override + String get nearby => "近辺"; + /// " VIP " + @override + String get member => " VIP "; + /// "新規取得" + @override + String get new_registration => "新規取得"; + /// "認証" + @override + String get authenticate => "認証"; + /// "オンライン" + @override + String get first_online => "オンライン"; + /// "位置付けが開けてないから他ユーザとの距離が計算できません" + @override + String get not_positioned => "位置付けが開けてないから他ユーザとの距離が計算できません"; + /// "未知" + @override + String get unknown => "未知"; + /// "秘密を守る" + @override + String get secrecy => "秘密を守る"; + /// "コレクション" + @override + String get collection => "コレクション"; + /// "コレクションをキャンセル" + @override + String get cancel_collection => "コレクションをキャンセル"; + /// "コレクションをキャンセルしました" + @override + String get canceled_collection => "コレクションをキャンセルしました"; + /// "お気に入り" + @override + String get like => "お気に入り"; + /// "お気になりに追加しました" + @override + String get added_like => "お気になりに追加しました"; + /// "お気になりをキャンセルしました" + @override + String get canceled_like => "お気になりをキャンセルしました"; + /// "ブロックする" + @override + String get blacklist => "ブロックする"; + /// "ブロックすると、このユーザーからのメッセージを受け取れなくなり、お互いにモーメンツの更新が表示されなくなります、このユーザーをブロックしますか" + @override + String get blacklist_choose => "ブロックすると、このユーザーからのメッセージを受け取れなくなり、お互いにモーメンツの更新が表示されなくなります、このユーザーをブロックしますか"; + /// "ブロックしました" + @override + String get blacklisted => "ブロックしました"; + /// "相手をブロックしました、相手のメッセージを拒否します" + @override + String get reject_message => "相手をブロックしました、相手のメッセージを拒否します"; + /// "ブロックリストから削除" + @override + String get remove_blacklist => "ブロックリストから削除"; + /// "ブロックリストから削除しました" + @override + String get blacklist_removed => "ブロックリストから削除しました"; + /// "相手をブロックリストから削除しました、メッセージ拒否を解除しました" + @override + String get receive_message => "相手をブロックリストから削除しました、メッセージ拒否を解除しました"; + /// "オンライン" + @override + String get online => "オンライン"; + /// "有料アルバム" + @override + String get paid_photo => "有料アルバム"; + /// "ブラウズを申請する" + @override + String get application_view => "ブラウズを申請する"; + /// "パスしました" + @override + String get passed => "パスしました"; + /// "公園" + @override + String get park => "公園"; + /// "放送局" + @override + String get radio => "放送局"; + /// "情報" + @override + String get news => "情報"; + /// "私" + @override + String get me => "私"; + /// "詳細操作" + @override + String get more_operations => "詳細操作"; + /// "匿名告発" + @override + String get anonymous_report => "匿名告発"; + /// "認証ビデオ" + @override + String get certified_video => "認証ビデオ"; + /// "彼女はビデオを通じて真実性を認証しました" + @override + String get passed_video => "彼女はビデオを通じて真実性を認証しました"; + /// "彼女はまだ身分の真実性を認証していません" + @override + String get not_video => "彼女はまだ身分の真実性を認証していません"; + /// "彼女からデートを誘っていますよ" + @override + String get her_appointment => "彼女からデートを誘っていますよ"; + /// "彼は有料で入る" + @override + String get pay_join => "彼は有料で入る"; + /// "彼は身分安全審査に合格しました" + @override + String get passed_review => "彼は身分安全審査に合格しました"; + /// "ベテランユーザー/s1贈った招待コードを通して入りました" + @override + String get invited_user => "ベテランユーザー/s1贈った招待コードを通して入りました"; + /// "彼からデートを誘っていますよ" + @override + String get his_appointment => "彼からデートを誘っていますよ"; + /// "彼女のダイナミック" + @override + String get her_dynamics => "彼女のダイナミック"; + /// "彼のダイナミック" + @override + String get his_dynamics => "彼のダイナミック"; + /// "彼女は非常に控えめ" + @override + String get low_key => "彼女は非常に控えめ"; + /// "彼は非常に控えめ" + @override + String get low_key2 => "彼は非常に控えめ"; + /// "彼女のアルバム" + @override + String get her_photo => "彼女のアルバム"; + /// "彼のアルバム" + @override + String get his_photo => "彼のアルバム"; + /// "彼はアルバムのロックを設置しました" + @override + String get set_lock => "彼はアルバムのロックを設置しました"; + /// "彼女はアルバムのロックを設置しました" + @override + String get set_lock2 => "彼女はアルバムのロックを設置しました"; + /// "アルバムのロックを解除(/s1)、VIPは無料" + @override + String get free_unlock => "アルバムのロックを解除(/s1)、VIPは無料"; + /// "/s1のアルバムロックを解除" + @override + String get unlock_user => "/s1のアルバムロックを解除"; + /// "有料でロックを解除(/s1H幤)" + @override + String get pay_unlock => "有料でロックを解除(/s1H幤)"; + /// " VIPになり、無料でロックを解除します" + @override + String get become_member => " VIPになり、無料でロックを解除します"; + /// " 1回のチャンスで/s1のアルバムロックを解除しますか?" + @override + String get consumption_once => " 1回のチャンスで/s1のアルバムロックを解除しますか?"; + /// "(今日はまだ/s1回チャンスがあります)" + @override + String get remaining_once => "(今日はまだ/s1回チャンスがあります)"; + /// "今日の無料機会はもうなくなりました、/s1を贈って/s2の全部資料をロック解除するか" + @override + String get no_times => "今日の無料機会はもうなくなりました、/s1を贈って/s2の全部資料をロック解除するか"; + /// "支払い" + @override + String get pay => "支払い"; + /// "彼は制限を設定、資料を見るには彼の同意が必要です" + @override + String get view_user => "彼は制限を設定、資料を見るには彼の同意が必要です"; + /// "彼女は制限を設定、資料を見るには彼女の同意が必要です" + @override + String get view_user2 => "彼女は制限を設定、資料を見るには彼女の同意が必要です"; + /// "レビューの申請はなたの写真を相手に送り必要があります、ご安心して、あなたの写真は相手が長いスクリーンを押して2秒後に焼却します" + @override + String get need_photo => "レビューの申請はなたの写真を相手に送り必要があります、ご安心して、あなたの写真は相手が長いスクリーンを押して2秒後に焼却します"; + /// "写真を選択" + @override + String get choose_photo => "写真を選択"; + /// "申請が発送済み、相手が確認したらメッセージが届きます" + @override + String get send_application => "申請が発送済み、相手が確認したらメッセージが届きます"; + /// "あなたはまだ認証していません" + @override + String get not_authenticate => "あなたはまだ認証していません"; + /// "あなたの真実性を認証してから、他人との対話することができます" + @override + String get after_authenticate => "あなたの真実性を認証してから、他人との対話することができます"; + /// "すぐ認証する" + @override + String get authenticate_now => "すぐ認証する"; + /// "読んだらすぐ焼却" + @override + String get destroy_after => "読んだらすぐ焼却"; + /// "焼却しました" + @override + String get destroyed => "焼却しました"; + /// "読んだらすぐ焼却のご礼儀写真" + @override + String get red_photo1 => "読んだらすぐ焼却のご礼儀写真"; + /// "二人きりチャットで私に請求してください" + @override + String get ask_me => "二人きりチャットで私に請求してください"; + /// "記入済み、クリックして確認してください" + @override + String get filled_in => "記入済み、クリックして確認してください"; + /// "全資料をロック解除する" + @override + String get unlock_information => "全資料をロック解除する"; + /// "1回無料でロックを解除する" + @override + String get unlock_choose => "1回無料でロックを解除する"; + /// "あなたの本当の評価" + @override + String get your_evaluation => "あなたの本当の評価"; + /// "彼女の本当の評価" + @override + String get her_evaluation => "彼女の本当の評価"; + /// "彼の本当の評価" + @override + String get his_evaluation => "彼の本当の評価"; + /// "評価" + @override + String get evaluate => "評価"; + /// "友好" + @override + String get friendly => "友好"; + /// "面白い" + @override + String get interesting => "面白い"; + /// "爽やか" + @override + String get readily => "爽やか"; + /// "辛抱強い" + @override + String get patient => "辛抱強い"; + /// "冷たい" + @override + String get indifferent => "冷たい"; + /// "気性が荒い" + @override + String get bad_temper => "気性が荒い"; + /// "礼儀正しい" + @override + String get courtesy => "礼儀正しい"; + /// "気前がいい" + @override + String get generous => "気前がいい"; + /// "口が軽い" + @override + String get lie => "口が軽い"; + /// "不友好" + @override + String get unfriendly => "不友好"; + /// "匿名評価" + @override + String get anonymous_evaluation => "匿名評価"; + /// "あなたはまだ彼女を誘ったことがないからコメントできません" + @override + String get cant_evaluate => "あなたはまだ彼女を誘ったことがないからコメントできません"; + /// "彼はまだあなたを誘ったことがないからコメントできません" + @override + String get cant_evaluate2 => "彼はまだあなたを誘ったことがないからコメントできません"; + /// "関連のスクリーンショットを提供してください、こちらはフォローして確認します" + @override + String get bad_evaluate => "関連のスクリーンショットを提供してください、こちらはフォローして確認します"; + /// "提出" + @override + String get submit => "提出"; + /// "コメント成功" + @override + String get evaluation_success => "コメント成功"; + /// "チャット" + @override + String get private_chat => "チャット"; + /// "メッセージのアラームをオフにする" + @override + String get close_reminder => "メッセージのアラームをオフにする"; + /// "メッセージのアラームをオフにしました" + @override + String get closed_reminder => "メッセージのアラームをオフにしました"; + /// "メッセージのアラームをオープンにする" + @override + String get open_reminder => "メッセージのアラームをオープンにする"; + /// "メッセージのアラームをオープンにしました" + @override + String get opened_reminder => "メッセージのアラームをオープンにしました"; + /// "彼女のSNSアカウント" + @override + String get her_account => "彼女のSNSアカウント"; + /// "彼のSNSアカウント" + @override + String get his_account => "彼のSNSアカウント"; + /// "コピー" + @override + String get copy => "コピー"; + /// "彼女に私のSNSアカウントを送ります" + @override + String get send_account => "彼女に私のSNSアカウントを送ります"; + /// "あなたのSNSアカウントを入力してください" + @override + String get enter_account => "あなたのSNSアカウントを入力してください"; + /// "例:ウィーキャットID abc " + @override + String get for_example => "例:ウィーキャットID abc "; + /// "彼女に送信します" + @override + String get sent_she => "彼女に送信します"; + /// "音声通話" + @override + String get chat => "音声通話"; + /// "相手はマイクの功能をオフしました" + @override + String get cantt_voice => "相手はマイクの功能をオフしました"; + /// "あなたの真実性を認証後音声ができます" + @override + String get authentication_voice => "あなたの真実性を認証後音声ができます"; + /// "音声を請求しています" + @override + String get requesting_voice => "音声を請求しています"; + /// "反応を待っています" + @override + String get waitting_answer => "反応を待っています"; + /// "受け入れ" + @override + String get answer => "受け入れ"; + /// "ハングアップ" + @override + String get hang_up => "ハングアップ"; + /// "音声繋がる中" + @override + String get chatting => "音声繋がる中"; + /// "ハンズフリー" + @override + String get handsfree => "ハンズフリー"; + /// "プレゼントを贈る" + @override + String get giving_gift => "プレゼントを贈る"; + /// "プレゼントを贈りました" + @override + String get give_success => "プレゼントを贈りました"; + /// "相手からプレゼントをくれました" + @override + String get others_gift => "相手からプレゼントをくれました"; + /// "あなたは/s1H幤のプレゼントを贈りました" + @override + String get given_gift => "あなたは/s1H幤のプレゼントを贈りました"; + /// "あなたは/s1H幤プレゼントを貰いました" + @override + String get earned_gift => "あなたは/s1H幤プレゼントを貰いました"; + /// "利用可能残高/s1" + @override + String get available_balance => "利用可能残高/s1"; + /// "チャージ" + @override + String get recharge => "チャージ"; + /// "贈る" + @override + String get give => "贈る"; + /// "すみません、あなたの残高が足りません" + @override + String get balance_insufficien => "すみません、あなたの残高が足りません"; + /// "プレゼントを贈る前チャージしてくださいね" + @override + String get first_recharge => "プレゼントを贈る前チャージしてくださいね"; + /// "今回は/s1H幤を贈りました" + @override + String get give_coin => "今回は/s1H幤を贈りました"; + /// "今回の音声は/s1H幤を貰いました。" + @override + String get get_coin => "今回の音声は/s1H幤を貰いました。"; + /// "今回の音声は/s1H幤を贈りました、/s2H幤を貰いました。" + @override + String get give_get => "今回の音声は/s1H幤を贈りました、/s2H幤を貰いました。"; + /// "音声会話は完了しました、長さ/s1" + @override + String get chat_over => "音声会話は完了しました、長さ/s1"; + /// "インフォメーションセンター" + @override + String get message_center => "インフォメーションセンター"; + /// "相手のユーザー詳細ページで二人きりチャット申請できます" + @override + String get can_chat => "相手のユーザー詳細ページで二人きりチャット申請できます"; + /// "チャット" + @override + String get text_chat => "チャット"; + /// "システムメッセージ" + @override + String get system_information => "システムメッセージ"; + /// "システム通知" + @override + String get system_notification => "システム通知"; + /// "あなたが告発した/s1の状況は事実ではありません、もっと有効な証拠を提出して再告発してください" + @override + String get report_failure => "あなたが告発した/s1の状況は事実ではありません、もっと有効な証拠を提出して再告発してください"; + /// "あなたが告発した/s1の状況は事実ですので、このユーザを処理しました" + @override + String get report_success => "あなたが告発した/s1の状況は事実ですので、このユーザを処理しました"; + /// "招待コードの申請が成功!招待コード【/s1】(クリックしてコピーできます)" + @override + String get successful_application => "招待コードの申請が成功!招待コード【/s1】(クリックしてコピーできます)"; + /// "招待コードの申請が成功、友達のご紹介、ありがとうございます。招待コード【/s1】(クリックしてコピーできます)" + @override + String get successful_application2 => "招待コードの申請が成功、友達のご紹介、ありがとうございます。招待コード【/s1】(クリックしてコピーできます)"; + /// "招待コードの申請が失敗した!残念ながら、あなたの申請は審査に合格できませんでした、真実な情報を記入して審査パス率が上げる" + @override + String get application_failed => "招待コードの申請が失敗した!残念ながら、あなたの申請は審査に合格できませんでした、真実な情報を記入して審査パス率が上げる"; + /// "【重要なお知らせ】:" + @override + String get important_notice => "【重要なお知らせ】:"; + /// "あなたの認証資料は要求に合わないから修正して再提出してください" + @override + String get authentication_failed => "あなたの認証資料は要求に合わないから修正して再提出してください"; + /// "1. 認証要求に基づいて認証ビデオを撮ってください" + @override + String get request1 => "1. 認証要求に基づいて認証ビデオを撮ってください"; + /// "2. 写真集に目鼻立ちのはっきりした顔写真をアップロードしてください" + @override + String get request2 => "2. 写真集に目鼻立ちのはっきりした顔写真をアップロードしてください"; + /// "あなたの認証申請は審査に合格しました,おめでとうございます" + @override + String get successful_authentication => "あなたの認証申請は審査に合格しました,おめでとうございます"; + /// "あなたがアップロードした写真は審査に合格しませんでした、必要に応じて再アップロードしてください" + @override + String get re_upload => "あなたがアップロードした写真は審査に合格しませんでした、必要に応じて再アップロードしてください"; + /// "新しくアップロードされた写真はもう審査に合格しました、おめでとうございます" + @override + String get upload_success => "新しくアップロードされた写真はもう審査に合格しました、おめでとうございます"; + /// "あなたのデートの申し込みは規則違反で削除されました、何回かの違反や事態重大な場合はシステムからあなたのアカウントを制限し凍結しますので、ご了承ください" + @override + String get caveat => "あなたのデートの申し込みは規則違反で削除されました、何回かの違反や事態重大な場合はシステムからあなたのアカウントを制限し凍結しますので、ご了承ください"; + /// "あなたのコメントは規則違反で削除されました。何回かの違反や事態重大な場合はシステムからあなたのアカウントを制限し凍結しますので、ご了承ください" + @override + String get caveat2 => "あなたのコメントは規則違反で削除されました。何回かの違反や事態重大な場合はシステムからあなたのアカウントを制限し凍結しますので、ご了承ください"; + /// "ラジオニュース" + @override + String get radio_message => "ラジオニュース"; + /// "このような情報はしばらくありません" + @override + String get no_message => "このような情報はしばらくありません"; + /// "/s1は//s2にデート情報を発表しました。クリックして確認してください" + @override + String get dating_news => "/s1は//s2にデート情報を発表しました。クリックして確認してください"; + /// "確認" + @override + String get go_see => "確認"; + /// "/s1はあなたのダイナミックをいいねにした" + @override + String get thumbs_up => "/s1はあなたのダイナミックをいいねにした"; + /// " /s1はあなたのデート番組をいいねした" + @override + String get thumbs_up2 => " /s1はあなたのデート番組をいいねした"; + /// "/s1はあなたのダイナミックにコメントしました" + @override + String get comment1 => "/s1はあなたのダイナミックにコメントしました"; + /// "/s1はあなたのデート番組にコメントしました" + @override + String get comment2 => "/s1はあなたのデート番組にコメントしました"; + /// "/s1はあなたのコメントを返信しました" + @override + String get replied_comment => "/s1はあなたのコメントを返信しました"; + /// "/s1はあなたのデート番組を申し込みました" + @override + String get signed_up => "/s1はあなたのデート番組を申し込みました"; + /// "あなた気に入りユーザー/s 1がデートを発表しました。クリックして確認してください" + @override + String get favorite_user => "あなた気に入りユーザー/s 1がデートを発表しました。クリックして確認してください"; + /// "お気に入りユーザ/s 1がダイナミックをリリースしました。クリックして確認してください" + @override + String get favorite_user2 => "お気に入りユーザ/s 1がダイナミックをリリースしました。クリックして確認してください"; + /// "ウォレットのリマインダ" + @override + String get wallet_reminder => "ウォレットのリマインダ"; + /// "/s1(/s2H 幤)を払ってあなたのご祝儀写真を見ました" + @override + String get paid_you => "/s1(/s2H 幤)を払ってあなたのご祝儀写真を見ました"; + /// "/s1は(/s2H幤)を払ってあなたのアルバムを見ました" + @override + String get paid_you2 => "/s1は(/s2H幤)を払ってあなたのアルバムを見ました"; + /// "/s1は有料で、あなたの資料を全部ロックしました" + @override + String get paid_you3 => "/s1は有料で、あなたの資料を全部ロックしました"; + /// "申請を確認します" + @override + String get view_application => "申請を確認します"; + /// "/s1はあなたの詳細ページ閲覧をリクエスする" + @override + String get view_application2 => "/s1はあなたの詳細ページ閲覧をリクエスする"; + /// "許可(有効期間15日間))" + @override + String get aging => "許可(有効期間15日間))"; + /// "拒否" + @override + String get refuse => "拒否"; + /// "リクエストをパスしました" + @override + String get passed_request => "リクエストをパスしました"; + /// "/s1はもうあなたの閲覧申請をパスしました、有効期間は15日間です" + @override + String get l15_days => "/s1はもうあなたの閲覧申請をパスしました、有効期間は15日間です"; + /// "コメントのお知らせ" + @override + String get evaluation_notice => "コメントのお知らせ"; + /// "もう/s1を誘いましたか?早く彼女を評価してください" + @override + String get rate_her => "もう/s1を誘いましたか?早く彼女を評価してください"; + /// "あなたに連絡した女性ユーザー(匿名)があなたにコメントした:/s1" + @override + String get received_evaluation => "あなたに連絡した女性ユーザー(匿名)があなたにコメントした:/s1"; + /// "あなたに連絡した男性ユーザー(匿名)があなたにコメントした:/s1" + @override + String get received_evaluation2 => "あなたに連絡した男性ユーザー(匿名)があなたにコメントした:/s1"; + /// "コメントは事実と合わない場合、申告してください、こちらは事実を確実します" + @override + String get application_appeal => "コメントは事実と合わない場合、申告してください、こちらは事実を確実します"; + /// "申告します" + @override + String get appeal => "申告します"; + /// "申告しました" + @override + String get appealed => "申告しました"; + /// "私たちはできるだけ早く状況を確認して、内部メールで処理結果を連絡します" + @override + String get waiting_results => "私たちはできるだけ早く状況を確認して、内部メールで処理結果を連絡します"; + /// "あなたの申告評価:/s 申告成功、コメントを取り消します" + @override + String get successful_appeal => "あなたの申告評価:/s 申告成功、コメントを取り消します"; + /// " SNSアカウント" + @override + String get social_account => " SNSアカウント"; + /// "/s1はあなたにSNSアカウントを送信します" + @override + String get get_account => "/s1はあなたにSNSアカウントを送信します"; + /// "資料編集" + @override + String get edit_information => "資料編集"; + /// "保存" + @override + String get save => "保存"; + /// "あなたの身分安全認証をパスしました" + @override + String get passed_verification1 => "あなたの身分安全認証をパスしました"; + /// "あなたはベテランユーザー/s 1の招待コードで入りました" + @override + String get by_code => "あなたはベテランユーザー/s 1の招待コードで入りました"; + /// "あなたは有料で入りました" + @override + String get by_paying => "あなたは有料で入りました"; + /// "あなたはビデオを通じて身分の真実性を認証しました" + @override + String get passed_verification => "あなたはビデオを通じて身分の真実性を認証しました"; + /// "あなたはまだ認証されていません" + @override + String get not_certified => "あなたはまだ認証されていません"; + /// "あなたの真実性を認証しています" + @override + String get verificating => "あなたの真実性を認証しています"; + /// "認証を受けた女性の方がもっと人気がありますよ" + @override + String get real_girl => "認証を受けた女性の方がもっと人気がありますよ"; + /// "認証中" + @override + String get certificating => "認証中"; + /// "ビデオを再アップロードをお待ちしております" + @override + String get re_upload2 => "ビデオを再アップロードをお待ちしております"; + /// "認証更新" + @override + String get update_certification => "認証更新"; + /// " VIPをアップして特権を尊ぶ" + @override + String get enjoy_privileges => " VIPをアップして特権を尊ぶ"; + /// "/s1満期" + @override + String get expires => "/s1満期"; + /// "財布" + @override + String get wallet => "財布"; + /// "プライバシー" + @override + String get setting => "プライバシー"; + /// "私のダイナミック" + @override + String get my_dynamic => "私のダイナミック"; + /// "私のアルバム" + @override + String get my_album => "私のアルバム"; + /// "第一枚写真をアップロードします" + @override + String get first_photo => "第一枚写真をアップロードします"; + /// "写真があったら男性を引き付けることができますよ" + @override + String get no_photo => "写真があったら男性を引き付けることができますよ"; + /// "写真をアップロード" + @override + String get upload_photos => "写真をアップロード"; + /// "ビデオをアップロード" + @override + String get upload_video => "ビデオをアップロード"; + /// "写真をアップロードする" + @override + String get upload => "写真をアップロードする"; + /// "ご祝儀の写真を設定する" + @override + String get set_photo => "ご祝儀の写真を設定する"; + /// "長いドラッグで写真の並べ替えができます" + @override + String get photo_order => "長いドラッグで写真の並べ替えができます"; + /// "私の評価" + @override + String get my_evaluation => "私の評価"; + /// "私の番組" + @override + String get my_show => "私の番組"; + /// "私の気に入り" + @override + String get i_like => "私の気に入り"; + /// "ご好きな女性がここを表示します" + @override + String get your_favorite => "ご好きな女性がここを表示します"; + /// "ご好きな男性がここを表示します" + @override + String get your_favorite2 => "ご好きな男性がここを表示します"; + /// "データがありません" + @override + String get no_data => "データがありません"; + /// "過去の訪問者" + @override + String get historical_visitor => "過去の訪問者"; + /// "/s1人が訪問したことがある" + @override + String get visit_you => "/s1人が訪問したことがある"; + /// "/s1人があなたの写真を焼却しました" + @override + String get visit_photo => "/s1人があなたの写真を焼却しました"; + /// "ワンタッチで回復" + @override + String get recovery_photo => "ワンタッチで回復"; + /// "設定" + @override + String get setting2 => "設定"; + /// "友達に招待コードを申請してあげます" + @override + String get apply_code => "友達に招待コードを申請してあげます"; + /// "招待コードの申し込みは無料です、あなたの過去消費履歴によって招待コードを発行するかどうかを評価します。公園の雰囲気を維持するために、ぜひ信頼できる友達に招待コードを贈ってしてください" + @override + String get issue_choose => "招待コードの申し込みは無料です、あなたの過去消費履歴によって招待コードを発行するかどうかを評価します。公園の雰囲気を維持するために、ぜひ信頼できる友達に招待コードを贈ってしてください"; + /// "申請書提出成功" + @override + String get successfully_submit => "申請書提出成功"; + /// "友達にAPPを共有する" + @override + String get share_app => "友達にAPPを共有する"; + /// "助けてください" + @override + String get need_help => "助けてください"; + /// "顧客サービスに連絡する" + @override + String get need_help2 => "顧客サービスに連絡する"; + /// "サービスの効率を高めるために、以下の問題があれば、直接番号を回答ください" + @override + String get need_help3 => "サービスの効率を高めるために、以下の問題があれば、直接番号を回答ください"; + /// "【1】アカウントが凍結された理由は何ですか??" + @override + String get question1 => "【1】アカウントが凍結された理由は何ですか??"; + /// "下記のいずれかの状況が発生したら、アカウントは凍結されます:①詐欺師②仲介③嫌がらせ広告④複数人が告発され。⑤他のアカウントがすでにありました。⑥何度も違法放送を発表して、警告を無視しました。⑦ユーザーが自分でログアウトを要求する" + @override + String get answer1 => "下記のいずれかの状況が発生したら、アカウントは凍結されます:①詐欺師②仲介③嫌がらせ広告④複数人が告発され。⑤他のアカウントがすでにありました。⑥何度も違法放送を発表して、警告を無視しました。⑦ユーザーが自分でログアウトを要求する"; + /// "【2】財布の現金はいつ換金できますか?" + @override + String get question2 => "【2】財布の現金はいつ換金できますか?"; + /// "すべての収益は直接財布に入ります。換金には三日間かかります(請求時間による計算開始)。三日後に受け取った金額は財布に入ります。金額>=10元の場合換金できます" + @override + String get answer2 => "すべての収益は直接財布に入ります。換金には三日間かかります(請求時間による計算開始)。三日後に受け取った金額は財布に入ります。金額>=10元の場合換金できます"; + /// "【3】私が出したご祝儀はなぜ表示されていませんか?" + @override + String get question3 => "【3】私が出したご祝儀はなぜ表示されていませんか?"; + /// "ネットの原因かもしれません。ご安心してください、この場合、相手はあなたのご祝儀を受け取ることができません。ご祝儀は24時間後に自動的にあなたの支払ルートに返却されます" + @override + String get answer3 => "ネットの原因かもしれません。ご安心してください、この場合、相手はあなたのご祝儀を受け取ることができません。ご祝儀は24時間後に自動的にあなたの支払ルートに返却されます"; + /// "【4】換金はどれぐらいかかりますか?" + @override + String get question4 => "【4】換金はどれぐらいかかりますか?"; + /// "換金申請を提出してから二つの出勤日以内に入金します。ご注意:アカウントは間違いないようご注意ください!" + @override + String get answer4 => "換金申請を提出してから二つの出勤日以内に入金します。ご注意:アカウントは間違いないようご注意ください!"; + /// "【5】どうやって匿名で他のユーザー/ラジオ放送の内容を告発しますか?" + @override + String get question5 => "【5】どうやって匿名で他のユーザー/ラジオ放送の内容を告発しますか?"; + /// "相手の詳細ページに入るか、ラジオ放送を選択し、右上をクリックして「匿名通報」を選択し、関連の告発情報を記入してください" + @override + String get answer5 => "相手の詳細ページに入るか、ラジオ放送を選択し、右上をクリックして「匿名通報」を選択し、関連の告発情報を記入してください"; + /// "【6】どのように認証ユーザになりますか?" + @override + String get question6 => "【6】どのように認証ユーザになりますか?"; + /// "認証をパスするには以下の要求を満たす必要があります。①個人資料には有効なsnsアカウントを記入する②アルバムは少なくとも本人のはっきりした顔写真をアップロードする③認証ページで検証コードを確認し、紙にニックネーム+認証コードを記入する④この紙を持って、あなたの顔と一緒にビデオを撮ってアップロードする" + @override + String get answer6 => "認証をパスするには以下の要求を満たす必要があります。①個人資料には有効なsnsアカウントを記入する②アルバムは少なくとも本人のはっきりした顔写真をアップロードする③認証ページで検証コードを確認し、紙にニックネーム+認証コードを記入する④この紙を持って、あなたの顔と一緒にビデオを撮ってアップロードする"; + /// "【7】認証されたビデオは公開しなくてもいいですか?" + @override + String get question7 => "【7】認証されたビデオは公開しなくてもいいですか?"; + /// "設定欄で公開するかどうかを選択できます。ユーザーセンター→認証ビデオをクリックして、左下に“認証ビデオを私の詳細ページに表示します" + @override + String get answer7 => "設定欄で公開するかどうかを選択できます。ユーザーセンター→認証ビデオをクリックして、左下に“認証ビデオを私の詳細ページに表示します"; + /// "【8】どうやって認証がキャンセルされるのを避けるべきですか?" + @override + String get question8 => "【8】どうやって認証がキャンセルされるのを避けるべきですか?"; + /// "アルバムには少なくとも一枚本人の写真があります" + @override + String get answer8 => "アルバムには少なくとも一枚本人の写真があります"; + /// "【9】ラジオ放送が削除された理由は何ですか?" + @override + String get question9 => "【9】ラジオ放送が削除された理由は何ですか?"; + /// "ラジオ放送は敏感図を発表できません。敏感語は含みますが、これに限らず、個人情報(顔写真、ニックネーム、連絡先を含む)を発表できません、違法放送は削除されます" + @override + String get answer9 => "ラジオ放送は敏感図を発表できません。敏感語は含みますが、これに限らず、個人情報(顔写真、ニックネーム、連絡先を含む)を発表できません、違法放送は削除されます"; + /// "【10】どうやってアカウントをキャンセルしますか?" + @override + String get question10 => "【10】どうやってアカウントをキャンセルしますか?"; + /// "アカウントの抹消はAPPにログインできなくなりますので、後でサービスを使用の場合は改めて新規取得必要です、それでもアカウントをキャンセルする場合は、シリアル番号[12]に顧客サービスに連絡してください " + @override + String get answer10 => "アカウントの抹消はAPPにログインできなくなりますので、後でサービスを使用の場合は改めて新規取得必要です、それでもアカウントをキャンセルする場合は、シリアル番号[12]に顧客サービスに連絡してください "; + /// "【11】パスワードを忘れたらどうすればいいですか?" + @override + String get question11 => "【11】パスワードを忘れたらどうすればいいですか?"; + /// "携帯番号で登録したユーザー或いは携帯番号を関連したたユーザーはページ右上の「パスワード忘れ」機能でパスワードをリセットできます。携帯番号を関連していないユーザはまず携帯番号を関連して、そして新しいログインパスワードを設定してください" + @override + String get answer11 => "携帯番号で登録したユーザー或いは携帯番号を関連したたユーザーはページ右上の「パスワード忘れ」機能でパスワードをリセットできます。携帯番号を関連していないユーザはまず携帯番号を関連して、そして新しいログインパスワードを設定してください"; + /// "【12】その他の問題/人工サービスに連絡" + @override + String get question12 => "【12】その他の問題/人工サービスに連絡"; + /// "こんにちは、なにかお手伝いところがありますか?ご質問を説明してください。(顧客サービスの出勤時間は毎日8時から翌日02時までです。問い合わせ人数が多いので、お待ちしてください)" + @override + String get answer12 => "こんにちは、なにかお手伝いところがありますか?ご質問を説明してください。(顧客サービスの出勤時間は毎日8時から翌日02時までです。問い合わせ人数が多いので、お待ちしてください)"; + /// "認証センター" + @override + String get certification_center => "認証センター"; + /// "認証ビデオの撮影例" + @override + String get for_example2 => "認証ビデオの撮影例"; + /// "認証条件" + @override + String get certification_conditions => "認証条件"; + /// "1. 個人のイメージが良い" + @override + String get conditions1 => "1. 個人のイメージが良い"; + /// "2. アルバムに少なくとも一枚本人の写真をアップロードしてください" + @override + String get conditions2 => "2. アルバムに少なくとも一枚本人の写真をアップロードしてください"; + /// "認証方法" + @override + String get verification_method => "認証方法"; + /// "1. 紙にニックネームと検証コードを書いてください" + @override + String get method3 => "1. 紙にニックネームと検証コードを書いてください"; + /// "2. この紙を持って、あなたの顔と一緒にビデオを撮ってください(3~15秒)(3~15秒)" + @override + String get method4 => "2. この紙を持って、あなたの顔と一緒にビデオを撮ってください(3~15秒)(3~15秒)"; + /// "認証ビデオをアップロードする" + @override + String get upload_video2 => "認証ビデオをアップロードする"; + /// "認証成功後にあなたのアバター写真にrealのマックが付いてる" + @override + String get after_authentication => "認証成功後にあなたのアバター写真にrealのマックが付いてる"; + /// "認証ビデオを私の詳細ページに表示する" + @override + String get show_video => "認証ビデオを私の詳細ページに表示する"; + /// "認証ビデオがアップロードしました" + @override + String get uploaded_video => "認証ビデオがアップロードしました"; + /// "審査中(24時間以内))" + @override + String get under_review => "審査中(24時間以内))"; + /// "認証状態" + @override + String get certification_status => "認証状態"; + /// "認証パスしました" + @override + String get certified => "認証パスしました"; + /// "認証は再提出する必要があります" + @override + String get wait_resubmitted => "認証は再提出する必要があります"; + /// "あなたの認証ビデオは要求に合わないです。原因は:" + @override + String get reason_failure => "あなたの認証ビデオは要求に合わないです。原因は:"; + /// "認証要求に基づいて認証ビデオを撮ってください" + @override + String get claim => "認証要求に基づいて認証ビデオを撮ってください"; + /// "アルバムにはっきりした顔の写真をアップロードしてください" + @override + String get claim2 => "アルバムにはっきりした顔の写真をアップロードしてください"; + /// "認証ビデオを再アップロードしてください" + @override + String get re_upload_video => "認証ビデオを再アップロードしてください"; + /// "アップロードした認証ビデオを更新する" + @override + String get update_video => "アップロードした認証ビデオを更新する"; + /// "H幣" + @override + String get mask_coin => "H幣"; + /// "チャージやマイク付けなど方法でH幣が貰える。" + @override + String get get_way => "チャージやマイク付けなど方法でH幣が貰える。"; + /// " H幣は、音声通話と報酬に使用できます。" + @override + String get coin_use => " H幣は、音声通話と報酬に使用できます。"; + /// "H幣総額" + @override + String get coin_total => "H幣総額"; + /// "両替可" + @override + String get can_redeemed => "両替可"; + /// "/s1アカウント" + @override + String get who_account => "/s1アカウント"; + /// "/s1アカウントを関連する" + @override + String get bind_account => "/s1アカウントを関連する"; + /// "あなたの/s1アカウント" + @override + String get your_account => "あなたの/s1アカウント"; + /// "チャージで/s1H幣を貰いました" + @override + String get get_coin2 => "チャージで/s1H幣を貰いました"; + /// "/s1はあなたのsnsアカウントを確認しました" + @override + String get viewed_your => "/s1はあなたのsnsアカウントを確認しました"; + /// "/s1からプレゼントをくれました:1个/s2" + @override + String get give_gift => "/s1からプレゼントをくれました:1个/s2"; + /// "+/s1H幣" + @override + String get add_coin => "+/s1H幣"; + /// " /s2に1個/s1を贈りました" + @override + String get give_one => " /s2に1個/s1を贈りました"; + /// "-/s1H幣" + @override + String get less_coin => "-/s1H幣"; + /// "換金" + @override + String get exchange_cash => "換金"; + /// "換金申請申请" + @override + String get withdrawal_application => "換金申請申请"; + /// "/s1枚のH貨は/s2に両替できます、両替後/s3枚H幣を残っています、両替確定ですか?" + @override + String get redeem_choose => "/s1枚のH貨は/s2に両替できます、両替後/s3枚H幣を残っています、両替確定ですか?"; + /// "換金申請が提出しました" + @override + String get application_submitted => "換金申請が提出しました"; + /// "二日間(出勤日)内で処理します、ご疑問がありれば顧客サービスに問い合わせしてください" + @override + String get working_days => "二日間(出勤日)内で処理します、ご疑問がありれば顧客サービスに問い合わせしてください"; + /// "現金" + @override + String get cash => "現金"; + /// "チャットベージで貰ったご祝儀はここに入ります、入金されてから3日間以内に通報がない場合は換金可能です、換金の場合は5%の手数料が掛かります" + @override + String get handling_fee => "チャットベージで貰ったご祝儀はここに入ります、入金されてから3日間以内に通報がない場合は換金可能です、換金の場合は5%の手数料が掛かります"; + /// "アカウント総額" + @override + String get total_account => "アカウント総額"; + /// "金額が不足で両替できません" + @override + String get cannot_redeemed => "金額が不足で両替できません"; + /// "両替成功" + @override + String get successful_redemption => "両替成功"; + /// "あなたのアカウント総額は/s1元、今回/s2元換金可能です、換金申請は確定ですか?" + @override + String get redeem_choose2 => "あなたのアカウント総額は/s1元、今回/s2元換金可能です、換金申請は確定ですか?"; + /// "個人情報" + @override + String get personal_details => "個人情報"; + /// "公開(推薦)" + @override + String get public => "公開(推薦)"; + /// "アルバムは有料で閲覧" + @override + String get paid_album => "アルバムは有料で閲覧"; + /// "あなたのアルバムは有料でしか見られない、費用はあなたが決めます、これはあなたの訪問量を減らすかもしれません" + @override + String get must_pay => "あなたのアルバムは有料でしか見られない、費用はあなたが決めます、これはあなたの訪問量を減らすかもしれません"; + /// "表示金額を設定する" + @override + String get set_amount1 => "表示金額を設定する"; + /// "有料アルバムを設定する前に写真をアップロードしてください" + @override + String get first_upload => "有料アルバムを設定する前に写真をアップロードしてください"; + /// "閲覧前に私の確認が必要です" + @override + String get need_permission => "閲覧前に私の確認が必要です"; + /// "あなたのホームページを閲覧する前に、他人は必ず写真をあなたに送って身分を確認必要です、確定ですか?" + @override + String get permission_choose => "あなたのホームページを閲覧する前に、他人は必ず写真をあなたに送って身分を確認必要です、確定ですか?"; + /// "近くの人のリストから私を隠す" + @override + String get hide_me => "近くの人のリストから私を隠す"; + /// "他人に私の位置を隠す" + @override + String get hide_distance => "他人に私の位置を隠す"; + /// "他人にわたしのSNSアカウントを隠す" + @override + String get hide_account => "他人にわたしのSNSアカウントを隠す"; + /// "音声コントロール" + @override + String get chat_setting => "音声コントロール"; + /// "密談の権限を持つユーザーに私と音声を許可する" + @override + String get chat_me => "密談の権限を持つユーザーに私と音声を許可する"; + /// "正常に保存されました" + @override + String get successfully_saved => "正常に保存されました"; + /// "あなたはまだダイナミックをリリースしたことはありません" + @override + String get on_dynamic => "あなたはまだダイナミックをリリースしたことはありません"; + /// "ダイナミックをリリース" + @override + String get release_dynamics => "ダイナミックをリリース"; + /// "ダイナミック詳細" + @override + String get dynamic_details => "ダイナミック詳細"; + /// "投稿" + @override + String get release => "投稿"; + /// "私が発表した" + @override + String get i_posted => "私が発表した"; + /// "ダイナミックを削除" + @override + String get delete_dynamic => "ダイナミックを削除"; + /// "このダイナミックを削除するのは確定ですが?" + @override + String get delete_choose => "このダイナミックを削除するのは確定ですが?"; + /// "/s1にリリースしました" + @override + String get posted_on => "/s1にリリースしました"; + /// "いいね" + @override + String get thumbs_up3 => "いいね"; + /// "いいねにした" + @override + String get already_praised => "いいねにした"; + /// "コメント" + @override + String get comment => "コメント"; + /// "送信" + @override + String get send => "送信"; + /// "コメントを閉じました" + @override + String get comment_closed => "コメントを閉じました"; + /// "投稿者だけがあなたのコメントを見られます" + @override + String get your_comment => "投稿者だけがあなたのコメントを見られます"; + /// "みんなさんがあなたのコメントを見えます" + @override + String get everyone_comment => "みんなさんがあなたのコメントを見えます"; + /// "コメント禁止" + @override + String get prohibit_comments => "コメント禁止"; + /// "コメント禁止しました" + @override + String get comments_disabled => "コメント禁止しました"; + /// "コメントオープン" + @override + String get open_comments => "コメントオープン"; + /// "コメントオープンしました" + @override + String get already_open => "コメントオープンしました"; + /// "返信" + @override + String get reply => "返信"; + /// "告発" + @override + String get report => "告発"; + /// "このコメントを告発しますか?" + @override + String get report_choose => "このコメントを告発しますか?"; + /// "告発できました、私たちは出来るだけ早く処理します" + @override + String get successful_report => "告発できました、私たちは出来るだけ早く処理します"; + /// "削除しました" + @override + String get successfully_deleted => "削除しました"; + /// "文明交流できる人はもっと人気があります、下品、ポルノ、または他人のプライバシーを暴露するコンテンツを投稿しないでください" + @override + String get please_civilization => "文明交流できる人はもっと人気があります、下品、ポルノ、または他人のプライバシーを暴露するコンテンツを投稿しないでください"; + /// "同性ユーザーには隠す" + @override + String get same_sex => "同性ユーザーには隠す"; + /// " VIPは無料、非VIPは/slH幤が必要" + @override + String get member_free => " VIPは無料、非VIPは/slH幤が必要"; + /// "認証された女性は3回無料です、その後、支払い/s1H幤が必要です" + @override + String get certified_free => "認証された女性は3回無料です、その後、支払い/s1H幤が必要です"; + /// "テキストを入力or写真を選んでください" + @override + String get enter_something => "テキストを入力or写真を選んでください"; + /// "有料リリース(/s1H币)" + @override + String get raid_release => "有料リリース(/s1H币)"; + /// " VIPになり、無料投稿" + @override + String get become_member2 => " VIPになり、無料投稿"; + /// "今すぐ認証、無料投稿" + @override + String get now_certification => "今すぐ認証、無料投稿"; + /// "投稿成功" + @override + String get successfully_released => "投稿成功"; + /// "あなたは番組を投稿したことがない" + @override + String get no_program => "あなたは番組を投稿したことがない"; + /// "番組詳細" + @override + String get program_details => "番組詳細"; + /// "番組テーマ" + @override + String get program_theme => "番組テーマ"; + /// "クリックして選択" + @override + String get click_select => "クリックして選択"; + /// "都市" + @override + String get city => "都市"; + /// "都市選択" + @override + String get select_city => "都市選択"; + /// "時間" + @override + String get time => "時間"; + /// "日付を選択" + @override + String get select_date => "日付を選択"; + /// "時間を選択" + @override + String get select_time => "時間を選択"; + /// "時間限定なし" + @override + String get unlimited_time => "時間限定なし"; + /// "補充説明" + @override + String get supplementary_explanation => "補充説明"; + /// "画像" + @override + String get image => "画像"; + /// "番組を削除" + @override + String get delete_program => "番組を削除"; + /// "この番組を削除しますか?" + @override + String get delete_choose2 => "この番組を削除しますか?"; + /// "番組のテーマを選んでください" + @override + String get please_choose => "番組のテーマを選んでください"; + /// "希望する相手を選んでください" + @override + String get please_choose2 => "希望する相手を選んでください"; + /// "都市を選んでください" + @override + String get please_choose3 => "都市を選んでください"; + /// "日付を選んでください" + @override + String get please_choose4 => "日付を選んでください"; + /// "時間を選んでください" + @override + String get please_choose5 => "時間を選んでください"; + /// "番組を投稿" + @override + String get release_program => "番組を投稿"; + /// "申し込み" + @override + String get sign_up => "申し込み"; + /// "登録を閉じる" + @override + String get end_registration => "登録を閉じる"; + /// "デートを終了しますか?" + @override + String get end_choose => "デートを終了しますか?"; + /// "彼女に連絡する" + @override + String get contact_her => "彼女に連絡する"; + /// "彼と二人チャット" + @override + String get talk_him => "彼と二人チャット"; + /// "この申し込みメッセージを告発しますか?" + @override + String get report_choose2 => "この申し込みメッセージを告発しますか?"; + /// "投稿時間" + @override + String get release_time => "投稿時間"; + /// "イベント時間" + @override + String get activity_time => "イベント時間"; + /// "性別を問わず" + @override + String get any_sex => "性別を問わず"; + /// "女性だけを見る" + @override + String get look_women => "女性だけを見る"; + /// "男性だけを見る" + @override + String get look_men => "男性だけを見る"; + /// "地域問わず" + @override + String get unlimited_area => "地域問わず"; + /// "この番組は削除しました" + @override + String get program_deleted => "この番組は削除しました"; + /// "非VIPはコメントできません" + @override + String get cant_comment => "非VIPはコメントできません"; + /// "申し込み" + @override + String get sign_up2 => "申し込み"; + /// "申し込みはあなたの正面写真が必要です(相手しか見られない)" + @override + String get need_photo2 => "申し込みはあなたの正面写真が必要です(相手しか見られない)"; + /// "申し込み成功、相手は気に入ったらあなたと連絡する" + @override + String get registration_success => "申し込み成功、相手は気に入ったらあなたと連絡する"; + /// "もう終了しました" + @override + String get has_ended => "もう終了しました"; + /// "男性は男性の番組に応募できまえん" + @override + String get men_cant => "男性は男性の番組に応募できまえん"; + /// "女性は女性の番組に応募できません" + @override + String get ms_cant => "女性は女性の番組に応募できません"; + /// "男性は男性の番組をコメントできなせん" + @override + String get men_cant2 => "男性は男性の番組をコメントできなせん"; + /// "女性は女性の番組をコメントできません" + @override + String get ms_cant2 => "女性は女性の番組をコメントできません"; + /// "メッセージ送信、パスワード修正" + @override + String get message_push => "メッセージ送信、パスワード修正"; + /// "携帯番号" + @override + String get phone_number => "携帯番号"; + /// "携帯番号を関連する" + @override + String get bind_phone1 => "携帯番号を関連する"; + /// "携帯番号を関連して、あなたのアカウントの安全性を高めます" + @override + String get more_safer => "携帯番号を関連して、あなたのアカウントの安全性を高めます"; + /// "関連した携帯番号を修正したいですか?" + @override + String get modify_choose => "関連した携帯番号を修正したいですか?"; + /// "パスワードを修正する" + @override + String get change_password => "パスワードを修正する"; + /// "ユーザー登録パスワードを設定する前に携帯番号を関連する必要です" + @override + String get first_bind => "ユーザー登録パスワードを設定する前に携帯番号を関連する必要です"; + /// "元パスワード" + @override + String get old_password => "元パスワード"; + /// "現行の登録パスワードを入力してください" + @override + String get current_password => "現行の登録パスワードを入力してください"; + /// "新しいパスワード" + @override + String get new_password => "新しいパスワード"; + /// "6桁までの新しいパスワードを設定してください" + @override + String get set_new => "6桁までの新しいパスワードを設定してください"; + /// "画像キャッシュをクリア" + @override + String get clear_cache => "画像キャッシュをクリア"; + /// "削除しました" + @override + String get cleared_successfully => "削除しました"; + /// "ユーザー使用協議" + @override + String get user_agreement1 => "ユーザー使用協議"; + /// "ログアウト" + @override + String get sign_out => "ログアウト"; + /// "ログアウトしますか?" + @override + String get out_choose => "ログアウトしますか?"; + /// "送信設定" + @override + String get push_settings => "送信設定"; + /// "権限が拒否されました" + @override + String get permission_denied => "権限が拒否されました"; + /// "メッセージ送信設定" + @override + String get push_setting2 => "メッセージ送信設定"; + /// "二人チャット内容" + @override + String get private_chat2 => "二人チャット内容"; + /// "新しいデート" + @override + String get new_date => "新しいデート"; + /// "私の視点からのアプリケーション" + @override + String get passed_request2 => "私の視点からのアプリケーション"; + /// "男性が私のプロフィールを見たい" + @override + String get men_view => "男性が私のプロフィールを見たい"; + /// "ある男性は私のSNSアカウントを見ました" + @override + String get men_view2 => "ある男性は私のSNSアカウントを見ました"; + /// "ある男性は私のお祝儀写真を見ました" + @override + String get men_view3 => "ある男性は私のお祝儀写真を見ました"; + /// "私の資料を確認した男性からSNSアカウントを送ってくれました" + @override + String get men_view4 => "私の資料を確認した男性からSNSアカウントを送ってくれました"; + /// "招待コード申請成功" + @override + String get applied_successfully => "招待コード申請成功"; + /// "開いたら、該当するメッセージタイプを送信する" + @override + String get after_open => "開いたら、該当するメッセージタイプを送信する"; + /// "もしあなたが最近3日間で彼女/彼に費用を支払ったとしたら、告発を確実した後、システムは自動的あなたに消費金額を返します" + @override + String get if_something => "もしあなたが最近3日間で彼女/彼に費用を支払ったとしたら、告発を確実した後、システムは自動的あなたに消費金額を返します"; + /// "広告を発表" + @override + String get advertise => "広告を発表"; + /// "偽り写真" + @override + String get false_photo => "偽り写真"; + /// "エロ低俗" + @override + String get erotic_vulgarity => "エロ低俗"; + /// "騒擾悪口" + @override + String get harassment => "騒擾悪口"; + /// "彼女は詐欺師です" + @override + String get she_liar => "彼女は詐欺師です"; + /// "彼は詐欺師です" + @override + String get he_liar => "彼は詐欺師です"; + /// "確認をフォローするために、関連のスクリーンショットを提供してください" + @override + String get provide_screenshots => "確認をフォローするために、関連のスクリーンショットを提供してください"; + /// "詳細を説明してください(200字以内))" + @override + String get describe_details => "詳細を説明してください(200字以内))"; + /// "告発の原因を選んでください" + @override + String get report_reason => "告発の原因を選んでください"; + /// "告発成功" + @override + String get report_success2 => "告発成功"; + /// "修正成功" + @override + String get successfully_modified => "修正成功"; + /// "男性" + @override + String get boy => "男性"; + /// "女性" + @override + String get girl => "女性"; + /// "申請しました" + @override + String get already_applied => "申請しました"; + /// "サインアップ" + @override + String get view_registration => "サインアップ"; + /// "展開" + @override + String get expand => "展開"; + /// "取入れる" + @override + String get collapse => "取入れる"; + /// "申請のお知らせ" + @override + String get application_notice => "申請のお知らせ"; + /// "あなたの申請をパスするユーザーがいる" + @override + String get agrees_application => "あなたの申請をパスするユーザーがいる"; + /// "ご祝儀写真" + @override + String get red_photo => "ご祝儀写真"; + /// "不法露出の低俗な写真/ビデオを掲載しないでください、深刻の場合はアカウントが永遠凍結処理する" + @override + String get dont => "不法露出の低俗な写真/ビデオを掲載しないでください、深刻の場合はアカウントが永遠凍結処理する"; + /// "現行バージヨン" + @override + String get current_version => "現行バージヨン"; + /// "銀行コード関連する" + @override + String get bank_card => "銀行コード関連する"; + /// "口座開設銀行を選んでください" + @override + String get choose_bank => "口座開設銀行を選んでください"; + /// "銀行カード番号を入力してください" + @override + String get bank_number => "銀行カード番号を入力してください"; + /// "証明番号を記入してください" + @override + String get id_number => "証明番号を記入してください"; + /// "名前" + @override + String get name => "名前"; + /// "銀行カード番号" + @override + String get bank_number2 => "銀行カード番号"; + /// "証明番号" + @override + String get license_number => "証明番号"; + /// "携帯番号を関連する" + @override + String get bind_phone => "携帯番号を関連する"; + /// "彼のホームページ" + @override + String get his_homepage => "彼のホームページ"; + /// "彼女のホームページ" + @override + String get her_homepage => "彼女のホームページ"; + /// "ウィーチャット支払い" + @override + String get wechat_pay => "ウィーチャット支払い"; + /// "フェイスブック支払い" + @override + String get facebook_pay => "フェイスブック支払い"; + /// " google支払い" + @override + String get google_pay => " google支払い"; + /// "支払い成功" + @override + String get payment_successful => "支払い成功"; + /// "換金金額を設定" + @override + String get set_amount => "換金金額を設定"; + /// "Hコインの数を入力してください" + @override + String get enter_amount => "Hコインの数を入力してください"; + /// "換金可能" + @override + String get can_withdraw => "換金可能"; + /// "言語設定" + @override + String get language_set => "言語設定"; + /// "ユーザー協議" + @override + String get user_agreement => "ユーザー協議"; + /// "続料" + @override + String get renewal_fee => "続料"; + /// "すぐ開通" + @override + String get open_immediately => "すぐ開通"; + /// "トータル" + @override + String get total => "トータル"; + /// "半月" + @override + String get half_month => "半月"; + /// "/s1ヶ月" + @override + String get month2 => "/s1ヶ月"; + /// "シールドを解除" + @override + String get cancel_shield => "シールドを解除"; + /// "ブロック" + @override + String get blacklist2 => "ブロック"; + /// "( VIPは6秒延長できます)" + @override + String get longTime => "( VIPは6秒延長できます)"; + /// "画面を押してチェックする" + @override + String get longClick => "画面を押してチェックする"; + /// "先に有効なプログラムを終了してください" + @override + String get stop_program => "先に有効なプログラムを終了してください"; + /// "男性は男性をコレクションできない" + @override + String get not_love => "男性は男性をコレクションできない"; + /// "女性は女性をコレクションできない" + @override + String get not_love2 => "女性は女性をコレクションできない"; + /// "女神は無料リリースできます" + @override + String get women_free => "女神は無料リリースできます"; + /// "彼はまだ写真をアップロードしてない" + @override + String get not_up_man => "彼はまだ写真をアップロードしてない"; + /// "彼女はまだ写真をアップロードしてない" + @override + String get not_up_women => "彼女はまだ写真をアップロードしてない"; + /// "プラットフォームを通じて不法取引をしないでください、告発された事実を確認出来たら、アカウントは永遠凍結で処理する" + @override + String get not_illage => "プラットフォームを通じて不法取引をしないでください、告発された事実を確認出来たら、アカウントは永遠凍結で処理する"; + /// "申し込み済み" + @override + String get alreay_join => "申し込み済み"; + /// "この写真は削除しますか" + @override + String get sure_delete => "この写真は削除しますか"; + /// "すぐ入力" + @override + String get white_now => "すぐ入力"; + /// "あなたは自己紹介はまだ入力してない、魅力的な個人紹介はデートの成功に大きく影響を与えますよ" + @override + String get personal => "あなたは自己紹介はまだ入力してない、魅力的な個人紹介はデートの成功に大きく影響を与えますよ"; + /// "成功" + @override + String get success => "成功"; + /// "失敗" + @override + String get fail => "失敗"; + /// "認証されたユーザーのみご祝儀写真を設定できる" + @override + String get moneyPageTip => "認証されたユーザーのみご祝儀写真を設定できる"; + /// "あなたは申しみました、相手は気に入ったらあなたと連絡します" + @override + String get alreadyJoin => "あなたは申しみました、相手は気に入ったらあなたと連絡します"; + /// "ルール違反警告" + @override + String get waring => "ルール違反警告"; + /// "ユーザーのプライバシーを尊重し、スクリーンショットを撮らないでください。次回があれば、他のユーザーの写真を見ることを禁止する" + @override + String get userPravicy => "ユーザーのプライバシーを尊重し、スクリーンショットを撮らないでください。次回があれば、他のユーザーの写真を見ることを禁止する"; + /// "デート時間が切りました、変更してください" + @override + String get outTime => "デート時間が切りました、変更してください"; + /// "審査中" + @override + String get reviewing => "審査中"; + /// "審査成功" + @override + String get reviewed => "審査成功"; + /// "審査失敗" + @override + String get reviewedFail => "審査失敗"; + /// "ユーザーは先に銀行カードを関連してから換金することができる" + @override + String get needCard => "ユーザーは先に銀行カードを関連してから換金することができる"; + /// "女性は女性のダイナミックをコメントできません" + @override + String get women_not_d => "女性は女性のダイナミックをコメントできません"; + /// "男性性は男性のダイナミックをコメントできません" + @override + String get man_not_d => "男性性は男性のダイナミックをコメントできません"; + /// "写真があれば女性を引き付けることができるよ" + @override + String get have_picture => "写真があれば女性を引き付けることができるよ"; + /// "上にスライドして送信をキャンセルする" + @override + String get up_cancle => "上にスライドして送信をキャンセルする"; + /// "メッセージはブランクにできません" + @override + String get msg_not => "メッセージはブランクにできません"; + /// "この機能は録音権限を与える必要があります" + @override + String get need_record => "この機能は録音権限を与える必要があります"; + /// "ビデオファイルをダウンロードしている" + @override + String get downloading_video => "ビデオファイルをダウンロードしている"; + /// "問題のシリアル番号を再入力してください" + @override + String get reinput => "問題のシリアル番号を再入力してください"; + /// "あなたのダイナミックはユーザーに匿名で告発されました。システムで確認した結果よりこの動態は削除されました。二度と不正操作の場合、アカウントは永遠凍結されます。" + @override + String get dy_delete => "あなたのダイナミックはユーザーに匿名で告発されました。システムで確認した結果よりこの動態は削除されました。二度と不正操作の場合、アカウントは永遠凍結されます。"; + /// "あなたの番組はユーザーから匿名で告発されました。システムで確認した結果より番組を削除しました。二度と不正操作の場合、アカウントは永遠凍結されます。" + @override + String get pro_delete => "あなたの番組はユーザーから匿名で告発されました。システムで確認した結果より番組を削除しました。二度と不正操作の場合、アカウントは永遠凍結されます。"; + /// "あなたのコメントはユーザーから匿名で告発されました。システムで確認した結果よりコメントを削除しました。二度と不正操作の場合、アカウントは永遠凍結されます。" + @override + String get con_delete => "あなたのコメントはユーザーから匿名で告発されました。システムで確認した結果よりコメントを削除しました。二度と不正操作の場合、アカウントは永遠凍結されます。"; + /// "匿名ユーザーの告発より、システムはあなた最近ルール違反したことを確認出来た、ご受け取ったH幤を返済しました、二度と不正操作の場合、アカウントは永遠凍結されます" + @override + String get coin_returen => "匿名ユーザーの告発より、システムはあなた最近ルール違反したことを確認出来た、ご受け取ったH幤を返済しました、二度と不正操作の場合、アカウントは永遠凍結されます"; + /// "通話中はエロやわいせつなどの違法行為が禁止されています、一旦発見したらアカウントは永遠凍結を処理する" + @override + String get voicing => "通話中はエロやわいせつなどの違法行為が禁止されています、一旦発見したらアカウントは永遠凍結を処理する"; + /// "顧客サービス" + @override + String get help => "顧客サービス"; + /// "人工翻訳をオンにする" + @override + String get translate_on => "人工翻訳をオンにする"; + /// "人工翻訳をオフにする" + @override + String get translate_off => "人工翻訳をオフにする"; + /// "/s1 H幤を使ってSVIPになります" + @override + String get becomeSvip => "/s1 H幤を使ってSVIPになります"; + /// " svip権限をオンにできます" + @override + String get need_svip => " svip権限をオンにできます"; + /// " SVIPはVIPのチャージができません" + @override + String get cannot_vip => " SVIPはVIPのチャージができません"; + /// "あなたはもうオフラインです。メッセージの送信と受信ができません" + @override + String get offline => "あなたはもうオフラインです。メッセージの送信と受信ができません"; + /// "アカウントは他のデバイスに登録されました、もうオフラインです" + @override + String get otherLogin => "アカウントは他のデバイスに登録されました、もうオフラインです"; + /// "暫く新しいニュースがありません" + @override + String get no_new => "暫く新しいニュースがありません"; + /// "翻訳完了" + @override + String get over => "翻訳完了"; + /// "この翻訳内容に悪評価しますか?" + @override + String get bad_ev => "この翻訳内容に悪評価しますか?"; + /// "もっと気持ちよくチャットする" + @override + String get right5 => "もっと気持ちよくチャットする"; + /// "もっと気持ちよくに使える" + @override + String get right6 => "もっと気持ちよくに使える"; + /// "お兄ちゃん" + @override + String get man_vi => "お兄ちゃん"; + /// "お姉ちゃん" + @override + String get women_vi => "お姉ちゃん"; + /// "サービスの効率を高めるために、以下に問題があれば、直接シリアル番号を回答してくださいね!" + @override + String get kf_tips => "サービスの効率を高めるために、以下に問題があれば、直接シリアル番号を回答してくださいね!"; + /// "拒否されました" + @override + String get rejected => "拒否されました"; + /// "あなたは/s1H幤を支払って、VIPを購入しました" + @override + String get buy_vip => "あなたは/s1H幤を支払って、VIPを購入しました"; + /// "あなたは/s1H幤を支払って、ダイナミック番組を発表しました" + @override + String get buy_program => "あなたは/s1H幤を支払って、ダイナミック番組を発表しました"; + /// "あなたは/s1H幤換金申請は処理出来ました、あなたの銀行カードに/s1を振込ました、ご査収ください" + @override + String get del_add_money => "あなたは/s1H幤換金申請は処理出来ました、あなたの銀行カードに/s1を振込ました、ご査収ください"; + /// "あなたが換金/s1H幤の申請は審査中です" + @override + String get adding_money => "あなたが換金/s1H幤の申請は審査中です"; + /// "無料で通訳専任者がリアルタイムで通訳してくれます" + @override + String get free_translate => "無料で通訳専任者がリアルタイムで通訳してくれます"; + /// "あなたに専用顧客サービスを提供する" + @override + String get personalTraff => "あなたに専用顧客サービスを提供する"; + /// "人工翻訳中..." + @override + String get ManTranslate => "人工翻訳中..."; + /// "マシン翻訳中..." + @override + String get robotTranslate => "マシン翻訳中..."; + /// "人工翻訳完了" + @override + String get translated => "人工翻訳完了"; + /// "健康交流、低俗な内容を放送しないでください、発見したら削除します" + @override + String get delete_progarm => "健康交流、低俗な内容を放送しないでください、発見したら削除します"; + /// "位置決め権限未許可" + @override + String get open_location => "位置決め権限未許可"; + /// "他のユーザーの距離を得るために、位置決め権限を設定してください" + @override + String get get_location => "他のユーザーの距離を得るために、位置決め権限を設定してください"; + /// "もう一度押してログアウトします" + @override + String get confirm_exit => "もう一度押してログアウトします"; + /// "毎日/s1回のチャンスに無料放送を発表します" + @override + String get free_program => "毎日/s1回のチャンスに無料放送を発表します"; + /// "写真" + @override + String get picture => "写真"; + /// "カメラ" + @override + String get camera => "カメラ"; + /// "ビデオ" + @override + String get video => "ビデオ"; + /// "ご祝儀" + @override + String get red_money => "ご祝儀"; + /// "スティック" + @override + String get stick => "スティック"; + /// "押したまま話す" + @override + String get press_say => "押したまま話す"; + /// "/s1はあなたのご祝儀を受け取りました" + @override + String get get_money => "/s1はあなたのご祝儀を受け取りました"; + /// "あなたは/s1のご祝儀を受領しました" + @override + String get you_get_money => "あなたは/s1のご祝儀を受領しました"; + /// "/s1のご祝儀" + @override + String get ones_money => "/s1のご祝儀"; + /// "ご祝儀は期限切り" + @override + String get money_over => "ご祝儀は期限切り"; + /// "ファイルのダウンロードに失敗しました" + @override + String get downloading_fail => "ファイルのダウンロードに失敗しました"; + /// "ビデオファイルをダウンロードしています" + @override + String get downloading => "ビデオファイルをダウンロードしています"; + /// "未受け取ったご祝儀は、24時間後に払い戻しいたします" + @override + String get back_money => "未受け取ったご祝儀は、24時間後に払い戻しいたします"; + /// "ご祝儀は存在しません" + @override + String get no_money => "ご祝儀は存在しません"; + /// "ご祝儀は受領しました" + @override + String get already_money => "ご祝儀は受領しました"; + /// "期限切り、アカウントへ返却しました" + @override + String get back_user => "期限切り、アカウントへ返却しました"; + /// "受取を待つ" + @override + String get waiting_user => "受取を待つ"; + /// "相手が受け取りました" + @override + String get other_get => "相手が受け取りました"; + /// "ささやかな気持ちですが、どうぞお受け取りください" + @override + String get little => "ささやかな気持ちですが、どうぞお受け取りください"; + /// "お金を入れます" + @override + String get put_money => "お金を入れます"; + /// "金額" + @override + String get mount => "金額"; + /// "期限切り" + @override + String get over_time => "期限切り"; + /// "受け取りました" + @override + String get has_get => "受け取りました"; + /// "暫くプレゼントがない" + @override + String get no_gift => "暫くプレゼントがない"; + /// "プレゼントを贈る" + @override + String get sent_gift => "プレゼントを贈る"; + /// "入力してから/s1H幤が得る、関連する後修正できません" + @override + String get fill_tips => "入力してから/s1H幤が得る、関連する後修正できません"; + /// "招待コード関連する" + @override + String get bind_code => "招待コード関連する"; + /// "招待コード" + @override + String get invide_code => "招待コード"; + /// "削除確認" + @override + String get confirm_delete => "削除確認"; + /// "あなたは既にコメントしました" + @override + String get has_eva => "あなたは既にコメントしました"; + /// "オープン" + @override + String get open => "オープン"; + /// "音声" + @override + String get voice => "音声"; + /// "離して送信" + @override + String get release_send => "離して送信"; + /// "録音時間が短すぎます" + @override + String get time_little => "録音時間が短すぎます"; + /// "相手はオンラインではなく、連絡ことができません" + @override + String get not_online => "相手はオンラインではなく、連絡ことができません"; + /// "あなたは/s1へ/s2H幤のご祝儀を送りました" + @override + String get give_red_money => "あなたは/s1へ/s2H幤のご祝儀を送りました"; + /// "あなたは/s1から/s2H幤のご祝儀を受領しました" + @override + String get get_red_money => "あなたは/s1から/s2H幤のご祝儀を受領しました"; + /// "あなたは/s1へ/s2H幤を贈りました" + @override + String get give_other_money => "あなたは/s1へ/s2H幤を贈りました"; + /// "あなたは/s1から/s2H幤を貰いました" + @override + String get get_other_money => "あなたは/s1から/s2H幤を貰いました"; + /// "スーパーメンバー" + @override + String get svip => "スーパーメンバー"; + /// "お薦め" + @override + String get recommend => "お薦め"; + /// "あなたは(/s2H幤)を支払って、/s1のご礼儀写真を見ました" + @override + String get paid_you4 => "あなたは(/s2H幤)を支払って、/s1のご礼儀写真を見ました"; + /// "あなたは(/s2H幤)を支払って、/s1の写真を見ました" + @override + String get paid_you5 => "あなたは(/s2H幤)を支払って、/s1の写真を見ました"; + /// "あなたが有料で/s1の全部資料をロック解除しました" + @override + String get paid_you6 => "あなたが有料で/s1の全部資料をロック解除しました"; + /// " hiAPP許可及びサービス協議" + @override + String get UG_LINE0 => " hiAPP許可及びサービス協議"; + /// "[序言]" + @override + String get UG_LINE1 => "[序言]"; + /// "Qianhai Youlong Technology Co., Ltd.(以下は“Qianhai Youlong Technology Co., Ltd.”と略称) ユーザーは、このサービス契約(以下「契約」と略称)を真面目読み、完全に理解必要です。Qianhai Youlong Technology Co., Ltd.の責任の免除またはユーザー権利の制限を含む本契約の条款を完全に理解すること。深く読みこの契約に同意するかどうかを選択してください(未成年者は法的保護者と一緒に読んでください)。 本契約のすべての条件に同意しない限り、本契約の対象となる関連サービスを登録、ログイン、または使用する権利はありません。 あなたの登録、ログイン、使用などは、本契約に同意したものとみなされ、また本契約の条件に拘束されることも同意すること。" + @override + String get UG_LINE2 => "Qianhai Youlong Technology Co., Ltd.(以下は“Qianhai Youlong Technology Co., Ltd.”と略称) ユーザーは、このサービス契約(以下「契約」と略称)を真面目読み、完全に理解必要です。Qianhai Youlong Technology Co., Ltd.の責任の免除またはユーザー権利の制限を含む本契約の条款を完全に理解すること。深く読みこの契約に同意するかどうかを選択してください(未成年者は法的保護者と一緒に読んでください)。 本契約のすべての条件に同意しない限り、本契約の対象となる関連サービスを登録、ログイン、または使用する権利はありません。 あなたの登録、ログイン、使用などは、本契約に同意したものとみなされ、また本契約の条件に拘束されることも同意すること。"; + /// "本「契約」は、あなた「以下は“ユーザー”と略称」を「hiサービス」のユーザー登録、ログイン、および使用に関するQianhai Youlong Technology Co., Ltd.との間の契約です。本契約は、「hiサービス」に関連するQianhai Youlong Technology Co., Ltd.とユーザー間の権利と義務について説明しています。「ユーザー」とは、登録、ログイン、使用、閲覧する個人または団体を意味します。本契約を同意することは、本契約の条款を受けることとQianhai Youlong Technology Co., Ltd.がいつでも契約条款変更することも受け入れること。本「契約」は、Qianhai Youlong Technology Co., Ltd.がいつでも更新できます。更新された契約条款が発表されると、元の契約条款を置き換えます、改めて通知しませんので、ユーザーはこのAPPで契約条款の最新バージョンが確認できます。Qianhai Youlong Technology Co., Ltd.が契約条件を改訂した後、ユーザーが改訂された条款に同意しない場合、Qianhai Youlong Technology Co., Ltd.が提供するサービスの使用を直ちに停止してください。CyhdLimitedが提供するサービスを継続使用ユーザーは、改訂された契約に同意したものとみなされます。" + @override + String get UG_LINE3 => "本「契約」は、あなた「以下は“ユーザー”と略称」を「hiサービス」のユーザー登録、ログイン、および使用に関するQianhai Youlong Technology Co., Ltd.との間の契約です。本契約は、「hiサービス」に関連するQianhai Youlong Technology Co., Ltd.とユーザー間の権利と義務について説明しています。「ユーザー」とは、登録、ログイン、使用、閲覧する個人または団体を意味します。本契約を同意することは、本契約の条款を受けることとQianhai Youlong Technology Co., Ltd.がいつでも契約条款変更することも受け入れること。本「契約」は、Qianhai Youlong Technology Co., Ltd.がいつでも更新できます。更新された契約条款が発表されると、元の契約条款を置き換えます、改めて通知しませんので、ユーザーはこのAPPで契約条款の最新バージョンが確認できます。Qianhai Youlong Technology Co., Ltd.が契約条件を改訂した後、ユーザーが改訂された条款に同意しない場合、Qianhai Youlong Technology Co., Ltd.が提供するサービスの使用を直ちに停止してください。CyhdLimitedが提供するサービスを継続使用ユーザーは、改訂された契約に同意したものとみなされます。"; + /// "一、使用規則" + @override + String get UG_LINE4 => "一、使用規則"; + /// "1、ユーザーが十分了解且つ同意して、ただユーザーに情況シェア、伝送、取得用のプラットフォームに限られる。ユーザーは必ずアカウントを登録した後の全ての行為に責任を取ってください。ユーザーが伝送したあらゆる内容及びそれによって発生した全ての結果も含めている。" + @override + String get UG_LINE5 => "1、ユーザーが十分了解且つ同意して、ただユーザーに情況シェア、伝送、取得用のプラットフォームに限られる。ユーザーは必ずアカウントを登録した後の全ての行為に責任を取ってください。ユーザーが伝送したあらゆる内容及びそれによって発生した全ての結果も含めている。"; + /// "2、ユーザーがサービス中或いはサービスを通して伝送した全ての内容はQianhai Youlong Technology Co., Ltd.の観点と政策を反映していないことである。Qianhai Youlong Technology Co., Ltd.はそのに対して一切責任を負わないことである。" + @override + String get UG_LINE6 => "2、ユーザーがサービス中或いはサービスを通して伝送した全ての内容はQianhai Youlong Technology Co., Ltd.の観点と政策を反映していないことである。Qianhai Youlong Technology Co., Ltd.はそのに対して一切責任を負わないことである。"; + /// "3、ユーザーが十分了解且つ同意して、ユーザーネットワークに基づく社交情況ブラウザ製品、ユーザーが必ずその上に登録した情況の真実性、合法性、有効性を全て責任を取ること。ユーザーは他人に見せ掛けていけない、他人の名義で一切の情報を広まっていけない。登録したアカウントを悪用して他のユーザーに誤認されてはいけない。でないとQianhai Youlong Technology Co., Ltd.は直ちにサーブすを停止し、ユーザーアカウントを回収して、ユーザーにそのにより単独で一切の責任を負うことになる。" + @override + String get UG_LINE7 => "3、ユーザーが十分了解且つ同意して、ユーザーネットワークに基づく社交情況ブラウザ製品、ユーザーが必ずその上に登録した情況の真実性、合法性、有効性を全て責任を取ること。ユーザーは他人に見せ掛けていけない、他人の名義で一切の情報を広まっていけない。登録したアカウントを悪用して他のユーザーに誤認されてはいけない。でないとQianhai Youlong Technology Co., Ltd.は直ちにサーブすを停止し、ユーザーアカウントを回収して、ユーザーにそのにより単独で一切の責任を負うことになる。"; + /// "4、ユーザーが必ずその上に登録した情況の真実性、合法性、無害性、有効性を全部責任と取る。ユーザーが広まった情報に関わる一切の法律責任はユーザー本人が担当する、Qianhai Youlong Technology Co., Ltd.に関係ないことである。" + @override + String get UG_LINE8 => "4、ユーザーが必ずその上に登録した情況の真実性、合法性、無害性、有効性を全部責任と取る。ユーザーが広まった情報に関わる一切の法律責任はユーザー本人が担当する、Qianhai Youlong Technology Co., Ltd.に関係ないことである。"; + /// "5、Qianhai Youlong Technology Co., Ltd.が業務発展の必要を保留し、一方的に当サービスの全部或いは一部分のサービス内容をどんな時になんにも通知しない場合に変更、止まる、限定、終止或いはサービスを廃止する権利があり、ユーザーはそのリスクを負うことである。" + @override + String get UG_LINE9 => "5、Qianhai Youlong Technology Co., Ltd.が業務発展の必要を保留し、一方的に当サービスの全部或いは一部分のサービス内容をどんな時になんにも通知しない場合に変更、止まる、限定、終止或いはサービスを廃止する権利があり、ユーザーはそのリスクを負うことである。"; + /// "6、提供しているサーブす中には広告がある可能性があり、ユーザーは使用過程中に第三方サプライヤー、経営パートナーと提供している広告を現れることを同意する。" + @override + String get UG_LINE10 => "6、提供しているサーブす中には広告がある可能性があり、ユーザーは使用過程中に第三方サプライヤー、経営パートナーと提供している広告を現れることを同意する。"; + /// "7、ユーザーは下記内容を利用又はサービス制作、アップロード、コーピー、送信をできないこと:" + @override + String get UG_LINE11 => "7、ユーザーは下記内容を利用又はサービス制作、アップロード、コーピー、送信をできないこと:"; + /// "(1 ) 憲法に定められる基本原則を反対する;" + @override + String get UG_LINE12 => "(1 ) 憲法に定められる基本原則を反対する;"; + /// "(2) 国家安全に危害すること、国家秘密を漏れること、国家政策を顛倒すること、国家統一を破壊すること;" + @override + String get UG_LINE13 => "(2) 国家安全に危害すること、国家秘密を漏れること、国家政策を顛倒すること、国家統一を破壊すること;"; + /// "(3) 国家の栄誉と利益を損害すること;" + @override + String get UG_LINE14 => "(3) 国家の栄誉と利益を損害すること;"; + /// "(4) 民族の恨みを煽動すること、民族差別、民族団結を破壊すること;" + @override + String get UG_LINE15 => "(4) 民族の恨みを煽動すること、民族差別、民族団結を破壊すること;"; + /// "(5) 国家の宗教政策を破壊すること、邪教と封建迷信を宣伝すること;" + @override + String get UG_LINE16 => "(5) 国家の宗教政策を破壊すること、邪教と封建迷信を宣伝すること;"; + /// "(6) 謡言を散布すること、社会秩序をすること、社会安定を破壊すること;" + @override + String get UG_LINE17 => "(6) 謡言を散布すること、社会秩序をすること、社会安定を破壊すること;"; + /// "(7) 猥褻、プルノ、ギャンブル、暴力、殺人、恐怖あるいは犯罪を扇動すること;" + @override + String get UG_LINE18 => "(7) 猥褻、プルノ、ギャンブル、暴力、殺人、恐怖あるいは犯罪を扇動すること;"; + /// "(8) 他者を侮辱または中傷し、その法的権利および利益を侵害すること;" + @override + String get UG_LINE19 => "(8) 他者を侮辱または中傷し、その法的権利および利益を侵害すること;"; + /// "(9) 法律および行政規制により禁止されている内容及び情報。" + @override + String get UG_LINE20 => "(9) 法律および行政規制により禁止されている内容及び情報。"; + /// "8、Qianhai Youlong Technology Co., Ltd.は、その合理的な判断より、法令または本契約に違反、または他人の権利やセキュリティを侵害、妨害、脅迫する、または他人になります行為、Qianhai Youlong Technology Co., Ltd.は法律に従って前述のコンテンツの送信を停止する権利があるし、独自の裁量でこの条項に違反した人に対して適切な法的措置を取る権利もあり。これには、サービスからの違法、侵害、不適切なコンテンツの削除が含まれますが、これらに限定されません 、違反者のメンバーシップを終了し、サービスのすべてまたは一部を使用することを禁止し、法令に従って関連する情報を保存し関係部門へ報告すること。" + @override + String get UG_LINE21 => "8、Qianhai Youlong Technology Co., Ltd.は、その合理的な判断より、法令または本契約に違反、または他人の権利やセキュリティを侵害、妨害、脅迫する、または他人になります行為、Qianhai Youlong Technology Co., Ltd.は法律に従って前述のコンテンツの送信を停止する権利があるし、独自の裁量でこの条項に違反した人に対して適切な法的措置を取る権利もあり。これには、サービスからの違法、侵害、不適切なコンテンツの削除が含まれますが、これらに限定されません 、違反者のメンバーシップを終了し、サービスのすべてまたは一部を使用することを禁止し、法令に従って関連する情報を保存し関係部門へ報告すること。"; + /// "9、ユーザーの権利と義務:" + @override + String get UG_LINE22 => "9、ユーザーの権利と義務:"; + /// "(1 ) Qianhai Youlong Technology Co., Ltd.アカウントはQianhai Youlong Technology Co., Ltd.が所有しています、ユーザーは新規取得登録手順を完了すると、アカウントを使用する権利を取得しますが、この権利は元の申請者のものであり、アカウントの付与、借用、賃貸、譲渡、販売は禁止されること。Qianhai Youlong Technology Co., Ltd.はビジネス上のニーズにより、アカウントを回収する権利があり、また、ユーザーの写真、ビデオ、音声を使って製品プロモーション活動を実施することの権利もあること。" + @override + String get UG_LINE23 => "(1 ) Qianhai Youlong Technology Co., Ltd.アカウントはQianhai Youlong Technology Co., Ltd.が所有しています、ユーザーは新規取得登録手順を完了すると、アカウントを使用する権利を取得しますが、この権利は元の申請者のものであり、アカウントの付与、借用、賃貸、譲渡、販売は禁止されること。Qianhai Youlong Technology Co., Ltd.はビジネス上のニーズにより、アカウントを回収する権利があり、また、ユーザーの写真、ビデオ、音声を使って製品プロモーション活動を実施することの権利もあること。"; + /// "(2) ユーザーはQianhai Youlong Technology Co., Ltd.での個人情報、登録情報、および送信コンテンツを変更または削除する権利を持っていますが、関連情報を削除すると、システムに保存されているテキストや写真も削除されます。 ユーザーはこのリスクを負うこと。" + @override + String get UG_LINE24 => "(2) ユーザーはQianhai Youlong Technology Co., Ltd.での個人情報、登録情報、および送信コンテンツを変更または削除する権利を持っていますが、関連情報を削除すると、システムに保存されているテキストや写真も削除されます。 ユーザーはこのリスクを負うこと。"; + /// "(3) ユーザはアカウント情報とアカウントパスワードを安全に保つこと責任があり、ユーザーは、登録されたアカウントとパスワードが以下のアクションに対して法律責任を負う。ユーザーは、いかなる状況でも他のメンバーのアカウントまたはパスワードを使用しないことに同意する。 あなたは、誰かがあなたのアカウントまたはパスワードを使用していることを疑い場合、Qianhai Youlong Technology Co., Ltd.に直ちに連絡することを同意する。" + @override + String get UG_LINE25 => "(3) ユーザはアカウント情報とアカウントパスワードを安全に保つこと責任があり、ユーザーは、登録されたアカウントとパスワードが以下のアクションに対して法律責任を負う。ユーザーは、いかなる状況でも他のメンバーのアカウントまたはパスワードを使用しないことに同意する。 あなたは、誰かがあなたのアカウントまたはパスワードを使用していることを疑い場合、Qianhai Youlong Technology Co., Ltd.に直ちに連絡することを同意する。"; + /// "(4) ユーザは本契約の各条款を遵守し、正しく適度に使用するものとします、ユーザーが本契約の条款に違反した場合、Qianhai Youlong Technology Co., Ltd.は契約に従ってサービスを終了する権利を持、 同時に、Qianhai Youlong Technology Co., Ltd.はアカウントとユーザー名をいつでも回収する権利を保留しています。" + @override + String get UG_LINE26 => "(4) ユーザは本契約の各条款を遵守し、正しく適度に使用するものとします、ユーザーが本契約の条款に違反した場合、Qianhai Youlong Technology Co., Ltd.は契約に従ってサービスを終了する権利を持、 同時に、Qianhai Youlong Technology Co., Ltd.はアカウントとユーザー名をいつでも回収する権利を保留しています。"; + /// "(5) ユーザーが自分の英語アカウントを持っている場合、優先的に該当アカウントをアカウントとして登録する権利を持ちます、ただし、サービスがオンラインになってから一定期間内ユーザーがアカウントを登録していない場合、あるいは、ユーザーはウィーキャットアカウント登録しますが、該当英語アカウントをウィーキャットアカウントとして使用しない場合、ユーザーは該当英語アカウントをウィーキャットアカウント登録する権利を諦めることに見られる、資源を無駄しないために、Qianhai Youlong Technology Co., Ltd.は該当英語アカウントを回収及び他ユーザーに配分使用権利があります、それらに引きこされる問題はユーザー自身責任を負うこと。" + @override + String get UG_LINE27 => "(5) ユーザーが自分の英語アカウントを持っている場合、優先的に該当アカウントをアカウントとして登録する権利を持ちます、ただし、サービスがオンラインになってから一定期間内ユーザーがアカウントを登録していない場合、あるいは、ユーザーはウィーキャットアカウント登録しますが、該当英語アカウントをウィーキャットアカウントとして使用しない場合、ユーザーは該当英語アカウントをウィーキャットアカウント登録する権利を諦めることに見られる、資源を無駄しないために、Qianhai Youlong Technology Co., Ltd.は該当英語アカウントを回収及び他ユーザーに配分使用権利があります、それらに引きこされる問題はユーザー自身責任を負うこと。"; + /// "(6)資源を無駄しないために、ユーザーはアカウントを登録した後、長期間該当アカウントをログインしない場合、Qianhai Youlong Technology Co., Ltd.は該当アカウントを回収する権利があり、それらに引きこされる問題はユーザー自身責任を負うこと。" + @override + String get UG_LINE28 => "(6)資源を無駄しないために、ユーザーはアカウントを登録した後、長期間該当アカウントをログインしない場合、Qianhai Youlong Technology Co., Ltd.は該当アカウントを回収する権利があり、それらに引きこされる問題はユーザー自身責任を負うこと。"; + /// "(7) ユーザは紛争を起きた場合、告発機能を使ってプラットフォーム利益を維持できるユーザーから告発フィードバックを受け取った場合、状況を確認するために、告発されたユーザーは顧客サービス担当者に積極的に回答または協力する義務があります、告発された内容を確認できたら、ユーザに警告し、アカウント使用機能を制限してルール違反ことを制約する権利があります、厳重者に対してhiはアカウントを直接凍結する権利がありますし、アカウントの残高も返金されません。もし、アカウントは凍結された場合、ユーザーはサービス担当者に連絡可能です 。" + @override + String get UG_LINE29 => "(7) ユーザは紛争を起きた場合、告発機能を使ってプラットフォーム利益を維持できるユーザーから告発フィードバックを受け取った場合、状況を確認するために、告発されたユーザーは顧客サービス担当者に積極的に回答または協力する義務があります、告発された内容を確認できたら、ユーザに警告し、アカウント使用機能を制限してルール違反ことを制約する権利があります、厳重者に対してhiはアカウントを直接凍結する権利がありますし、アカウントの残高も返金されません。もし、アカウントは凍結された場合、ユーザーはサービス担当者に連絡可能です 。"; + /// "二、プライバシー保護" + @override + String get UG_LINE30 => "二、プライバシー保護"; + /// "ユーザーは、個人のプライバシー情報とは、ユーザーに対して個人識別、個人的なコミュニケーション情報を指すことに同意する、下記の情報を含め:ユーザーの本名、携帯電話番号、ウィーキャット、faceboodアカウント、IPアドレス。非個人のプライバシー情報とは、ユーザーの操作状態及びサービスの使用習慣、客観的にQianhai Youlong Technology Co., Ltd.サーバーへ反映されている基本情報、および個人のプライバシー情報の範囲外の他のすべての一般情報、ユーザーが開示することを同意する上記のプライバシー情報を指す。ユーザーの個人プライバシーを尊敬することはQianhai Youlong Technology Co., Ltd. 一貫の制度です、法律あるいは法律許可した政府部門からの要求あるいはユーザーの許可を得た原因以外、Qianhai Youlong Technology Co., Ltd.は合理的の方法でユーザーの個人プライバシーを保護する、ユーザーの許可がない限り、Qianhai Youlong Technology Co., Ltd.は協力パートナー以外の第三者にユーザーの個人プライバシー情報を開示する。ただし、ユーザーは登録の時、許可を選択して、またはQianhai Youlong Technology Co., Ltd.と協力パートナーとユーザーの個人プライバシー情報の開示は別の約束は以外、同時に発生する可能のリスクはユーザー自分負担する必要です、Qianhai Youlong Technology Co., Ltd.はこれについて責任を負いません。また、Qianhai Youlong Technology Co., Ltd.の技術とサービスを運用および改善するため、Qianhai Youlong Technology Co., Ltd.は自ら収集、使用あるいは第三者にユーザーの非個人プライバシー情報を提供する、これにより、Qianhai Youlong Technology Co., Ltd.はユーザーにより良いユーザーエクスペリエンスを提供し、Qianhai Youlong Technology Co., Ltd.のサービスの品質を向上させることができる。Qianhai Youlong Technology Co., Ltd. はユーザーとのインタラクティブ、またはユーザーの選択より収集出来たデータ、ユーザーのプライバシー設定及びユーザー使用製品と機能。Qianhai Youlong Technology Co., Ltd.が収集するデータには、SDK / API / JSコードバージョン、IPアドレス、プラットフォーム、タイムスタンプ、アプリケーション識別子、アプリケーションバージョン、アプリケーション配布チャネル、独立したデバイス識別子、iOS Advertising Identifier(IDFA)、Android Advertising識別子、ネットワークカード(MAC)アドレス、International Mobile Equipment Identity(IMEI)、デバイスモデル、端末メーカー、端末デバイスのオペレーティングシステムのバージョン、セッションの開始/停止時間、言語の場所、タイムゾーン、ネットワークステータス(WiFiなど) ハードドライブ、CPU、バッテリーの使用量などを含まれる場合がある。これにより、Qianhai Youlong Technology Co., Ltd.は、内部データ分析と調査、第三者SDK統計サービスを実施し、Qianhai Youlong Technology Co., Ltd.の製品またはサービスを改善することができます。ユーザーID情報の信頼性を確保し、ユーザーにより良いセキュリティを提供するために、ユーザーはID情報または顔の特徴などの生物識別情報(どちらも個人敏感情報)を提供して、特定の製品サービスまたは本人の認証を完成する。上記の情報は、ユーザーの身元の信頼性を確認するためにのみ使用されます。ユーザーが提供する上記の情報は、ユーザーがサービスを使用している間、Qianhai Youlong Technology Co., Ltd.による使用を引き続き許可します。Qianhai Youlong Technology Co., Ltd.はユーザーがログアウトすると使用を停止します。上記の情報は、中華人民共和国に保存されます。 国境を越えて送信が必要な場合、Qianhai Youlong Technology Co., Ltd.はユーザーの承認を取得します。 APPユーザーの認証はユーザーがユーザーのIDの信頼性を検証できる情報を提供する必要があります。関連情報はプラットフォーム監査にのみ使用され、介入を必要とする法務部門または関連部門を除き、他のユーザーに開示されたり、商業目的に使用されたりすることはありません。" + @override + String get UG_LINE31 => "ユーザーは、個人のプライバシー情報とは、ユーザーに対して個人識別、個人的なコミュニケーション情報を指すことに同意する、下記の情報を含め:ユーザーの本名、携帯電話番号、ウィーキャット、faceboodアカウント、IPアドレス。非個人のプライバシー情報とは、ユーザーの操作状態及びサービスの使用習慣、客観的にQianhai Youlong Technology Co., Ltd.サーバーへ反映されている基本情報、および個人のプライバシー情報の範囲外の他のすべての一般情報、ユーザーが開示することを同意する上記のプライバシー情報を指す。ユーザーの個人プライバシーを尊敬することはQianhai Youlong Technology Co., Ltd. 一貫の制度です、法律あるいは法律許可した政府部門からの要求あるいはユーザーの許可を得た原因以外、Qianhai Youlong Technology Co., Ltd.は合理的の方法でユーザーの個人プライバシーを保護する、ユーザーの許可がない限り、Qianhai Youlong Technology Co., Ltd.は協力パートナー以外の第三者にユーザーの個人プライバシー情報を開示する。ただし、ユーザーは登録の時、許可を選択して、またはQianhai Youlong Technology Co., Ltd.と協力パートナーとユーザーの個人プライバシー情報の開示は別の約束は以外、同時に発生する可能のリスクはユーザー自分負担する必要です、Qianhai Youlong Technology Co., Ltd.はこれについて責任を負いません。また、Qianhai Youlong Technology Co., Ltd.の技術とサービスを運用および改善するため、Qianhai Youlong Technology Co., Ltd.は自ら収集、使用あるいは第三者にユーザーの非個人プライバシー情報を提供する、これにより、Qianhai Youlong Technology Co., Ltd.はユーザーにより良いユーザーエクスペリエンスを提供し、Qianhai Youlong Technology Co., Ltd.のサービスの品質を向上させることができる。Qianhai Youlong Technology Co., Ltd. はユーザーとのインタラクティブ、またはユーザーの選択より収集出来たデータ、ユーザーのプライバシー設定及びユーザー使用製品と機能。Qianhai Youlong Technology Co., Ltd.が収集するデータには、SDK / API / JSコードバージョン、IPアドレス、プラットフォーム、タイムスタンプ、アプリケーション識別子、アプリケーションバージョン、アプリケーション配布チャネル、独立したデバイス識別子、iOS Advertising Identifier(IDFA)、Android Advertising識別子、ネットワークカード(MAC)アドレス、International Mobile Equipment Identity(IMEI)、デバイスモデル、端末メーカー、端末デバイスのオペレーティングシステムのバージョン、セッションの開始/停止時間、言語の場所、タイムゾーン、ネットワークステータス(WiFiなど) ハードドライブ、CPU、バッテリーの使用量などを含まれる場合がある。これにより、Qianhai Youlong Technology Co., Ltd.は、内部データ分析と調査、第三者SDK統計サービスを実施し、Qianhai Youlong Technology Co., Ltd.の製品またはサービスを改善することができます。ユーザーID情報の信頼性を確保し、ユーザーにより良いセキュリティを提供するために、ユーザーはID情報または顔の特徴などの生物識別情報(どちらも個人敏感情報)を提供して、特定の製品サービスまたは本人の認証を完成する。上記の情報は、ユーザーの身元の信頼性を確認するためにのみ使用されます。ユーザーが提供する上記の情報は、ユーザーがサービスを使用している間、Qianhai Youlong Technology Co., Ltd.による使用を引き続き許可します。Qianhai Youlong Technology Co., Ltd.はユーザーがログアウトすると使用を停止します。上記の情報は、中華人民共和国に保存されます。 国境を越えて送信が必要な場合、Qianhai Youlong Technology Co., Ltd.はユーザーの承認を取得します。 APPユーザーの認証はユーザーがユーザーのIDの信頼性を検証できる情報を提供する必要があります。関連情報はプラットフォーム監査にのみ使用され、介入を必要とする法務部門または関連部門を除き、他のユーザーに開示されたり、商業目的に使用されたりすることはありません。"; + /// "三、Qianhai Youlong Technology Co., Ltd.商標情報" + @override + String get UG_LINE32 => "三、Qianhai Youlong Technology Co., Ltd.商標情報"; + /// " Qianhai Youlong Technology Co., Ltd.サービスに関するlogoなどの図形、文字またはその構成、及び他Qianhai Youlong Technology Co., Ltd.マークと製品、サービス名称などは全部Qianhai Youlong Technology Co., Ltd.の商標です(以下略称“Qianhai Youlong Technology Co., Ltd.標示”)事前に Qianhai Youlong Technology Co., Ltd.の書式許可がないとユーザーはQianhai Youlong Technology Co., Ltd.標示 をいかなる方法で表示または他の処理が禁止、あなたがQianhai Youlong Technology Co., Ltd.標示の展示、使用、またはその他の権利を持っていることを他人に表明してはいけません。" + @override + String get UG_LINE33 => " Qianhai Youlong Technology Co., Ltd.サービスに関するlogoなどの図形、文字またはその構成、及び他Qianhai Youlong Technology Co., Ltd.マークと製品、サービス名称などは全部Qianhai Youlong Technology Co., Ltd.の商標です(以下略称“Qianhai Youlong Technology Co., Ltd.標示”)事前に Qianhai Youlong Technology Co., Ltd.の書式許可がないとユーザーはQianhai Youlong Technology Co., Ltd.標示 をいかなる方法で表示または他の処理が禁止、あなたがQianhai Youlong Technology Co., Ltd.標示の展示、使用、またはその他の権利を持っていることを他人に表明してはいけません。"; + /// "四、法律責任及び免責" + @override + String get UG_LINE34 => "四、法律責任及び免責"; + /// "1、ユーザーは本「協議」または関連サービス条項の規定に違反し、任意の第三者の主張によるいかなる賠償、要求または損失を引き起こし、合理的な弁護士費を含み、ユーザーはQianhai Youlong Technology Co., Ltd.と協力会社、関連会社を賠償することに同意し、損害を免除させること。" + @override + String get UG_LINE35 => "1、ユーザーは本「協議」または関連サービス条項の規定に違反し、任意の第三者の主張によるいかなる賠償、要求または損失を引き起こし、合理的な弁護士費を含み、ユーザーはQianhai Youlong Technology Co., Ltd.と協力会社、関連会社を賠償することに同意し、損害を免除させること。"; + /// "2、ユーザは、電信部門の通信回線の故障、技術問題、ネットワーク、コンピュータの故障、システムの不安定性及びその他の様々な不可抗力の原因によって被ったすべての損失については、Qianhai Youlong Technology Co., Ltd.及び協力機関は責任を負いません。" + @override + String get UG_LINE36 => "2、ユーザは、電信部門の通信回線の故障、技術問題、ネットワーク、コンピュータの故障、システムの不安定性及びその他の様々な不可抗力の原因によって被ったすべての損失については、Qianhai Youlong Technology Co., Ltd.及び協力機関は責任を負いません。"; + /// "3、技術障害などの不可抗事件によってサービスの正常運行に影響を与えた場合、Qianhai Youlong Technology Co., Ltd.と協力会社は第一時間内に関連会社と協力し、直ちに処理して修復することを承諾しましたが、ユーザーが被ったすべての損失に対して、Qianhai Youlong Technology Co., Ltd.と協力会社は責任を負いません。" + @override + String get UG_LINE37 => "3、技術障害などの不可抗事件によってサービスの正常運行に影響を与えた場合、Qianhai Youlong Technology Co., Ltd.と協力会社は第一時間内に関連会社と協力し、直ちに処理して修復することを承諾しましたが、ユーザーが被ったすべての損失に対して、Qianhai Youlong Technology Co., Ltd.と協力会社は責任を負いません。"; + /// "4、本サービスは大多数のインターネットサービスと同じで、ユーザーの原因、ネットサービスの質、社会環境などの要素の違いによって影響されるかもしれません。様々な安全問題に侵される可能性があります、他人がユーザーの資料を利用して、現実的な生活における嫌がらせを引き起こすかもしれません。ユーザーがインストールした他のソフトウェアや訪問した他のウェブサイトには「トロイの木馬」などのウィルスが含まれています。ユーザーのコンピュータ情報やデータの安全を脅かし、本サービスの正常な利用に影響を及ぼすなど。ユーザーは情報の安全と利用者資料の保護意識を強化し、損失や迷惑にならないように、パスワードの保護を強化してください。" + @override + String get UG_LINE38 => "4、本サービスは大多数のインターネットサービスと同じで、ユーザーの原因、ネットサービスの質、社会環境などの要素の違いによって影響されるかもしれません。様々な安全問題に侵される可能性があります、他人がユーザーの資料を利用して、現実的な生活における嫌がらせを引き起こすかもしれません。ユーザーがインストールした他のソフトウェアや訪問した他のウェブサイトには「トロイの木馬」などのウィルスが含まれています。ユーザーのコンピュータ情報やデータの安全を脅かし、本サービスの正常な利用に影響を及ぼすなど。ユーザーは情報の安全と利用者資料の保護意識を強化し、損失や迷惑にならないように、パスワードの保護を強化してください。"; + /// "5、ユーザーは、本サービスの利用はインターネットサービスに関わるため、各環節の不安定要素の影響を受ける可能性があることを理解してください。したがって、本サービスは、不可抗力、コンピュータウイルスまたはハッカー攻撃、システムの不安定性、ユーザーの位置、ユーザのシャットダウン、その他のいかなる技術、インターネット、通信回線の原因などによるサービスの中断またはユーザーの要求を満たすことができないリスクがあります。ユーザーは以上のリスクを負担し、Qianhai Youlong Technology Co., Ltd.は担保しない。その結果、ユーザが閲覧情報を送信したり、受信したりすることができなくなり、Qianhai Youlong Technology Co., Ltd.は一切の責任を負いません。" + @override + String get UG_LINE39 => "5、ユーザーは、本サービスの利用はインターネットサービスに関わるため、各環節の不安定要素の影響を受ける可能性があることを理解してください。したがって、本サービスは、不可抗力、コンピュータウイルスまたはハッカー攻撃、システムの不安定性、ユーザーの位置、ユーザのシャットダウン、その他のいかなる技術、インターネット、通信回線の原因などによるサービスの中断またはユーザーの要求を満たすことができないリスクがあります。ユーザーは以上のリスクを負担し、Qianhai Youlong Technology Co., Ltd.は担保しない。その結果、ユーザが閲覧情報を送信したり、受信したりすることができなくなり、Qianhai Youlong Technology Co., Ltd.は一切の責任を負いません。"; + /// "6、ユーザーは、サービスの使用中に、脅迫的、中傷的、好ましくない、または違法なコンテンツ、行動、または他者の権利(知的財産を含む)の侵害を含む、他者からの匿名性または匿名性があることを理解する必要があります 詐欺的な情報のリスク、ユーザーは上記のリスクを負わなければなりません、。Qianhai Youlong Technology Co., Ltd.と協力会社は本サービスに対していかなる種類の保証をしないで、明確であるかまたは暗黙的であるかに関わらず、すべての関連情報の真実性、適商性、ある特定の用途、所有権と非侵害性に適した黙示担保と条件を含み、それによっていかなる使用者の不正または不法使用サービスによって発生した直接、間接、偶然、特殊及び後続の損害に至るかについていかなる責任も負いません。" + @override + String get UG_LINE40 => "6、ユーザーは、サービスの使用中に、脅迫的、中傷的、好ましくない、または違法なコンテンツ、行動、または他者の権利(知的財産を含む)の侵害を含む、他者からの匿名性または匿名性があることを理解する必要があります 詐欺的な情報のリスク、ユーザーは上記のリスクを負わなければなりません、。Qianhai Youlong Technology Co., Ltd.と協力会社は本サービスに対していかなる種類の保証をしないで、明確であるかまたは暗黙的であるかに関わらず、すべての関連情報の真実性、適商性、ある特定の用途、所有権と非侵害性に適した黙示担保と条件を含み、それによっていかなる使用者の不正または不法使用サービスによって発生した直接、間接、偶然、特殊及び後続の損害に至るかについていかなる責任も負いません。"; + /// "7、Qianhai Youlong Technology Co., Ltd.で定義されている情報の内容は、文字、ソフトウェア、音声、写真、ビデオ、図表;広告中のすべての内容を含み;Qianhai Youlong Technology Co., Ltd.はユーザーに提供された商業情報で、これらのすべて著作権、商標権、その他の知的財産権と所有権は法律の保護を受けます。したがって、ユーザーはQianhai Youlong Technology Co., Ltd.と広告主の授権がある状況でしかこれらのコンテンツを使用できません。これらの内容を無断でコピー、修正、編集すること、またはコンテンツに関する派生商品を創造することは一切禁止です。" + @override + String get UG_LINE41 => "7、Qianhai Youlong Technology Co., Ltd.で定義されている情報の内容は、文字、ソフトウェア、音声、写真、ビデオ、図表;広告中のすべての内容を含み;Qianhai Youlong Technology Co., Ltd.はユーザーに提供された商業情報で、これらのすべて著作権、商標権、その他の知的財産権と所有権は法律の保護を受けます。したがって、ユーザーはQianhai Youlong Technology Co., Ltd.と広告主の授権がある状況でしかこれらのコンテンツを使用できません。これらの内容を無断でコピー、修正、編集すること、またはコンテンツに関する派生商品を創造することは一切禁止です。"; + /// "8、いずれの場合も、Qianhai Youlong Technology Co., Ltd.は任意の間接性、結果性、懲罰性、偶然性、特殊性または刑罰性の損害、ユーザーのサービスご利用による利益損失も含め、以上について責任を負いません(たとえすでにそのような損失の可能性が告知されたとしても。)。本契約にはパラドックスな規定が含まれているかもしれませんが、Qianhai Youlong Technology Co., Ltd.があなたに対して負担しているすべての責任は、どのような行為があっても、いつまでもメンバー期間内にサービスを利用してQianhai Youlong Technology Co., Ltd.に支払う費用を超えません。" + @override + String get UG_LINE42 => "8、いずれの場合も、Qianhai Youlong Technology Co., Ltd.は任意の間接性、結果性、懲罰性、偶然性、特殊性または刑罰性の損害、ユーザーのサービスご利用による利益損失も含め、以上について責任を負いません(たとえすでにそのような損失の可能性が告知されたとしても。)。本契約にはパラドックスな規定が含まれているかもしれませんが、Qianhai Youlong Technology Co., Ltd.があなたに対して負担しているすべての責任は、どのような行為があっても、いつまでもメンバー期間内にサービスを利用してQianhai Youlong Technology Co., Ltd.に支払う費用を超えません。"; + /// "五、VIP条項" + @override + String get UG_LINE43 => "五、VIP条項"; + /// "1、Hibok VIPは平等に会員の権利を享有し、同時にQianhai Youlong Technology Co., Ltd.の規則、本サービス条項と「ユーザー協議」を含むがこれに限らないの各条項を遵守しなければならない。" + @override + String get UG_LINE44 => "1、Hibok VIPは平等に会員の権利を享有し、同時にQianhai Youlong Technology Co., Ltd.の規則、本サービス条項と「ユーザー協議」を含むがこれに限らないの各条項を遵守しなければならない。"; + /// "2、Qianhai Youlong Technology Co., Ltd.の「ユーザー協議」に違反したた原因でVIPサービスの利用を一時停止させたことに関する損失はユーザー自身で負担すること。" + @override + String get UG_LINE45 => "2、Qianhai Youlong Technology Co., Ltd.の「ユーザー協議」に違反したた原因でVIPサービスの利用を一時停止させたことに関する損失はユーザー自身で負担すること。"; + /// "3、VIPはVIP資格の有効期限内にhiviipの各種付加価値サービスも享有できること。" + @override + String get UG_LINE46 => "3、VIPはVIP資格の有効期限内にhiviipの各種付加価値サービスも享有できること。"; + /// "4、VIPがVIP資格の有効期限内に自発的にVIP資格を終了したり、キャンセルしたりする場合、Qianhai Youlong Technology Co., Ltd.は当該VIPの残りのVIP資格の有効期限に対応するサービス費用を返還しないこと。" + @override + String get UG_LINE47 => "4、VIPがVIP資格の有効期限内に自発的にVIP資格を終了したり、キャンセルしたりする場合、Qianhai Youlong Technology Co., Ltd.は当該VIPの残りのVIP資格の有効期限に対応するサービス費用を返還しないこと。"; + /// "5、VIPは自分でhiの中で情報を伝達して、発表しておよびhi無料サービスあるいは有料サービスを使う法律責任を負って、VIPはhiサービスを使って、無料サービスと有料サービスの行為を含んで、すべて各法律法規、規則、規範性文書を守るべきであること。" + @override + String get UG_LINE48 => "5、VIPは自分でhiの中で情報を伝達して、発表しておよびhi無料サービスあるいは有料サービスを使う法律責任を負って、VIPはhiサービスを使って、無料サービスと有料サービスの行為を含んで、すべて各法律法規、規則、規範性文書を守るべきであること。"; + /// "6、VIPサービスを開通後は他人に譲り渡す、キャンセルなどはできません。" + @override + String get UG_LINE49 => "6、VIPサービスを開通後は他人に譲り渡す、キャンセルなどはできません。"; + /// "7、VIPはQianhai Youlong Technology Co., Ltd.無料サービスまたは有料サービスを利用する過程で、法律法規に違反する行為がある場合、Qianhai Youlong Technology Co., Ltd.は会員資格を取り消す権利があり、一切の補償もありません、会員は自ら責任を負うべきです。" + @override + String get UG_LINE50 => "7、VIPはQianhai Youlong Technology Co., Ltd.無料サービスまたは有料サービスを利用する過程で、法律法規に違反する行為がある場合、Qianhai Youlong Technology Co., Ltd.は会員資格を取り消す権利があり、一切の補償もありません、会員は自ら責任を負うべきです。"; + /// "六、他条款" + @override + String get UG_LINE51 => "六、他条款"; + /// "1、Qianhai Youlong Technology Co., Ltd.は慎重にユーザーに本「協議」中のQianhai Youlong Technology Co., Ltd.の責任を免除し、ユーザーの義務を強める条項に注意してください。未成年者は法定保護者の同伴で本「協議」を読むべきです。以上の各条項の内容の最終説明権と修正権はQianhai Youlong Technology Co., Ltd.の所有になります。" + @override + String get UG_LINE52 => "1、Qianhai Youlong Technology Co., Ltd.は慎重にユーザーに本「協議」中のQianhai Youlong Technology Co., Ltd.の責任を免除し、ユーザーの義務を強める条項に注意してください。未成年者は法定保護者の同伴で本「協議」を読むべきです。以上の各条項の内容の最終説明権と修正権はQianhai Youlong Technology Co., Ltd.の所有になります。"; + /// "2、本「協議」に定められた如何なる条項の一部または全部無効者は、他の条項の効力に影響しません。" + @override + String get UG_LINE53 => "2、本「協議」に定められた如何なる条項の一部または全部無効者は、他の条項の効力に影響しません。"; + /// "3、本「協議」の解釈、効力及び紛争の解決は中華人民共和国の法律に適用される。ユーザーとQianhai Youlong Technology Co., Ltd.の間に如何なる紛争や紛争が発生した場合、まず友好的に協議して解決しなければならず、協議が成立しない場合、ユーザーはここで紛争や争議をQianhai Youlong Technology Co., Ltd.住所地の人民法院の管轄に提出することに完全に同意すること。" + @override + String get UG_LINE54 => "3、本「協議」の解釈、効力及び紛争の解決は中華人民共和国の法律に適用される。ユーザーとQianhai Youlong Technology Co., Ltd.の間に如何なる紛争や紛争が発生した場合、まず友好的に協議して解決しなければならず、協議が成立しない場合、ユーザーはここで紛争や争議をQianhai Youlong Technology Co., Ltd.住所地の人民法院の管轄に提出することに完全に同意すること。"; + /// "4、本『契約』の著作権はQianhai Youlong Technology Co., Ltd.が所有し、Qianhai Youlong Technology Co., Ltd.は一切の解釈と修正の権利を保留します。" + @override + String get UG_LINE55 => "4、本『契約』の著作権はQianhai Youlong Technology Co., Ltd.が所有し、Qianhai Youlong Technology Co., Ltd.は一切の解釈と修正の権利を保留します。"; + /// "Qianhai Youlong Technology Co., Ltd." + @override + String get UG_LINE56 => "Qianhai Youlong Technology Co., Ltd."; + /// "ネットワーク異常" + @override + String get net_error => "ネットワーク異常"; + /// "お名前を入力してください" + @override + String get enter_name => "お名前を入力してください"; + /// "訳" + @override + String get translate => "訳"; + /// "位置" + @override + String get locate => "位置"; + /// "押しまま録音,離して送信" + @override + String get voice_tips => "押しまま録音,離して送信"; + /// "アンロック" + @override + String get unlock => "アンロック"; + /// "チャット内容を入力してください" + @override + String get input_content => "チャット内容を入力してください"; + /// "接続中..." + @override + String get connecting => "接続中..."; + /// "登録中..." + @override + String get logining => "登録中..."; + /// "/s1はあなたのレビューリクエストを拒否されたました" + @override + String get reject_reply => "/s1はあなたのレビューリクエストを拒否されたました"; + /// " H幣は入金三日間以内告発されない場合、両替可能です(1:1000ベトナムドン)" + @override + String get warning_text => " H幣は入金三日間以内告発されない場合、両替可能です(1:1000ベトナムドン)"; + /// "入力数量は大きくても/s1" + @override + String get more_big => "入力数量は大きくても/s1"; + /// "入力数量は少なくても/s1" + @override + String get little_min => "入力数量は少なくても/s1"; + /// "/s1音声呼び出しに招待する" + @override + String get voice_msg => "/s1音声呼び出しに招待する"; + /// "あなたは相手に/s1个/s2を贈りました" + @override + String get send_gift => "あなたは相手に/s1个/s2を贈りました"; + /// "先方は/s1个/s2アイテムを贈りました" + @override + String get receive_gift => "先方は/s1个/s2アイテムを贈りました"; + /// "非VIPは申し込みできない" + @override + String get cannot_join => "非VIPは申し込みできない"; + /// "バックしました" + @override + String get alreay_back => "バックしました"; + /// "ファイルが大き過ぎ" + @override + String get video_more_big => "ファイルが大き過ぎ"; + /// "全てを選択" + @override + String get select_all => "全てを選択"; + /// "再接続" + @override + String get re_connect => "再接続"; + /// "離して送信、スライドしてキャンセル" + @override + String get voice_tips2 => "離して送信、スライドしてキャンセル"; + /// "国" + @override + String get country => "国"; + /// "写真検定中" + @override + String get have_picture_view => "写真検定中"; + /// "スピーカー再生" + @override + String get speaker_play => "スピーカー再生"; + /// "受話器再生" + @override + String get handset_playback => "受話器再生"; + /// "受話器モード" + @override + String get play_model => "受話器モード"; + /// "パスワードが短すぎる" + @override + String get password_less => "パスワードが短すぎる"; + /// "歳" + @override + String get years_old => "歳"; + /// "匿名のユーザーからの告発を受けて、最近の不正行為を確認しました。二度と不正行為をしないでください。次回があれば、アカウントを凍結します" + @override + String get coin_returen1 => "匿名のユーザーからの告発を受けて、最近の不正行為を確認しました。二度と不正行為をしないでください。次回があれば、アカウントを凍結します"; + /// "すでに最新バージョンです" + @override + String get already_new => "すでに最新バージョンです"; + /// "すぐ試します" + @override + String get test_it => "すぐ試します"; + /// "新しいバージョンが発見" + @override + String get found_new => "新しいバージョンが発見"; + /// "広告" + @override + String get ad => "広告"; + /// "注目" + @override + String get attention => "注目"; + /// "ファン" + @override + String get fans => "ファン"; + /// "/s1 は私の資料ベージを見るリクエストがあります" + @override + String get apply_see => "/s1 は私の資料ベージを見るリクエストがあります"; + /// "/s1 は私のリクエストをパスしました" + @override + String get agree_apply => "/s1 は私のリクエストをパスしました"; + /// "/s1 はご祝儀写真を見ました" + @override + String get see_redBag => "/s1 はご祝儀写真を見ました"; + /// "注意" + @override + String get notice => "注意"; + /// "携帯電話の設定で通知権限をオンにして、メッセージの通知が受け取ります。" + @override + String get notice_open => "携帯電話の設定で通知権限をオンにして、メッセージの通知が受け取ります。"; + /// "通知権限がオンになっていません" + @override + String get open_notice => "通知権限がオンになっていません"; + /// "通知権限がオンになっていませんので、通知を受信できません" + @override + String get not_open => "通知権限がオンになっていませんので、通知を受信できません"; + /// "換金を申請した/s1H幤が返却されました、関連されたアカウントが正しいかを確認してください" + @override + String get withdraw_fail => "換金を申請した/s1H幤が返却されました、関連されたアカウントが正しいかを確認してください"; + /// "タイムカプセル" + @override + String get dynamics => "タイムカプセル"; + /// "注釈とタグ" + @override + String get Remark => "注釈とタグ"; + /// "設定ノート" + @override + String get setRemark => "設定ノート"; + /// "/s1通のコメント" + @override + String get content_num => "/s1通のコメント"; + /// "ポイント交換で/s1H幤を得る" + @override + String get Redeem => "ポイント交換で/s1H幤を得る"; + /// "携帯メモリーにアクセスする権限がありません" + @override + String get location_permission => "携帯メモリーにアクセスする権限がありません"; + /// "カメラにアクセスする権限がありません" + @override + String get camera_permission => "カメラにアクセスする権限がありません"; + /// "アルバムにアクセスする権限がありません" + @override + String get photo_permission => "アルバムにアクセスする権限がありません"; + /// "マイクにアクセス権限がありません" + @override + String get video_permission => "マイクにアクセス権限がありません"; + /// "ご祝儀が期限切り" + @override + String get your_redMoney_over => "ご祝儀が期限切り"; + /// "相手からのご祝儀が期限切り" + @override + String get other_redMoney_over => "相手からのご祝儀が期限切り"; + /// "ちょっと不具合があるようです..." + @override + String get server_error_tips => "ちょっと不具合があるようです..."; + /// "ステッカー" + @override + String get emoji => "ステッカー"; + /// "本日サインして/s1ポイントが受け入れる" + @override + String get today_score => "本日サインして/s1ポイントが受け入れる"; + /// "1.毎日サインしてポイントが受け入れます、累積日数が多ければ多いほどポイントが高くなります.\n2.ポイントはH幤に交換できます、交換はポイントを消費しますので慎重に交換してください.\n3.サインは毎月の最終日にリセットされ、ポイントもクリアされます。時間内に交換することを忘れないでください." + @override + String get sign_tips => "1.毎日サインしてポイントが受け入れます、累積日数が多ければ多いほどポイントが高くなります.\n2.ポイントはH幤に交換できます、交換はポイントを消費しますので慎重に交換してください.\n3.サインは毎月の最終日にリセットされ、ポイントもクリアされます。時間内に交換することを忘れないでください."; + /// "サイン" + @override + String get sign_in => "サイン"; + /// "私のポイント" + @override + String get my_score => "私のポイント"; + /// "すぐサインする" + @override + String get signin_now => "すぐサインする"; + /// "累計サイン/s1日" + @override + String get sign_in_day => "累計サイン/s1日"; + /// "交換しました" + @override + String get have_get => "交換しました"; + /// "スキャン " + @override + String get scan => "スキャン "; + /// "自分のQRコード" + @override + String get my_qr => "自分のQRコード"; + /// "スキャンして友人を追加する" + @override + String get scan_and_add => "スキャンして友人を追加する"; + /// "高徳マップ" + @override + String get amap => "高徳マップ"; + /// "百度マップ" + @override + String get baidumap => "百度マップ"; + /// "Google マップ" + @override + String get googlemap => "Google マップ"; + /// "Apple マップ" + @override + String get applemap => "Apple マップ"; + /// "オンにする" + @override + String get go_open => "オンにする"; + /// "プレビュー" + @override + String get Preview => "プレビュー"; + /// "アルバム" + @override + String get Photo_album => "アルバム"; + /// "全ての画像" + @override + String get all_photo => "全ての画像"; + /// "/s1枚の画像を選択しました" + @override + String get have_select => "/s1枚の画像を選択しました"; + /// "読み込み中…" + @override + String get loading => "読み込み中…"; + /// "新しいメッセージがあります" + @override + String get new_chat_msg => "新しいメッセージがあります"; + /// "新しい音声メッセージがあります" + @override + String get new_video_msg => "新しい音声メッセージがあります"; + /// "/s1から友人になる申請が入りました" + @override + String get apply_friends => "/s1から友人になる申請が入りました"; + /// "/s1は友人の追加をパスしました" + @override + String get applyed_friends => "/s1は友人の追加をパスしました"; + /// "連絡先にアクセスする権限がありません" + @override + String get contact_permission => "連絡先にアクセスする権限がありません"; + /// "連絡先" + @override + String get contact => "連絡先"; + /// "検索" + @override + String get search => "検索"; + /// "携帯のアドレス帳から追加" + @override + String get contact_add => "携帯のアドレス帳から追加"; + /// "発見" + @override + String get find => "発見"; + /// "翻訳ロボット" + @override + String get translate_robot => "翻訳ロボット"; + /// "こんにちは、私は翻訳ロボットです…" + @override + String get robot_hello => "こんにちは、私は翻訳ロボットです…"; + /// "中国語(簡体字)" + @override + String get Simplified_Chinese => "中国語(簡体字)"; + /// "中国語(繁体字)" + @override + String get traditional_Chinese => "中国語(繁体字)"; + /// "英語" + @override + String get english => "英語"; + /// "ベトナム語" + @override + String get Vietnamese => "ベトナム語"; + /// "韓国語" + @override + String get Korean => "韓国語"; + /// "日本語" + @override + String get Japanese => "日本語"; + /// "友人の追加" + @override + String get add_friends => "友人の追加"; + /// "見知らぬ人" + @override + String get stranger => "見知らぬ人"; + /// "見知らぬ人からのメッセージを受信する" + @override + String get receive_stranger => "見知らぬ人からのメッセージを受信する"; + /// "SignIn" + @override + String get signin => "SignIn"; + /// "メッセージの受信を拒否された、すべての情報のロックを解除し続けますか。" + @override + String get stranger_close => "メッセージの受信を拒否された、すべての情報のロックを解除し続けますか。"; + /// "追加" + @override + String get add => "追加"; + /// "追加済み" + @override + String get added => "追加済み"; + /// "相手は見知らぬ人からのメッセージの受信を拒否した。" + @override + String get stranger_close_tips => "相手は見知らぬ人からのメッセージの受信を拒否した。"; + /// "翻訳失敗" + @override + String get translate_fail => "翻訳失敗"; + /// "ご祝儀写真を設定する前に写真をアップロードしてください。" + @override + String get no_photos => "ご祝儀写真を設定する前に写真をアップロードしてください。"; + /// "あなたのアピールコメント:/s1アピール失敗" + @override + String get successful_appeal1 => "あなたのアピールコメント:/s1アピール失敗"; + /// "追加しました,相手の同意を待つ" + @override + String get add_success => "追加しました,相手の同意を待つ"; + /// "他人が立て替える" + @override + String get other_pay => "他人が立て替える"; + /// "友人認証" + @override + String get friend_verification => "友人認証"; + /// "認証申請は発送しました、相手の承認待ち" + @override + String get add_friends_tips => "認証申請は発送しました、相手の承認待ち"; + /// "私は/s1" + @override + String get i_am => "私は/s1"; + /// "許可" + @override + String get agree => "許可"; + /// "\"Hi\"《プライバシー協議》に同意していただくと使えます" + @override + String get privacyAgreement => "\"Hi\"《プライバシー協議》に同意していただくと使えます"; + /// "プライバシー協議" + @override + String get privacy => "プライバシー協議"; + /// "Hi!友人要請が入りました、誰か確認しましょう" + @override + String get notification_addfriend => "Hi!友人要請が入りました、誰か確認しましょう"; + /// "顔を付き合わせて友人追加しかできませんよ" + @override + String get distance_long => "顔を付き合わせて友人追加しかできませんよ"; + /// "翻訳内容の正確さのために、略語は遠慮してください" + @override + String get chat_tips => "翻訳内容の正確さのために、略語は遠慮してください"; + /// "ファンリスト" + @override + String get fans_list => "ファンリスト"; + /// "機能内テスト中" + @override + String get system_not_open => "機能内テスト中"; + /// "iOSクライアントはまだサポートされていません。Androidクライアントを使って引き出したり、下のボタンを押して引き出したりできます" + @override + String get service_withdraw_tips => "iOSクライアントはまだサポートされていません。Androidクライアントを使って引き出したり、下のボタンを押して引き出したりできます"; + /// "クリックして引き出し" + @override + String get withdraw_tips => "クリックして引き出し"; + /// "メンバー追加" + @override + String get add_member => "メンバー追加"; + /// "メンバー削除" + @override + String get delete_member => "メンバー削除"; + /// "グループ名を修正" + @override + String get change_group_name => "グループ名を修正"; + /// "マイエイリアスグループ" + @override + String get my_group_nickname => "マイエイリアスグループ"; + /// "グループチャット" + @override + String get group_chat => "グループチャット"; + /// "グループチャットを作る" + @override + String get create_group_chat => "グループチャットを作る"; + /// "認証申請を送信必要、相手がパスまで待ちます" + @override + String get added_friends_tips => "認証申請を送信必要、相手がパスまで待ちます"; + /// "グループ名" + @override + String get group_chat_name => "グループ名"; + /// "ここであなたのグループニックネームを設定できます、このニックネームはこのグループにしか表示されません" + @override + String get my_group_nickname_tips => "ここであなたのグループニックネームを設定できます、このニックネームはこのグループにしか表示されません"; + /// "男神タイムカプセル" + @override + String get man_gold => "男神タイムカプセル"; + /// "女神タイムカプセル" + @override + String get woman_gold => "女神タイムカプセル"; + /// "新しいグループオーナーを選択" + @override + String get choose_group_owner => "新しいグループオーナーを選択"; + /// "グループ通知" + @override + String get group_announcement => "グループ通知"; + /// "チャットメッセージ" + @override + String get chat_news => "チャットメッセージ"; + /// "グループQRコード" + @override + String get group_qr => "グループQRコード"; + /// "グループを管理" + @override + String get group_setting => "グループを管理"; + /// "ミュート通知" + @override + String get close_news_notice => "ミュート通知"; + /// "一番上に表示する" + @override + String get set_chat_top => "一番上に表示する"; + /// "グループメンバーのニックネームを表示" + @override + String get show_group_member_name => "グループメンバーのニックネームを表示"; + /// "退出後グループチャットの他のメンバーには通知せず,これからこのグループからメッセージを受け取りません" + @override + String get quit_group_tips => "退出後グループチャットの他のメンバーには通知せず,これからこのグループからメッセージを受け取りません"; + /// "削除して退出" + @override + String get quit_and_delete => "削除して退出"; + /// "さらにメンバーを見る" + @override + String get show_more_member => "さらにメンバーを見る"; + /// "グループチャットの招待確認" + @override + String get group_invite => "グループチャットの招待確認"; + /// "グループオーナー管理権譲渡" + @override + String get change_group_owner => "グループオーナー管理権譲渡"; + /// "有効にすると、グループメンバーは、グループに友人を招待するためにグループオーナーからの確認を必要とします。ORコードスキャンしてグループに入ることは同時に停止されました。" + @override + String get group_setting_tips => "有効にすると、グループメンバーは、グループに友人を招待するためにグループオーナーからの確認を必要とします。ORコードスキャンしてグループに入ることは同時に停止されました。"; + /// "招待内容" + @override + String get invite_detail => "招待内容"; + /// "未命名" + @override + String get undefine_name => "未命名"; + /// "グループQRコードカード" + @override + String get group_qr_code => "グループQRコードカード"; + /// "該当QRコード七日内(/s1月/s2日前)有効,再度ログインすると更新されます" + @override + String get group_qr_code_tips => "該当QRコード七日内(/s1月/s2日前)有効,再度ログインすると更新されます"; + /// "女神人気" + @override + String get Goddess_heat => "女神人気"; + /// "累計収穫のプレゼント" + @override + String get Goddess_heat_tips => "累計収穫のプレゼント"; + /// "新しい友人" + @override + String get new_friends => "新しい友人"; + /// "三日前" + @override + String get before_three_day => "三日前"; + /// "この三日間" + @override + String get after_three_day => "この三日間"; + /// "チャット履歴の削去" + @override + String get group_clean_chat_record => "チャット履歴の削去"; + /// "確認" + @override + String get check => "確認"; + /// "友人要請" + @override + String get apply_fro_friends => "友人要請"; + /// "非VIPは引き出しできません" + @override + String get no_vip_cannot_withdraw => "非VIPは引き出しできません"; + /// "このユーザは認証されていません、騙されないように注意してください" + @override + String get not_true_woman => "このユーザは認証されていません、騙されないように注意してください"; + /// "グループチャットに参加する" + @override + String get join_group => "グループチャットに参加する"; + /// "Appleで登録" + @override + String get sign_in_apple => "Appleで登録"; + /// "グループオーナーだけがグループ通知を編集することができる" + @override + String get only_host => "グループオーナーだけがグループ通知を編集することができる"; + /// "あなたは相手に/s1個プレゼントを贈りました" + @override + String get send_gift1 => "あなたは相手に/s1個プレゼントを贈りました"; + /// "相手は/s1個プレゼントをあなたに贈りました" + @override + String get receive_gift1 => "相手は/s1個プレゼントをあなたに贈りました"; + /// "あなたはもうこのグループにいません" + @override + String get not_in_group => "あなたはもうこのグループにいません"; + /// "作成中です,少々お待ちください" + @override + String get creating_group => "作成中です,少々お待ちください"; + /// "条" + @override + String get article => "条"; + /// "このグループはすでにグループ認証をオンにしました。招待によってのみグループに入ることができます" + @override + String get group_open_verification => "このグループはすでにグループ認証をオンにしました。招待によってのみグループに入ることができます"; + /// "グループメンバー" + @override + String get group_memeber => "グループメンバー"; + /// "/s1名友人をこのグループに招待する" + @override + String get invite_members => "/s1名友人をこのグループに招待する"; + /// "トータル/s1人" + @override + String get total_members => "トータル/s1人"; + /// "QRコードが失効しました" + @override + String get qr_outtime => "QRコードが失効しました"; + /// "このグループ通知がありません" + @override + String get no_goupr_info => "このグループ通知がありません"; + /// "あなたは/s1をグループに招待する" + @override + String get you_invite => "あなたは/s1をグループに招待する"; + /// "あなたは/s1にグループへ招待されました" + @override + String get invite_you => "あなたは/s1にグループへ招待されました"; + /// " /s1 は /s2 を招待しました" + @override + String get invite_someone => " /s1 は /s2 を招待しました"; + /// "あなた" + @override + String get you => "あなた"; + /// " /s1は /s2 をグループに削除しました" + @override + String get delete_group => " /s1は /s2 をグループに削除しました"; + /// "あなたは新しいグループオーナーになりました" + @override + String get you_group_owner => "あなたは新しいグループオーナーになりました"; + /// "/s1は新しいグループオーナーになりました" + @override + String get someone_group_owner => "/s1は新しいグループオーナーになりました"; + /// "グループ名は/s1に変更しました" + @override + String get change_group_owner1 => "グループ名は/s1に変更しました"; + /// "グループ通知は更新しました" + @override + String get update_group_announce => "グループ通知は更新しました"; + /// "あなたはQRコードスキャンしてグループに入る" + @override + String get you_qr => "あなたはQRコードスキャンしてグループに入る"; + /// "/s1はQRコードスキャンしてグループに入る" + @override + String get others_qr => "/s1はQRコードスキャンしてグループに入る"; + /// "\"/s1\"は/s2名友人をグループに招待したい \$確認\$ " + @override + String get invite_confirm => "\"/s1\"は/s2名友人をグループに招待したい \$確認\$ "; + /// " \"/s1\" は\"/s2\" をグループに招待したいです " + @override + String get want_invite_confirm => " \"/s1\" は\"/s2\" をグループに招待したいです "; + /// "\"/s1\" はグループに入りました、確認済み" + @override + String get join_group_confirm => "\"/s1\" はグループに入りました、確認済み"; + /// "あなたは /s1にグループへ招待されました " + @override + String get you_invite_gourp => "あなたは /s1にグループへ招待されました "; + /// " \"/s1\" はグループに入りました " + @override + String get someone_join_group => " \"/s1\" はグループに入りました "; + /// "グループオーナーはすでに「グループチャット招待確認」をオンにしています。グループメンバーはグループオーナーを確認してから友達をグループに招待することができます" + @override + String get group_setting_tips1 => "グループオーナーはすでに「グループチャット招待確認」をオンにしています。グループメンバーはグループオーナーを確認してから友達をグループに招待することができます"; + /// "グループオーナーがデフォルトのグループ参加方法を戻す" + @override + String get group_setting_tips2 => "グループオーナーがデフォルトのグループ参加方法を戻す"; + /// "グループメンバーが上限になりました" + @override + String get members_max => "グループメンバーが上限になりました"; + /// "グループの数量は上限になりました" + @override + String get group_max => "グループの数量は上限になりました"; + /// "私の請求書" + @override + String get my_money_info => "私の請求書"; + /// "残高" + @override + String get my_left_money => "残高"; + /// "H幣はチャージや両替で得られます、引き出しができません" + @override + String get money_tips => "H幣はチャージや両替で得られます、引き出しができません"; + /// "所得明細" + @override + String get get_money_detail => "所得明細"; + /// "Hibox收入" + @override + String get hibok_money => "Hibox收入"; + /// "H幤に両替" + @override + String get charge_h => "H幤に両替"; + /// "引き出し規則" + @override + String get charge_tips => "引き出し規則"; + /// "百変の位置" + @override + String get splash_tips1 => "百変の位置"; + /// "翻訳ロボット" + @override + String get splash_tips2 => "翻訳ロボット"; + /// "交友APP" + @override + String get splash_tips3 => "交友APP"; + /// "百変の女神,好きのを選ぶ" + @override + String get splash_tips_content1 => "百変の女神,好きのを選ぶ"; + /// "音声チャット" + @override + String get splash_tips_content2 => "音声チャット"; + /// "言語問題解決" + @override + String get splash_tips_content3 => "言語問題解決"; + /// "すぐ体験" + @override + String get splash_go => "すぐ体験"; + /// "収入から/s1H幤を両替します" + @override + String get change_h_coin => "収入から/s1H幤を両替します"; + /// "申し立ては成功し、システムは返金しました" + @override + String get Representation_succes => "申し立ては成功し、システムは返金しました"; + /// "システム支払い" + @override + String get system_give => "システム支払い"; + /// "引き出し申請は失敗しました,返送されました" + @override + String get exchange_fail => "引き出し申請は失敗しました,返送されました"; + /// "Hibox収入で/s 1 H幤に両替します" + @override + String get hibok_exchange => "Hibox収入で/s 1 H幤に両替します"; + /// "招待コード関連成功" + @override + String get bind_code_success => "招待コード関連成功"; + /// "人工翻訳のために/s1H幤を消費しました" + @override + String get translate_money => "人工翻訳のために/s1H幤を消費しました"; + /// "システムキャンセルリターン" + @override + String get system_back => "システムキャンセルリターン"; + /// "相手にプレゼントを贈る" + @override + String get you_give => "相手にプレゼントを贈る"; + /// "相手からプレゼントを貰った" + @override + String get you_get => "相手からプレゼントを貰った"; + /// "交換数量(单位K)" + @override + String get enter_num_qian => "交換数量(单位K)"; + /// "引き出し数量(单位K)" + @override + String get enter_num_qian1 => "引き出し数量(单位K)"; + /// "翻译券" + @override + String get daily_translate_voucher => "翻译券"; + /// "通知消息" + @override + String get msg_notice => "通知消息"; + /// "选择提醒的人" + @override + String get select_notice_people => "选择提醒的人"; + /// "查找手机号" + @override + String get search_phone => "查找手机号"; + /// "用户不存在" + @override + String get not_have_user => "用户不存在"; + /// "你不能添加自己" + @override + String get not_add_Myself => "你不能添加自己"; + /// "对方已拉黑了你" + @override + String get you_are_blaklisted => "对方已拉黑了你"; + /// "确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)" + @override + String get confrim_recovery => "确定恢复已被焚毁的照片吗?\n(已经看过的用户可以再看一次)"; + /// "發送到" + @override + String get send_to => "發送到"; + + @override + TextDirection get textDirection => TextDirection.ltr; +} + +class GeneratedLocalizationsDelegate extends LocalizationsDelegate { + const GeneratedLocalizationsDelegate(); + List get supportedLocales { + return const [ + const Locale("en", "US"), + const Locale("vi", "VN"), + const Locale("zh", "HK"), + const Locale("zh", "CN"), + const Locale("ko", "KR"), + const Locale("ja", "JP") + ]; + } + + LocaleResolutionCallback resolution({Locale fallback}) { + return (Locale locale, Iterable supported) { + if (this.isSupported(locale)) { + return locale; + } + final Locale fallbackLocale = fallback ?? supported.first; + return fallbackLocale; + }; + } + + @override + Future load(Locale _locale) { + I18n._locale ??= _locale; + I18n._shouldReload = false; + final Locale locale = I18n._locale; + final String lang = locale != null ? locale.toString() : ""; + final String languageCode = locale != null ? locale.languageCode : ""; + if ("en_US" == lang) { + return new SynchronousFuture(const _I18n_en_US()); + } + else if ("vi_VN" == lang) { + return new SynchronousFuture(const _I18n_vi_VN()); + } + else if ("zh_HK" == lang) { + return new SynchronousFuture(const _I18n_zh_HK()); + } + else if ("zh_CN" == lang) { + return new SynchronousFuture(const _I18n_zh_CN()); + } + else if ("ko_KR" == lang) { + return new SynchronousFuture(const _I18n_ko_KR()); + } + else if ("ja_JP" == lang) { + return new SynchronousFuture(const _I18n_ja_JP()); + } + else if ("en" == languageCode) { + return new SynchronousFuture(const _I18n_en_US()); + } + else if ("vi" == languageCode) { + return new SynchronousFuture(const _I18n_vi_VN()); + } + else if ("zh" == languageCode) { + return new SynchronousFuture(const _I18n_zh_HK()); + } + else if ("ko" == languageCode) { + return new SynchronousFuture(const _I18n_ko_KR()); + } + else if ("ja" == languageCode) { + return new SynchronousFuture(const _I18n_ja_JP()); + } + + return new SynchronousFuture(const I18n()); + } + + @override + bool isSupported(Locale locale) { + for (var i = 0; i < supportedLocales.length && locale != null; i++) { + final l = supportedLocales[i]; + if (l.languageCode == locale.languageCode) { + return true; + } + } + return false; + } + + @override + bool shouldReload(GeneratedLocalizationsDelegate old) => I18n._shouldReload; +} \ No newline at end of file diff --git a/lib/home/AddProgram.dart b/lib/home/AddProgram.dart new file mode 100644 index 0000000..4ca992e --- /dev/null +++ b/lib/home/AddProgram.dart @@ -0,0 +1,1381 @@ +import 'dart:io'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/chat/emoji_text.dart'; +import 'package:chat/chat/input_bar.dart'; +import 'package:chat/chat/my_special_text_span_builder.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/MyDialogContent.dart'; +import 'package:chat/home/SelectPage.dart'; +import 'package:chat/home/VerificationCenter.dart'; +import 'package:chat/home/VipPage.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/photo/entity/options.dart'; +import 'package:chat/photo/photo.dart'; +import 'package:chat/utils/ChargeMoney.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/PicSwiper.dart'; +import 'package:chat/utils/keyboard/bottom_area_avoider.dart'; +import 'package:chat/utils/keyboard_utils.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:extended_text_field/extended_text_field.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +import 'package:oktoast/oktoast.dart'; +import 'package:photo_manager/photo_manager.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import '../utils/ShadowButton.dart'; +import '../data/UserData.dart'; +import '../utils/TokenMgr.dart'; +import '../data/WebData.dart'; + +class AddProgram extends StatefulWidget { + @required + final bool isProgram; + + AddProgram({Key key, this.isProgram = true}) : super(key: key); + + _AddProgramState createState() => _AddProgramState(); +} + +const double LEFT_WIDTH = 80; + +const int Max_Img_Num = 4; + +class _AddProgramState extends State { + //期待对象 + String lovePeople = ""; + Set lovePeopleId = new Set(); + + //约会范围 + String dateRange = ""; + Set dateRangeId = new Set(); + + //开始时间 + String beginTime = ''; + String beginTimeId = ''; + + //结束时间 + String endTime = ''; + var endTimeId = -1; + + //List imgFileList = []; + + //上传图片地址 + List imgUrlList = []; + + //禁止评论 + bool isCanContent = false; + bool isHidden = false; + + int programId = -1; + + String programCat = ''; + +// String content = ''; + + @override + void initState() { + super.initState(); + + print('AddProgram initState'); + + _bloc.start(); + getKeyboardHeight(); + focusNode.addListener(_focusNodeListener); + msgMgr.on('Keyboard Hide', dealWithKeyboardHide); + } + + @override + void dispose() { + focusNode.removeListener(_focusNodeListener); + _bloc.dispose(); + msgMgr.off('Keyboard Hide', dealWithKeyboardHide); + + super.dispose(); + } + + ///keyboard相关----------------------------------------------------------------------------------------------- + KeyboardBloc _bloc = KeyboardBloc(); + MessageMgr msgMgr = MessageMgr(); + double keyboardHeight; + final _keyParent = GlobalKey(); + double _offset = 0; + Duration _timeToDismiss = Duration(milliseconds: 120); + OverlayEntry _overlayEntry; + FocusNode focusNode = new FocusNode(); + + bool get _isShowing { + return _overlayEntry != null; + } + + bool isShowEmoji = false; + bool _dismissAnimationNeeded = true; + double _kBarSize = 45.0; + bool isActionFromButton = false; + + dealWithKeyboardHide(args) { + if (!isActionFromButton) { + closeEmojiAction(); + } + } + + TextEditingController _textCtrl = TextEditingController(); + final ValueNotifier _counter = ValueNotifier(false); + + void _insertOverlay() { + print('插入界面'); + OverlayState os = Overlay.of(context); + _overlayEntry = OverlayEntry(builder: (context) { + // Update and build footer, if any + + final queryData = MediaQuery.of(context); + return Positioned( + bottom: queryData.viewInsets.bottom, + left: 0, + right: 0, + child: SafeArea( + child: Container( + height: _kBarSize, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Material( + color: Colors.grey[200], + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Divider( + height: 1, + color: Color(0xffb0b0b0), + ), + InkWell( + child: Container( + padding: EdgeInsets.only(left: 15), + height: 43, + color: Colors.white, + alignment: Alignment.centerLeft, + child: Icon( + IconData(isShowEmoji ? 0xe655 : 0xe651, + fontFamily: Constants.IconFontFamily), + size: 27, + color: Color(0xffb0b0b0)), + ), + onTap: () { + setState(() { + isActionFromButton = true; + isShowEmoji = !isShowEmoji; + _kBarSize = isShowEmoji ? keyboardHeight : 45; + + if (isShowEmoji) { + SystemChannels.textInput + .invokeMethod('TextInput.hide'); + } else { + SystemChannels.textInput + .invokeMethod('TextInput.show'); + } + if (isShowEmoji) { + Future.delayed(Duration(milliseconds: 200), () { + ///150延迟防止界面越界 + _counter.value = isShowEmoji; + }); + + Future.delayed(Duration(milliseconds: 1000), () { + ///缩下键盘的时候-防止表情被关闭 + isActionFromButton = false; + }); + } else { + _counter.value = isShowEmoji; + Future.delayed(Duration(milliseconds: 360), () { + ///150延迟防止界面越界 + isActionFromButton = false; + }); + } + }); + }, + ), + ValueListenableBuilder( + builder: + (BuildContext context, bool value, Widget child) { + return value + ? Container( + width: MediaQuery.of(context).size.width, + child: buildEmojiGird(), + ) + : SizedBox( + height: 1, + ); + }, + valueListenable: _counter, + ), + ], + ), + ), + ], + ), + ), + ), + ); + }); + os.insert(_overlayEntry); + } + + getKeyboardHeight() async { + var sp = await SharedPreferences.getInstance(); + keyboardHeight = sp.getDouble(Constants.KeyboardHeight); + print('keyboardHeight : $keyboardHeight'); + } + + Future _focusNodeListener() async { + print('监听'); + + if (isShowEmoji) { + return; + } + _focusChanged(focusNode.hasFocus); + } + + _focusChanged(bool showBar) { + print('showBar $showBar _isShowing:$_isShowing'); + if (showBar && !_isShowing) { + _insertOverlay(); + } else if (!showBar && _isShowing) { + _removeOverlay(); + } else if (showBar && _isShowing) { + _overlayEntry.markNeedsBuild(); + } + } + + /// Remove the overlay bar. Call when losing focus or being dismissed. + void _removeOverlay({bool fromDispose = false}) async { + if (_dismissAnimationNeeded) { + if (mounted && !fromDispose) { + _overlayEntry?.markNeedsBuild(); + await Future.delayed(_timeToDismiss); + } + } + _overlayEntry?.remove(); + _overlayEntry = null; + if (!fromDispose && _dismissAnimationNeeded) _updateOffset(); + _dismissAnimationNeeded = true; + } + + void _updateOffset() { + if (!mounted) { + return; + } + + if (!_isShowing) { + setState(() { + _offset = 0.0; + }); + return; + } + + double newOffset = _kBarSize; // offset for the actions bar + newOffset += MediaQuery.of(context) + .viewInsets + .bottom; // + offset for the system keyboard + + if (newOffset < 0) newOffset = 0; + + // Update state if changed + if (_offset != newOffset) { + setState(() { + _offset = newOffset; + }); + } + } + + Widget buildEmojiGird() { + return Container( + height: keyboardHeight - 44, + child: Stack( + children: [ + Padding( + padding: EdgeInsets.fromLTRB(5, 8, 50, 0), + child: GridView.builder( + controller: new ScrollController(keepScrollOffset: false), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 7, crossAxisSpacing: 0, mainAxisSpacing: 0), + itemBuilder: (context, index) { + return GestureDetector( + child: Container( + padding: EdgeInsets.all(7), + child: Image.asset(EmojiUitl + .instance.emojiMap[EmojiText.flag + "${index + 1}]"]), + ), + behavior: HitTestBehavior.translucent, + onTap: () { + if (_textCtrl.value.text.length < 94) { + InputBarState.insertText( + EmojiText.flag + "${index + 1}]", _textCtrl); + } + +// setState(() { +// _isComposingMessage = _textCtrl.text.length > 0; +// }); + }, + ); + }, + itemCount: EmojiUitl.instance.emojiMap.length, + padding: EdgeInsets.all(5.0), + ), + ), + Positioned.fill( + child: Container( + padding: EdgeInsets.fromLTRB(0, 0, 0, 14), + alignment: Alignment(1, 1), + child: InkWell( + onTap: () { + InputBarState.deleteText(_textCtrl); + }, + child: Container( + decoration: BoxDecoration( + color: Color(0x4d0E0E10), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(4.0), + bottomLeft: Radius.circular(4))), + width: 37, + height: 28, + child: Icon( + IconData( + 0xe679, + fontFamily: 'iconfont', + ), + size: 16, + color: Colors.white, + ), + ), + ), + )), + ], + ), + ); + } + + ///keyboard相关------------------------------------------------------------------------------------------------------------ + + void closeEmojiAction() { + print('### closeEmojiAction'); + FocusScope.of(context).requestFocus(FocusNode()); + isShowEmoji = false; + _counter.value = isShowEmoji; + _removeOverlay(); + _offset = 0; + _kBarSize = isShowEmoji ? keyboardHeight : 45; + } + + ScrollController _scrollController = new ScrollController(); + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + widget.isProgram + ? I18n.of(context).release_program + : I18n.of(context).release_dynamics, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + elevation: 0, + leading: CustomUI.buildCustomLeading(context, onTap: () { + closeEmojiAction(); + Navigator.of(context).pop(); + }), + centerTitle: true, + ); + return WillPopScope( + child: Scaffold( + appBar: appBar, + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: GestureDetector( + onTap: () { + closeEmojiAction(); + }, + child: Material( + color: Colors.transparent, + child: SizedBox( + width: double.maxFinite, + key: _keyParent, + child: BottomAreaAvoider( + scrollTo: _scrollController, + areaToAvoid: _offset, + duration: Duration( + milliseconds: + (_timeToDismiss.inMilliseconds * 1.8).toInt()), + autoScroll: true, + child: Container( + child: Column( + children: [_buildBody()], + ), + ), + ), + ), + ), + ), + ), + )), + ), + onWillPop: () { + closeEmojiAction(); + + return Future.value(true); + }); + } + +// Future _willPop() { +// print('###### willpop'); +//// tempDispose=true; +//// closeEmojiAction(); +//// print('isshowemoji:$isShowEmoji'); +//// _counter.value = false; +//// print('关闭emoji'); +//// FocusScope.of(context).requestFocus(FocusNode()); +// Navigator.pop(context); +// return new Future.value(false); +// } + + BoxDecoration _getCardDecoration() { + return new BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(230, 230, 230, 1), + offset: Offset(0, 10), + blurRadius: 8, + ) + ], + ); + } + + //节目主题 + Widget _buildProgramCat() { + return new Container( + margin: EdgeInsets.only(top: 15), + decoration: _getCardDecoration(), + child: _bottomBorderBox( + I18n.of(context).program_theme, + programCat == '' ? I18n.of(context).choose : programCat, + false, + null, () { + CustomUI.buildTip( + context, I18n.of(context).please_choose, _buildCategoryButton()); + }, rightTextGrey: programCat == ''), + ); + } + + //选择期待对象 + void selectLovePeople() { + var tempSet = lovePeopleId.toSet(); + List actions = [ + FlatButton( + child: fixedText(I18n.of(context).close), + onPressed: () { + tempSet.clear(); + Navigator.of(context).pop(); + }, + ), + FlatButton( + child: fixedText(I18n.of(context).determine), + onPressed: () { + Navigator.of(context).pop(); + setState(() { + lovePeopleId = tempSet.toSet(); + lovePeople = ''; + lovePeopleId.forEach((k) { + lovePeople += (lovePeople == '') + ? WebData().loverPeopleMap[k] + : ('/' + WebData().loverPeopleMap[k]); + }); + }); + }, + ), + ]; + //约会节目 + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: new Align( + alignment: Alignment.center, + child: Text(I18n.of(context).expect_lover, textScaleFactor: 1.0), + ), + content: new MyDialogContent( + mostNum: 4, + dataMap: WebData().loverPeopleMap, + keyList: tempSet, + ), + contentPadding: EdgeInsets.only(top: 10), + actions: actions, + ); + }); + } + + //选择约会地区 + void selectDateRange() async { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return SelectPage( + mostNum: 4, + dataId: dateRangeId, + title: I18n.of(context).select_city, + provinces: {'VietNam': WebData().provinces['VietNam']}, + cities: WebData().cities, + isSingle: true, + callback: (tempRankId) { + dateRangeId = tempRankId.toSet(); + dateRange = ''; + dateRangeId.forEach((item) { + var city = item.split('-'); + dateRange += dateRange == '' + ? WebData().cities[city[0]][city[1]] + : '/${WebData().cities[city[0]][city[1]]}'; + }); + Navigator.of(context).pop(); + }, + ); + }, + ), + ); + } + + //选择开始时间 + void selectBegin() async { + DateTime _date = DateTime.now(); + final DateTime picked = await showDatePicker( + context: context, + initialDate: _date, + firstDate: DateTime(_date.year, _date.month, _date.day), + locale: WebData().locale, + lastDate: DateTime(_date.year, _date.month, _date.day + 7)); + setState(() { + if (picked != null) { + beginTime = '${picked.year}-${picked.month}-${picked.day}'; + beginTimeId = '${picked.year}-${picked.month}-${picked.day}'; + } + }); + if (picked == null) _date = DateTime.now(); + } + + //分类按钮 + Widget _buildCategoryButton() { + return Container( + padding: EdgeInsets.only(top: 10), + child: Column( + children: [ + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildIconButton(1, WebData().getProgramName(context, 0), + Constants.Category1Color, 0), + _buildIconButton(2, WebData().getProgramName(context, 1), + Constants.Category2Color, 1), + _buildIconButton(3, WebData().getProgramName(context, 2), + Constants.Category3Color, 2), + _buildIconButton(4, WebData().getProgramName(context, 3), + Constants.Category4Color, 3), + ], + ), + ), + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildIconButton(5, WebData().getProgramName(context, 4), + Constants.Category5Color, 4), + _buildIconButton(6, WebData().getProgramName(context, 5), + Constants.Category6Color, 5), + _buildIconButton(7, WebData().getProgramName(context, 6), + Constants.Category7Color, 6), + _buildIconButton(8, WebData().getProgramName(context, 7), + Constants.Category8Color, 7), + ], + ), + ), + ], + )); + } + + Widget _buildIconButton(iconNum, str, strColor, value) { + Widget icon = Container( + padding: EdgeInsets.only(bottom: 10), + child: Image.asset( + 'assets/images/park/qz_icon$iconNum.png', + height: 60, + )); + + Widget text = Positioned( + bottom: 0, + child: Container( + child: new Text(str, + textScaleFactor: 1.0, + style: TextStyle( + color: strColor, fontWeight: FontWeight.w700, fontSize: 13)), + )); + return InkWell( + onTap: () { + setState(() { + programId = value; + programCat = WebData().getProgramName(context, value); + Navigator.of(context).pop(); + }); + }, + highlightColor: Colors.transparent, + radius: 0, + child: Container( + width: (MediaQuery.of(context).size.width * 0.9) / 4, + margin: EdgeInsets.only(top: 10), + child: Stack( + alignment: Alignment.center, + children: [ + icon, + text, + ], + ), + )); + } + + Widget _buildTimeSelect(str, value) { + return InkWell( + child: Container( + margin: EdgeInsets.only(top: 5, bottom: 5), + height: 20, + alignment: Alignment.center, + child: Text( + str, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 15, color: Constants.BlackTextColor), + ), + ), + onTap: () async { + if (WebData().testTimeOver(value, beginTimeId)) { + showToast(I18n.of(context).outTime); + return; + } + setState(() { + endTimeId = value; + endTime = str; + Navigator.of(context).pop(); + }); + }, + ); + } + + //选择结束时间 + void selectEnd() async { + Widget title = Container( + margin: EdgeInsets.only(top: 15, bottom: 10), + alignment: Alignment.center, + child: Text( + I18n.of(context).select_time, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 19, color: Constants.BlackTextColor), + ), + ); + List list = [title]; + WebData().getDateTime(context).forEach((k, v) { + list.add(Divider()); + list.add(_buildTimeSelect(v, k)); + }); + if (beginTimeId == '') { + showToast(I18n.of(context).please_choose4); + return; + } + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SafeArea( + child: Container( + height: 345, + child: Column(children: list), + )); + }, + ).then((val) {}); + } + + void _sendPicture() async { + closeEmojiAction(); + var photos = await PhotoPicker.pickAsset( + context: context, + themeColor: Color(0xFFF0F0F0), + maxSelected: Max_Img_Num - imgUrlList.length, + textColor: Color(0xFF3F3F3F), + pickType: PickType.onlyImage); + + if (photos != null && photos.length > 0) { + List fileList = []; + for (var i = 0; i < photos.length; i++) { + AssetEntity photoEntity = photos[i]; + fileList.add(await photoEntity.file); + } + Map data = {"type": 3, "userId": UserData().basicInfo.userId}; + data['sign'] = TokenMgr().getSign(data); + Response res = await HttpUtil().uploadFiles( + fileList, data, 'upload/post/postfiles', 'image', + isShowLoading: true); + var resData = res.data; + if (resData['code'] == 0 && resData['msg'] != null) { + imgUrlList.addAll(resData['msg'].split("|")); + setState(() {}); + } + } + } + + Widget _buildDynicContent() { + Widget moreInfo = Container( + alignment: Alignment.topCenter, + padding: EdgeInsets.only(left: 15, right: 15), + child: ExtendedTextField( + keyboardAppearance: Brightness.light, + onTap: () { +// if(!isActionFromButton){ + isShowEmoji = false; + _counter.value = isShowEmoji; + _kBarSize = isShowEmoji ? keyboardHeight : 45; +// } + }, + focusNode: focusNode, + specialTextSpanBuilder: + MySpecialTextSpanBuilder(showAtBackground: true, emojiSize: 17.0), + decoration: new InputDecoration( + hintText: I18n.of(context).please_civilization, + hintStyle: TextStyle(fontSize: 13, height: 1.25), + border: InputBorder.none, + ), + maxLines: 6, + controller: _textCtrl, + style: TextStyle( + fontSize: ScreenUtil().setSp(14), + textBaseline: TextBaseline.alphabetic), + inputFormatters: [LengthLimitingTextInputFormatter(100)], + onChanged: (str) { + if (str.length > 100) { + print('超过100了'); + _textCtrl.text = _textCtrl.value.text.substring(0, 100); + int length = _textCtrl.text.length; + Future.delayed(Duration(milliseconds: 100), () { + _textCtrl.selection = + TextSelection(baseOffset: length, extentOffset: length); + }); + } + }, + )); + + List imgList = imgUrlList.map((f) { + return _buildImg(f); + }).toList(); + if (imgList.length < Max_Img_Num) { + imgList.add(_buildUpButton()); + } + + Widget picture = Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only(left: 15, bottom: 15), + child: Wrap(alignment: WrapAlignment.start, children: imgList)); + List list = [moreInfo, picture]; + return new Container( + margin: EdgeInsets.only(top: 15), + decoration: _getCardDecoration(), + child: Column( + children: list, + ), + ); + } + + Widget _buildUpButton() { + var color = Colors.grey[350]; + return Container( + child: InkWell( + onTap: _sendPicture, + child: Container( + margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10.0), + border: Border.all(color: color)), + width: 75, + height: 75, + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Icon( + IconData( + 0xe616, + fontFamily: 'iconfont', + ), + color: color), + )))); + } + + //节目内容 + Widget _buildProgramContent() { + Widget moreInfo = Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + width: Screen.width, + padding: EdgeInsets.only( + top: 15, + ), + margin: EdgeInsets.only(left: 15), + child: Text( + I18n.of(context).describe_details, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600), + )), + Container( + padding: EdgeInsets.only(right: 5), + margin: EdgeInsets.only(left: 15), + child: ExtendedTextField( + keyboardAppearance: Brightness.light, + focusNode: focusNode, + onTap: () { +// if(!isActionFromButton){ + isShowEmoji = false; + _counter.value = isShowEmoji; + _kBarSize = isShowEmoji ? keyboardHeight : 45; +// } + + if (_scrollController != null) { + ///解决键盘遮挡输入框 + _scrollController.position.moveTo( + 200, + duration: Duration(milliseconds: 100), + curve: Curves.easeIn, + ); + } + }, + + controller: _textCtrl, + specialTextSpanBuilder: MySpecialTextSpanBuilder( + showAtBackground: true, emojiSize: 17.0), + decoration: new InputDecoration( + contentPadding: + EdgeInsets.only(top: 6, bottom: 10, right: 10), + hintText: I18n.of(context).please_civilization, + hintStyle: TextStyle(fontSize: 12, height: 1.15), + border: InputBorder.none, + ), + style: TextStyle( + fontSize: 13, textBaseline: TextBaseline.alphabetic), + maxLines: 6, +// inputFormatters: [LengthLimitingTextInputFormatter(100)], + onChanged: (str) { + if (str.length > 100) { + print('超过100了'); + _textCtrl.text = _textCtrl.value.text.substring(0, 100); + int length = _textCtrl.text.length; + Future.delayed(Duration(milliseconds: 100), () { + _textCtrl.selection = TextSelection( + baseOffset: length, extentOffset: length); + }); + } + }, + )), + ], + ), + ); + + List imgList = imgUrlList.map((f) { + return _buildImg(f); + }).toList(); + if (imgList.length < Max_Img_Num) { + imgList.add(_buildUpButton()); + } + + Widget picture = Container( + alignment: Alignment.topCenter, + child: Row( + children: [ + Container( + alignment: Alignment.centerLeft, + width: LEFT_WIDTH, + margin: EdgeInsets.only(left: 15), + child: fixedText(I18n.of(context).image, + fontSize: 14, fontWeight: FontWeight.w600)), + Expanded( + child: Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + child: + Wrap(alignment: WrapAlignment.start, children: imgList))), + ], + ), + ); + List list = [ + _bottomBorderBox( + I18n.of(context).expect_lover, + lovePeople == '' ? I18n.of(context).choose : lovePeople, + false, + null, + selectLovePeople, + rightTextGrey: lovePeople == ''), + _buildDivider(), + // _bottomBorderBox( + // I18n.of(context).city, + // dateRange == '' ? I18n.of(context).choose : dateRange, + // false, + // null, + // selectDateRange, + // rightTextGrey: dateRange == ''), + // _buildDivider(), + _bottomBorderBox( + I18n.of(context).time, + beginTime == '' ? I18n.of(context).choose : beginTime, + false, + null, + selectBegin, + rightTextGrey: beginTime == ''), + _buildDivider(), + _bottomBorderBox('', endTime == '' ? I18n.of(context).choose : endTime, + false, null, selectEnd, + rightTextGrey: endTime == ''), + _buildDivider(), + moreInfo, + _buildDivider(), + picture + ]; + return new Container( + margin: EdgeInsets.only(top: 15), + decoration: _getCardDecoration(), + child: Column( + children: list, + ), + ); + } + + //下划线 + Widget _buildDivider() { + return new Container( + margin: EdgeInsets.zero, + padding: EdgeInsets.zero, + decoration: BoxDecoration(border: Border(top: Constants.GreyBorderSide)), + height: 1, + width: MediaQuery.of(context).size.width * 0.9, + ); + } + + Widget _buildImg(f) { + return Stack( + children: [ + InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return PicSwiper( + id: imgUrlList.indexOf(f), + pics: imgUrlList + .map((f) => PicSwiperItem( + f, + id: imgUrlList.indexOf(f), + )) + .toList(), + ); + }, + ), + ); + }, + child: Container( + height: 75, + width: 75, + margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10.0), + border: Border.all(color: Colors.grey[300], width: 1), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: f == null + ? Container() + : CachedNetworkImage( + imageUrl: f, + fit: BoxFit.cover, + ), + ))), + Positioned( + right: 0, + child: InkWell( + onTap: () { + imgUrlList.remove(f); + setState(() {}); + }, + child: Image.asset( + 'assets/images/login/delete.png', + height: 20, + )), + ) + ], + ); + } + + //自定义item + Widget _bottomBorderBox( + String textLeft, String textRight, bool flag, controller, callback, + {bool rightTextGrey = true}) { + Widget left = new Container( + width: LEFT_WIDTH, + child: new Text( + textLeft, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600), + )); + + Widget right = flag + ? new Expanded( + child: new TextField( + keyboardAppearance: Brightness.light, + controller: controller, + decoration: new InputDecoration( + hintText: textRight, + hintStyle: TextStyle(fontSize: 14), + border: InputBorder.none, + ), + style: TextStyle(textBaseline: TextBaseline.alphabetic), + maxLines: 1, + onChanged: (str) { + if (flag && callback != null) callback(str); + }, + ), + ) + : new Expanded( + child: GestureDetector( + onTap: () { + if (!flag && callback != null) callback(); + }, + child: Container( + color: Colors.transparent, + height: 53, + width: MediaQuery.of(context).size.width, + alignment: Alignment.centerLeft, + padding: EdgeInsets.only(left: 5), + child: Text( + textRight, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 14, + color: rightTextGrey + ? Constants.GreyTextColor + : Constants.BlackTextColor), + ), + ), + ), + ); + + return new Container( + height: 53, + margin: EdgeInsets.only(left: 15, bottom: 0), + child: new Row( + children: [left, right], + ), + ); + } + + Widget _buildSwitch(str, value, callback) { + Widget left = new Text( + str, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 14, + fontWeight: widget.isProgram ? FontWeight.w600 : FontWeight.normal), + ); + Widget right = new Expanded( + child: new Align( + alignment: Alignment.centerRight, + child: new Switch( + activeTrackColor: Constants.ConfrimButtonColor.withOpacity(0.3), + value: value, + onChanged: (bool val) { + callback(); + }, + ))); + return new Container( + padding: EdgeInsets.only(left: 15), + height: 53, + child: new Row( + children: [left, right], + ), + ); + } + + Widget _buildSelct() { + return new Container( + decoration: _getCardDecoration(), + //margin: EdgeInsets.only(top: , bottom: 0), + child: Column( + children: [ + _buildSwitch(I18n.of(context).prohibit_comments, isCanContent, () { + setState(() { + isCanContent = !isCanContent; + }); + }), + _buildDivider(), + _buildSwitch(I18n.of(context).same_sex, isHidden, () { + setState(() { + isHidden = !isHidden; + }); + }), + ], + )); + } + + Widget _buildTip() { + return Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(top: 10, bottom: 10, left: 10), + child: Text( + I18n.of(context).dont, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 12, color: Constants.GreyTextColor), + ), + ); + } + + Widget _buildTips() { + String str = ''; + if (UserData().isMan()) { + str = I18n.of(context) + .member_free + .replaceFirst('/s1', UserData().addProgramPrice.toString()); + } else { + str = I18n.of(context) + .certified_free + .replaceFirst('/s1', UserData().addProgramPrice.toString()); + } + return Container( + padding: EdgeInsets.only(bottom: 100, left: 20, right: 20), + child: Text( + str, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 12, color: Constants.GreyTextColor), + ), + ); + } + + Widget _buildBody() { + List program = [ + _buildProgramCat(), + _buildProgramContent(), + _buildTip(), + _buildSelct(), + _buildLoginButton(), + _buildTips() + ]; + + List dynamics = [ + _buildDynicContent(), + _buildTip(), + _buildSelct(), + _buildLoginButton(), + _buildTips() + ]; + + return Column( + children: widget.isProgram ? program : dynamics, + ); + } + + //构建登陆按钮 + Widget _buildLoginButton() { + Text text = new Text(I18n.of(context).release, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 15, color: Colors.white)); + + LinearGradient gradientColor = new LinearGradient(colors: [ + Constants.ConfrimButtonColor, + Constants.ConfrimButtonColor + ]); + callback() async { + closeEmojiAction(); + + if (widget.isProgram) { + if (programId == -1) { + showToast(I18n.of(context).please_choose); + return; + } + if (lovePeopleId.length == 0) { + showToast(I18n.of(context).please_choose2); + return; + } + // if (dateRangeId.length == 0) { + // showToast(I18n.of(context).please_choose3); + // return; + // } + if (beginTimeId == '') { + showToast(I18n.of(context).please_choose4); + return; + } + if (endTimeId == -1) { + showToast(I18n.of(context).please_choose5); + return; + } + } else { + if (_textCtrl.value.text.trim().length == 0 && imgUrlList.length == 0) { + showToast(I18n.of(context).enter_something); + return; + } + } + + payCallback() { + if (Provider.of(context).money < + UserData().addProgramPrice) { + CustomUI.buildOneConfirm( + context, + I18n.of(context).balance_insufficien, + I18n.of(context).recharge, () { + Navigator.of(context).pop(); + ChargeMoney.showChargeSheet(context, () { + setState(() {}); + }); + }); + return; + } + Navigator.of(context).pop(); + postAddProgram(UserData().addProgramPrice); + } + + String title = widget.isProgram + ? I18n.of(context).release_program + : I18n.of(context).release_dynamics; + + //非会员男士提示付费 + if (!UserData().isVip && UserData().isMan()) { + bool isMan = UserData().isMan(); + + CustomUI.buildTowConfirm( + context, + title, + isMan + ? I18n.of(context).become_member2 + : I18n.of(context).now_certification, + () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return isMan ? VipPage() : VerificationCenterPage(); + }, + ), + ); + }, + I18n.of(context) + .raid_release + .replaceFirst('/s1', UserData().addProgramPrice.toString()), + payCallback, + ); + return; + } + //免费次数用完提示付费 + if (UserData().basicInfo.usedPublishNum >= + UserData().basicInfo.publishNum) { + CustomUI.buildOneConfirm( + context, + title, + I18n.of(context) + .pay_unlock + .replaceFirst('/s1', UserData().addProgramPrice.toString()), + payCallback); + return; + } + HttpUtil().userFreeTime(context, UserData().basicInfo.userId, 3, () { + UserData().basicInfo.usedPublishNum++; + postAddProgram(0); + }); + } + + return new Container( + margin: EdgeInsets.only(top: 30, bottom: 10), + height: 44, + width: MediaQuery.of(context).size.width * 0.8, + child: ShadowButton().builder(gradientColor, text, callback), + ); + } + + postAddProgram(price) async { + var dateRangeStr = ''; + dateRangeId.forEach((f) => dateRangeStr += dateRangeStr == '' ? f : ',$f'); + + var hopeObject = ''; + lovePeopleId.forEach((f) => hopeObject += hopeObject == '' ? f : ',$f'); + + String temp = ''; + String postTemp = ''; + imgUrlList.forEach((str) { + temp += (temp == "" ? str : '|$str'); + postTemp += (postTemp == "" + ? WebData().deleteDemain(str) + : '|${WebData().deleteDemain(str)}'); + }); + + var type = widget.isProgram ? 0 : 1; + Map data = { + "userId": UserData().basicInfo.userId, + "type": type, + "price": price, + }; + data['sign'] = TokenMgr().getSign(data); + //data['city'] = dateRangeStr; + data['programType'] = programId; + data['hopeObject'] = hopeObject; + data['aboutTime'] = beginTimeId; + data['content'] = _textCtrl.text; + data['imgUrl'] = postTemp; + data['evaluateStatus'] = isCanContent; + data['sexStatus'] = isHidden; + data['timeQuantum'] = endTimeId; + + Response res = await HttpUtil() + .post('station/publish/program', data: data, isShowLoading: true); + var resData = res.data; + if (resData['code'] == 0) { + if (widget.isProgram) { + UserData().isCanProgram = false; + } + MessageMgr().emit('Add_program', { + 'Id': resData['data'], + 'UserId': UserData().basicInfo.userId, + 'NickName': UserData().basicInfo.nickName, + 'HeadimgUrl': UserData().basicInfo.headimgurl, + 'Type': type, + 'Sex': UserData().basicInfo.sex, + 'IsMember': UserData().basicInfo.isMember, + 'ProgramType': programId, + 'HopeObject': hopeObject, + 'City': dateRangeStr, + 'AboutTime': beginTimeId, + 'timeQuantum': endTimeId, + 'Content': _textCtrl.text, + 'ImgUrl': temp, + 'EvaluateStatus': isCanContent ? 1 : 0, + 'SexStatus': isHidden, + 'Status': 0, + 'CreateTime': DateTime.now().toIso8601String(), + 'FabulousNum': 0, + 'EvaluateNum': 0, + 'EnrollNum': 0, + 'IsAttestation': UserData().basicInfo.isAttestation ? 1 : 0, + 'IsFabulous': 0, + 'IsEnroll': 0, + 'EvaluateList': null, + "FabulousList": [] + }); + Navigator.of(context).pop(); + focusNode.removeListener(_focusNodeListener); + } else { + showToast(resData['msg']); + } + } +} diff --git a/lib/home/BindAccount.dart b/lib/home/BindAccount.dart new file mode 100644 index 0000000..e0998eb --- /dev/null +++ b/lib/home/BindAccount.dart @@ -0,0 +1,151 @@ +import 'package:chat/utils/CustomUI.dart'; +import 'package:flutter/material.dart'; + +class BindAccountPage extends StatefulWidget { + BindAccountPage({Key key}) : super(key: key); + + _BindAccountPageState createState() => _BindAccountPageState(); +} + +class _BindAccountPageState extends State + with SingleTickerProviderStateMixin { + TabController tabCtrl; + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('绑定账号'), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ), + body: SafeArea( + child: Center( + child: Container( + color: Colors.grey[200], + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + ))); + } + + Widget _buildBody() { + return Column( + children: [ + _buildCard(), + _buildCardList(), + ], + ); + } + + // Widget _buildItem() { + // Widget radio = new Radio( + // value: 0, + // groupValue: 0, //当value和groupValue一致的时候则选中 + // activeColor: Colors.red, + // onChanged: (T) { + // setState(() {}); + // }); + // return Container( + // height: 60, + // child: Row( + // crossAxisAlignment: CrossAxisAlignment.center, + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Padding( + // padding: EdgeInsets.only(left: 25), + // child: Text( + // '小熊猫', + // style: TextStyle(fontWeight: FontWeight.w500), + // ), + // ), + // Expanded( + // child: Padding( + // padding: EdgeInsets.only(left: 60), + // child: Text( + // '134598412354698', + // style: TextStyle(color: Colors.grey), + // ), + // ), + // ), + // Padding( + // padding: EdgeInsets.only(right: 10), + // child: radio, + // ), + // ], + // ), + // ); + // } + + Widget _buildCardList() { + return Container( + color: Colors.white, + width: double.infinity, + child: Column( + children: [ + //_buildItem(), + // _buildDivider(), + // _buildItem(), + ], + ), + ); + } + + Widget _buildCard() { + return InkWell( + onTap: () { + // Navigator.of(context).push( + // new MaterialPageRoute( + // builder: (context) { + // return BindBankPage(isBind: ,); + // }, + // ), + // ); + }, + child: Container( + margin: EdgeInsets.only(top: 20, bottom: 30), + width: MediaQuery.of(context).size.width * 0.92, + decoration: BoxDecoration( + color: const Color(0xFF2172FF), + boxShadow: [ + BoxShadow( + color: const Color(0xA80ECFFF), + blurRadius: 8, + ) + ], + borderRadius: BorderRadius.all(Radius.circular(5))), + child: Column( + children: [ + Container( + margin: EdgeInsets.only(top: 10), + child: Text('+', + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.white, + fontSize: 55, + fontWeight: FontWeight.w700)), + ), + Container( + padding: EdgeInsets.only(right: 10), + height: 30, + child: Text( + '添加银行卡', + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white, fontSize: 14), + )) + ], + ), + )); + } +} diff --git a/lib/home/BindBank.dart b/lib/home/BindBank.dart new file mode 100644 index 0000000..6a108bc --- /dev/null +++ b/lib/home/BindBank.dart @@ -0,0 +1,386 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/ShadowButton.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:city_pickers/city_pickers.dart'; +import 'package:city_pickers/modal/result.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import 'package:oktoast/oktoast.dart'; + +class BindBankPage extends StatefulWidget { + @required + final bool isBind; + @required + final Map bankInfo; + BindBankPage({Key key, this.isBind = true, this.bankInfo}) : super(key: key); + + _BindBankPageState createState() => _BindBankPageState(); +} + +class _BindBankPageState extends State + with SingleTickerProviderStateMixin { + String bankId; + var bankCatId; + + Map bankInfo; + + bool isLoading = false; + + TextEditingController nickNameController = new TextEditingController(); + TextEditingController cardIdController = new TextEditingController(); + TextEditingController idController = new TextEditingController(); + TextEditingController mobileController = new TextEditingController(); + + @override + void initState() { + super.initState(); + + print('BindBankPage initState'); + + if (widget.bankInfo == null) { + bankInfo = {}; + } else { + bankInfo = widget.bankInfo; + } + + nickNameController.text = bankInfo['Name'] == null ? '' : bankInfo['Name']; + cardIdController.text = + bankInfo['CardNo'] == null ? '' : bankInfo['CardNo']; + idController.text = + bankInfo['IdNumber'] == null ? '' : bankInfo['IdNumber']; + mobileController.text = + bankInfo['MobileNo'] == null ? '' : bankInfo['MobileNo']; + bankCatId = bankInfo['Bid'] == null ? '' : bankInfo['Bid']; + } + + @override + void dispose() { + nickNameController.dispose(); + cardIdController.dispose(); + idController.dispose(); + mobileController.dispose(); + + super.dispose(); + + //_cancelTimer(); + } + + initValue() { + if (!isLoading) { + bankId = bankInfo['Bid'] == null || bankInfo['Bid'] == 0 + ? I18n.of(context).choose + : WebData().bankData[bankInfo['Bid'].toString()]; + isLoading = true; + setState(() {}); + } + } + + @override + Widget build(BuildContext context) { + initValue(); + return Scaffold( + appBar: AppBar( + title: Text(I18n.of(context).bank_card, textScaleFactor: 1.0), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ), + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + ))); + } + + Widget _buildBody() { + return Column( + children: [ + _buildInputList(), + _buildBotton(), + ], + ); + } + + Widget _buildBotton() { + return Container( + margin: EdgeInsets.only(top: 30), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildCancelButton(), + _buildRegisterButton(), + ], + ), + ); + } + + //构建注册按钮 + Widget _buildRegisterButton() { + Text text = new Text( + widget.isBind ? I18n.of(context).determine : I18n.of(context).save, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 15, color: Colors.white)); + + LinearGradient gradientColor = new LinearGradient(colors: [ + Constants.ConfrimButtonColor, + Constants.ConfrimButtonColor + ]); + callback() { + if (nickNameController.text == '') { + showToast(I18n.of(context).enter_name); + return; + } + if (bankCatId == '' || bankCatId == null) { + showToast(I18n.of(context).choose_bank); + return; + } + if (cardIdController.text == '') { + showToast(I18n.of(context).bank_number); + return; + } + if (idController.text == '') { + showToast(I18n.of(context).id_number); + return; + } + if (mobileController.text == '') { + showToast(I18n.of(context).enter_number); + return; + } + widget.isBind ? addBank() : editBank(); + } + + return new Container( + height: 44, + width: MediaQuery.of(context).size.width * 0.4, + child: ShadowButton().builder(gradientColor, text, callback), + ); + } + + void addBank() async { + var data = { + "userId": UserData().basicInfo.userId, + "name": nickNameController.text, + "idNumber": idController.text, + }; + data['sign'] = TokenMgr().getSign(data); + data['bId'] = bankCatId; + data['cardNo'] = cardIdController.text; + data['mobile'] = mobileController.text; + + Response res = await HttpUtil().post('wallet/banding/bankcard', data: data); + + if (res == null) { + return; + } + Map resData = res.data; + if (resData['code'] == 0) { + Navigator.of(context).pop(); + MessageMgr().emit('bind_bank', { + 'Name': data['name'], + 'Bid': bankCatId, + 'CardNo': data['cardNo'], + 'IdNumber': data['idNumber'], + 'MobileNo': data['mobile'] + }); + + showToast(resData['msg']); + return; + } + } + + void editBank() async { + var data = { + "userId": UserData().basicInfo.userId, + "cId": bankInfo['CId'], + "name": nickNameController.text, + "idNumber": idController.text, + }; + data['sign'] = TokenMgr().getSign(data); + data['bId'] = bankCatId; + data['mobile'] = mobileController.text; + data['cardNo'] = cardIdController.text; + + Response res = await HttpUtil().post('wallet/edit/accountbank', data: data); + + if (res == null) { + return ; + } + Map resData = res.data; + if (resData['code'] == 0) { + Navigator.of(context).pop(); + MessageMgr().emit('bind_bank', { + 'Name': data['name'], + 'Bid': bankCatId, + 'CardNo': data['cardNo'], + 'IdNumber': data['idNumber'], + 'MobileNo': data['mobile'] + }); + showToast(resData['msg']); + return; + } + } + + //构建注册按钮 + Widget _buildCancelButton() { + Text text = new Text( + widget.isBind ? I18n.of(context).cancel : I18n.of(context).cancel, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 15, color: Constants.BlackTextColor)); + + LinearGradient gradientColor = new LinearGradient(colors: [ + Colors.white, + Colors.white, + ]); + callback() { + Navigator.of(context).pop(); + } + + return new Container( + height: 44, + width: MediaQuery.of(context).size.width * 0.4, + child: ShadowButton().builder(gradientColor, text, callback), + ); + } + + Widget _buildInputList() { + return Container( + margin: EdgeInsets.only(top: 10), + color: Colors.white, + child: Column( + children: [ + _buildItem(I18n.of(context).name, nickNameController, + [LengthLimitingTextInputFormatter(8)]), + _buildDivider(), + _buildSelectRank(I18n.of(context).career10, selectBankCat), + _buildDivider(), + _buildItem(I18n.of(context).bank_number2, cardIdController, [ + WhitelistingTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(30) + ]), + + _buildDivider(), + _buildItem(I18n.of(context).license_number, idController, [ + WhitelistingTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(20) + ]), + _buildDivider(), + _buildItem(I18n.of(context).bind_phone, mobileController, [ + WhitelistingTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(11) + ]), + // _buildDivider(), + // _buildVerifyCode() + ], + ), + ); + } + + void selectBankCat() async { + Result temp = await CityPickers.showCityPicker( + context: context, + showType: ShowType.p, + provincesData: WebData().bankData, + citiesData: WebData().bankListData, + height: 400, + ); + setState(() { + if (temp == null) return; + bankId = temp.provinceName; + bankCatId = temp.provinceId; + }); + } + + Widget _buildSelectRank(str, callback) { + return Container( + height: 45, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 100, + padding: EdgeInsets.only(left: 25), + child: Text( + str, + textScaleFactor: 1.0, + ), + ), + Expanded( + child: new InkWell( + highlightColor: Colors.transparent, + radius: 0.0, + onTap: callback, + child: Padding( + padding: EdgeInsets.only(left: 35), + child: new Text( + bankId, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14), + ), + ), + )) + ], + ), + ); + } + + Widget _buildItem(str, controller, inputFormatters) { + return Container( + height: 45, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 100, + padding: EdgeInsets.only(left: 25), + child: Text( + str, + textScaleFactor: 1.0, + ), + ), + Expanded( + child: Container( + alignment: Alignment.center, + padding: EdgeInsets.only(left: 25), + child: TextField( + keyboardAppearance: Brightness.light, + style: TextStyle(fontSize: 14,textBaseline: TextBaseline.alphabetic), + controller: controller, + decoration: new InputDecoration( + hintText: I18n.of(context).fill_out, + hintStyle: TextStyle(fontSize: 14), + border: InputBorder.none, + ), + maxLines: 1, + inputFormatters: inputFormatters, + //onChanged: callback, + ), + ), + ), + ], + ), + ); + } + + //下划线 + Widget _buildDivider() { + return new Container( + margin: EdgeInsets.zero, + padding: EdgeInsets.zero, + width: MediaQuery.of(context).size.width * 0.85, + child: new Divider( + color: Colors.grey[300], + height: 0.1, + ), + ); + } +} diff --git a/lib/home/BindCode.dart b/lib/home/BindCode.dart new file mode 100644 index 0000000..651b687 --- /dev/null +++ b/lib/home/BindCode.dart @@ -0,0 +1,161 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:oktoast/oktoast.dart'; +import '../utils/ShadowButton.dart'; +import '../utils/HttpUtil.dart'; +import 'package:dio/dio.dart'; +import "../data/UserData.dart"; +import '../utils/TokenMgr.dart'; + +class BindCodePage extends StatefulWidget { + BindCodePage({Key key, bool flag}) : super(key: key); + + _BindCodePageState createState() => _BindCodePageState(); +} + +class _BindCodePageState extends State { + String _code = ''; + @override + Widget build(BuildContext context) { + Widget appBar = AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + I18n.of(context).bind_code, + style: TextStyle(color:AppColors.NewAppbarTextColor ), + textScaleFactor: 1.0, + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ); + return Scaffold( + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + )), + appBar: appBar, + resizeToAvoidBottomPadding: false, + ); + } + @override + void initState() { + super.initState(); + print('BindCodePage initState'); + } + @override + void dispose() { + super.dispose(); + } + + Widget _buildBody() { + return new Column( + children: [ + _buildTextInput(), + _buildTips(), + _buildLoginButton(), + ], + ); + } + + Widget _buildTips() { + var greyStyle = TextStyle(fontSize: 12, color: Constants.GreyTextColor); + var redStyle = TextStyle(fontSize: 12, color: Colors.red); + List list = I18n.of(context).fill_tips.split('/s1'); + return Container( + alignment: Alignment.centerLeft, + margin: EdgeInsets.only(top: 12, left: 13.5), + child: RichText( + text: TextSpan(children: [ + TextSpan(text: list[0], style: greyStyle), + TextSpan(text: UserData().inviteCodePrice.toString(), style: redStyle), + TextSpan(text: list[1], style: greyStyle), + ])), + ); + } + + Widget _buildTextInput() { + return Container( + margin: EdgeInsets.only(top: 5.5), + color: Colors.white, + child: Row( + children: [ + Container( + margin: + EdgeInsets.only(left: 14, right: 25, top: 27.5, bottom: 27.5), + child: Text(I18n.of(context).invide_code, + style: TextStyle(color: Constants.BlackTextColor)), + ), + Expanded( + child: TextField( + keyboardAppearance: Brightness.light, + style: + TextStyle(fontSize: 14, textBaseline: TextBaseline.alphabetic), + decoration: new InputDecoration( + hintText: I18n.of(context).enter_incode, + hintStyle: TextStyle(fontSize: 14), + border: InputBorder.none, + ), + maxLines: 1, + keyboardType: TextInputType.phone, + inputFormatters: [ + WhitelistingTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(5) + ], + onChanged: (str) { + _code = str; + setState(() {}); + }, + )) + ], + ), + ); + } + + //构建绑定按钮 + Widget _buildLoginButton() { + Text text = new Text(I18n.of(context).determine, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: Constants.ShaderButtonFontSize, color: Colors.white)); + + LinearGradient gradientColor = new LinearGradient(colors: [ + Constants.ConfrimButtonColor, + Constants.ConfrimButtonColor, + ]); + callback() async { + if (_code == null || _code == "") { + showToast(I18n.of(context).enter_incode); + return; + } + + Map data = { + "userId": UserData().basicInfo.userId, + "agentId": int.parse(_code), + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil() + .post('user/bind/agent', data: data, isShowLoading: true); + + var resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + UserData().agentId = int.parse(_code); + Navigator.of(context).pop(); + } + } + + return new Container( + margin: EdgeInsets.only(top: 35.5), + height: Constants.ShaderButtonHeight, + width: MediaQuery.of(context).size.width * 0.85, + child: ShadowButton().builder(gradientColor, text, callback), + ); + } +} diff --git a/lib/home/ConversActionPage.dart b/lib/home/ConversActionPage.dart new file mode 100644 index 0000000..3a35f78 --- /dev/null +++ b/lib/home/ConversActionPage.dart @@ -0,0 +1,483 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/conversation.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/InfoList.dart'; +import 'package:chat/home/last_chat_record_widget.dart'; +import 'package:chat/home/rich_title.dart'; +import 'package:chat/home/unread_dot_widget.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import '../data/constants.dart' show AppColors, AppStyles, Constants; +import 'package:cached_network_image/cached_network_image.dart'; + +class _ConversationItem extends StatelessWidget { + const _ConversationItem( + {Key key, + this.conversation, + this.callback, + this.icon, + this.bgColor, + this.iconSize = 20}) + : assert(conversation != null), + super(key: key); + final icon; + final double iconSize; + final Conversation conversation; + final callback; + final bgColor; + + @override + Widget build(BuildContext context) { + Widget avatar; + if (icon != null) { + avatar = Container( + height: 47.5, + width: 47.5, + margin: EdgeInsets.only(left: 6), + alignment: Alignment.center, + decoration: BoxDecoration( + gradient: bgColor, + borderRadius: BorderRadius.all(Radius.circular(50))), + child: Image.asset( + icon, + height: iconSize, + )); + } else if (conversation.isAvatarFromNet()) { + avatar = CachedNetworkImage( + imageUrl: conversation.avatar, + placeholder: CustomUI.buildImgLoding, + width: Constants.ConversationAvatarSize, + height: Constants.ConversationAvatarSize, + ); + } else { + avatar = Image.asset( + conversation.avatar, + width: Constants.ConversationAvatarSize, + height: Constants.ConversationAvatarSize, + ); + } + List _rightArea = [ + Container( + padding: EdgeInsets.only(top: 4), + alignment: Alignment.center, + child: Text(conversation.updateAt, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 11, color: const Color(0xFFC6C6C6))), + ) + ]; + if (conversation.unreadMsgCount > 0) { + var countStr = conversation.unreadMsgCount.toString(); + if (conversation.unreadMsgCount > 99) { + countStr = '99+'; + } + // 未读消息角标 + Widget unreadMsgCountText = Container( + width: Constants.UnReadMsgNotifyDotSize, + height: Constants.UnReadMsgNotifyDotSize, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(Constants.UnReadMsgNotifyDotSize / 2.0), + color: Color(0xFFFF5454), + ), + child: Text(countStr, + textScaleFactor: 1.0, style: AppStyles.UnreadMsgCountDotStyle), + ); + _rightArea.add(Expanded( + child: Align( + alignment: Alignment.bottomCenter, + child: unreadMsgCountText, + ))); + } + + return InkWell( + child: Container( + padding: const EdgeInsets.all(10.0), + decoration: BoxDecoration( + color: Color(AppColors.ConversationItemBgColor), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + avatar, + Container(width: 17.0), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(conversation.title, + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.black, + )), + SizedBox( + height: 5, + ), + Text(conversation.desc, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 12, color: const Color(0xFF9B9B9B))) + ], + ), + ), + // Container(width: 10.0), + SizedBox( + height: Constants.ConversationAvatarSize, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: _rightArea, + ), + ) + ], + ), + ), + onTap: () { + callback(); + }, + ); + } +} + +class ConversActionPage extends StatefulWidget { + ConversActionPage({Key key}) : super(key: key); + + _ConversActionPageState createState() => _ConversActionPageState(); +} + +Map systemInfo = { + 'applyList': null, + 'applyCount': 0, + 'evaluateList': null, + 'evaluateCount': 0, + 'parkList': null, + 'parkCount': 0, + 'castList': null, + 'castCount': 0, + 'walletList': null, + 'walletCount': 0, +}; + +int msgNum = 0; +bool isShowMsg() { + return msgNum > 0; +} + +getAllResNum(prefs) { + getResNum(prefs, Constants.ApplyCount); + getResNum(prefs, Constants.EvaluateCount); + getResNum(prefs, Constants.ParkCount); + getResNum(prefs, Constants.CastCount); + getResNum(prefs, Constants.WalletCount); +} + +getResNum(prefs, url) async { + var count = prefs.getInt(url + UserData().basicInfo.userId.toString()); + systemInfo[url] = count == null ? systemInfo[url] : (systemInfo[url] - count); + + msgNum += systemInfo[url]; +} + +setResNum(url) async { + var localKey = url + UserData().basicInfo.userId.toString(); + if (systemInfo[url] > 0) { + SharedPreferences prefs = await SharedPreferences.getInstance(); + var count = prefs.getInt(localKey); + prefs.setInt( + localKey, count == null ? systemInfo[url] : (systemInfo[url] + count)); + msgNum -= systemInfo[url]; + systemInfo[url] = 0; + } +} + +class _ConversActionPageState extends State + with SingleTickerProviderStateMixin { + TabController tabCtrl; + + void getSystemMsg(data) async { + Map data = { + "userId": UserData().basicInfo.userId, + "type": UserData().basicInfo.sex + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('message/all/message', data: data); + if (res == null) { + return; + } + Map resData = res.data; + if (resData['code'] == 0) { + SharedPreferences prefs = await SharedPreferences.getInstance(); + systemInfo = resData['data']; + msgNum = 0; + getAllResNum(prefs); + if (mounted) { + setState(() {}); + } + } + } + + @override + void initState() { + super.initState(); + + MessageMgr().on('update_system', getSystemMsg); + getSystemMsg(null); + + tabCtrl = TabController(length: 2, vsync: this); + } + + @override + void dispose() { + tabCtrl.dispose(); + MessageMgr().off('update_system', getSystemMsg); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + //backgroundColor: Constants.LightGreyBackgroundColor, + centerTitle: false, + title: Text( + I18n.of(context).message_center, + textScaleFactor: 1.0, + style: Constants.MainTitleStyle, + ), + actions: [ + Container( + child: IconButton( + icon: CircleAvatar( + backgroundColor: Constants.GreyBackgroundColor, + radius: 13.75, + child: Padding( + padding: EdgeInsets.only(bottom: 1.5), + child: Icon( + IconData(0xe659, + fontFamily: Constants.IconFontFamily), + color: Constants.BlackTextColor, + size: 21, + ))), + onPressed: () { + CustomUI().goScanPage(context); + }, + ), + ), + // InkWell( + // onTap: () { + // Navigator.of(context).push( + // new MaterialPageRoute( + // builder: (context) { + // return MessagePushPage(); + // }, + // ), + // ); + // }, + // child: Padding( + // padding: EdgeInsets.only(right: 10), + // child: CircleAvatar( + // backgroundColor: Constants.GreyBackgroundColor, + // radius: 13.75, + // child: Icon( + // Icons.settings, + // color: Constants.BlackTextColor, + // size: 22, + // )), + // )), + ], + elevation: 0, + bottom: PreferredSize( + preferredSize: Size.fromHeight(28), + child: Container( + padding: EdgeInsets.only(left: 2), + decoration: BoxDecoration( + //color: Constants.LightGreyBackgroundColor, + border: + Border(bottom: BorderSide(color: Color(0xffeaeaea)))), + alignment: Alignment.centerLeft, + child: TabBar( + isScrollable: true, + indicatorPadding: EdgeInsets.only(left: 9, right: 9), + tabs: [ + UnreadDot( + child: Container( + margin: EdgeInsets.only(right: 4), + child: Text(I18n.of(context).text_chat, + textScaleFactor: 1.0), + ), + type: 1), + UnreadDot( + child: Container( + margin: EdgeInsets.only(right: 4), + child: Text(I18n.of(context).system_information, + textScaleFactor: 1.0)), + type: 2), + ], + controller: tabCtrl, + ), + )), + ), + body: SafeArea( + child: TabBarView( + children: [ + LastChatPage(), + ListView( + children: [ + SizedBox(height: 8.5), + _ConversationItem( + icon: 'assets/images/chat/icon1.png', + bgColor: Constants.RadioGradient, + conversation: Conversation( + avatar: 'assets/images/ic_tx_news.png', + title: I18n.of(context).radio_message, + desc: RichTitle.normalTitle( + systemInfo['castList'], context, InfoType.Radio), + updateAt: systemInfo['castList'] == null + ? "" + : WebData().getLoginTime( + context, systemInfo['castList']['CreateTime']), + unreadMsgCount: systemInfo['castCount'], + ), + callback: () { + setResNum(Constants.CastCount); + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return InfoListPage( + title: I18n.of(context).radio_message, + type: InfoType.Radio, + ); + }, + ), + ); + }, + ), + _ConversationItem( + icon: 'assets/images/chat/icon4.png', + bgColor: Constants.MoneyGradient, + conversation: Conversation( + avatar: 'assets/images/ic_tx_news.png', + title: I18n.of(context).wallet_reminder, + desc: RichTitle.normalTitle( + systemInfo['walletList'], context, InfoType.Money), + updateAt: systemInfo['walletList'] == null + ? "" + : WebData().getLoginTime( + context, systemInfo['walletList']['CreateTime']), + unreadMsgCount: systemInfo['walletCount'], + ), + callback: () { + setResNum(Constants.WalletCount); + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return InfoListPage( + title: I18n.of(context).wallet_reminder, + type: InfoType.Money, + ); + }, + ), + ); + }, + ), + _ConversationItem( + icon: 'assets/images/chat/icon3.png', + iconSize: 27, + bgColor: Constants.ApplyGradient, + conversation: Conversation( + avatar: 'assets/images/ic_tx_news.png', + title: I18n.of(context).application_notice, + desc: RichTitle.normalTitle( + systemInfo['applyList'], context, InfoType.Apply), + updateAt: systemInfo['applyList'] == null + ? "" + : WebData().getLoginTime( + context, systemInfo['applyList']['CreatTime']), + unreadMsgCount: systemInfo['applyCount'], + ), + callback: () { + setResNum(Constants.ApplyCount); + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return InfoListPage( + title: I18n.of(context).application_notice, + type: InfoType.Apply, + ); + }, + ), + ); + }, + ), + _ConversationItem( + icon: 'assets/images/chat/icon6.png', + bgColor: Constants.EvaGradient, + conversation: Conversation( + avatar: 'assets/images/ic_tx_news.png', + title: I18n.of(context).evaluation_notice, + desc: RichTitle.normalTitle(systemInfo['evaluateList'], + context, InfoType.Evaluation), + updateAt: systemInfo['evaluateList'] == null + ? '' + : WebData().getLoginTime( + context, systemInfo['evaluateList']['CreateTime']), + unreadMsgCount: systemInfo['evaluateCount'], + ), + callback: () { + setResNum(Constants.EvaluateCount); + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return InfoListPage( + title: I18n.of(context).evaluation_notice, + type: 2, + ); + }, + ), + ); + }, + ), + _ConversationItem( + icon: 'assets/images/chat/icon5.png', + bgColor: Constants.ParkGradient, + conversation: Conversation( + avatar: 'assets/images/ic_tx_news.png', + title: I18n.of(context).appName, + desc: RichTitle.normalTitle( + systemInfo['parkList'], context, InfoType.System), + updateAt: systemInfo['parkList'] == null + ? "" + : WebData().getLoginTime( + context, systemInfo['parkList']['CreateTime']), + unreadMsgCount: systemInfo['parkCount'], + ), + callback: () { + setResNum(Constants.ParkCount); + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return InfoListPage( + title: I18n.of(context).appName, + type: InfoType.System, + ); + }, + ), + ); + }, + ) + ], + ) + ], + controller: tabCtrl, + ))); + } +} diff --git a/lib/home/DiscoverPage.dart b/lib/home/DiscoverPage.dart new file mode 100644 index 0000000..46d6217 --- /dev/null +++ b/lib/home/DiscoverPage.dart @@ -0,0 +1,743 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/SearchPage.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/DropDownMemu.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/Toggle.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/UserCard.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:location_permissions/location_permissions.dart'; +import 'package:provider/provider.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; + +class DisCoverPage extends StatefulWidget { + DisCoverPage({Key key}) : super(key: key); + + _DisCoverPageState createState() => _DisCoverPageState(); +} + +class _DisCoverPageState extends State + with TickerProviderStateMixin { + TabController sameTabCtrl; + TabController diffTabCtrl; + + RefreshController _scrollControllerNear = + RefreshController(initialRefresh: true); + + RefreshController _scrollControllerNew = + RefreshController(initialRefresh: true); + + RefreshController _scrollControllerApply = + RefreshController(initialRefresh: true); + + RefreshController _scrollControllerVIP = + RefreshController(initialRefresh: true); + + bool isPerformingRequest = false; + + Map listMap = { + 1: {'list': [], 'page': 1, 'control': null}, + 2: {'list': [], 'page': 1, 'control': null}, + 3: {'list': [], 'page': 1, 'control': null}, + 4: {'list': [], 'page': 1, 'control': null}, + }; //不同类别的数据 + + int type = 1; + int rows = 20; + + bool isLoading = false; //是否正在加载数据 + + static const SEPARATE_SIZE = 20.0; + + bool isOnline = false; + + bool isWomen = UserData().isMan(); + + String search = '1'; + + String titleStr = ''; + + GZXDropdownMenuController _dropdownMenuController = + GZXDropdownMenuController(); + + //获取新的数据 + void getNewData() { + listMap[type]['page'] = 1; + + getData((data) { + listMap[type]['list'].clear(); + if (data != null) { + listMap[type]['list'].addAll(data); + } + if (mounted) { + setState(() {}); + } + }); + } + + void _onLoading() async { + listMap[type]['page']++; + getData((data) { + if (data == null || data.length == 0) { + listMap[type]['page']--; + listMap[type]['control'].loadNoData(); + } else { + listMap[type]['list'].addAll(data); + listMap[type]['control'].loadComplete(); + } + + if (mounted) { + setState(() {}); + } + }); + } + + void getData(callback) async { + var data = { + "userId": UserData().basicInfo.userId, + "type": type, + "search": search, + }; + data['sign'] = TokenMgr().getSign(data); + data['lng'] = UserData().longitude; + data['lat'] = UserData().latitude; + data['page'] = listMap[type]['page']; + data['rows'] = rows; + data['sex'] = isWomen ? 2 : 1; + data['online'] = isOnline ? 1 : 0; + Response res = await HttpUtil().post('user/main/interface', data: data); + listMap[type]['control'].refreshCompleted(); + isLoading = false; + if (res == null) { + return; + } + var resData = res.data; + print(resData); + if (resData['code'] == 0) { + callback(resData['data']); + } + } + + @override + void initState() { + super.initState(); + diffTabCtrl = TabController(length: 3, vsync: this); + sameTabCtrl = TabController(length: 2, vsync: this); + + listMap[1]['control'] = _scrollControllerNear; + listMap[2]['control'] = _scrollControllerNew; + listMap[3]['control'] = _scrollControllerApply; + listMap[4]['control'] = _scrollControllerVIP; + + //getNewData(); + + sameTabCtrl.addListener(() { + type = sameTabCtrl.index == 0 ? 1 : 4; + if (listMap[type]['list'].length == 0) getNewData(); + }); + + diffTabCtrl.addListener(() { + type = diffTabCtrl.index + 1; + if (listMap[type]['list'].length == 0) getNewData(); + }); + MessageMgr().on('test_Permission', msgTestPermission); + MessageMgr().on('refresh_love_list', msgRefreshLoveList); + } + + msgRefreshLoveList(data) { + print('msgRefreshLoveList ${data['UserId'] is String}'); + for (int i = 0; i < listMap[type]['list'].length; i++) { + var item = listMap[type]['list'][i]; + print(item['UserId'] == data['UserId']); + if (item['UserId'] == data['UserId']) { + item['Follow'] = data['flag']; + print(listMap[type]['list'][i]); + break; + } + } + setState(() {}); + } + + msgTestPermission(data) async { + PermissionStatus status = + await LocationPermissions().checkPermissionStatus(); + if (status == PermissionStatus.granted) { + UserData().hasLocationPermission = true; + _onRefresh(); + } + } + + @override + void dispose() { + _scrollControllerNear.dispose(); + _scrollControllerNew.dispose(); + _scrollControllerApply.dispose(); + _scrollControllerVIP.dispose(); + sameTabCtrl.dispose(); + diffTabCtrl.dispose(); + MessageMgr().off('test_Permission', msgTestPermission); + MessageMgr().off('refresh_love_list', msgRefreshLoveList); + super.dispose(); + } + + var _selectTempFirstLevelIndex = '1'; + var _selectFirstLevelIndex = '1'; + + var _selectSecondLevelIndex = '-1'; + _buildAddressWidget(void itemOnTap(String key, String value)) { + List firstLevels = [ + {'key': '1', 'value': I18n.of(context).nearby}, + ]; + + if (WebData().provinces.length > 0) { + if (UserData().isInChina) { + firstLevels + .add({'key': 'China', 'value': WebData().provinces['China']}); + } else { + firstLevels + .add({'key': 'VietNam', 'value': WebData().provinces['VietNam']}); + } + } + + List secondLevels = []; + if (WebData().cities.length > 0) { + if (UserData().isInChina) { + WebData() + .cities['China'] + .forEach((k, v) => secondLevels.add({'key': k, 'value': v})); + } else { + WebData() + .cities['VietNam'] + .forEach((k, v) => secondLevels.add({'key': k, 'value': v})); + } + } + + Widget _buildRow(item) { + var index = item['key']; + return GestureDetector( + onTap: () { + _selectSecondLevelIndex = index; + _selectFirstLevelIndex = _selectTempFirstLevelIndex; + itemOnTap(index, item['value']); + }, + child: Container( + height: 50, + decoration: BoxDecoration( + border: Border(top: Constants.GreyBorderSide), + ), + alignment: Alignment.center, + child: Text( + item['value'], + textScaleFactor: 1.0, + style: TextStyle( + decoration: TextDecoration.none, + color: _selectFirstLevelIndex == _selectTempFirstLevelIndex && + _selectSecondLevelIndex == index + ? const Color(0xFF0368FF) + : Constants.BlackTextColor, + fontWeight: FontWeight.normal, + fontSize: 14), + )), + ); + } + + return Container( + child: Row( + children: [ + Container( + width: MediaQuery.of(context).size.width * 0.4, + child: ListView( + padding: EdgeInsets.zero, + children: firstLevels.map((item) { + var index = item['key']; + return GestureDetector( + onTap: () { + _selectTempFirstLevelIndex = index; + + if (index == '1' || index == '2') { + itemOnTap(index, item['value']); + return; + } + setState(() {}); + }, + child: Container( + height: 50, + decoration: BoxDecoration( + color: _selectTempFirstLevelIndex == index + ? const Color(0xFF0368FF) + : Colors.white, + border: Border(top: Constants.GreyBorderSide), + ), + alignment: Alignment.center, + child: Text( + item['value'], + textScaleFactor: 1.0, + style: TextStyle( + color: _selectTempFirstLevelIndex == index + ? Colors.white + : Constants.BlackTextColor, + fontWeight: FontWeight.normal, + decoration: TextDecoration.none, + fontSize: 14), + ))); + }).toList(), + )), + Expanded( + child: Container( + width: double.infinity, + decoration: + BoxDecoration(border: Border(left: Constants.GreyBorderSide)), + child: ListView( + padding: EdgeInsets.zero, + children: _selectTempFirstLevelIndex == '1' + ? [ + _buildRow({'key': '1', 'value': I18n.of(context).nearby}) + ] + : (_selectTempFirstLevelIndex == '2' + ? [ + _buildRow({ + 'key': '2', + 'value': I18n.of(context).Resident_city + }) + ] + : secondLevels.map((item) { + return _buildRow(item); + }).toList()), + ), + ), + ) + ], + )); + } + + Widget _buildAppBar() { + Widget title = InkWell( + highlightColor: Colors.transparent, + radius: 0, + onTap: UserData().isInChina + ? null + : () { + _dropdownMenuController.dropDownHearderHeight = 70; + _dropdownMenuController.show(0); + }, + child: Container( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + titleStr == '' ? I18n.of(context).nearby : titleStr, + textScaleFactor: 1.0, + //style: Constants.MainTitleStyle, + ), + UserData().isInChina + ? Container() + : Icon( + Icons.arrow_drop_down, + color: Constants.BlackTextColor, + ) + ], + ))); + Widget leading = Container( + child: Row( + children: [ + CircleAvatar( + backgroundColor: Constants.GreyBackgroundColor, + radius: 13.75, + child: Padding( + padding: EdgeInsets.only(bottom: 1.5), + child: ToggleButton( + activeIcon: IconData( + 0xe61e, + fontFamily: 'iconfont', + ), + unActiveIcon: IconData( + 0xe61f, + fontFamily: 'iconfont', + ), + active: isWomen, + activeColor: Constants.BlackTextColor, + unActiveColor: Colors.transparent, + onChange: (state) { + setState(() { + isWomen = !isWomen; + sameTabCtrl.index = 0; + diffTabCtrl.index = 0; + getNewData(); + }); + }, + ))), + Container( + padding: EdgeInsets.only(left: 10), + child: IconButton( + icon: CircleAvatar( + backgroundColor: Constants.GreyBackgroundColor, + radius: 13.75, + child: Padding( + padding: EdgeInsets.only(bottom: 1), + child: Icon( + IconData(0xe619, fontFamily: Constants.IconFontFamily), + color: Constants.BlackTextColor, + size: 22, + ))), + onPressed: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return SearchPage(); + }, + ), + ); + }, + ), + ), + // Container( + // child: IconButton( + // icon: CircleAvatar( + // backgroundColor: Constants.GreyBackgroundColor, + // radius: 13.75, + // child: Padding( + // padding: EdgeInsets.only(bottom: 1.5), + // child: Icon( + // IconData(0xe659, fontFamily: Constants.IconFontFamily), + // color: Constants.BlackTextColor, + // size: 21, + // ))), + // onPressed: () { + // goScanPage(); + // }, + // ), + // ) + ], + ), + ); + + Color borderColor = + isOnline ? Constants.LightBlueButtonColor : Constants.GreyTextColor; + Color textColor = isOnline ? Colors.white : Constants.GreyTextColor; + Color bgColor = isOnline + ? Constants.LightBlueButtonColor + : Constants.LightGreyBackgroundColor; + Widget actions = GestureDetector( + child: Container( + margin: EdgeInsets.only(right: 16, bottom: 0), + alignment: Alignment.center, + child: Text( + I18n.of(context).first_online, + textScaleFactor: 1.0, + style: TextStyle(color: textColor, fontSize: 11.5), + ), + padding: EdgeInsets.only(left: 11, right: 11, bottom: 3, top: 2), + decoration: BoxDecoration( + color: bgColor, + border: Border.all(color: borderColor, width: 1), + borderRadius: BorderRadius.all(Radius.circular(5.0))), + ), + onTap: () { + setState(() { + isOnline = !isOnline; + getNewData(); + }); + }, + ); + return AppBar( + backgroundColor: Constants.LightGreyBackgroundColor, + title: title, + centerTitle: true, + actions: [leading], + leading: CustomUI.buildCustomLeading(context), + elevation: 0, + bottom: PreferredSize( + preferredSize: + Size.fromHeight(UserData().hasLocationPermission ? 28 : 52), + child: Column( + children: [ + Container( + padding: EdgeInsets.only(left: 2), + width: Screen.width, + decoration: BoxDecoration( + color: Constants.LightGreyBackgroundColor, + border: Border( + bottom: UserData().hasLocationPermission + ? BorderSide(color: Color(0xffeaeaea)) + : BorderSide.none)), + alignment: Alignment.centerLeft, + child: Stack( + alignment: Alignment.centerLeft, + children: [ + tabBar(), + Positioned(right: 0, bottom: 4, child: actions) + ], + ), + ), + // !UserData().hasLocationPermission + // ? InkWell( + // onTap: () { + // CustomUI.buildOneConfirm( + // context, + // I18n.of(context).get_location, + // I18n.of(context).determine, () async { + // Navigator.of(context).pop(); + // LocationPermissions().openAppSettings(); + // }, title: I18n.of(context).open_location); + // }, + // child: Container( + // height: 25, + // alignment: Alignment.center, + // width: double.infinity, + // child: Row( + // crossAxisAlignment: CrossAxisAlignment.center, + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Text( + // I18n.of(context).not_positioned, + // textScaleFactor: 1, + // style: TextStyle( + // fontSize: 12.5, + // color: const Color(0xffab8f60)), + // ), + // Icon( + // Icons.chevron_right, + // size: 18, + // color: const Color(0xffab8f60), + // ) + // ], + // ), + // color: const Color(0xfffaefcf), + // )) + // : Container() + ], + )), + ); + } + + buildSexBar(bool isWomen) { + List feMaleTabs = [ + Text(I18n.of(context).nearby, textScaleFactor: 1.0), + Text(I18n.of(context).new_registration, textScaleFactor: 1.0), + Text(I18n.of(context).authenticate, textScaleFactor: 1.0), + ]; + + List maleTabs = [ + Text(I18n.of(context).nearby, textScaleFactor: 1.0), + Text(I18n.of(context).member, textScaleFactor: 1.0), + ]; + + return TabBar( + isScrollable: true, + indicatorPadding: EdgeInsets.only(left: 9, right: 9), + tabs: isWomen ? feMaleTabs : maleTabs, + controller: isWomen ? diffTabCtrl : sameTabCtrl, + ); + } + + Widget tabBar() { + return Container( + alignment: Alignment.centerLeft, + width: Screen.width, + child: buildSexBar(isWomen)); + } + + @override + Widget build(BuildContext context) { + GZXDropDownMenu menu = GZXDropDownMenu( + // controller用于控制menu的显示或隐藏 + controller: _dropdownMenuController, + // 下拉菜单显示或隐藏动画时长 + animationMilliseconds: 150, + // 下拉菜单,高度自定义,你想显示什么就显示什么,完全由你决定,你只需要在选择后调用_dropdownMenuController.hide();即可 + menus: [ + GZXDropdownMenuBuilder( + dropDownHeight: 50 * 8.0, + callback: () { + setState(() {}); + }, + dropDownWidget: _buildAddressWidget((key, value) { + setState(() {}); + isLoading = true; + titleStr = value; + _dropdownMenuController.hide(); + + search = key; + getNewData(); + })), + ], + ); + + var footer = CustomUI.buildLoadingFooter(); + + Widget diffView = TabBarView( + children: [ + SmartRefresher( + enablePullDown: true, + enablePullUp: true, + header: MaterialClassicHeader(), + footer: footer, + controller: _scrollControllerNear, + onRefresh: _onRefresh, + onLoading: _onLoading, + child: + (_scrollControllerNear.headerStatus == RefreshStatus.completed && + listMap[1]['list'].length == 0) + ? CustomUI.buildNoData(context) + : ListView.builder( + itemBuilder: _renderRowNear, + itemCount: listMap[1]['list'].length, + ), + ), + SmartRefresher( + enablePullDown: true, + enablePullUp: true, + header: MaterialClassicHeader(), + footer: footer, + controller: _scrollControllerNew, + onRefresh: _onRefresh, + onLoading: _onLoading, + child: + (_scrollControllerNew.headerStatus == RefreshStatus.completed && + listMap[2]['list'].length == 0) + ? CustomUI.buildNoData(context) + : ListView.builder( + itemBuilder: _renderRowNew, + itemCount: listMap[2]['list'].length, + ), + ), + SmartRefresher( + enablePullDown: true, + enablePullUp: true, + header: MaterialClassicHeader(), + footer: footer, + controller: _scrollControllerApply, + onRefresh: _onRefresh, + onLoading: _onLoading, + child: + (_scrollControllerApply.headerStatus == RefreshStatus.completed && + listMap[3]['list'].length == 0) + ? CustomUI.buildNoData(context) + : ListView.builder( + itemBuilder: _renderRowApply, + itemCount: listMap[3]['list'].length, + ), + ), + ], + controller: diffTabCtrl, + ); + + Widget sampView = TabBarView( + children: [ + SmartRefresher( + enablePullDown: true, + enablePullUp: true, + header: MaterialClassicHeader(), + footer: footer, + controller: _scrollControllerNear, + onRefresh: _onRefresh, + onLoading: _onLoading, + child: + (_scrollControllerNear.headerStatus == RefreshStatus.completed && + listMap[1]['list'].length == 0) + ? CustomUI.buildNoData(context) + : ListView.builder( + itemBuilder: _renderRowNear, + itemCount: listMap[1]['list'].length, + ), + ), + SmartRefresher( + enablePullDown: true, + enablePullUp: true, + header: MaterialClassicHeader(), + footer: footer, + controller: _scrollControllerVIP, + onRefresh: _onRefresh, + onLoading: _onLoading, + child: + (_scrollControllerVIP.headerStatus == RefreshStatus.completed && + listMap[4]['list'].length == 0) + ? CustomUI.buildNoData(context) + : ListView.builder( + itemBuilder: _renderRowVIP, + itemCount: listMap[4]['list'].length, + ), + ), + ], + controller: sameTabCtrl, + ); + return Stack( + children: [ + Scaffold( + appBar: _buildAppBar(), + body: SafeArea( + child: Stack( + children: [ + !isWomen ? sampView : diffView, + isLoading ? CustomUI.buildLoaingAnim(context) : Container(), + ], + ), + )), + menu + ], + ); + } + + Widget _renderRow(int index, list, page) { + if (index < list.length) { + var userInfo = list[index]; + return UserCard( + key: UniqueKey(), + userName: Provider.of(context) + .getRefName(userInfo['UserId'], userInfo['NickName']), + city: WebData().getCountry( + userInfo['Country']), //WebData().getCity(userInfo['City']), + headUrl: userInfo['Headimgurl'], + isReal: userInfo['IsAttestation'] == 1, + constellation: + WebData().getConstellation(context, userInfo['Constellation']), + distance: userInfo['Distance'].toDouble(), + age: userInfo['Age'], + professional: WebData().getProffesionName(userInfo['Occupation']), + isOnline: userInfo['OnlineStatus'] == 1 + ? I18n.of(context).online + : WebData().getLoginTime(context, userInfo['LoginDate']), + hiddenDistince: userInfo['DistanceStatus'] == 1, + sex: userInfo['Sex'], + isLove: userInfo['Follow'] == 0, + isBalck: userInfo['Follow'] == 1, + userId: userInfo['UserId'], + payImg: userInfo['PhotoAut'] == 1, + isHidden: userInfo['InfoAut'] == 1, + member: userInfo['IsMember'], + imgNum: userInfo['PhotoNum'], + ); + } + return Container(); + } + + Widget _renderRowNear(BuildContext context, int index) { + return _renderRow(index, listMap[1]['list'], listMap[1]['page']); + } + + Widget _renderRowNew(BuildContext context, int index) { + return _renderRow(index, listMap[2]['list'], listMap[2]['page']); + } + + Widget _renderRowApply(BuildContext context, int index) { + return _renderRow(index, listMap[3]['list'], listMap[3]['page']); + } + + Widget _renderRowVIP(BuildContext context, int index) { + return _renderRow(index, listMap[4]['list'], listMap[4]['page']); + } + + Future _onRefresh() async { + getNewData(); + } +} diff --git a/lib/home/EditData.dart b/lib/home/EditData.dart new file mode 100644 index 0000000..8984dce --- /dev/null +++ b/lib/home/EditData.dart @@ -0,0 +1,1033 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/MyDialogContent.dart'; +import 'package:chat/home/SelectPage.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:city_pickers/city_pickers.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; +import 'package:image_cropper/image_cropper.dart'; + +import 'package:oktoast/oktoast.dart'; +import '../utils/ShadowButton.dart'; +import 'package:image_picker/image_picker.dart'; +import 'dart:io'; +import '../data/UserData.dart'; +import '../utils/TokenMgr.dart'; +import '../data/WebData.dart'; +import 'IndexPage.dart'; +import 'UserAgreement.dart'; + +const double TipLeft = 20; +const double BorderLeft = 25; + +const double LeftTextFontSize = 13; +const LetfTextStyle = TextStyle( + fontSize: LeftTextFontSize, + fontWeight: FontWeight.w600, + color: Constants.BlackTextColor); + +class EditPage extends StatefulWidget { + @required + final bool isEditPage; + EditPage({Key key, this.isEditPage = false}) : super(key: key); + + _EditPageState createState() => _EditPageState(); +} + +class _EditPageState extends State { +//职业 + String profession = ''; + Set professionId = Set.from([ + UserData().basicInfo.occupation == null + ? 'Information-Internet' + : UserData().basicInfo.occupation + ]); + + //国家 + String country = ''; + Set countryId = Set.from([ + UserData().basicInfo.country == null + ? 'Country-VietNam' + : 'Country-${UserData().basicInfo.country}' + ]); + +//期待对象 + String lovePeople = ''; + Set lovePeopleId = Set.from(UserData().basicInfo.hopeObject == null + ? ['Indifferent'] + : UserData().basicInfo.hopeObject.split(',')); + +//是否展示社交账号 + bool isHiddenSocialAccount = UserData().basicInfo.accountStatus == 1; + +//昵称 + String nickname = UserData().basicInfo.nickName; + +//约会范围 + String dateRange = ''; + Set dateRangeId = Set.from(UserData().basicInfo.meetPlace == null + ? [] + : UserData().basicInfo.meetPlace.split(',')); + +//生日 + String birthday = ''; + String birthdayId = UserData().basicInfo.birthday == null + ? '1995-01-01' + : UserData().basicInfo.birthday; + +//身高数据 + String heightStr = ''; + String heightId = UserData().basicInfo.height == null + ? '0' + : UserData().basicInfo.height.toInt().toString(); +//体重数据 + String weightStr = ''; + String weightId = UserData().basicInfo.weight == null + ? '0' + : UserData().basicInfo.weight.toInt().toString(); + +//是否同意用户协议 + bool isAgree = false; + + File headFile; + + bool loadSuccess = false; + + String wechat = UserData().basicInfo.wechat; + String facebook = UserData().basicInfo.facebook; + + TextEditingController nickNameController = + new TextEditingController(text: UserData().basicInfo.nickName); + TextEditingController mymsgController = + new TextEditingController(text: UserData().basicInfo.ownMsg); + + TextEditingController wechatController = + new TextEditingController(text: UserData().basicInfo.wechat); + TextEditingController fbController = + new TextEditingController(text: UserData().basicInfo.facebook); + + initValue() { + if (!loadSuccess) { + profession = WebData().getProffesionName(professionId.first); + if (!widget.isEditPage) { + switch (UserData().language) { + case LanguageType.English: + countryId = Set.from(['Country-UnitedStates']); + break; + case LanguageType.Vietnamese: + countryId = Set.from(['Country-VietNam']); + break; + case LanguageType.TraditionalChinese: + case LanguageType.TraditionalChinese: + countryId = Set.from(['Country-China']); + break; + case LanguageType.Korean: + countryId = Set.from(['Country-Korea']); + break; + case LanguageType.Japanese: + countryId = Set.from(['Country-Japan']); + break; + default: + } + } + country = WebData().getCountry(countryId.first.split('-')[1]); + var hopeObject = ''; + lovePeopleId.forEach((f) => hopeObject += hopeObject == '' ? f : ',$f'); + lovePeople = WebData().getLovePeople(hopeObject); + + var dateRangeStr = ''; + dateRangeId + .forEach((f) => dateRangeStr += dateRangeStr == '' ? f : ',$f'); + dateRange = WebData().getDateRange(dateRangeStr); + + birthday = birthdayId; + + heightStr = (UserData().basicInfo.height == 0.0 || + UserData().basicInfo.height == null) + ? I18n.of(context).not_show + : '${UserData().basicInfo.height}M'; + weightStr = (UserData().basicInfo.weight == 0.0 || + UserData().basicInfo.weight == null) + ? I18n.of(context).not_show + : '${UserData().basicInfo.weight}KG'; + loadSuccess = true; + setState(() {}); + } + } + + BoxDecoration _getCardDecoration() { + return new BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, bottom: Constants.GreyBorderSide)); + } + + @override + void initState() { + super.initState(); + MessageMgr().on('change_currentcity', changeCurrentcity); + print('EditPage initState'); + } + + changeCurrentcity(data) { + if (!widget.isEditPage && dateRangeId.length == 0) { + var dateRangeStr = ''; + dateRangeId = Set.from([UserData().currentCity]); + dateRangeId + .forEach((f) => dateRangeStr += dateRangeStr == '' ? f : ',$f'); + dateRange = WebData().getDateRange(dateRangeStr); + setState(() {}); + } + } + + @override + void dispose() { + nickNameController.dispose(); + mymsgController.dispose(); + MessageMgr().on('change_currentcity', changeCurrentcity); + super.dispose(); + } + + _showDialog() { + CustomUI.buildOneConfirm( + context, I18n.of(context).exit_registration, I18n.of(context).determine, + () { + HttpUtil().clearCacheData(); + Navigator.of(context).pushAndRemoveUntil(new MaterialPageRoute( + builder: (context) { + return IndexPage(); + }, + ), (route) => route == null); + }); + } + + Future _requestPop() { + if (!widget.isEditPage) { + _showDialog(); + } else { + Navigator.of(context).pop(); + } + return new Future.value(false); + } + + @override + Widget build(BuildContext context) { + initValue(); + + var keyHeight = MediaQuery.of(context).viewInsets.bottom; + if (keyHeight > 0) { + UserData().setKeyboardHeight(keyHeight); + } + + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + widget.isEditPage + ? I18n.of(context).edit_information + : I18n.of(context).complete_material, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + elevation: 1, + leading: CustomUI.buildCustomLeading(context), + actions: [ + widget.isEditPage + ? Container( + alignment: Alignment.center, + child: new InkWell( + child: new Padding( + padding: EdgeInsets.only( + right: 15, left: 15, top: 10, bottom: 10), + child: new Text( + I18n.of(context).save, + textScaleFactor: 1.0, + style: TextStyle(color: Constants.BlueTextColor), + ), + ), + onTap: () { + postSettion((data) { + showToast(I18n.of(context).successfully_saved); + Navigator.of(context).pop(); + MessageMgr().emit('update_data', data); + }); + }, + ), + ) + : Container(), + ], + centerTitle: true); + return WillPopScope( + onWillPop: _requestPop, + child: Scaffold( + backgroundColor: const Color(0xFFEDEDED), + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + )), + appBar: appBar, + )); + } + + Widget _buildBody() { + List body = [ + _buildHeadUrl(), + _buildBasicData(context), + UserData().isMan() ? Container() : _buildSocialContact(), + // _buildHiddenButtom(), + // _buildMoreInfo(), + _buildCommitButton(), + ]; + List body2 = [ + _buildBasicData(context), + _buildSocialContact(), + _buildHiddenButtom(), + _buildMoreInfo(), + ]; + return new ListView( + children: widget.isEditPage ? body2 : body, + ); + } + + Widget _buildCommitButton() { + return new Column( + children: [ + _buildRegisterButton(), + _buildAgreement(), + ], + ); + } + + Widget _buildAgreement() { + return InkWell( + onTap: () async { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return UserAgreement(); + }, + ), + ); + }, + child: Container( + margin: EdgeInsets.only(top: 10, bottom: 20, left: 10, right: 10), + child: Text( + I18n.of(context).agreed_agreement, + style: TextStyle(color: Colors.red), + textAlign: TextAlign.center, + ))); + } + + postSettion(callback) async { + if (nickname == null || nickname == "" || nickname.length > 25) { + showToast(I18n.of(context).only1_8); + return; + } + if (dateRangeId.length == 0) { + showToast(I18n.of(context).Please_select_a_resident_city); + return; + } + if (birthdayId == null || birthdayId == '0') { + showToast(I18n.of(context).choose_birthday); + return; + } + if (professionId.length == 0) { + showToast(I18n.of(context).choose_career); + return; + } + // if (dateItemId.length == 0) { + // showToast(I18n.of(context).select_program); + // return; + // } + + if (countryId.length == 0) { + showToast(I18n.of(context).select_program); + return; + } + + if (lovePeopleId.length == 0) { + showToast(I18n.of(context).choose_lover); + return; + } + if (!UserData().isMan() && + (wechat == null || wechat == '') && + (facebook == null || facebook == '')) { + showToast(I18n.of(context).least_account); + return; + } + + var program = ''; + //dateItemId.forEach((f) => program += program == '' ? f : ',$f'); + var hopeObject = ''; + lovePeopleId.forEach((f) => hopeObject += hopeObject == '' ? f : ',$f'); + var dateRangeStr = ''; + dateRangeId.forEach((f) => dateRangeStr += dateRangeStr == '' ? f : ',$f'); + + Map data = { + "userId": UserData().basicInfo.userId, + "nickName": nickname, + "birthday": birthdayId, + }; + data['sign'] = TokenMgr().getSign(data); + data["occupation"] = professionId.first; + data["program"] = program; + data["hopeObject"] = hopeObject; + data["height"] = heightId; + data['Country'] = countryId.first.split('-')[1]; + data["weight"] = weightId; + data["ownMsg"] = mymsgController.text; + data["meetPlace"] = dateRangeStr; + data['wxAccount'] = wechat; + data['fbAccount'] = facebook; + data['accountStatus'] = isHiddenSocialAccount ? 1 : 0; + data["lat"] = UserData().latitude; + data["lng"] = UserData().longitude; + + try { + Response res = await HttpUtil() + .post('user/complete/material', data: data, isShowLoading: true); + Map resData = res.data; + if (resData['code'] == 0) { + UserData().basicInfo.ownMsg = mymsgController.text; + callback(mymsgController.text); + } else { + showToast(resData['msg']); + } + } catch (e) {} + } + + //构建注册按钮 + Widget _buildRegisterButton() { + Text text = + fixedText(I18n.of(context).submit, fontSize: 15, color: Colors.white); + + LinearGradient gradientColor = new LinearGradient(colors: [ + Constants.ConfrimButtonColor, + Constants.ConfrimButtonColor, + ]); + callback() { + postSettion((data) async { + Navigator.of(context) + .pushNamedAndRemoveUntil('/main', (route) => route == null); + }); + } + + return new Container( + margin: EdgeInsets.only(top: 20), + height: 44, + width: MediaQuery.of(context).size.width * 0.85, + child: ShadowButton().builder(gradientColor, text, callback), + ); + } + + //自定义item + Widget _bottomBorderBox(String textLeft, String textRight, bool flag, + controller, bool isInit, callback, + {inputFormatters}) { + Widget left = Container( + width: 90, + margin: EdgeInsets.only(right: 10), + child: Text( + textLeft, + textScaleFactor: 1.0, + style: LetfTextStyle, + )); + + Widget right = flag + ? Expanded( + child: TextField( + keyboardAppearance: Brightness.light, + controller: controller, + style: TextStyle( + fontSize: 14, textBaseline: TextBaseline.alphabetic), + decoration: InputDecoration( + contentPadding: EdgeInsets.zero, + hintText: textRight, + hintStyle: TextStyle( + fontSize: 14, + color: Constants.LightGreyTextColor, + fontWeight: FontWeight.normal), + border: InputBorder.none, + ), + maxLines: 1, + inputFormatters: inputFormatters, + onChanged: (str) { + if (flag && callback != null) callback(str); + }, + ), + ) + : Expanded( + child: Text( + textRight, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 14, + color: !isInit + ? Constants.LightGreyTextColor + : Constants.BlackTextColor), + ), + ); + + var icon = !flag + ? Padding( + padding: EdgeInsets.only(right: 7), + child: Icon( + IconData(0xe63c, fontFamily: 'iconfont'), + size: 20.0, + color: Color(AppColors.TabIconNormal), + )) + : Container(); + + return new InkWell( + highlightColor: Colors.transparent, + radius: 0.0, + onTap: () { + if (!flag && callback != null) callback(); + }, + child: Container( + height: 53, + margin: EdgeInsets.only(left: BorderLeft, bottom: 0), + child: new Row( + children: [left, right, icon], + ), + )); + } + + //下划线 + Widget _buildDivider() { + return new Container( + margin: EdgeInsets.zero, + padding: EdgeInsets.zero, + height: 1, + width: MediaQuery.of(context).size.width, + child: new Divider( + color: Colors.grey[300], + ), + ); + } + + //基本数据 + Widget _buildBasicData(context) { + Widget tip = CustomUI.buildTopTip( + BorderLeft, I18n.of(context).basic_information, + showStar: true); + + //选择约会地区 + void selectDateRange() async { + print(WebData().provinces['China']); + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return SelectPage( + mostNum: 1, + dataId: dateRangeId, + title: I18n.of(context).Resident_city, + provinces: UserData().isInChina + ? {'China': WebData().provinces['China']} + : { + 'VietNam': WebData().provinces['VietNam'], + }, + cities: WebData().cities, + isSingle: true, + callback: (tempRankId) { + if (tempRankId.length == 0) return; + dateRangeId = tempRankId.toSet(); + if (dateRangeId.length != 0) { + dateRange = ''; + dateRangeId.forEach((item) { + var city = item.split('-'); + dateRange += dateRange == '' + ? WebData().cities[city[0]][city[1]] + : '/${WebData().cities[city[0]][city[1]]}'; + }); + } + Navigator.of(context).pop(); + }, + ); + }, + ), + ); + } + + //选择生日 + void selectDate() async { + var locale; + switch (UserData().language) { + case LanguageType.English: + locale = LocaleType.en; + break; + case LanguageType.Vietnamese: + locale = LocaleType.vi; + break; + case LanguageType.TraditionalChinese: + case LanguageType.SimplifiedChinese: + locale = LocaleType.zh; + break; + case LanguageType.Korean: + locale = LocaleType.ko; + break; + case LanguageType.Japanese: + locale = LocaleType.jp; + break; + default: + locale = LocaleType.en; + } + var list = []; + if (birthdayId != null) list = birthdayId.split('-'); + var nowDate; + nowDate = list.length == 3 + ? DateTime(int.parse(list[0]), int.parse(list[1]), int.parse(list[2])) + : DateTime(1990, 1, 1); + DatePicker.showDatePicker(context, + showTitleActions: true, + minTime: DateTime(1900, 3, 5), + maxTime: DateTime(DateTime.now().year - 18, 1, 1), + onChanged: (date) {}, onConfirm: (date) { + birthday = '${date.year}-${date.month}-${date.day}'; + birthdayId = '${date.year}-${date.month}-${date.day}'; + setState(() {}); + }, currentTime: nowDate, locale: locale); + } + + //选择职业 + void selectProfession() async { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return SelectPage( + mostNum: 4, + dataId: professionId, + provinces: WebData().professionCate, + isSingle: true, + cities: WebData().professionList, + title: I18n.of(context).choose_career, + callback: (Set tempRankId) { + professionId = tempRankId.toSet(); + if (professionId.length != 0) { + profession = ''; + professionId.forEach((item) { + var city = item.split('-'); + profession += profession == '' + ? WebData().professionList[city[0]][city[1]] + : '/${WebData().professionList[city[0]][city[1]]}'; + }); + } + Navigator.of(context).pop(); + }, + ); + }, + ), + ); + } + + //选择国家 + void selectCountry() async { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return SelectPage( + mostNum: 4, + dataId: countryId, + title: I18n.of(context).country, + provinces: {'Country': I18n.of(context).country}, + cities: {'Country': WebData().provinces}, + isSingle: true, + callback: (tempRankId) { + countryId = tempRankId.toSet(); + print('countryID ${countryId.length}'); + if (countryId.length != 0) { + country = ''; + countryId.forEach((item) { + var city = item.split('-'); + country += country == '' + ? WebData().provinces[city[1]] + : '/${WebData().provinces[city[1]]}'; + }); + } + Navigator.of(context).pop(); + }, + ); + }, + ), + ); + } + + //选择期待对象 + void selectLovePeople() { + var tempSet = lovePeopleId.toSet(); + List actions = [ + FlatButton( + child: fixedText(I18n.of(context).close), + onPressed: () { + tempSet.clear(); + Navigator.of(context).pop(); + }, + ), + FlatButton( + child: fixedText(I18n.of(context).determine), + onPressed: () { + Navigator.of(context).pop(); + setState(() { + lovePeopleId = tempSet.toSet(); + if (lovePeopleId.length != 0) { + lovePeople = ''; + lovePeopleId.forEach((k) { + lovePeople += (lovePeople == '') + ? WebData().loverPeopleMap[k] + : ('/' + WebData().loverPeopleMap[k]); + }); + } + }); + }, + ), + ]; + //约会节目 + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: new Align( + alignment: Alignment.center, + child: Text(I18n.of(context).expect_lover), + ), + content: new MyDialogContent( + mostNum: 4, + dataMap: WebData().loverPeopleMap, + keyList: tempSet, + ), + contentPadding: EdgeInsets.only(top: 10), + actions: actions, + ); + }); + } + + Widget idItem = new InkWell( + highlightColor: Colors.transparent, + radius: 0.0, + onTap: () {}, + child: Container( + height: 53, + margin: EdgeInsets.only(left: BorderLeft, bottom: 0), + child: new Row( + children: [ + Container( + width: 90, + margin: EdgeInsets.only(right: 10), + child: Text( + 'ID', + textScaleFactor: 1.0, + style: LetfTextStyle, + )), + Text( + UserData().basicInfo.userId.toString(), + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14, color: Constants.GreyTextColor), + ) + ], + ), + )); + + List basicList = [ + widget.isEditPage ? idItem : Container(), + _buildDivider(), + _bottomBorderBox(I18n.of(context).nickname, I18n.of(context).fill_out, + true, nickNameController, true, (str) => nickname = str, + inputFormatters: [LengthLimitingTextInputFormatter(20)]), + _buildDivider(), + _bottomBorderBox(I18n.of(context).country, country, false, null, + countryId.length != 0, selectCountry), + _buildDivider(), + _bottomBorderBox( + I18n.of(context).Resident_city, + !UserData().hasLocationPermission + ? I18n.of(context).unknown + : dateRange, + false, + null, + dateRangeId.length != 0, + UserData().hasLocationPermission ? selectDateRange : null), + _buildDivider(), + _bottomBorderBox(I18n.of(context).birthday, birthday, false, null, + birthdayId != null, selectDate), + _buildDivider(), + _bottomBorderBox(I18n.of(context).job, profession, false, null, + professionId.length != 0, selectProfession), + // _bottomBorderBox(I18n.of(context).country, dateItem, false, null, + // dateItemId.length != 0, selectCountry), + _buildDivider(), + _bottomBorderBox(I18n.of(context).expect_lover, lovePeople, false, null, + lovePeopleId.length != 0, selectLovePeople), + ]; + + Widget basicCard = new Container( + color: Colors.white, + child: new Column( + children: basicList, + ), + ); + return new Column( + children: [ + tip, + basicCard, + ], + ); + } + + //社交账号 + Widget _buildSocialContact() { + Widget tip = CustomUI.buildTopTip( + BorderLeft, I18n.of(context).social_account, + showStar: !UserData().isMan()); + List basicList = [ + _bottomBorderBox( + I18n.of(context).wechat_number, + I18n.of(context).fill_out, + true, + wechatController, + true, + (str) => wechat = str, + inputFormatters: [ + //WhitelistingTextInputFormatter(RegExp("^[A-Za-z0-9]+\$")), + LengthLimitingTextInputFormatter(20) + ]), + _buildDivider(), + _bottomBorderBox(I18n.of(context).facebook, I18n.of(context).fill_out, + true, fbController, true, (str) => facebook = str, + inputFormatters: [ + //WhitelistingTextInputFormatter(RegExp("^[A-Za-z0-9]+\$")), + LengthLimitingTextInputFormatter(20) + ]), + ]; + + Widget socialCard = new Container( + color: Colors.white, + child: new Column( + children: basicList, + ), + ); + return new Column( + children: [tip, socialCard], + ); + } + + Widget _buildHeadUrl() { + double width = 95; + return Container( + color: Colors.white, + padding: EdgeInsets.only(top: 20, bottom: 10), + child: Column( + children: [ + InkWell( + onTap: () { + _sendPicture(); + }, + child: Container( + width: width, + height: width, + child: ClipRRect( + borderRadius: BorderRadius.circular(6.0), + child: uploadImageUrl == null + ? Image.asset(Constants.DefaultHeadImgUrl, + height: width, width: width) +// : Image.file(headFile, height: width, width: width), + : CachedNetworkImage( + imageUrl: uploadImageUrl, + placeholder: CustomUI.buildImgLoding, + width: width, + height: width, + ), + ), + ), + ), + Padding( + padding: EdgeInsets.only(top: 5), + child: InkWell( + onTap: () { + _sendPicture(); + }, + child: fixedText( + I18n.of(context).upload_avatar, + color: Constants.BlackTextColor, + ), + )), + ], + ), + ); + } + + void _sendPicture() async { + if (await CustomUI.showPhotoPermissionSetting(context)) { + var tempFile = await ImagePicker.pickImage(source: ImageSource.gallery); + if (tempFile != null) { + //裁剪图片 + _cropPicture(tempFile); + } + } + } + + String uploadImageUrl; + void _cropPicture(tempFile) async { + File croppedFile = await ImageCropper.cropImage( + sourcePath: tempFile.path, + aspectRatio: CropAspectRatio(ratioX: 1, ratioY: 1), + ); + uploadImageUrl = null; + if (croppedFile != null) { + headFile = croppedFile; + Map data = {"type": 1, "userId": UserData().basicInfo.userId}; + data['sign'] = TokenMgr().getSign(data); + Response response = await HttpUtil() + .uploadFile(headFile, data, 'upload/file/postflie', 'image'); + + var resData = response.data; + if (resData['code'] == 0 && resData['msg'] != null) { + setState(() { + uploadImageUrl = resData['msg']; + }); + } else { + showToast(I18n.of(context).fail); + } + + setState(() {}); + } else { + print('裁剪失败---'); + } + } + + //是否隐藏社交账号 + Widget _buildHiddenButtom() { + Widget left = Text( + I18n.of(context).hide_account1, + textScaleFactor: 1.0, + style: TextStyle(fontSize: LeftTextFontSize, fontWeight: FontWeight.w500), + ); + Widget right = new Expanded( + child: Container( + margin: EdgeInsets.only(right: 20), + alignment: Alignment.centerRight, + child: new Switch( + activeTrackColor: Constants.ConfrimButtonColor.withOpacity(0.3), + value: isHiddenSocialAccount, + onChanged: (bool val) { + setState(() { + isHiddenSocialAccount = !isHiddenSocialAccount; + }); + }, + ))); + return new Container( + decoration: _getCardDecoration(), + margin: EdgeInsets.only(top: 15, bottom: 0), + padding: EdgeInsets.only(left: BorderLeft), + height: 53, + child: new Row( + children: [left, right], + ), + ); + } + + //更多信息 + Widget _buildMoreInfo() { + Widget tip = + CustomUI.buildTopTip(BorderLeft, I18n.of(context).more_information); + + //选择升高 + void selectHeight() async { + Result temp = await CityPickers.showCityPicker( + context: context, + showType: ShowType.p, + provincesData: WebData().heightData, + citiesData: WebData().heightListData, + height: 280, + ); + setState(() { + if (temp == null) return; + heightStr = "${temp.provinceName}"; + heightId = temp.provinceId; + }); + } + + //选择升高 + void selectWeight() async { + Result temp = await CityPickers.showCityPicker( + context: context, + showType: ShowType.p, + provincesData: WebData().weightData, + citiesData: WebData().weightListData, + height: 280, + ); + setState(() { + if (temp == null) return; + weightStr = "${temp.provinceName}"; + weightId = temp.provinceId; + }); + } + + //个人介绍框 + var myselfBox = Container( + margin: EdgeInsets.only(left: BorderLeft, bottom: 0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 90, + margin: EdgeInsets.only(top: 14), + child: Text( + I18n.of(context).self_introduction, + textScaleFactor: 1.0, + style: LetfTextStyle, + )), + Expanded( + child: TextField( + keyboardAppearance: Brightness.light, + controller: mymsgController, + style: TextStyle( + fontSize: 14, + color: Constants.BlackTextColor, + textBaseline: TextBaseline.alphabetic), + decoration: InputDecoration( + contentPadding: + EdgeInsets.only(top: 14, right: 10, bottom: 10, left: 10), + hintText: I18n.of(context).introduce_yourself, + hintStyle: TextStyle(fontSize: 14, color: Colors.grey), + border: InputBorder.none, + ), + maxLines: 5, + inputFormatters: [LengthLimitingTextInputFormatter(100)], + ), + ) + ], + ), + ); + + List basicList = [ + _bottomBorderBox(I18n.of(context).height, heightStr, false, null, + heightId != '0', selectHeight), + _buildDivider(), + _bottomBorderBox(I18n.of(context).weight, weightStr, false, null, + weightId != '0', selectWeight), + _buildDivider(), + myselfBox, + ]; + + Widget socialCard = new Container( + color: Colors.white, + child: new Column( + children: basicList, + ), + ); + return new Column( + children: [tip, socialCard], + ); + } +} diff --git a/lib/home/GetRegisterCodePage.dart b/lib/home/GetRegisterCodePage.dart new file mode 100644 index 0000000..3ea91b8 --- /dev/null +++ b/lib/home/GetRegisterCodePage.dart @@ -0,0 +1,289 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import 'package:oktoast/oktoast.dart'; +import '../utils/ShadowButton.dart'; +import '../utils/HttpUtil.dart'; +import '../utils/TokenMgr.dart'; +import 'package:dio/dio.dart'; + +enum socialNo { + wechat, + facebook, +} + +const BorderColor = const Color(0xFFD5D5D5); + +class GetRegisterCodePage extends StatefulWidget { + GetRegisterCodePage({Key key, bool flag}) : super(key: key); + + _GetRegisterCodePageState createState() => _GetRegisterCodePageState(); +} + +class _GetRegisterCodePageState extends State { + String _address = ''; + String _sourceChan = ''; + String _weChatNo = ''; + String _facebookNo = ''; + int _socialType = 0; + String _socialNo = ''; + + @override + void initState() { + super.initState(); + print('GetRegisterCodePage initState'); + } + + @override + Widget build(BuildContext context) { + Widget appBar = AppBar( + title: Text( + I18n.of(context).apply_incode, + textScaleFactor: 1.0, + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ); + return Scaffold( + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + )), + appBar: appBar, + resizeToAvoidBottomPadding: false, + ); + } + + Widget _buildBody() { + return new Column( + children: [ + _buildInputs(), + _buildSocialContact(), + _buildLoginButton(), + ], + ); + } + + Widget _bottomBorderBox(String textLeft, String textRight, bool flag, radio, + inputFormatters, callback) { + Widget left = Container( + width: 90, + child: Text( + textLeft, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600), + )); + + Widget right = flag + ? new Expanded( + child: new TextField( + keyboardAppearance: Brightness.light, + style: TextStyle(textBaseline: TextBaseline.alphabetic), + decoration: new InputDecoration( + hintText: textRight, + hintStyle: TextStyle(fontSize: 15), + border: InputBorder.none, + ), + maxLines: 1, + inputFormatters: inputFormatters, + onChanged: (str) { + if (flag && callback != null) callback(str); + }, + ), + ) + : new Expanded( + child: new InkWell( + highlightColor: Colors.transparent, + radius: 0.0, + child: fixedText( + textRight, + fontSize: 15, + ), + onTap: () { + if (!flag && callback != null) callback(); + }, + ), + ); + return new Container( + height: 53, + margin: EdgeInsets.only(left: 15, bottom: 0), + child: new Row( + children: [left, right, radio == null ? Container() : radio], + ), + ); + } + + //下划线 + Widget _buildDivider() { + return new Container( + margin: EdgeInsets.zero, + padding: EdgeInsets.zero, + height: 1, + width: MediaQuery.of(context).size.width, + child: new Divider( + color: BorderColor, + ), + ); + } + + //所在地,信息渠道 + Widget _buildInputs() { + List basicList = [ + _buildDivider(), + _bottomBorderBox(I18n.of(context).location, I18n.of(context).fill_out, + true, null, null, (str) { + _address = str; + }), + _buildDivider(), + _bottomBorderBox(I18n.of(context).message_channel, + I18n.of(context).fill_out, true, null, null, (str) { + _sourceChan = str; + }), + _buildDivider(), + ]; + + Widget socialCard = new Container( + color: Colors.white, + child: new Column( + children: basicList, + ), + ); + return new Container( + margin: EdgeInsets.only(top: 11), + child: Column( + children: [socialCard], + )); + } + + //社交账号 + Widget _buildSocialContact() { + Widget radio1 = new Radio( + value: socialNo.wechat.index, + groupValue: _socialType, //当value和groupValue一致的时候则选中 + onChanged: (T) { + _socialType = T; + setState(() {}); + }); + Widget radio2 = new Radio( + value: socialNo.facebook.index, + groupValue: _socialType, //当value和groupValue一致的时候则选中 + onChanged: (T) { + _socialType = T; + setState(() {}); + }); + Widget tip = new Container( + margin: EdgeInsets.only(top: 25, bottom: 10, left: 16.5), + alignment: Alignment.centerLeft, + child: fixedText(I18n.of(context).your_social, + color: const Color(0xFF9A9A9A)), + ); + List basicList = [ + _buildDivider(), + _bottomBorderBox( + I18n.of(context).wechat_number, + I18n.of(context).fill_out, + true, + radio1, + [WhitelistingTextInputFormatter(RegExp("^[A-Za-z0-9]+\$"))], (str) { + _weChatNo = str; + }), + _buildDivider(), + _bottomBorderBox( + I18n.of(context).facebook, + I18n.of(context).fill_out, + true, + radio2, + [WhitelistingTextInputFormatter(RegExp("^[A-Za-z0-9]+\$"))], (str) { + _facebookNo = str; + }), + _buildDivider(), + ]; + + Widget socialCard = new Container( + color: Colors.white, + child: new Column( + children: basicList, + ), + ); + return new Container( + margin: EdgeInsets.only(top: 10), + child: Column( + children: [tip, socialCard], + )); + } + + //构建登陆按钮 + Widget _buildLoginButton() { + Text text = fixedText(I18n.of(context).apply_now, color: Colors.white); + + LinearGradient gradientColor = new LinearGradient(colors: [ + Constants.ConfrimButtonColor, + Constants.ConfrimButtonColor, + ]); + callback() async { + if (_address == null || _address == "") { + showToast(I18n.of(context).enter_city); + return; + } + if (_sourceChan == null || _sourceChan == "") { + showToast(I18n.of(context).so_know); + return; + } + if (_socialType == socialNo.wechat.index) { + _socialNo = _weChatNo; + } + if (_socialType == socialNo.facebook.index) { + _socialNo = _facebookNo; + } + if (_socialNo == null || _socialNo == '') { + showToast(I18n.of(context).your_social); + return; + } + + var data = { + "UserId": UserData().basicInfo.userId, + "Address": _address, + "SourceChannel": _sourceChan, + "SocialNo": _socialNo, + "SocialType": _socialType + }; + data['sign'] = TokenMgr().getSign(data); + try { + Response res = await HttpUtil().post('user/apply/code', data: data); + if (res == null) { + return; + } + var resData = res.data; + if (resData['code'] == 0) { + MessageMgr().emit('register_code'); + CustomUI.buildOneConfirm(context, I18n.of(context).receive_incode, + I18n.of(context).determine, () { + Navigator.of(context).pop(); + Navigator.of(context).pop(); + }, + title: I18n.of(context).successfully_submit, + failcallbak: () => Navigator.of(context).pop()); + } else { + showToast(resData['msg']); + } + } catch (e) {} + } + + return new Container( + margin: EdgeInsets.only(top: 53), + height: 44, + width: MediaQuery.of(context).size.width * 0.85, + child: ShadowButton().builder(gradientColor, text, callback), + ); + } +} diff --git a/lib/home/IndexPage.dart b/lib/home/IndexPage.dart new file mode 100644 index 0000000..b7bd449 --- /dev/null +++ b/lib/home/IndexPage.dart @@ -0,0 +1,349 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:connectivity/connectivity.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:wifi_info_plugin/wifi_info_plugin.dart'; +import '../utils/OtherLogin.dart'; +import 'LoginPage.dart'; +import 'Registerpage.dart'; +import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx; +import 'package:chat/data/constants.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:dio/dio.dart'; +import 'dart:convert'; +import 'package:chat/utils/TokenMgr.dart'; + +const RATE_NUM = 0.82; + +class IndexPage extends StatefulWidget { + IndexPage({Key key}) : super(key: key); + + _IndexPageState createState() => _IndexPageState(); +} + +class _IndexPageState extends State { + bool isShow = false; + var subscription = Connectivity(); + bool isOffline = false; + var subStript; + + GlobalKey registKey = new GlobalKey(); + + @override + void initState() { + super.initState(); + fluwx.responseFromAuth.listen((data) { + if (data.errCode == 0) { + getLoginData(data.code); + } else {} + }); + + // subscription.onConnectivityChanged.listen((ConnectivityResult result) { + // if (result == ConnectivityResult.none) { + // if (mounted) { + // setState(() { + // isOffline = true; + // }); + // } + // } else { + // if (mounted) { + // setState(() { + // if (isOffline == true) { + // isOffline = false; + // autoLogin(); + // } + // }); + // } + // } + // }); + + autoLogin(); + } + + void autoLogin({showLoading: false}) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String autoLoginKey = prefs.getString(Constants.AutoLoginKey); + if (autoLoginKey != null) { + if (UserData().basicInfo.userId == null) { + Future.delayed(Duration(seconds: 10), () { + if (mounted) { + setState(() { + isOffline = true; + }); + } + }); + var data = { + "key": autoLoginKey, + "language": UserData().language, + }; + + data['sign'] = TokenMgr().getSign(data); + + print('~~~~~~~~~~~indexPage autologin ~~~~~~~~~~'); + Response res = await HttpUtil() + .post('user/auto/login', data: data, isShowLoading: showLoading); + var resData = res.data; + if (resData['code'] == 0) { + print('### 跳转 成功--'); + HttpUtil().changePage(context, resData); + } else { + isShow = true; + setState(() {}); + showToast(resData['msg']); + } + } else { + HttpUtil().changePage(context, { + 'data': { + 'userid': UserData().basicInfo.userId, + 'sex': UserData().basicInfo.sex, + 'mobile': UserData().mobile.toString(), + 'bindId': UserData().agentId + } + }); + } + } else { + print('### 跳转 失败 autoLoginKey null--'); + isShow = true; + setState(() {}); + } + } + + getLoginData(String code) async { + Response f = await HttpUtil().getDataWX( + 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=${Constants.AppId}&secret=${Constants.Secret}&code=$code&grant_type=authorization_code'); + var tokenData = json.decode(f.data); + print(tokenData); + if (tokenData['unionid'] == null || tokenData['unionid'] == '') { + return; + } + var data = { + "onlyid": tokenData['unionid'], + "type": 0, + "language": UserData().language, + }; + + data['sign'] = TokenMgr().getSign(data); + data['openid'] = tokenData['openid']; + data['lng'] = UserData().longitude; + data['lat'] = UserData().latitude; + + try { + WifiInfoWrapper wifiObject = await WifiInfoPlugin.wifiDetails; + if (wifiObject != null) { + data['routerName'] = wifiObject.ssid.replaceAll('"', ''); + data['mac'] = wifiObject.bssId; + } + } catch (e) { + print(e); + } + + Response res = await HttpUtil() + .post('user/auth/login', data: data, isShowLoading: true); + + var resData = res.data; + print(resData); + if (resData['code'] != 0) { + showToast(resData['msg']); + return; + } + if (resData['data'] != null) { + HttpUtil().changePage(LoadingManage.context, resData); + } + } + + @override + void dispose() { + subStript?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + ScreenUtil.instance = ScreenUtil(width: 360, height: 744)..init(context); + return new Scaffold( + key: registKey, + backgroundColor: Colors.white, + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + ), + )); + } + + Widget buildNetState() { + return isOffline + ? Container( + margin: EdgeInsets.only(top: ScreenUtil().setHeight(450)), + width: Screen.width, + child: Column( + children: [ + Container( + child: Text( + I18n.of(context).net_error, + style: TextStyle(color: Color(0xFF8F8E8E), fontSize: 21.5), + ), + ), + InkWell( + onTap: () { + print('~~~~~~~~~~~indexPage click autologin ~~~~~~~~~~'); + + autoLogin(showLoading: true); + }, + child: Container( + margin: EdgeInsets.only(top: 28), + padding: + EdgeInsets.symmetric(horizontal: 26, vertical: 9.5), + decoration: BoxDecoration( + border: Border.all(color: const Color(0xFF3875E9)), + borderRadius: BorderRadius.circular(8)), + child: Text( + I18n.of(context).re_connect, + style: + TextStyle(color: Color(0xFF3875E9), fontSize: 20.22), + ), + ), + ) + ], + )) + : Container(); + } + + Widget _buildBody() { + List show = [ + _buildLoginButton(), + _buildRegisterButton(), + _buildOtherLogin(), + ]; + List hidden = [ + buildNetState(), + ]; + return Stack( + alignment: Alignment.center, + children: [ + Positioned( + top: 0, child: isOffline ? _buildErrorBg() : _buildNormalBg()), + Column( + children: isShow ? show : hidden, + ) + ], + ); + } + + //构建底部第三方登陆 + Widget _buildOtherLogin() { + return new Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + new Container( + alignment: Alignment.bottomCenter, + child: OtherLogin().builder(context), + ) + ], + ), + ); + } + + //构建登陆按钮 + Widget _buildLoginButton() { + Text text = fixedText(I18n.of(context).login, + fontSize: Constants.ShaderButtonFontSize, color: Colors.white); + return InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return LoginPage(); + }, + ), + ); + }, + child: Container( + margin: EdgeInsets.only(top: ScreenUtil().setHeight(460)), + alignment: Alignment.center, + height: Constants.ShaderButtonHeight, + width: ScreenUtil.instance.setWidth(282.9), + decoration: BoxDecoration( + color: Constants.ConfrimButtonColor, + //border: Border.all(color: const Color(0x803875E9)), + borderRadius: + BorderRadius.all(Radius.circular(Constants.BigButtonRadius))), + child: text, + ), + ); + } + + //构建注册按钮 + Widget _buildRegisterButton() { + Text text = fixedText(I18n.of(context).number_registration, + fontSize: Constants.ShaderButtonFontSize, + color: Constants.ConfrimButtonColor); + return InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return RegisterPage( + type: PageType.register.index, + ); + }, + ), + ); + }, + child: Container( + margin: EdgeInsets.only(top: 30), + alignment: Alignment.center, + height: Constants.ShaderButtonHeight, + width: ScreenUtil.instance.setWidth(282.9), + decoration: BoxDecoration( + border: Border.all(color: Constants.ConfrimButtonColor), + borderRadius: + BorderRadius.all(Radius.circular(Constants.BigButtonRadius))), + child: text, + ), + ); + } + + // Widget _buildLogo() { + // return Container( + // alignment: Alignment.center, + // margin: EdgeInsets.only(top: ScreenUtil.instance.setHeight(53)), + // child: Image.asset( + // 'assets/images/login/SY_logo.png', + // width: ScreenUtil.instance.setWidth(120.5), + // )); + // } + + Widget _buildNormalBg() { + return Container( + margin: EdgeInsets.only(top: ScreenUtil.instance.setHeight(35)), + child: Image.asset( + 'assets/images/login/SY_bg.png', + width: Screen.width, + //width: ScreenUtil.instance.setHeight(266), + ), + ); + } + + Widget _buildErrorBg() { + return Container( + margin: EdgeInsets.only( + top: ScreenUtil.instance.setHeight(180), + bottom: ScreenUtil.instance.setHeight(49)), + child: Image.asset( + 'assets/images/net_error.png', + width: ScreenUtil.instance.setWidth(150), + ), + ); + } +} diff --git a/lib/home/InfoList.dart b/lib/home/InfoList.dart new file mode 100644 index 0000000..7bb2823 --- /dev/null +++ b/lib/home/InfoList.dart @@ -0,0 +1,811 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/ProfilePage.dart'; +import 'package:chat/home/rich_title.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/PicSwiper.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/conversation_table.dart'; +import 'package:chat/utils/friend_list_mgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; +import 'package:url_launcher/url_launcher.dart'; +import '../data/constants.dart' show AppColors, Constants; +import '../data/conversation.dart'; +import 'package:cached_network_image/cached_network_image.dart'; + +import 'ProgramDetail.dart'; + +class _ConversationItem extends StatelessWidget { + const _ConversationItem( + {Key key, + this.conversation, + this.callback, + this.showRight = true, + this.rightButton, + this.applyInfo, + this.bgColor, + this.title}) + : assert(conversation != null), + super(key: key); + final Widget rightButton; + final Conversation conversation; + final callback; + final bool showRight; + final title; + final applyInfo; + final bgColor; + + @override + Widget build(BuildContext context) { + Widget avatar; + double width = 53; + if (conversation.isAvatarFromNet()) { + avatar = ClipRRect( + borderRadius: BorderRadius.circular(10), + child: CachedNetworkImage( + imageUrl: conversation.avatar, + placeholder: (context, url) => Image.asset( + Constants.DefaultHeadImgUrl, + width: width, + height: width, + ), + fit: BoxFit.cover, + width: width, + height: width, + )); + } else { + avatar = ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Container( + width: width, + height: width, + alignment: Alignment.center, + decoration: BoxDecoration( + gradient: this.bgColor, + borderRadius: BorderRadius.all(Radius.circular(50))), + child: Image.asset( + conversation.avatar, + height: 27, + ))); + } + _buildBotton(str, callback) { + return InkWell( + onTap: callback, + child: Container( + padding: EdgeInsets.only(top: 5, left: 15, right: 15, bottom: 5), + decoration: BoxDecoration( + border: + Border.all(color: Constants.ConfrimButtonColor, width: 1), + color: Constants.ConfrimButtonColor, + borderRadius: BorderRadius.all(Radius.circular(5))), + child: fixedText( + str, + fontSize: 12, + color: Colors.white, + ), + )); + } + + void doApply(state, callback) async { + Map data = { + "id": applyInfo['applyId'], + "userId": UserData().basicInfo.userId, + "status": state, + }; + data['sign'] = TokenMgr().getSign(data); + Response res = await HttpUtil().post('user/handler/apply', data: data); + if (res == null) { + return; + } + var resData = res.data; + if (resData['code'] == 0) { + callback(resData['msg']); + } else {} + } + + void doFriendApply(state, callback) async { + Map data = { + "id": applyInfo['applyId'], + "userId": UserData().basicInfo.userId, + "status": state, + }; + data['sign'] = TokenMgr().getSign(data); + Response res = + await HttpUtil().post('friendship/handler/apply', data: data); + if (res == null) { + return; + } + var resData = res.data; + if (resData['code'] == 0) { + callback(resData['msg']); + } else {} + } + + var bottomWiget = applyInfo == null + ? Container() + : Container( + padding: EdgeInsets.only(left: 0, top: 10), + decoration: BoxDecoration( + color: Color(AppColors.ConversationItemBgColor), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: applyInfo['type'] == 0 || applyInfo['type'] == 6 + ? [ + CustomUI.buildImgCover( + applyInfo['imgId'], + [ + PicSwiperItem(applyInfo['showUrl'], + id: applyInfo['imgId'], + type: applyInfo['type'] == 0 + ? PhotoType.destroy.index + : PhotoType.free.index, + isWatch: applyInfo['isWatch'], + userId: applyInfo['userId']) + ], + applyInfo['showUrl'], + 65, + 10, + applyInfo['isWatch'], + context, + applyInfo['type'] == 0 + ? PhotoType.destroy.index + : PhotoType.free.index), + Expanded( + child: applyInfo['type'] == 0 + ? Container( + alignment: Alignment.centerRight, + padding: EdgeInsets.only(top: 40), + child: applyInfo['state'] == 0 + ? Row( + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + _buildBotton(I18n.of(context).aging, + () { + doApply(1, (msg) { + showToast(msg); + applyInfo['state'] = 1; + MessageMgr() + .emit('do_info_apply'); + }); + }), + SizedBox( + width: 10, + ), + _buildBotton(I18n.of(context).refuse, + () { + doApply(2, (msg) { + showToast(msg); + applyInfo['state'] = 2; + MessageMgr() + .emit('do_info_apply'); + }); + }), + ], + ) + : Padding( + padding: EdgeInsets.only(right: 0), + child: Text( + applyInfo['state'] == 1 + ? I18n.of(context).passed + : I18n.of(context).rejected, + style: TextStyle( + color: Constants.GreyTextColor, + fontSize: 13), + textScaleFactor: 1.0, + ), + ), + ) + : Container(), + ) + ] + : [ + Expanded(child: Container()), + Container( + alignment: Alignment.centerRight, + child: applyInfo['state'] == 0 + ? Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + _buildBotton(I18n.of(context).agree, () { + doFriendApply(1, (msg) { + showToast(msg); + applyInfo['state'] = 1; + var friendModel = + FriendModel.fromServerJson({ + 'UserId': applyInfo['userId'], + 'ImgUrl': applyInfo['imgUrl'], + 'UserName': applyInfo['name'] + }); + FriendListMgr().addFriend(friendModel); + MessageMgr().emit('do_info_apply'); + MessageMgr().emit('do_friend_apply', { + 'userId': applyInfo['userId'], + 'state': 1 + }); + MessageMgr().emit('Add friend'); + }); + }), + SizedBox( + width: 10, + ), + _buildBotton(I18n.of(context).refuse, () { + doFriendApply(2, (msg) { + showToast(msg); + applyInfo['state'] = 2; + MessageMgr().emit('do_info_apply'); + MessageMgr().emit('do_friend_apply', { + 'userId': applyInfo['userId'], + 'state': 2 + }); + }); + }), + ], + ) + : Padding( + padding: EdgeInsets.only(right: 0), + child: Text( + applyInfo['state'] == 1 + ? I18n.of(context).passed + : I18n.of(context).rejected, + style: TextStyle( + color: Constants.GreyTextColor, + fontSize: 13), + textScaleFactor: 1.0, + ), + ), + ), + ], + ), + ); + return InkWell( + child: Container( + padding: + const EdgeInsets.only(left: 16.5, top: 11, bottom: 11, right: 14.5), + decoration: BoxDecoration( + color: Color(AppColors.ConversationItemBgColor), + border: Border( + bottom: BorderSide( + color: AppColors.DividerColor, + width: Constants.DividerWidth))), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + avatar, + Container(width: 19.0), + Expanded( + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: title == null + ? Text(conversation.title, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 12, + color: Constants.LightGreyTextColor)) + : title), + Container( + padding: EdgeInsets.only(top: 5, bottom: 5), + child: Row( + children: [ + Text(conversation.desc, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 11, + color: Constants.LightGreyTextColor)), + showRight + ? Expanded( + child: Container( + alignment: Alignment.centerRight, + child: rightButton == null + ? Text( + '${I18n.of(context).go_see}>', + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 11, + color: Constants + .LightGreyTextColor)) + : rightButton, + ), + ) + : Container() + ], + )), + applyInfo != null && applyInfo['content'] != null + ? Container( + child: Text(applyInfo['content'], + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 14, + color: Constants.LightGreyTextColor))) + : Container(), + ], + ), + )), + ], + ), + bottomWiget + ], + ), + ), + onTap: () { + callback(); + }, + ); + } +} + + + +class InfoListPage extends StatefulWidget { + @required + final String title; + @required + final int type; + InfoListPage({Key key, this.title = "", this.type = 1}) : super(key: key); + + _InfoListPageState createState() => _InfoListPageState(); +} + +class _InfoListPageState extends State + with SingleTickerProviderStateMixin { + List list = new List(); //列表要展示的数据 + RefreshController _refreshController = + RefreshController(initialRefresh: true); + int _page = 1; //加载的页数 + int rows = 20; + + @override + void initState() { + super.initState(); + messageOn(); + } + + void initList(data) { + list.clear(); + if (data != null) { + list.addAll(data); + } + if (mounted) setState(() {}); + } + + void addList(data) { + if (data == null || data.length == 0) { + _page--; + _refreshController.loadNoData(); + } else { + list.addAll(data); + _refreshController.loadComplete(); + } + setState(() {}); + } + + messageApply(data) { + _onRefresh(); + } + + msgPhoto(id) { + for (int i = 0; i < list.length; i++) { + if (list[i]['ApplyImg'] == id) { + setState(() { + list[i]['IsCheck'] = 1; + }); + break; + } + } + } + + void messageOn() { + MessageMgr().on('do_info_apply', messageApply); + MessageMgr().on('refresh_photo', msgPhoto); + } + + void messageOff() { + MessageMgr().off('do_info_apply', messageApply); + MessageMgr().off('refresh_photo', msgPhoto); + } + + getNewData(callback) { + switch (widget.type) { + case InfoType.Apply: //获取申请通知 + getData('user/check/realecords', callback); + break; + case InfoType.Evaluation: //获取评价通知 + getData('evaluate/user/realecordslist', callback); + break; + case InfoType.System: //获取系统通知 + getData('message/center/list', callback); + break; + case InfoType.Radio: //获取电台消息 + getData('message/center/cast', callback); + break; + case InfoType.Money: //获取钱包通知 + getData('message/wallet/message', callback); + break; + default: + } + } + + Future getData(url, callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + if (widget.type == InfoType.System) { + data['type'] = UserData().basicInfo.sex; + } + data['sign'] = TokenMgr().getSign(data); + if (widget.type == InfoType.Money) { + data['type'] = 1; + } + data["page"] = _page; + data['rows'] = rows; + Response res = await HttpUtil() + .post(url, data: data, failback: () => Navigator.of(context).pop()); + _refreshController.refreshCompleted(); + var resData = res.data; + print(resData); + if (resData['code'] == 0) { + callback(resData['data']); + } else { + showToast(resData['msg']); + } + } + + /* + * 下拉刷新方法,为list重新赋值 + */ + Future _onRefresh() async { + _page = 1; + getNewData(initList); + } + + @override + void dispose() { + _refreshController.dispose(); + messageOff(); + super.dispose(); + } + + //钱包通知 + Widget _buildMoneyInfo(data) { + String imgUrl = data['HeadImg'] == null || data['HeadImg'] == '' + ? 'assets/images/chat/icon4.png' + : data['HeadImg']; + + bool showIndex = data['ChangeUserId'] != 0; + return _ConversationItem( + conversation: Conversation( + avatar: imgUrl, + title: '', + desc: WebData().getLoginTime(context, data['CreateTime']), + updateAt: '', + ), + bgColor: Constants.MoneyGradient, + showRight: data['DetailType'] == 10, + title: RichTitle.getRichTitleWidget(data, context, InfoType.Money), + rightButton: Text(I18n.of(context).alreay_back, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.normal, + color: Constants.BlackTextColor)), + callback: () { + if (showIndex) { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: data['UserId'] == UserData().basicInfo.userId + ? data['ChangeUserId'] + : data['UserId'], + ); + }, + ), + ); + } + }, + ); + } + + //申请列表 + Widget _buildApllayInfo(userInfo) { + bool isMyself = userInfo['ApplyUserId'] == UserData().basicInfo.userId; + String name = isMyself ? userInfo['UserName'] : userInfo['ApplyName']; + String imgUrl = isMyself ? userInfo['UserUrl'] : userInfo['ApplyUrl']; + + var applyInfo = { + 'applyId': userInfo['Id'], + 'userId': userInfo['ApplyUserId'], + 'name': name, + 'type': userInfo['Type'], + 'imgUrl': imgUrl, + 'showUrl': userInfo['ImgUrl'], + 'content': userInfo['Content'], + 'imgId': userInfo['ApplyImg'], + 'createTime': userInfo['CreatTime'], + 'isWatch': userInfo['IsCheck'] == 1, + 'state': userInfo['Status'], + }; + + return _ConversationItem( + conversation: Conversation( + avatar: imgUrl == null || imgUrl == '' + ? Constants.DefaultHeadImgUrl + : imgUrl, + title: '', + desc: WebData().getLoginTime(context, userInfo['CreatTime']), + updateAt: '17:20', + ), + title: RichTitle.getRichTitleWidget(userInfo, context, InfoType.Apply), + applyInfo: isMyself ? null : applyInfo, + callback: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: isMyself ? userInfo['UserId'] : userInfo['ApplyUserId'], + ); + }, + ), + ); + }, + ); + } + + //评价列表 + Widget _buildContentInfo(userInfo) { + Widget botton = InkWell( + onTap: () async { + var data = { + "userid": UserData().basicInfo.userId, + "evaluateuserid": userInfo['EvaluateUserId'], + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = + await HttpUtil().post('evaluate/user/appeal', data: data); + if (res == null) { + return; + } + Map resData = res.data; + if (resData['code'] == 0) { + setState(() { + userInfo['Status'] = 1; + }); + } + }, + child: Container( + padding: EdgeInsets.only(top: 2, left: 5, right: 5, bottom: 2), + decoration: BoxDecoration( + border: + Border.all(color: Constants.LightBlueButtonColor, width: 1), + color: Constants.LightBlueButtonColor, + borderRadius: BorderRadius.all(Radius.circular(5))), + child: fixedText( + I18n.of(context).appeal, + fontSize: 9, + color: Colors.white, + ), + )); + + return _ConversationItem( + conversation: Conversation( + avatar: 'assets/images/chat/icon6.png', + title: '', + desc: WebData().getLoginTime(context, userInfo['CreateTime']), + updateAt: '17:20', + ), + bgColor: Constants.EvaGradient, + rightButton: userInfo['Status'] == 0 || userInfo['Status'] == 3 + ? botton + : Text(userInfo['Status'] == 1 ? I18n.of(context).appealed : "", + style: + TextStyle(fontSize: 11, color: Constants.LightGreyTextColor)), + title: + RichTitle.getRichTitleWidget(userInfo, context, InfoType.Evaluation), + callback: () {}, + ); + } + + String getReportTilte(bool isMyself, data) { + String res = ''; + switch (data['ReportType']) { + //举报用户 + case 1: + if (isMyself) { + res = data['Status'] == 1 + ? I18n.of(context) + .report_success + .replaceFirst('/s1', data['ReportedUserName']) + : I18n.of(context) + .report_failure + .replaceFirst('/s1', data['ReportedUserName']); + } else { + res = I18n.of(context).coin_returen; + } + break; + //举报节目 + case 2: + break; + //举报动态 + case 3: + break; + //举报评论 + case 4: + break; + default: + } + return res; + } + + //系统通知 + Widget _buildSystemInfo(data) { + bool isMyself = data['UserId'] == UserData().basicInfo.userId; + String imgUrl = data['Type'] == 3 + ? (isMyself ? data['HeadImg'] : 'assets/images/chat/icon5.png') + : 'assets/images/chat/icon5.png'; + var applyInfo = { + 'applyId': data['Id'], + 'userId': data['ApplyUserId'], + 'name': data['Theme'], + 'type': data['Type'], + 'imgUrl': imgUrl, + 'showUrl': data['HeadImg'], + 'content': data['Content'], + 'imgId': data['ApplyImg'], + 'createTime': data['CreatTime'], + 'isWatch': data['IsCheck'] == 1, + 'links': data['Links'], + 'state': data['Status'], + }; + return _ConversationItem( + conversation: Conversation( + avatar: imgUrl, + title: '', + desc: WebData().getLoginTime(context, data['CreateTime']), + updateAt: '17:20', + ), + showRight: data['Type'] == 6, + applyInfo: data['Type'] == 6 ? applyInfo : null, // applyInfo, + bgColor: Constants.ParkGradient, + title: data['Type'] == 6 + ? Text(data['Theme']) + : RichTitle.getRichTitleWidget(data, context, InfoType.System), + callback: () { + if (data['Type'] == 4 && data['Status'] == 1) { + ClipboardData clipboardData = + new ClipboardData(text: data['Content']); + Clipboard.setData(clipboardData); + showToast(I18n.of(context).successful_copy); + } + if (data['Type'] == 3) { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: data['ReportedUserId'], + ); + }, + ), + ); + } + if (data['Type'] == 6) { + launch(applyInfo['links']); + } + }, + ); + } + + //电台消息 + Widget _buildRadioInfo(data) { + String imgUrl = data['HeadImg'] == null || data['HeadImg'] == '' + ? Constants.DefaultHeadImgUrl + : data['HeadImg']; + + return _ConversationItem( + conversation: Conversation( + avatar: imgUrl, + title: '', + desc: WebData().getLoginTime(context, data['CreateTime']), + updateAt: '17:20', + ), + title: RichTitle.getRichTitleWidget(data, context, InfoType.Radio), + callback: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProgramDetailPage( + programId: data['Id'], + ); + }, + ), + ); + }, + ); + } + + Widget _renderRow(BuildContext context, int index) { + if (index < list.length) { + var userInfo = list[index]; + Widget result = Container(); + switch (widget.type) { + case InfoType.Apply: + result = _buildApllayInfo(userInfo); + break; + case InfoType.Evaluation: + result = _buildContentInfo(userInfo); + break; + case InfoType.System: + result = _buildSystemInfo(userInfo); + break; + case InfoType.Radio: + result = _buildRadioInfo(userInfo); + break; + case InfoType.Money: + result = _buildMoneyInfo(userInfo); + break; + default: + } + + if (index == 0) { + result = Padding(padding: EdgeInsets.only(top: 10), child: result); + } + + return result; + } + return Container(); + } + + void _onLoading() async { + _page++; + getNewData(addList); + } + + @override + Widget build(BuildContext context) { + var content = Scaffold( + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + widget.title, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ), + body: SafeArea( + child: SmartRefresher( + enablePullDown: true, + enablePullUp: true, + header: MaterialClassicHeader(), + footer: CustomUI.buildLoadingFooter(), + controller: _refreshController, + onRefresh: _onRefresh, + onLoading: _onLoading, + child: (_refreshController.headerStatus == RefreshStatus.completed && + list.length == 0) + ? CustomUI.buildNoData(context) + : ListView.builder( + itemBuilder: _renderRow, + itemCount: list.length, + ), + ))); + return content; // CustomUI.buildPageLoading(context, content, !isLoadingFish); + } +} diff --git a/lib/home/InformUser.dart b/lib/home/InformUser.dart new file mode 100644 index 0000000..b148482 --- /dev/null +++ b/lib/home/InformUser.dart @@ -0,0 +1,445 @@ +import 'dart:io'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/photo/entity/options.dart'; +import 'package:chat/photo/photo.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/PicSwiper.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; + +import 'package:oktoast/oktoast.dart'; +import 'package:photo_manager/photo_manager.dart'; +import '../data/UserData.dart'; +import '../utils/TokenMgr.dart'; + +enum reason { + advertising, + rail, + breakAppointment, + sex, + liar, +} + +int Max_Img_Num = 4; + +class InformUserPage extends StatefulWidget { + @required + final userId; + final programId; + final isProgram; + @required + final bool isMan; + InformUserPage( + {Key key, + this.userId, + this.programId, + this.isMan = false, + this.isProgram = false}) + : super(key: key); + + _InformUserPageState createState() => _InformUserPageState(); +} + +class _InformUserPageState extends State { + int _socialType = 0; + bool parkHidden = false; + bool distanceHidden = false; + bool msgHidden = false; + String explain = ''; + + //List imgFileList = []; + + //上传图片地址 + List imgUrlList = []; + + BoxDecoration _getCardDecoration() { + return new BoxDecoration(color: Colors.white); + } + + @override + void initState() { + super.initState(); + print('InformUserPage initState'); + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + title: Text( + I18n.of(context).anonymous_report, + textScaleFactor: 1.0, + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + actions: [ + new Container( + alignment: Alignment.center, + child: new InkWell( + child: new Padding( + padding: + EdgeInsets.only(right: 15, left: 15, top: 10, bottom: 10), + child: new Text(I18n.of(context).submit, + textScaleFactor: 1.0, style: Constants.AppBarActionTextStyle), + ), + onTap: () async { + if (imgUrlList == null || imgUrlList.length == 0) { + showToast(I18n.of(context).bad_evaluate); + return; + } + var data = { + "reportuserId": UserData().basicInfo.userId, + "userid": widget.userId, + }; + data['sign'] = TokenMgr().getSign(data); + data['type'] = + widget.programId == null ? 1 : (widget.isProgram ? 2 : 3); + data['objectId'] = + widget.programId == null ? 0 : widget.programId; + data['reason'] = _socialType + 1; + String temp = ""; + imgUrlList.forEach((str) { + temp += (temp == "" + ? WebData().deleteDemain(str) + : '|${WebData().deleteDemain(str)}'); + }); + data["imgurl"] = temp; + data["explain"] = explain; + Response res = await HttpUtil() + .post('report/user/insert', data: data, isShowLoading: true); + Map resData = res.data; + if (resData['code'] == 0) { + CustomUI.buildOneConfirm(context, + I18n.of(context).waiting_results, I18n.of(context).ok, () { + Navigator.of(context).pop(); + Navigator.of(context).pop(); + }, failcallbak: () { + Navigator.of(context).pop(); + }); + } else { + showToast(resData['msg']); + } + }, + ), + ) + ], + ); + return Scaffold( + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + )), + appBar: appBar, + ); + } + + Widget _buildBody() { + return new ListView( + children: [ + _userDetail(), + _buildMoreInfo(), + _buildTips(), + ], + ); + } + + Widget _buildTips() { + return Container( + margin: EdgeInsets.only(top: 5, left: 30, right: 30), + child: Text( + I18n.of(context).if_something, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 12, color: Colors.grey[700]), + textAlign: TextAlign.center, + ), + ); + } + + //下划线 + Widget _buildDivider() { + return new Container( + margin: EdgeInsets.zero, + padding: EdgeInsets.zero, + height: 1, + width: MediaQuery.of(context).size.width, + child: new Divider( + color: Colors.grey[300], + ), + ); + } + + void _sendPicture() async { + var photos = await PhotoPicker.pickAsset( + context: context, + themeColor: Color(0xFFF0F0F0), + maxSelected: Max_Img_Num - imgUrlList.length, + textColor: Color(0xFF3F3F3F), + pickType: PickType.onlyImage); + + if (photos != null && photos.length > 0) { + List fileList = []; + for (var i = 0; i < photos.length; i++) { + AssetEntity photoEntity = photos[i]; + fileList.add(await photoEntity.file); + } + Map data = {"type": 3, "userId": UserData().basicInfo.userId}; + data['sign'] = TokenMgr().getSign(data); + Response res = await HttpUtil().uploadFiles( + fileList, data, 'upload/post/postfiles', 'image', + isShowLoading: true); + var resData = res.data; + if (resData['code'] == 0 && resData['msg'] != null) { + imgUrlList.addAll(resData['msg'].split("|")); + setState(() {}); + } + } + } + + Widget _buildRadioButtom(str, radio, callback) { + Widget left = Text( + str, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14), + ); + Widget right = new Expanded( + child: new Align( + alignment: Alignment.centerRight, + child: radio, + )); + return InkWell( + onTap: () { + callback(); + }, + child: Container( + padding: EdgeInsets.only(left: 15), + child: new Row( + children: [left, right], + ), + ), + ); + } + + //个人详情 + Widget _userDetail() { + Widget tip = + CustomUI.buildTopTip(15, I18n.of(context).report_reason, fontSize: 16); + + Widget radio1 = new Radio( + value: reason.advertising.index, + groupValue: _socialType, //当value和groupValue一致的时候则选中 + onChanged: (T) { + setState(() { + _socialType = T; + }); + }); + Widget radio2 = new Radio( + value: reason.rail.index, + groupValue: _socialType, //当value和groupValue一致的时候则选中 + onChanged: (T) { + setState(() { + _socialType = T; + }); + }); + Widget radio3 = new Radio( + value: reason.breakAppointment.index, + groupValue: _socialType, //当value和groupValue一致的时候则选中 + onChanged: (T) { + setState(() { + _socialType = T; + }); + }); + Widget radio4 = new Radio( + value: reason.sex.index, + groupValue: _socialType, //当value和groupValue一致的时候则选中 + onChanged: (T) { + setState(() { + _socialType = T; + }); + }); + Widget radio5 = new Radio( + value: reason.liar.index, + groupValue: _socialType, //当value和groupValue一致的时候则选中 + onChanged: (T) { + setState(() { + _socialType = T; + }); + }); + + List basicList = [ + _buildRadioButtom(I18n.of(context).advertise, radio1, () { + setState(() { + _socialType = reason.advertising.index; + }); + }), + _buildDivider(), + _buildRadioButtom(I18n.of(context).harassment, radio2, () { + setState(() { + _socialType = reason.rail.index; + }); + }), + _buildDivider(), + _buildRadioButtom(I18n.of(context).false_photo, radio3, () { + setState(() { + _socialType = reason.breakAppointment.index; + }); + }), + _buildDivider(), + _buildRadioButtom(I18n.of(context).erotic_vulgarity, radio4, () { + setState(() { + _socialType = reason.sex.index; + }); + }), + _buildDivider(), + _buildRadioButtom( + widget.isMan ? I18n.of(context).he_liar : I18n.of(context).she_liar, + radio5, () { + setState(() { + _socialType = reason.liar.index; + }); + }), + ]; + var socialCard = new Container( + decoration: _getCardDecoration(), + width: MediaQuery.of(context).size.width, + child: new Column( + children: basicList, + ), + ); + return new Column( + children: [tip, socialCard], + ); + } + + Widget _buildMoreInfo() { + Widget tip = CustomUI.buildTopTip(15, I18n.of(context).provide_screenshots, + fontSize: 15); + Widget upButton = Container( + child: InkWell( + onTap: _sendPicture, + child: Container( + margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10.0), + border: Border.all(color: Colors.grey)), + width: 75, + height: 75, + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Icon( + IconData( + 0xe616, + fontFamily: 'iconfont', + ), + color: Colors.grey, + ), + )))); + List list = imgUrlList.map((f) { + return _buildImg(f); + }).toList(); + if (list.length < Max_Img_Num) { + list.add(upButton); + } + var socialCard = new Container( + width: MediaQuery.of(context).size.width, + decoration: _getCardDecoration(), + padding: EdgeInsets.only(bottom: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(left: 10, top: 10, bottom: 10), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: list)), + _buildDivider(), + Container( + margin: EdgeInsets.only(top: 10, left: 14), + child: fixedText(I18n.of(context).describe_details)), + Container( + padding: EdgeInsets.only(top: 2, left: 8, right: 14), + child: TextField( + keyboardAppearance: Brightness.light, + style: TextStyle(textBaseline: TextBaseline.alphabetic), + decoration: new InputDecoration( + hintText: I18n.of(context).optional, + hintStyle: TextStyle(fontSize: 14), + border: InputBorder.none, + ), + maxLines: 5, + maxLength: 200, + onChanged: (str) { + explain = str; + }, + ), + ), + ], + ), + ); + + return new Column( + children: [tip, socialCard], + ); + } + + Widget _buildImg(f) { + return Stack( + children: [ + InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return PicSwiper( + id: imgUrlList.indexOf(f), + pics: imgUrlList + .map((f) => PicSwiperItem( + f, + id: imgUrlList.indexOf(f), + )) + .toList(), + ); + }, + ), + ); + }, + child: Container( + height: 75, + width: 75, + margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5), + decoration: + BoxDecoration(borderRadius: BorderRadius.circular(2.0)), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: f == null + ? Container() + : CachedNetworkImage( + imageUrl: f, + fit: BoxFit.cover, + ), + ))), + Positioned( + right: 0, + child: InkWell( + onTap: () { + imgUrlList.remove(f); + setState(() {}); + }, + child: Image.asset( + 'assets/images/login/delete.png', + height: 20, + )), + ) + ], + ); + } +} diff --git a/lib/home/LoginPage.dart b/lib/home/LoginPage.dart new file mode 100644 index 0000000..acdbb32 --- /dev/null +++ b/lib/home/LoginPage.dart @@ -0,0 +1,285 @@ +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/Registerpage.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:oktoast/oktoast.dart'; +import '../utils/OtherLogin.dart'; +import '../utils/HttpUtil.dart'; +import "../data/UserData.dart"; + +const RATE_NUM = 0.82; + +//const BlueColor = const Color(0xFF93C3FF); +const BlueColor = Constants.BlueTextColor; + +class LoginPage extends StatefulWidget { + LoginPage({Key key, bool flag}) : super(key: key); + + _LoginPageState createState() => _LoginPageState(); +} + +class _LoginPageState extends State { + String _phoneNumber = ''; + String _passWorld = ''; + + String _selectType = UserData().language == LanguageType.Vietnamese + ? phone.keys.toList()[1] + : phone.keys.toList()[0]; + + @override + Widget build(BuildContext context) { + var keyHeight = MediaQuery.of(context).viewInsets.bottom; + if (keyHeight > 0) { + UserData().setKeyboardHeight(keyHeight); + } + + Widget appBar = AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + I18n.of(context).login, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ); + return Scaffold( + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + )), + appBar: appBar, + resizeToAvoidBottomPadding: false, + ); + } + + @override + void initState() { + super.initState(); + + print('LoginPage initState'); + } + + @override + void dispose() { + super.dispose(); + } + + Widget _buildBody() { + return new Column( + children: [ + _buildAcountInput(), + _buildPasswordInput(), + _buildForgetPassWord(), + SizedBox( + height: 40, + ), + _buildLoginButton(), + _buildOtherLogin(), + ], + ); + } + + //构建底部第三方登陆 + Widget _buildOtherLogin() { + return new Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + new Container( + alignment: Alignment.bottomCenter, + child: OtherLogin().builder(context), + ) + ], + ), + ); + } + + //账号输入框 + Widget _buildAcountInput() { + double height = 54.5; + return new Container( + alignment: Alignment.center, + margin: EdgeInsets.only(top: 8.5), + height: height, + padding: EdgeInsets.only(left: 17), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, + bottom: Constants.GreyBorderSide)), + child: Stack( + children: [ + Container( + width: Screen.width, + height: height, + alignment: Alignment.centerLeft, + child: Icon( + Icons.phone_android, + color: BlueColor, + size: Constants.TextFieldIconSize, + ), + ), + Positioned( + left: 46, + child: Container( + padding: EdgeInsets.only(top: 5), + margin: EdgeInsets.all(0), + alignment: Alignment.centerLeft, + child: new DropdownButtonHideUnderline( + child: new DropdownButton( + items: phone.keys.map((key) { + return DropdownMenuItem( + child: new Text(key, textScaleFactor: 1.0), + value: key, + ); + }).toList(), + onChanged: (value) { + setState(() { + _selectType = value; + }); + }, + value: _selectType, + elevation: 24, //设置阴影的高度 + style: new TextStyle( + //设置文本框里面文字的样式 + color: Constants.BlackTextColor, + fontSize: 12, + ), + iconSize: 25.0, + )), + ), + ), + Positioned( + left: 90, + child: Container( + alignment: Alignment.center, + width: Screen.width - 90, + height: height, + child: TextField( + keyboardAppearance: Brightness.light, + decoration: new InputDecoration( + hintText: I18n.of(context).enter_number, + hintStyle: TextStyle(fontSize: 14), + border: InputBorder.none, + ), + maxLines: 1, + style: TextStyle(textBaseline: TextBaseline.alphabetic), + inputFormatters: [ + WhitelistingTextInputFormatter.digitsOnly, + ], + onChanged: (str) { + _phoneNumber = str; + //_phoneNumber = str; + setState(() {}); + }, + keyboardType: TextInputType.phone, + ), + ), + ) + ], + )); + } + + //构建密码按钮 + Widget _buildPasswordInput() { + return new Container( + alignment: Alignment.center, + child: new TextField( + keyboardAppearance: Brightness.light, + decoration: new InputDecoration( + hintText: I18n.of(context).enter_password, + hintStyle: TextStyle(fontSize: 14), + icon: new Icon( + Icons.lock, + color: BlueColor, + size: Constants.TextFieldIconSize, + ), + border: InputBorder.none, + ), + style: TextStyle(textBaseline: TextBaseline.alphabetic), + maxLines: 1, + obscureText: true, + onChanged: (str) { + _passWorld = str; + setState(() {}); + }, + ), + height: 54.5, + padding: EdgeInsets.only(left: 17), + decoration: BoxDecoration( + color: Colors.white, + border: Border(bottom: Constants.GreyBorderSide)), + ); + } + + //构建忘记密码 + Widget _buildForgetPassWord() { + return new Container( + child: new Align( + alignment: FractionalOffset.centerRight, + child: new FlatButton( + child: new Text( + I18n.of(context).forget_password, + textScaleFactor: 1.0, + style: TextStyle(color: BlueColor), + ), + onPressed: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return RegisterPage( + type: PageType.changePWD.index, + ); + }, + ), + ); + }, + ), + ), + ); + } + + //构建登陆按钮 + Widget _buildLoginButton() { + Text text = new Text(I18n.of(context).login, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: Constants.ShaderButtonFontSize, color: Colors.white)); + callback() async { + if (_phoneNumber == null || _phoneNumber == "") { + showToast(I18n.of(context).enter_number); + return; + } + if (_passWorld == null || _passWorld == "") { + showToast(I18n.of(context).enter_password); + return; + } + HttpUtil().login(phone[_selectType] + _phoneNumber, _passWorld, context); + } + + return InkWell( + onTap: callback, + child: Container( +// margin: EdgeInsets.only(top: 40), + alignment: Alignment.center, + height: Constants.ShaderButtonHeight, + width: Screen.width * RATE_NUM, + decoration: BoxDecoration( + color: Constants.ConfrimButtonColor, + border: Border.all(color: const Color(0x803875E9)), + borderRadius: + BorderRadius.all(Radius.circular(Constants.BigButtonRadius))), + child: text, + ), + ); + } +} diff --git a/lib/home/MessagePushPage.dart b/lib/home/MessagePushPage.dart new file mode 100644 index 0000000..f1f90dd --- /dev/null +++ b/lib/home/MessagePushPage.dart @@ -0,0 +1,234 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; + +import 'package:oktoast/oktoast.dart'; +import '../data/UserData.dart'; +import '../utils/TokenMgr.dart'; + +class MessagePushPage extends StatefulWidget { + MessagePushPage({Key key}) : super(key: key); + + _MessagePushPageState createState() => _MessagePushPageState(); +} + +class _MessagePushPageState extends State { + bool isMan = true; + + //私聊信息 + bool privatyMsg = false; + //消息推送 + bool msgPush = false; + //男士申请查看资料页 + bool watchMyData = false; + //男士查看社交账号 + bool watchSocialAccount = false; + //查看红包照片 + bool watchMyPicture = false; + //男士给我发送社交账号 + bool sendSocialAccount = false; + //新约会 + bool newDate = false; + //女士通过我的查看请求 + bool womenAgree = false; + //邀请码申请成功 + bool codeSucess = false; + + bool isLoadingFish = false; + + BoxDecoration _getCardDecoration() { + return new BoxDecoration( + color: Colors.white, + ); + } + + getSettingInfo() async { + Map data = { + "userId": UserData().basicInfo.userId, + "sex": UserData().basicInfo.sex, + }; + data['sign'] = TokenMgr().getSign(data); + try { + Response res = await HttpUtil().post('message/push/message', + data: data, failback: () => Navigator.of(context).pop()); + Map resData = res.data; + if (resData['code'] == 0) { + privatyMsg = resData['data']['PrivacyChat'] == 1; + newDate = resData['data']['NewBroadcast'] == 1; + if (isMan) { + womenAgree = resData['data']['AcceptCheck'] == 1; + codeSucess = resData['data']['ApplySuccess'] == 1; + } else { + watchMyData = resData['data']['ApplyCheck'] == 1; + watchMyPicture = resData['data']['CheckPhoto'] == 1; + } + Future.delayed(Duration(milliseconds: Constants.CloseLoaindTime), () { + isLoadingFish = true; + setState(() {}); + }); + setState(() {}); + } + } catch (e) {} + } + + @override + void initState() { + super.initState(); + isMan = UserData().isMan(); + getSettingInfo(); + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + I18n.of(context).push_setting2, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + leading: CustomUI.buildCustomLeading(context), + actions: [ + Container( + alignment: Alignment.center, + child: new InkWell( + child: new Padding( + padding: + EdgeInsets.only(right: 15, left: 15, top: 10, bottom: 10), + child: new Text(I18n.of(context).save, + textScaleFactor: 1.0, style: Constants.AppBarActionTextStyle), + ), + onTap: () async { + Map data = { + "userId": UserData().basicInfo.userId, + "sex": UserData().basicInfo.sex, + }; + data['sign'] = TokenMgr().getSign(data); + data['privacyChat'] = privatyMsg ? 1 : 0; + data['newBroadcast'] = newDate ? 1 : 0; + if (isMan) { + data['acceptCheck'] = womenAgree ? 1 : 0; + data['applySuccess'] = codeSucess ? 1 : 0; + } else { + data['applyCheck'] = watchMyData ? 1 : 0; + data['checkPhoto'] = watchMyPicture ? 1 : 0; + data['checkAccount'] = 1; + data['sendAccount'] = 1; + } + try { + Response res = await HttpUtil() + .post('message/setting/message', data: data); + Map resData = res.data; + showToast('${resData['msg']}'); + + if (resData['code'] == 0) { + UserData().privatyMsgPushSwitch = privatyMsg; + UserData().newDateSwitch = newDate; + UserData().applyCheckSwitch = watchMyData; + UserData().acceptCheckSwitch = womenAgree; + UserData().checkPhotoSwitch = watchMyPicture; + UserData().codeSucessSwitch = codeSucess; + } + } catch (e) {} + }, + ), + ) + ], + centerTitle: true, + ); + Widget content = Scaffold( + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + )), + appBar: appBar, + ); + return CustomUI.buildPageLoading(context, content, !isLoadingFish); + } + + Widget _buildBody() { + List man = [ + _buildHiddenButtom(I18n.of(context).private_chat2, privatyMsg, () { + setState(() { + privatyMsg = !privatyMsg; + }); + }), + _buildHiddenButtom(I18n.of(context).new_date, newDate, () { + setState(() { + newDate = !newDate; + }); + }), + _buildHiddenButtom(I18n.of(context).passed_request2, womenAgree, () { + setState(() { + womenAgree = !womenAgree; + }); + }), + _buildHiddenButtom(I18n.of(context).applied_successfully, codeSucess, () { + setState(() { + codeSucess = !codeSucess; + }); + }), + ]; + List women = [ + _buildHiddenButtom(I18n.of(context).private_chat2, privatyMsg, () { + setState(() { + privatyMsg = !privatyMsg; + }); + }), + _buildHiddenButtom(I18n.of(context).new_date, newDate, () { + setState(() { + newDate = !newDate; + }); + }), + _buildHiddenButtom(I18n.of(context).men_view, watchMyData, () { + setState(() { + watchMyData = !watchMyData; + }); + }), + _buildHiddenButtom(I18n.of(context).men_view3, watchMyPicture, () { + setState(() { + watchMyPicture = !watchMyPicture; + }); + }), + ]; + return new ListView( + children: isMan ? man : women, + ); + } + + //是否隐藏社交账号 + Widget _buildHiddenButtom(str, value, callback) { + Widget left = new Text( + str, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.normal), + ); + Widget right = new Expanded( + child: new Align( + alignment: Alignment.centerRight, + child: new Switch( + value: value, + activeTrackColor: Constants.ConfrimButtonColor.withOpacity(0.3), + onChanged: (bool val) { + callback(); + }, + ))); + return new Container( + decoration: _getCardDecoration(), + margin: EdgeInsets.only(top: 15, bottom: 0), + padding: EdgeInsets.only(left: 15), + height: 53, + child: new Row( + children: [left, right], + ), + ); + } +} diff --git a/lib/home/MoneyPage.dart b/lib/home/MoneyPage.dart new file mode 100644 index 0000000..9e77f1a --- /dev/null +++ b/lib/home/MoneyPage.dart @@ -0,0 +1,800 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/BindBank.dart'; +import 'package:chat/home/money_detail.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/utils/ChargeMoney.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart'; + +import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import 'VipPage.dart'; + +class MoneyPage extends StatefulWidget { + MoneyPage({Key key}) : super(key: key); + + MoneyPageState createState() => MoneyPageState(); +} + +class MoneyPageState extends State + with SingleTickerProviderStateMixin { + List list = new List(); //列表要展示的数据 + ScrollController _scrollController = ScrollController(); //listview的控制器 + + int _page = 1; //加载的页数 + int rows = 20; + bool isLoading = false; //是否正在加载数据 + bool isLoadingFish = false; + bool showMore = false; + + TabController tabCtrl; + + var bindAccount; + messageGetBindBank(data) { + getBinkInfo(); + } + + @override + void initState() { + super.initState(); + print('MoneyPage initState'); + tabCtrl = TabController(length: 2, vsync: this); + getBinkInfo(); + MessageMgr().on('bind_bank', messageGetBindBank); + + fluwx.responseFromPayment.listen((data) { + if (data.errCode == 0) { + Navigator.of(context).pop(); + setState(() {}); + showToast(I18n.of(context).payment_successful); + } + }); + + getNewData(initList); + _scrollController.addListener(() { + if (_scrollController.position.pixels == + _scrollController.position.maxScrollExtent) { + setState(() { + showMore = true; + }); + _getMore(); + } + }); + } + + void addList(data) { + data == null || data.length == 0 ? _page-- : list.addAll(data); + isLoading = false; + showMore = false; + setState(() {}); + } + + Future _getMore() async { + if (!isLoading) { + setState(() { + isLoading = true; + }); + _page++; + getNewData(addList); + } + } + + void changeMoney() async { + int minMoney = 350; + int maxMoney = 4000; + if (UserData().incomeMoney < minMoney) { + showToast(I18n.of(context).not_enough); + return; + } + + //自己是女性,且未认证,提示去认证 + if (!UserData().isMan() && !UserData().basicInfo.isAttestation) { + CustomUI.buildNotTrue(context); + return; + } + //如果是男性非会员,提示去开会员 + if (UserData().isMan() && !UserData().isVip) { + CustomUI.buildOneConfirm(context, I18n.of(context).no_vip_cannot_withdraw, + I18n.of(context).joinvip, () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return VipPage(); + }, + ), + ); + }); + return; + } + + if (Platform.isIOS) { + AppNavigator.pushServicePage(context, questionIndex: 1); + return; + } + if (bindAccount == null || bindAccount['CId'] == null) { + showToast(I18n.of(context).needCard); + return; + } + + String money; + + var confirm = + CustomUI.buildConfirmBotton(I18n.of(context).determine, () async { + var m; + if (money == null || money == '' || (m = int.parse(money)) == 0) { + showToast(I18n.of(context).enter_num_qian1); + return; + } + + if (m > Provider.of(context).money) { + showToast(I18n.of(context).not_enough); + return; + } + + if (m < minMoney) { + showToast(I18n.of(context) + .little_min + .replaceFirst('/s1', (minMoney * 1000).toString())); + return; + } + + if (m > maxMoney) { + showToast(I18n.of(context) + .more_big + .replaceFirst('/s1', (maxMoney * 1000).toString())); + return; + } + + var data = { + "userId": UserData().basicInfo.userId, + "cId": bindAccount['CId'], + "amount": m * 1000, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('wallet/draw/order', data: data); + Map resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + Navigator.of(context).pop(); + UserData().incomeMoney -= m; + MessageMgr().emit('refresh_money'); + } + }); + var tip = Column( + children: [ + Container( + margin: EdgeInsets.only(top: 20), + child: Text( + I18n.of(context).withdrawal_application, + style: TextStyle(color: Constants.BlackTextColor, fontSize: 16), + ), + ), + Container( + margin: EdgeInsets.only(top: 23, bottom: 25), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.all(Radius.circular(8))), + child: TextField( + keyboardAppearance: Brightness.light, + textAlign: TextAlign.center, + textInputAction: TextInputAction.search, + style: + TextStyle(textBaseline: TextBaseline.alphabetic, fontSize: 14), + decoration: InputDecoration( + hintText: I18n.of(context).enter_num_qian1, + filled: true, + contentPadding: EdgeInsets.only(top: 10, bottom: 10), + fillColor: Colors.transparent, + border: InputBorder.none, + ), + keyboardType: TextInputType.phone, + maxLines: 1, + inputFormatters: [ + WhitelistingTextInputFormatter(RegExp("^([1-9][0-9]*)\$")), + WhitelistingTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(5) + ], + onChanged: (str) { + money = str; + }, + ), + ) + ], + ); + var content = CustomUI.buildConfirmContent(tip, confirm); + CustomUI.buildTip(context, '', content); + } + + void changeHCoin() async { + int minMoney = 1; + int maxMoney = UserData().incomeMoney - UserData().frozenMoney; + if (UserData().incomeMoney < minMoney) { + showToast(I18n.of(context).not_enough); + return; + } + + String money; + + var confirm = + CustomUI.buildConfirmBotton(I18n.of(context).determine, () async { + var m; + if (money == null || money == '' || (m = int.parse(money)) == 0) { + showToast(I18n.of(context).enter_num_qian); + return; + } + + if (m > maxMoney) { + showToast(I18n.of(context).not_enough); + return; + } + + if (m < minMoney) { + showToast(I18n.of(context) + .little_min + .replaceFirst('/s1', minMoney.toString())); + return; + } + + Map data = { + "userId": UserData().basicInfo.userId, + "amount": m * 1000, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = + await HttpUtil().post('/wallet/income/exchange', data: data); + Map resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + Navigator.of(context).pop(); + UserData().incomeMoney -= m; + Provider.of(context, listen: false).addMoney(m); + MessageMgr().emit('refresh_money'); + setState(() {}); + } + }); + var tip = Column( + children: [ + Container( + margin: EdgeInsets.only(top: 20), + child: Text( + I18n.of(context).charge_h, + style: TextStyle(color: Constants.BlackTextColor, fontSize: 16), + ), + ), + Container( + margin: EdgeInsets.only(top: 23, bottom: 25), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.all(Radius.circular(8))), + child: TextField( + keyboardAppearance: Brightness.light, + textAlign: TextAlign.center, + textInputAction: TextInputAction.search, + style: + TextStyle(textBaseline: TextBaseline.alphabetic, fontSize: 14), + decoration: InputDecoration( + hintText: I18n.of(context).enter_num_qian, + filled: true, + contentPadding: EdgeInsets.only(top: 10, bottom: 10), + fillColor: Colors.transparent, + border: InputBorder.none, + ), + keyboardType: TextInputType.phone, + maxLines: 1, + inputFormatters: [ + WhitelistingTextInputFormatter(RegExp("^([1-9][0-9]*)\$")), + WhitelistingTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(5) + ], + onChanged: (str) { + money = str; + }, + ), + ) + ], + ); + var content = CustomUI.buildConfirmContent(tip, confirm); + CustomUI.buildTip(context, '', content); + } + + void getBinkInfo() async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('wallet/bind/bankInfo', + data: data, failback: () => Navigator.of(context).pop()); + Map resData = res.data; + if (resData['code'] == 0) { + bindAccount = resData['data']; + isLoadingFish = true; + setState(() {}); + } + } + + @override + void dispose() { + tabCtrl.dispose(); + MessageMgr().off('bind_bank', messageGetBindBank); + if (_conectionSubscription != null) { + _conectionSubscription.cancel(); + _conectionSubscription = null; + } + if (_purchaseUpdatedSubscription != null) { + _purchaseUpdatedSubscription.cancel(); + _purchaseUpdatedSubscription = null; + } + + if (_purchaseErrorSubscription != null) { + _purchaseErrorSubscription.cancel(); + _purchaseErrorSubscription = null; + } + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + Widget content = Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + leading: CustomUI.buildCustomLeading(context), + title: Text( + I18n.of(context).wallet, + textScaleFactor: 1.0, + ), + centerTitle: true, + bottom: PreferredSize( + preferredSize: Size.fromHeight(Platform.isIOS ? 0 : 49), + child: Platform.isIOS ? Container() : _buildBindAccount()), + ), + body: SafeArea(child: showCoin()), + ); + return CustomUI.buildPageLoading(context, content, !isLoadingFish); + } + + Widget _buildBindAccount() { + return InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return BindBankPage( + isBind: (bindAccount == null || bindAccount == ''), + bankInfo: bindAccount, + ); + }, + ), + ); + }, + child: Container( + color: Colors.white, + padding: EdgeInsets.only(top: 15, bottom: 15, left: 30, right: 8), + child: Row( + children: [ + Text( + I18n.of(context).bind_account.replaceFirst('/s1', ''), + textScaleFactor: 1.0, + style: TextStyle(fontWeight: FontWeight.normal), + ), + Expanded( + child: Container( + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + (bindAccount == null || bindAccount == '') + ? Container() + : Text( + bindAccount['Name'], + textScaleFactor: 1.0, + style: TextStyle(), + ), + Icon( + IconData(0xe63c, fontFamily: 'iconfont'), + size: 22.0, + color: Colors.grey, + ) + ], + )), + ) + ], + ), + )); + } + + Widget _buildCard1() { + var chargeButton = InkWell( + onTap: () { + ChargeMoney.showChargeSheet(context, () { + setState(() {}); + }); + }, + child: Container( + height: 30, + decoration: BoxDecoration( + color: Colors.white, borderRadius: BorderRadius.circular(5.5)), + alignment: Alignment.center, + width: 120, + child: Text( + I18n.of(context).recharge, + style: TextStyle(color: const Color(0xFFFF717D), fontSize: 14.8), + ), + )); + + var joinVipButton = InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return VipPage(); + }, + ), + ); + }, + child: Container( + height: 30, + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + borderRadius: BorderRadius.circular(5.5)), + alignment: Alignment.center, + width: 120, + child: Text( + I18n.of(context).joinvip, + style: TextStyle(color: Colors.white, fontSize: 14.8), + ), + )); + return Container( + margin: EdgeInsets.only(left: 21.5, right: 21.5, top: 20), + color: Colors.white, + child: Stack( + children: [ + Container( + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: const Color(0x42C4474E), + offset: Offset(0, 1.5), + blurRadius: 9, + ) + ], + borderRadius: BorderRadius.circular(5), + gradient: LinearGradient(colors: [ + const Color(0xFFFFC689), + const Color(0xFFFC818C), + ])), + child: Column( + children: [ + SizedBox(height: 17), + InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return MoneyDetailPage(type: 1); + }, + ), + ); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded(child: SizedBox()), + Container( + child: Text( + I18n.of(context).my_money_info, + style: + TextStyle(color: Colors.white, fontSize: 12), + ), + ), + Icon( + IconData(0xe63c, fontFamily: 'iconfont'), + size: 16.0, + color: Colors.white, + ), + SizedBox(width: 5) + ], + )), + Container( + alignment: Alignment.center, + child: Text( + I18n.of(context).my_left_money, + style: TextStyle(color: Colors.white, fontSize: 15), + ), + ), + Container( + margin: EdgeInsets.only(bottom: 30), + alignment: Alignment.center, + child: Text( + '${Provider.of(context).money}' + + I18n.of(context).mask_coin, + style: TextStyle(color: Colors.white, fontSize: 31.29), + ), + ), + UserData().isMan() + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + chargeButton, + joinVipButton, + ], + ) + : chargeButton, + Container( + margin: EdgeInsets.only(top: 25, bottom: 10, left: 13.5), + alignment: Alignment.centerLeft, + child: Text( + I18n.of(context).money_tips, + style: TextStyle(color: Colors.white, fontSize: 11), + ), + ), + ], + ), + ), + ], + )); + } + + Widget _buildCard2() { + return Container( + margin: EdgeInsets.only(left: 21.5, right: 21.5, top: 60), + color: Colors.white, + child: Stack( + children: [ + Container( + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: const Color(0x42023BBE), + offset: Offset(0, 1.5), + blurRadius: 8.5, + ) + ], + borderRadius: BorderRadius.circular(5), + gradient: LinearGradient(colors: [ + const Color(0xFF5FA2FF), + const Color(0xFFDDA4FF), + ])), + child: Column( + children: [ + SizedBox(height: 17), + InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return MoneyDetailPage(type: 2); + }, + ), + ); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded(child: SizedBox()), + Container( + child: Text( + I18n.of(context).get_money_detail, + style: + TextStyle(color: Colors.white, fontSize: 12), + ), + ), + Icon( + IconData(0xe63c, fontFamily: 'iconfont'), + size: 16.0, + color: Colors.white, + ), + SizedBox(width: 5) + ], + )), + Container( + alignment: Alignment.center, + child: Text( + I18n.of(context).hibok_money, + style: TextStyle(color: Colors.white, fontSize: 15), + ), + ), + Container( + margin: EdgeInsets.only(bottom: 30), + alignment: Alignment.center, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + (UserData().incomeMoney + UserData().frozenMoney) + .toString() + + 'K', + style: + TextStyle(color: Colors.white, fontSize: 31.29), + ), + Text( + "(${I18n.of(context).can_withdraw}${UserData().incomeMoney}K)", + style: TextStyle(color: Colors.white, fontSize: 18), + ), + ], + )), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + InkWell( + onTap: changeMoney, + child: Container( + height: 30, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(5.5)), + alignment: Alignment.center, + width: 120, + child: Text( + I18n.of(context).exchange_cash, + style: TextStyle( + color: const Color(0xFF4F8BFF), + fontSize: 14.8), + ), + )), + InkWell( + onTap: changeHCoin, + child: Container( + height: 30, + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + borderRadius: BorderRadius.circular(5.5)), + alignment: Alignment.center, + width: 120, + child: Text( + I18n.of(context).charge_h, + style: TextStyle( + color: Colors.white, fontSize: 14.8), + ), + )), + ], + ), + InkWell( + onTap: () { + launch( + "https://datasm.chengyouhd.com/zh-CN/Home/WithdrawalRole?language=${UserData().language}"); + }, + child: Container( + margin: EdgeInsets.only(top: 25, bottom: 10, left: 13.5), + alignment: Alignment.centerLeft, + child: Text( + I18n.of(context).charge_tips, + style: TextStyle(color: Colors.white, fontSize: 11), + ), + ), + ) + ], + ), + ), + ], + )); + } + + Widget showCoin() { + return Scaffold( + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildCoinBody(), + ), + ))); + } + + void initList(data) { + list.clear(); + if (data != null) { + list.addAll(data); + } + isLoadingFish = true; + setState(() {}); + } + + getNewData(callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + data["page"] = _page; + data['rows'] = rows; + data['type'] = 2; + Response res = await HttpUtil().post('message/wallet/message', data: data); + var resData = res.data; + print(resData); + if (resData['code'] == 0) { + callback(resData['data']); + } else { + showToast(resData['msg']); + } + } + + Widget _buildCoinBody() { + return Container( + width: Screen.width, + height: Screen.height, + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: const Color(0x87C6C6C6), + offset: Offset(0, 0.5), + blurRadius: 5.5, + ) + ], + ), + margin: EdgeInsets.only(top: 9.5), + child: Column( + children: [ + _buildCard1(), + _buildCard2(), + ], + ), + ); + } + + static String currentGoodsId = ''; + static StreamSubscription _conectionSubscription, + _purchaseUpdatedSubscription, + _purchaseErrorSubscription; + + ///ios 内购初始化 + static Future initPayConf(BuildContext context) async { + if (_purchaseErrorSubscription != null) { + return; + } + + // prepare + print('initPayConf -------- start: '); + var result = await FlutterInappPurchase.instance.initConnection; + print('initPayConf -------- result: $result'); + FlutterInappPurchase.instance.clearTransactionIOS(); + + _conectionSubscription = + FlutterInappPurchase.connectionUpdated.listen((connected) { + print('connected: $connected'); + }); + + _purchaseUpdatedSubscription = + FlutterInappPurchase.purchaseUpdated.listen((productItem) { + print('支付成功,成功回调 ------ purchase-updated: $productItem'); +// showToast('支付成功,成功回调 ------ purchase-updated: $productItem'); + if (productItem.transactionReceipt != null && + productItem.transactionReceipt.isNotEmpty) { + HttpUtil().createOrder(currentGoodsId, productItem.transactionReceipt, + productItem.purchaseToken, + context: context); + + showToast(I18n.of(context).payment_successful); + } + Navigator.of(context).pop(); + }); + + _purchaseErrorSubscription = + FlutterInappPurchase.purchaseError.listen((purchaseError) { +// showToast('支付失败回调 -------- purchase-error: $purchaseError'); + FlutterInappPurchase.instance.clearTransactionIOS(); + Navigator.of(context).pop(); + }); + } +} diff --git a/lib/home/MoneyPageOld.dart b/lib/home/MoneyPageOld.dart new file mode 100644 index 0000000..e42fe91 --- /dev/null +++ b/lib/home/MoneyPageOld.dart @@ -0,0 +1,867 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/data/conversation.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/BindBank.dart'; +import 'package:chat/home/InfoList.dart'; +import 'package:chat/home/ProfilePage.dart'; +import 'package:chat/home/rich_title.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/utils/ChargeMoney.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; + +class _ConversationItem extends StatelessWidget { + const _ConversationItem( + {Key key, + this.conversation, + this.callback, + this.showRight = true, + this.rightButton, + this.showReturn = false, + this.applyInfo, + this.bgColor, + this.money, + this.title}) + : assert(conversation != null), + super(key: key); + final Widget rightButton; + final Conversation conversation; + final callback; + final int money; + final bool showRight; + final title; + final applyInfo; + final bgColor; + final bool showReturn; + + @override + Widget build(BuildContext context) { + Widget avatar; + double width = 44.55; + if (conversation.isAvatarFromNet()) { + avatar = ClipRRect( + borderRadius: BorderRadius.circular(10), + child: CachedNetworkImage( + imageUrl: conversation.avatar, + placeholder: (context, url) => Image.asset( + Constants.DefaultHeadImgUrl, + width: width, + height: width, + ), + fit: BoxFit.cover, + width: width, + height: width, + )); + } else { + avatar = ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Container( + width: width, + height: width, + alignment: Alignment.center, + decoration: BoxDecoration( + gradient: this.bgColor, + borderRadius: BorderRadius.all(Radius.circular(50))), + child: Image.asset( + conversation.avatar, + height: 27, + ))); + } + + return InkWell( + child: Container( + padding: + const EdgeInsets.only(left: 21, top: 9.5, bottom: 9.5, right: 24.5), + decoration: BoxDecoration( + color: Color(AppColors.ConversationItemBgColor), + border: Border( + bottom: BorderSide( + color: AppColors.DividerColor, + width: Constants.DividerWidth))), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + avatar, + Container(width: 14.0), + Expanded( + child: Container( + padding: EdgeInsets.only(top: 3), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: title == null + ? Text(conversation.title, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 11, + color: Constants.LightGreyTextColor)) + : title), + Container( + padding: EdgeInsets.only(top: 10), + child: Text(conversation.desc, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 11, color: Constants.LightGreyTextColor)), + ) + ], + ), + )), + Container( + height: width, + margin: EdgeInsets.only(left: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '${money > 0 ? '+' : ''}$money${I18n.of(context).mask_coin}', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: + money > 0 ? Color(0xFFFE4624) : Color(0xFF5498FF)), + ), + showReturn + ? Padding( + padding: EdgeInsets.only(top: 3), + child: Text( + I18n.of(context).alreay_back, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.normal, + color: Constants.BlackTextColor), + )) + : Container() + ], + ), + alignment: Alignment.center, + ), + ], + ), + ), + onTap: () { + callback(); + }, + ); + } +} + +class MoneyPageOld extends StatefulWidget { + MoneyPageOld({Key key}) : super(key: key); + + MoneyPageOldState createState() => MoneyPageOldState(); +} + +class MoneyPageOldState extends State + with SingleTickerProviderStateMixin { + List list = new List(); //列表要展示的数据 + ScrollController _scrollController = ScrollController(); //listview的控制器 + + int _page = 1; //加载的页数 + int rows = 20; + bool isLoading = false; //是否正在加载数据 + bool isLoadingFish = false; + bool showMore = false; + + TabController tabCtrl; + + var bindAccount; + messageGetBindBank(data) { + getBinkInfo(); + } + + @override + void initState() { + super.initState(); + print('MoneyPageOld initState'); + tabCtrl = TabController(length: 2, vsync: this); + getBinkInfo(); + MessageMgr().on('bind_bank', messageGetBindBank); + + fluwx.responseFromPayment.listen((data) { + if (data.errCode == 0) { + Navigator.of(context).pop(); + setState(() {}); + showToast(I18n.of(context).payment_successful); + } + }); + + getNewData(initList); + _scrollController.addListener(() { + if (_scrollController.position.pixels == + _scrollController.position.maxScrollExtent) { + setState(() { + showMore = true; + }); + _getMore(); + } + }); + } + + void addList(data) { + data == null || data.length == 0 ? _page-- : list.addAll(data); + isLoading = false; + showMore = false; + setState(() {}); + } + + Future _getMore() async { + if (!isLoading) { + setState(() { + isLoading = true; + }); + _page++; + getNewData(addList); + } + } + + void changeMoney() async { + if (Provider.of(context).money < 40) { + showToast(I18n.of(context).not_enough); + return; + } + if (bindAccount == null || bindAccount['CId'] == null) { + showToast(I18n.of(context).needCard); + return; + } + + if (Platform.isIOS) { + AppNavigator.pushServicePage(context, questionIndex: 1); + return; + } + + String money; + + var confirm = + CustomUI.buildConfirmBotton(I18n.of(context).determine, () async { + int minMoney = 40; + int maxMoney = 4000; + var m = int.parse(money); + if (m == null || m == 0) { + showToast(I18n.of(context).enter_amount); + return; + } + + if (m > Provider.of(context).money) { + showToast(I18n.of(context).not_enough); + return; + } + + if (m < minMoney) { + showToast(I18n.of(context) + .little_min + .replaceFirst('/s1', minMoney.toString())); + return; + } + + if (m > maxMoney) { + showToast( + I18n.of(context).more_big.replaceFirst('/s1', maxMoney.toString())); + return; + } + + var data = { + "userId": UserData().basicInfo.userId, + "cId": bindAccount['CId'], + "amount": m, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('wallet/draw/order', data: data); + Map resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + Navigator.of(context).pop(); + UserData().totalMoney -= m; + Provider.of(context, listen: false).subMoney(m); + MessageMgr().emit('refresh_money'); + _onRefresh(); + } + }); + var tip = Column( + children: [ + Container( + margin: EdgeInsets.only(top: 20), + child: Text( + I18n.of(context).withdrawal_application, + style: TextStyle(color: Constants.BlackTextColor, fontSize: 16), + ), + ), + Container( + margin: EdgeInsets.only(top: 23, bottom: 25), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.all(Radius.circular(8))), + child: TextField( + keyboardAppearance: Brightness.light, + textAlign: TextAlign.center, + textInputAction: TextInputAction.search, + style: + TextStyle(textBaseline: TextBaseline.alphabetic, fontSize: 14), + decoration: InputDecoration( + hintText: I18n.of(context).enter_amount, + filled: true, + contentPadding: EdgeInsets.only(top: 10, bottom: 10), + fillColor: Colors.transparent, + border: InputBorder.none, + ), + keyboardType: TextInputType.phone, + maxLines: 1, + inputFormatters: [ + WhitelistingTextInputFormatter(RegExp("^([1-9][0-9]*)\$")), + WhitelistingTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(5) + ], + onChanged: (str) { + money = str; + }, + ), + ) + ], + ); + var content = CustomUI.buildConfirmContent(tip, confirm); + CustomUI.buildTip(context, '', content); + } + + void getBinkInfo() async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('wallet/bind/bankInfo', + data: data, failback: () => Navigator.of(context).pop()); + Map resData = res.data; + if (resData['code'] == 0) { + bindAccount = resData['data']; + isLoadingFish = true; + setState(() {}); + } + } + + @override + void dispose() { + tabCtrl.dispose(); + MessageMgr().off('bind_bank', messageGetBindBank); + if (_conectionSubscription != null) { + _conectionSubscription.cancel(); + _conectionSubscription = null; + } + if (_purchaseUpdatedSubscription != null) { + _purchaseUpdatedSubscription.cancel(); + _purchaseUpdatedSubscription = null; + } + + if (_purchaseErrorSubscription != null) { + _purchaseErrorSubscription.cancel(); + _purchaseErrorSubscription = null; + } + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + Widget content = Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + leading: CustomUI.buildCustomLeading(context), + title: Text( + I18n.of(context).wallet, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + ), + body: SafeArea(child: showCoin()), + ); + return CustomUI.buildPageLoading(context, content, !isLoadingFish); + } + + Widget _buildBindAccount() { + return InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return BindBankPage( + isBind: (bindAccount == null || bindAccount == ''), + bankInfo: bindAccount, + ); + }, + ), + ); + }, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: BorderSide(color: Colors.grey, width: 0.2), + bottom: BorderSide(color: Colors.grey, width: 0.2), + )), + padding: EdgeInsets.only(top: 15, bottom: 15, left: 30, right: 8), + child: Row( + children: [ + Text( + I18n.of(context).bind_account.replaceFirst('/s1', ''), + textScaleFactor: 1.0, + style: TextStyle(fontWeight: FontWeight.normal), + ), + Expanded( + child: Container( + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + (bindAccount == null || bindAccount == '') + ? Container() + : Text( + bindAccount['Name'], + textScaleFactor: 1.0, + style: TextStyle(), + ), + Icon( + IconData(0xe63c, fontFamily: 'iconfont'), + size: 22.0, + color: Colors.grey, + ) + ], + )), + ) + ], + ), + )); + } + + Widget _buildCard(int money2) { + return Container( + color: Colors.white, + child: Stack( + children: [ + Container( + margin: EdgeInsets.only(bottom: 2), + color: Colors.white, + width: Screen.width, + child: Image.asset( + 'assets/images/qianbao_bg.png', + fit: BoxFit.fitWidth, + ), + ), + Container( + margin: EdgeInsets.only(top: 20, left: 25, right: 25, bottom: 20), + child: Column( + children: [ + Padding( + child: Text( + '${I18n.of(context).get_way}${I18n.of(context).coin_use}', + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white, fontSize: 10.5), + ), + padding: EdgeInsets.only( + left: 5, + right: 5, + top: 13, + bottom: Screen.width * 0.05), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + alignment: Alignment.centerLeft, + child: Text( + I18n.of(context).coin_total, + textAlign: TextAlign.left, + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.white, fontSize: 15), + ), + padding: + EdgeInsets.only(right: 5, top: 0, left: 22), + ), + Row( + children: [ + Padding( + child: Container( + child: Text( + UserData().totalMoney.toString(), + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.white, fontSize: 31.5), + ), + ), + padding: EdgeInsets.only(left: 25, right: 5), + ), + ], + ) + ], + ), + ), + Platform.isIOS + ? Container() + : Expanded( + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + InkWell( + onTap: changeMoney, + child: Container( + margin: EdgeInsets.only( + top: 23, right: 5), + width: double.infinity, + child: Row( + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + Text( + I18n.of(context) + .exchange_cash, + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.white, + fontSize: 14)), + Icon( + IconData(0xe63c, + fontFamily: 'iconfont'), + size: 20.0, + color: Colors.white, + ), + ], + ))), + Container( + padding: EdgeInsets.only(top: 5, right: 10), + alignment: Alignment.centerRight, + child: Consumer( + builder: (context, + MoneyChangeProvider counter, + child) => + Text( + '${I18n.of(context).can_withdraw} $money2', + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.white, fontSize: 12), + ), + ), + ) + ], + ), + )) + ], + ), + ], + ), + ), + Positioned( + bottom: 6, + //left: ScreenUtil().setWidth(20), + child: Platform.isIOS + ? Container() + : Container( + //color: Colors.red, + margin: EdgeInsets.only(left: ScreenUtil().setWidth(20)), + width: Screen.width - ScreenUtil().setWidth(35), + child: Text( + I18n.of(context).warning_text, + style: TextStyle( + fontSize: 11, color: const Color(0xFFFE4624)), + ), + ), + ) + ], + )); + } + + Widget _buildBottomSheet() { + var blueColor = AppColors.NewAppbarBgColor; + return Container( + height: 50, + decoration: BoxDecoration( + color: Constants.LightGreyBackgroundColor, + border: Border(top: BorderSide(color: Color(0xffeaeaea)))), + child: Row( + mainAxisAlignment: Platform.isIOS + ? MainAxisAlignment.center + : MainAxisAlignment.spaceEvenly, + children: [ + InkWell( + onTap: () { + ChargeMoney.showChargeSheet(context, () { + setState(() {}); + }); + }, + child: Container( + width: MediaQuery.of(context).size.width / 2, + alignment: Alignment.center, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + IconData( + 0xe642, + fontFamily: 'iconfont', + ), + color: blueColor, + ), + SizedBox(width: 7.5), + Text( + I18n.of(context).recharge, + textScaleFactor: 1.0, + style: TextStyle(color: blueColor), + ), + ], + ))), + Platform.isIOS + ? Container() + : InkWell( + onTap: changeMoney, + child: Container( + width: MediaQuery.of(context).size.width / 2, + alignment: Alignment.center, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + IconData( + 0xe64a, + fontFamily: 'iconfont', + ), + color: blueColor, + ), + SizedBox(width: 7.5), + Text( + Platform.isIOS + ? '咨询客服' + : I18n.of(context).exchange_cash, + textScaleFactor: 1.0, + style: TextStyle(color: blueColor), + ), + ], + ))) + ], + ), + ); + } + + Widget showCoin() { + return Scaffold( + bottomNavigationBar: _buildBottomSheet(), + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildCoinBody(), + ), + ))); + } + + /* + * 下拉刷新方法,为list重新赋值 + */ + Future _onRefresh() async { + _page = 1; + _scrollController.jumpTo(0); + getNewData(initList); + } + + void initList(data) { + list.clear(); + if (data != null) { + list.addAll(data); + } + isLoadingFish = true; + setState(() {}); + } + + getNewData(callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + data["page"] = _page; + data['rows'] = rows; + data['type'] = 2; + Response res = await HttpUtil().post('message/wallet/message', data: data); + var resData = res.data; + print(resData); + if (resData['code'] == 0) { + callback(resData['data']); + } else { + showToast(resData['msg']); + } + } + + bool isAdd(bool isMyself, int type) { + return type == 1 || + type == 10 || + type == 11 || + (!isMyself && type == 3) || + (!isMyself && type == 4) || + (!isMyself && type == 7) || + (!isMyself && type == 8) || + (!isMyself && type == 9); + } + + //钱包通知 + Widget _buildMoneyInfo(data) { + bool isMyself = data['UserId'] == UserData().basicInfo.userId; + String imgUrl = data['HeadImg'] == null || data['HeadImg'] == '' + ? UserData().basicInfo.headimgurl + : data['HeadImg']; + + return _ConversationItem( + conversation: Conversation( + avatar: imgUrl, + title: '', + desc: WebData().getLoginTime(context, data['CreateTime']), + updateAt: '', + ), + bgColor: Constants.MoneyGradient, + showReturn: data['DetailType'] == 10 || + data['Status'] == 2 || + (data['DetailType'] != 9 && + data['DetailType'] != 6 && + data['Status'] == 1), + money: + isAdd(isMyself, data['DetailType']) ? data['Value'] : -data['Value'], + title: RichTitle.getRichTitleWidget(data, context, InfoType.Money, + titleStyle: TextStyle(fontSize: 12, color: const Color(0XFF7F7F7F)), + nameStyle: TextStyle( + fontWeight: FontWeight.normal, + fontSize: 13, + color: Constants.BlackTextColor)), + callback: () { + if (data['ChangeUserId'] != 0) { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: data['UserId'] == UserData().basicInfo.userId + ? data['ChangeUserId'] + : data['UserId'], + ); + }, + ), + ); + } + }, + ); + } + + Widget _renderRow(BuildContext context, int index) { + if (list.length == 0) { + return Column( + children: [ + _buildCard(Provider.of(context).money), +// _buildBindAccount(), + ], + ); + } + if (index < list.length) { + var userInfo = list[index]; + Widget result = _buildMoneyInfo(userInfo); + if (index == 0) { + result = Column( + children: [ + _buildCard(Provider.of(context).money), + Platform.isIOS ? Container() : _buildBindAccount(), + Padding(padding: EdgeInsets.only(top: 10), child: result) + ], + ); + } + + return result; + } else if (showMore) { + _getMoreWidget(); + } + return Container(); + } + + Widget _getMoreWidget() { + return Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Constants.BlueTextColor))); + } + + Widget _buildCoinBody() { + return RefreshIndicator( + onRefresh: _onRefresh, + child: ListView.builder( + physics: AlwaysScrollableScrollPhysics(), + itemBuilder: _renderRow, + itemCount: list.length + 1, + controller: _scrollController, + ), + ); + } + + static String currentGoodsId = ''; + static StreamSubscription _conectionSubscription, + _purchaseUpdatedSubscription, + _purchaseErrorSubscription; + + ///ios 内购初始化 + static Future initPayConf(BuildContext context) async { + if (_purchaseErrorSubscription != null) { + return; + } + + // prepare + print('initPayConf -------- start: '); + var result = await FlutterInappPurchase.instance.initConnection; + print('initPayConf -------- result: $result'); + FlutterInappPurchase.instance.clearTransactionIOS(); + + _conectionSubscription = + FlutterInappPurchase.connectionUpdated.listen((connected) { + print('connected: $connected'); + }); + + _purchaseUpdatedSubscription = + FlutterInappPurchase.purchaseUpdated.listen((productItem) { + print('支付成功,成功回调 ------ purchase-updated: $productItem'); +// showToast('支付成功,成功回调 ------ purchase-updated: $productItem'); + if (productItem.transactionReceipt != null && + productItem.transactionReceipt.isNotEmpty) { + HttpUtil().createOrder(currentGoodsId, productItem.transactionReceipt, + productItem.purchaseToken, + context: context); + + showToast(I18n.of(context).payment_successful); + } + Navigator.of(context).pop(); + }); + + _purchaseErrorSubscription = + FlutterInappPurchase.purchaseError.listen((purchaseError) { +// showToast('支付失败回调 -------- purchase-error: $purchaseError'); + FlutterInappPurchase.instance.clearTransactionIOS(); + Navigator.of(context).pop(); + }); + } +} diff --git a/lib/home/MyDialogContent.dart b/lib/home/MyDialogContent.dart new file mode 100644 index 0000000..2239782 --- /dev/null +++ b/lib/home/MyDialogContent.dart @@ -0,0 +1,76 @@ +//用于刷新DialogContent +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:flutter/material.dart'; + +import 'package:oktoast/oktoast.dart'; + +class MyDialogContent extends StatefulWidget { + final dataMap; + final keyList; + @required + final mostNum; + MyDialogContent({Key key, this.dataMap, this.keyList, this.mostNum}) + : super(key: key); + + _MyDialogContentState createState() => _MyDialogContentState(); +} + +class _MyDialogContentState extends State { + @override + Widget build(BuildContext context) { + Widget buildItem(key, str) { + Text text = new Text(str, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 14, + color: widget.keyList.contains(key) + ? Constants.BlueTextColor + : Constants.BlackTextColor)); + return InkWell( + highlightColor: Colors.transparent, + radius: 0.0, + child: Container( + decoration: BoxDecoration( + border: Border(bottom: Constants.GreyBorderSide), + ), + height: 50, + alignment: Alignment.center, + child: text), + onTap: () { + setState(() { + if (widget.keyList.contains(key)) { + widget.keyList.remove(key); + } else { + if (widget.keyList.length >= widget.mostNum) { + showToast(I18n.of(context) + .most + .replaceFirst('/s1', widget.mostNum.toString())); + return; + } + widget.keyList.add(key); + } + }); + }, + ); + } + + List buildDateprogram() { + List result = new List(); + widget.dataMap.forEach((k, v) => result.add(buildItem(k, v))); + return result; + } + + return new Container( + decoration: BoxDecoration( + border: Border(top: BorderSide(color: Colors.grey, width: 1)), + ), + + height: 230.0, // Change as per your requirement + width: 350.0, // Change as per your requirement + child: ListView( + children: buildDateprogram(), + ), + ); + } +} diff --git a/lib/home/Myprogram.dart b/lib/home/Myprogram.dart new file mode 100644 index 0000000..f29f67b --- /dev/null +++ b/lib/home/Myprogram.dart @@ -0,0 +1,306 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/AddProgram.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/MessageBox.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:flutter/material.dart'; +import 'package:chat/utils/PopUpMenu.dart' as myPop; + +import 'package:oktoast/oktoast.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; +import '../utils/HttpUtil.dart'; +import 'package:dio/dio.dart'; +import "../data/UserData.dart"; +import '../utils/TokenMgr.dart'; + +class MyProgramPage extends StatefulWidget { + @required + final bool isProgram; + @required + final bool isMan; + final userId; + MyProgramPage( + {Key key, this.isProgram = true, this.userId, this.isMan = false}) + : super(key: key); + + @override + _MyProgramPageState createState() => new _MyProgramPageState(); +} + +class _MyProgramPageState extends State { + List list = new List(); //列表要展示的数据 + RefreshController _refreshController = + RefreshController(initialRefresh: true); + int _page = 1; //加载的页数 + int rows = 20; + + bool isMyself = false; + + addProgramCallback(data) { + list.insert(0, data); + } + + @override + void initState() { + isMyself = widget.userId == UserData().basicInfo.userId; + super.initState(); + MessageMgr().on('delete_program', msgListDelete); + MessageMgr().on('Add_program', addProgramCallback); + MessageMgr().on('refresh_list', msgRefreshList); + MessageMgr().on('join_program', msgJoinList); + } + + msgJoinList(data) { + for (int i = 0; i < list.length; i++) { + if (list[i]['Id'] == data) { + list[i]['EnrollNum']++; + list[i]['IsEnroll']++; + setState(() {}); + break; + } + } + } + + msgRefreshList(data) { + _onRefresh(); + } + + msgListLove(data) { + for (int i = 0; i < list.length; i++) { + if (list[i]['Id'] == data) { + list[i]['FabulousNum']++; + list[i]['IsFabulous']++; + setState(() {}); + break; + } + } + } + + msgListDelete(data) { + for (int i = 0; i < list.length; i++) { + if (list[i]['Id'] == data) { + list.removeAt(i); + setState(() {}); + break; + } + } + } + + Future getData(callback) async { + var data = { + "userId": UserData().basicInfo.userId, + "visitUserId": widget.userId, + //"type": widget.isProgram == true ? 1 : 2, + }; + data['sign'] = TokenMgr().getSign(data); + data['page'] = _page; + data['rows'] = rows; + Response res = await HttpUtil().post('station/gain/program', + data: data, failback: () => Navigator.of(context).pop()); + _refreshController.refreshCompleted(); + var resData = res.data; + if (resData['code'] == 0) { + callback(resData['data']); + } else { + showToast(resData['msg']); + } + } + + void addProgram(str) async { + if (str == 'program') { + //自己是女性,且未认证,提示去认证 + if (!UserData().isMan() && !UserData().basicInfo.isAttestation) { + CustomUI.buildNotTrue(context); + return; + } + if (!UserData().isCanProgram) { + showToast(I18n.of(context).stop_program); + } else { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return AddProgram( + isProgram: true, + ); + }, + ), + ); + } + } else if (str == 'dynamic') { + //自己是女性,且未认证,提示去认证 + if (!UserData().isMan() && !UserData().basicInfo.isAttestation) { + CustomUI.buildNotTrue(context); + return; + } + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return AddProgram( + isProgram: false, + ); + }, + ), + ); + } + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + // widget.isProgram + // ? (isMyself + // ? I18n.of(context).my_show + // : (widget.isMan + // ? I18n.of(context).his_dynamics + // : I18n.of(context).her_dynamics)) + // : (isMyself + // ? I18n.of(context).my_dynamic + // : (widget.isMan + // ? I18n.of(context).his_dynamics + // : I18n.of(context).her_dynamics)), + isMyself + ? I18n.of(context).my_dynamic + : (widget.isMan + ? I18n.of(context).his_dynamics + : I18n.of(context).her_dynamics), + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + elevation: 1, + actions: [ + isMyself + ? myPop.PopupMenuButton( + padding: EdgeInsets.zero, + offset: Offset(0, 45), + child: Container( + alignment: Alignment.center, + child: new Padding( + padding: EdgeInsets.only( + right: 15, left: 15, top: 10, bottom: 10), + child: new Text( + I18n.of(context).release, + textScaleFactor: 1.0, + style: Constants.AppBarActionTextStyle, + ), + ), + ), + onSelected: (str) { + addProgram(str); + }, + itemBuilder: (BuildContext context) => + >[ + myPop.PopupMenuItem( + value: 'program', + child: Container( + margin: EdgeInsets.only(top: 15, bottom: 15), + child: Text( + I18n.of(context).release_program, + textScaleFactor: 1.0, + textAlign: TextAlign.center, + ), + )), + myPop.PopupMenuDivider( + height: 1, + ), + myPop.PopupMenuItem( + value: 'dynamic', + child: Container( + margin: EdgeInsets.only(top: 15, bottom: 15), + child: Text( + I18n.of(context).release_dynamics, + textScaleFactor: 1.0, + textAlign: TextAlign.center, + )), + ), + ], + ) + : Container() + ], + ); + Widget content = Scaffold( + appBar: appBar, + body: SafeArea( + child: SmartRefresher( + enablePullDown: true, + enablePullUp: true, + header: MaterialClassicHeader(), + footer: CustomUI.buildLoadingFooter(), + controller: _refreshController, + onRefresh: _onRefresh, + onLoading: _onLoading, + child: (_refreshController.headerStatus == RefreshStatus.completed && + list.length == 0) + ? CustomUI.buildNoData(context) + : ListView.builder( + itemBuilder: _renderRow, + itemCount: list.length, + ), + )), + ); + return content; + } + + Widget _renderRow(BuildContext context, int index) { + // if (list.length == 0) { + // return CustomUI.buildNoData( + // context, + // str: isMyself + // ? (widget.isProgram + // ? I18n.of(context).no_program + // : I18n.of(context).on_dynamic) + // : (widget.isMan + // ? I18n.of(context).low_key2 + // : I18n.of(context).low_key), + // ); + // } + if (index < list.length) { + var userInfo = list[index]; + print('--------------------------------------------'); + print(userInfo); + return MessageBox( + programInfo: userInfo, + ); + } + return Container(); + } + + Future _onRefresh() async { + _page = 1; + getData((data) { + list.clear(); + if (data != null) { + list.addAll(data); + } + setState(() {}); + }); + } + + Future _onLoading() async { + _page++; + getData((data) { + if (data == null || data.length == 0) { + _page--; + _refreshController.loadNoData(); + } else { + list.addAll(data); + _refreshController.loadComplete(); + } + setState(() {}); + }); + } + + @override + void dispose() { + _refreshController.dispose(); + MessageMgr().off('delete_program', msgListDelete); + MessageMgr().off('Add_program', addProgramCallback); + MessageMgr().off('refresh_list', msgRefreshList); + MessageMgr().off('join_program', msgJoinList); + super.dispose(); + } +} diff --git a/lib/home/ParkPage.dart b/lib/home/ParkPage.dart new file mode 100644 index 0000000..f02846e --- /dev/null +++ b/lib/home/ParkPage.dart @@ -0,0 +1,944 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/AddProgram.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageBox.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/PopUpMenu.dart' as myPop; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart' + as myExt; +import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_swiper/flutter_swiper.dart'; +import 'package:chat/utils/DropDownMemu.dart'; + +import 'package:oktoast/oktoast.dart'; +import 'package:url_launcher/url_launcher.dart'; + +const ChinaKey = 'China-ChinaRepeat'; + +class SortCondition { + String key; + String name; + bool isSelected; + + SortCondition({this.name, this.isSelected, this.key}); +} + +class ParkPage extends StatefulWidget { + final int searchType; + + ParkPage({Key key, this.searchType = -1}) : super(key: key); + + _ParkPageState createState() => _ParkPageState(); +} + +class _ParkPageState extends State { + List _dropDownHeaderItemStrings = []; + List _sexSortCondition = []; + List _timeSortConditions = []; + SortCondition _selectSexSortCondition; + SortCondition _selectTimeSortCondition; + + ScrollController _scrollController = new ScrollController(); + GlobalKey _key = GlobalKey(); + + bool isLoadingFinish = false; + + List bannerImages = []; + + String timeCat = '1'; + + String search = '1'; + + String guid = ''; + + bool isLoading = false; //是否正在加载数据 + + int _page = 1; + int rows = 20; + + bool isHomePage = true; + + bool isOnline = false; + + bool loadSuccess = false; + + List list = []; + + GlobalKey _stackKey = GlobalKey(); + GZXDropdownMenuController _dropdownMenuController = + GZXDropdownMenuController(); + + initValues() { + if (!loadSuccess) { + _dropDownHeaderItemStrings = [ + I18n.of(context).release_time, + I18n.of(context).any_sex, + UserData().isInChina + ? WebData().provinces['China'] + : I18n.of(context).unlimited_area + ]; + search = UserData().isInChina ? ChinaKey : '1'; + _sexSortCondition = [ + SortCondition( + key: '0', name: I18n.of(context).any_sex, isSelected: true), + SortCondition( + key: '2', name: I18n.of(context).look_women, isSelected: false), + SortCondition( + key: '1', name: I18n.of(context).look_men, isSelected: false) + ]; + _selectSexSortCondition = _sexSortCondition[0]; + + _timeSortConditions.add(SortCondition( + key: '1', name: I18n.of(context).release_time, isSelected: true)); + _timeSortConditions.add(SortCondition( + key: '2', name: I18n.of(context).activity_time, isSelected: false)); + _selectTimeSortCondition = _timeSortConditions[0]; + loadSuccess = true; + getNewData(); + setState(() {}); + } + } + + //获取新的数据 + + void getData(callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + "time": _selectTimeSortCondition.key, + "sex": _selectSexSortCondition.key, + "area": search, + }; + data['sign'] = TokenMgr().getSign(data); + data['page'] = _page; + data['guid'] = guid; + data['rows'] = rows; + data['type'] = widget.searchType; + data['online'] = isOnline ? 1 : 0; + data['lng'] = UserData().longitude; + data['lat'] = UserData().latitude; + Response res = await HttpUtil().post('station/program/dynamic', data: data); + + var resData = res.data; + isLoadingFinish = true; + if (resData['code'] == 0) { + guid = resData['data']['guid']; + callback(resData['data']['list']); + } + } + + void getNewData() { + _page = 1; + guid = ''; + getData((data) { + list.clear(); + if (data != null) { + list.addAll(data); + } + setState(() {}); + }); + } + + @override + void dispose() { + _scrollController.dispose(); + MessageMgr().off('delete_program', msgListDelete); + MessageMgr().off('Add_program', addProgramCallback); + MessageMgr().off('love_program', msgListLove); + MessageMgr().off('refresh_list', msgRefreshList); + MessageMgr().off('join_program', msgJoinList); + super.dispose(); + } + + //发布添加回调 + addProgramCallback(data) { + if (list.length > 0 && + list[0]['UserId'] == UserData().basicInfo.userId && + list[0]['Type'] == 0) { + list.insert(1, data); + } else { + list.insert(0, data); + } + } + + getBanner() async { + Map data = { + "userid": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + Response res = await HttpUtil().post('banner/get/list', data: data); + var resData = res.data; + if (resData['code'] == 0) { + setState(() { + bannerImages = resData['data']; + }); + } + } + + @override + void initState() { + WidgetsBinding.instance.renderView.automaticSystemUiAdjustment = false; + super.initState(); + + _scrollController.addListener(() { + //print('---_scrollController offset: ${_scrollController.offset}'); + }); + + getBanner(); + + isHomePage = widget.searchType == -1; + + MessageMgr().on('delete_program', msgListDelete); + MessageMgr().on('Add_program', addProgramCallback); + MessageMgr().on('love_program', msgListLove); + MessageMgr().on('refresh_list', msgRefreshList); + MessageMgr().on('join_program', msgJoinList); + } + + msgJoinList(data) { + for (int i = 0; i < list.length; i++) { + if (list[i]['Id'] == data) { + list[i]['EnrollNum']++; + list[i]['IsEnroll']++; + setState(() {}); + break; + } + } + } + + msgRefreshList(data) { + _onRefresh(); + } + + msgListDelete(data) { + for (int i = 0; i < list.length; i++) { + if (list[i]['Id'] == data) { + list.removeAt(i); + setState(() {}); + break; + } + } + } + + msgListLove(data) { + print('msgListLove $data'); + for (int i = 0; i < list.length; i++) { + if (list[i]['Id'] == data) { + list[i]['FabulousNum']++; + list[i]['IsFabulous']++; + setState(() {}); + break; + } + } + } + + Future _getMore() async { + if (!isLoading) { + setState(() { + isLoading = true; + }); + getMoreData(); + } + } + + void getMoreData() { + _page++; + getData((data) { + data == null || data.length == 0 ? _page-- : list.addAll(data); + isLoading = false; + setState(() {}); + }); + } + + void addProgram(str) async { + if (str == 'program') { + //自己是女性,且未认证,提示去认证 + if (!UserData().isMan() && !UserData().basicInfo.isAttestation) { + CustomUI.buildNotTrue(context); + return; + } + if (!UserData().isCanProgram) { + showToast(I18n.of(context).stop_program); + } else { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return AddProgram( + isProgram: true, + ); + }, + ), + ); + } + } else if (str == 'dynamic') { + //自己是女性,且未认证,提示去认证 + if (!UserData().isMan() && !UserData().basicInfo.isAttestation) { + CustomUI.buildNotTrue(context); + return; + } + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return AddProgram( + isProgram: false, + ); + }, + ), + ); + } + } + + @override + Widget build(BuildContext context) { + initValues(); + Color btnColor = isOnline ? Constants.BlueTextColor : Colors.grey[400]; + + Widget appBar = AppBar( + //automaticallyImplyLeading: !isHomePage, + title: Text( + isHomePage + ? I18n.of(context).radio + : WebData().getProgramName(context, widget.searchType), + textScaleFactor: 1.0, + ), + leading: CustomUI.buildCustomLeading(context), + elevation: 0, + actions: [ + isHomePage + ? myPop.PopupMenuButton( + padding: EdgeInsets.zero, + offset: Offset(0, 45), + child: new Padding( + padding: + EdgeInsets.only(right: 15, left: 15, top: 20, bottom: 10), + child: CircleAvatar( + backgroundColor: Constants.GreyBackgroundColor, + radius: 13.75, + child: Icon( + IconData(0xe697, fontFamily: 'iconfont'), + color: Constants.BlackTextColor, + size: 15, + )), + ), + onSelected: (str) { + addProgram(str); + }, + itemBuilder: (BuildContext context) => + >[ + myPop.PopupMenuItem( + value: 'program', + child: Container( + margin: EdgeInsets.only(top: 15, bottom: 15), + child: Text( + I18n.of(context).release_program, + textScaleFactor: 1.0, + textAlign: TextAlign.center, + ), + )), + myPop.PopupMenuDivider( + height: 1, + ), + myPop.PopupMenuItem( + value: 'dynamic', + child: Container( + margin: EdgeInsets.only(top: 15, bottom: 15), + child: Text( + I18n.of(context).release_dynamics, + textScaleFactor: 1.0, + textAlign: TextAlign.center, + )), + ), + ], + ) + : GestureDetector( + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.only(top: 15, bottom: 10, right: 10), + child: Text(I18n.of(context).first_online, + textScaleFactor: 1.0, + style: TextStyle(color: btnColor, fontSize: 13), + textAlign: TextAlign.center), + padding: EdgeInsets.only(left: 20, right: 20), + decoration: BoxDecoration( + border: Border.all(color: btnColor, width: 1), + borderRadius: BorderRadius.all(Radius.circular(5.0))), + ), + onTap: () { + setState(() { + isOnline = !isOnline; + getNewData(); + }); + }, + ), + ], + centerTitle: true, + ); + return Scaffold( + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + )), + appBar: appBar, + ); + } + + Future _onRefresh() async { + getNewData(); + } + + //分类按钮 + Widget _buildCategoryButton() { + return Container( + padding: EdgeInsets.only(top: 10), + child: Column( + children: [ + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildIconButton(1, WebData().getProgramName(context, 0), + Constants.Category1Color, 0), + _buildIconButton(2, WebData().getProgramName(context, 1), + Constants.Category2Color, 1), + _buildIconButton(3, WebData().getProgramName(context, 2), + Constants.Category3Color, 2), + _buildIconButton(4, WebData().getProgramName(context, 3), + Constants.Category4Color, 3), + ], + ), + ), + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildIconButton(5, WebData().getProgramName(context, 4), + Constants.Category5Color, 4), + _buildIconButton(6, WebData().getProgramName(context, 5), + Constants.Category6Color, 5), + _buildIconButton(7, WebData().getProgramName(context, 6), + Constants.Category7Color, 6), + _buildIconButton(8, WebData().getProgramName(context, 7), + Constants.Category8Color, 7), + ], + ), + ), + ], + )); + } + + Widget _buildIconButton(iconNum, str, strColor, value) { + Widget icon = Container( + padding: EdgeInsets.only(left: 10, right: 10, bottom: 8), + child: Image.asset( + 'assets/images/park/qz_icon$iconNum.png', + height: 50, + )); + + Widget text = Positioned( + bottom: 0, + child: Container( + child: new Text(str, + textScaleFactor: 1.0, + style: TextStyle(color: strColor, fontSize: 11)), + )); + return InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ParkPage( + searchType: value, + ); + }, + ), + ); + }, + highlightColor: Colors.transparent, + radius: 0, + child: Container( + alignment: Alignment.center, + width: (MediaQuery.of(context).size.width) / 4, + margin: EdgeInsets.only(top: 10), + child: Stack( + alignment: Alignment.center, + children: [ + icon, + text, + ], + ), + )); + } + + Widget _buildBody() { + double height = Screen.width * 0.285 + 205; + double headerHeight = 46; + Widget header = Container( + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: Colors.grey[350]))), + padding: EdgeInsets.only(left: 5, right: 5), + child: GZXDropDownHeader( + // 下拉的头部项,目前每一项,只能自定义显示的文字、图标、图标大小修改 + items: [ + GZXDropDownHeaderItem(_dropDownHeaderItemStrings[0]), + GZXDropDownHeaderItem(_dropDownHeaderItemStrings[1]), + GZXDropDownHeaderItem(_dropDownHeaderItemStrings[2]), + ], + style: TextStyle(color: Constants.BlackTextColor, fontSize: 12), + height: headerHeight, + // GZXDropDownHeader对应第一父级Stack的key + stackKey: _stackKey, + // controller用于控制menu的显示或隐藏 + controller: _dropdownMenuController, + // 当点击头部项的事件,在这里可以进行页面跳转或openEndDrawer + onItemTap: (index) { + var nums = height - headerHeight; + if (_scrollController.offset < nums) { + _scrollController.jumpTo(nums); + } + }, + dividerHeight: 0, + borderColor: Colors.white, + borderWidth: 0, + dropDownStyle: + TextStyle(color: const Color(0xFF0368FF), fontSize: 12), + )); + + GZXDropDownMenu menu = GZXDropDownMenu( + // controller用于控制menu的显示或隐藏 + controller: _dropdownMenuController, + // 下拉菜单显示或隐藏动画时长 + animationMilliseconds: 150, + // 下拉菜单,高度自定义,你想显示什么就显示什么,完全由你决定,你只需要在选择后调用_dropdownMenuController.hide();即可 + menus: [ + GZXDropdownMenuBuilder( + dropDownHeight: 50.0 * _timeSortConditions.length, + callback: () { + setState(() {}); + }, + dropDownWidget: + _buildConditionListWidget(_timeSortConditions, (value) { + _selectTimeSortCondition = value; + _dropDownHeaderItemStrings[0] = _selectTimeSortCondition.name; + _dropdownMenuController.hide(); + isLoadingFinish = false; + getNewData(); + setState(() {}); + })), + GZXDropdownMenuBuilder( + dropDownHeight: 50.0 * _sexSortCondition.length, + callback: () { + setState(() {}); + }, + dropDownWidget: + _buildConditionListWidget(_sexSortCondition, (value) { + _selectSexSortCondition = value; + _dropDownHeaderItemStrings[1] = _selectSexSortCondition.name; + _dropdownMenuController.hide(); + isLoadingFinish = false; + getNewData(); + setState(() {}); + })), + GZXDropdownMenuBuilder( + dropDownHeight: 50 * 8.0, + callback: () { + setState(() {}); + }, + dropDownWidget: _buildAddressWidget((key, value) { + search = key; + _dropDownHeaderItemStrings[2] = value; + _dropdownMenuController.hide(); + isLoadingFinish = false; + getNewData(); + setState(() {}); + })), + ], + ); + + var v = Column( + children: [ + _buildSwiperImageWidget(), + _buildCategoryButton(), + ], + ); + + var body = myExt.NestedScrollView( + key: _key, + controller: _scrollController, + pinnedHeaderSliverHeightBuilder: () { + return headerHeight; + }, + innerScrollPositionKeyBuilder: () { + var index = "Tab"; + +// index += primaryTC.index.toString(); + + return Key(index); + }, + headerSliverBuilder: (BuildContext context, bool boxIsScrolled) { + return [ + SliverAppBar( + pinned: true, + automaticallyImplyLeading: false, + floating: true, + elevation: 0, + snap: false, + forceElevated: boxIsScrolled, + flexibleSpace: FlexibleSpaceBar( + collapseMode: CollapseMode.pin, + background: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [v], + ), + ), + expandedHeight: (Screen.width * 0.285 + 205), + bottom: PreferredSize( + preferredSize: Size(double.infinity, headerHeight + 1), + child: Stack( + key: _stackKey, + children: [ + header, + ], + ), + ), + ) + ]; + }, + body: Center( + child: Container( + color: Constants.GreyBackgroundColor, + child: NotificationListener( + onNotification: (scrollNotification) { + final maxScroll = scrollNotification.metrics.maxScrollExtent; + final currentScroll = scrollNotification.metrics.pixels; + if (maxScroll == currentScroll) { + _getMore(); + } + return; + }, + child: ListView.builder( + physics: ClampingScrollPhysics(), + itemBuilder: _renderRowNear, + itemCount: list.length + 1, + ), + )), + ), + ); + + var newBody = myExt.NestedScrollViewRefreshIndicator( + onRefresh: _onRefresh, + child: body, + ); + + var body1 = Stack( + key: _stackKey, + children: [ + Container( + margin: EdgeInsets.only(top: headerHeight), + child: RefreshIndicator( + onRefresh: _onRefresh, + child: NotificationListener( + onNotification: (scrollNotification) { + final maxScroll = scrollNotification.metrics.maxScrollExtent; + final currentScroll = scrollNotification.metrics.pixels; + if (maxScroll == currentScroll) { + _getMore(); + } + return; + }, + child: ListView.builder( + itemBuilder: _renderRowNear, + itemCount: list.length + 1, + ), + ), + )), + Container( + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: Colors.grey[300])), + color: Colors.white, + ), + child: header, + ), + ], + ); + return Stack( + children: [ + isHomePage ? newBody : body1, + menu, + isLoadingFinish ? Container() : CustomUI.buildLoaingAnim(context) + ], + ); + } + + Widget _renderRowNear(BuildContext context, int index) { + if ((list == null || list.length == 0) && isLoadingFinish) { + return CustomUI.buildNoData(context); + //return CustomUI.buildNoData(context); + } + if (index < list.length) { + var userInfo = list[index]; + return MessageBox(programInfo: userInfo); + } + if (list.length > rows * _page) return _getMoreWidget(); + + return Container(); + } + + Widget _getMoreWidget() { + return Center( + child: Padding( + padding: EdgeInsets.all(10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + '', + style: TextStyle(fontSize: 16.0), + ), + CircularProgressIndicator( + strokeWidth: 1.0, + valueColor: AlwaysStoppedAnimation(Constants.BlueTextColor)) + ], + ), + ), + ); + } + + //轮播图 + Widget _buildSwiperImageWidget() { + double width = MediaQuery.of(context).size.width * 0.95; + return Container( + height: width * 0.3, + width: width, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(50.0), + ), + child: (bannerImages == null || bannerImages.length == 0) + ? Container() + : Swiper( + // 初始的时候下标位置 + index: 0, + + /// 无限轮播模式开关 + loop: true, + itemBuilder: (context, index) { + return GestureDetector( + onTap: () async { + var url = bannerImages[index]['Url']; + if (await canLaunch(url)) { + await launch(url); + } else { + throw 'Could not launch $url'; + } + }, + child: Container( + child: ClipPath( + child: Stack(children: [ + Container( + width: double.infinity, + child: ClipRRect( + borderRadius: BorderRadius.circular(10.0), + child: CachedNetworkImage( + fadeOutDuration: const Duration(milliseconds: 300), + fadeInDuration: const Duration(milliseconds: 700), + fit: BoxFit.fill, + imageUrl: bannerImages[index]['ImgUrl'], + placeholder: CustomUI.buildImgLoding, + errorWidget: (context, url, error) => + new Icon(Icons.error), + ), + ), + ), + ]), + )), + ); + }, + itemCount: bannerImages.length, + + /// 设置 new SwiperPagination() 展示默认分页指示器 + pagination: SwiperPagination(alignment: Alignment.bottomRight), + + /// 设置 new SwiperControl() 展示默认分页按钮 + // control: SwiperControl(), + /// 自动播放开关. + autoplay: true, + + /// 动画时间,单位是毫秒 + duration: 300, + + /// 当用户点击某个轮播的时候调用 + onTap: (index) {}, + + /// 滚动方向,设置为Axis.vertical如果需要垂直滚动 + scrollDirection: Axis.horizontal, + ), + ); + } + + var _selectTempFirstLevelIndex = '1'; + var _selectFirstLevelIndex = '1'; + + var _selectSecondLevelIndex = '-1'; + + _buildAddressWidget(void itemOnTap(String key, String value)) { + List firstLevels = []; + if (WebData().provinces.length > 0) { + if (UserData().isInChina) { + firstLevels + .add({'key': 'China', 'value': WebData().provinces['China']}); + } else { + firstLevels + .add({'key': 'VietNam', 'value': WebData().provinces['VietNam']}); + } + } + + List secondLevels = []; + if (WebData().cities.length > 0) { + if (UserData().isInChina) { + secondLevels.add( + {'key': ChinaKey, 'value': WebData().provinces['China']}); + } else { + secondLevels + .add({'key': '1', 'value': I18n.of(context).unlimited_area}); + WebData() + .cities['VietNam'] + .forEach((k, v) => secondLevels.add({'key': 'VietNam-$k', 'value': v})); + } + } + + _selectTempFirstLevelIndex = firstLevels[0]['key']; + _selectFirstLevelIndex = firstLevels[0]['key']; + _selectSecondLevelIndex = secondLevels[0]['key']; + Widget buildRow(item) { + var index = item['key']; + return GestureDetector( + onTap: () { + _selectSecondLevelIndex = index; + _selectFirstLevelIndex = _selectTempFirstLevelIndex; + itemOnTap(index, item['value']); + }, + child: Container( + height: 50, + decoration: BoxDecoration( + border: Border(top: Constants.GreyBorderSide), + ), + alignment: Alignment.center, + child: Text( + item['value'], + textScaleFactor: 1.0, + style: TextStyle( + color: _selectFirstLevelIndex == _selectTempFirstLevelIndex && + _selectSecondLevelIndex == index + ? const Color(0xFF0368FF) + : Constants.BlackTextColor, + ), + )), + ); + } + + return Container( + child: Row( + children: [ + Container( + width: MediaQuery.of(context).size.width * 0.4, + child: ListView( + children: firstLevels.map((item) { + var index = item['key']; + return GestureDetector( + onTap: () { + _selectTempFirstLevelIndex = index; + + if (index == 'China') { + itemOnTap(ChinaKey, item['value']); + return; + } + setState(() {}); + }, + child: Container( + height: 50, + decoration: BoxDecoration( + color: _selectTempFirstLevelIndex == index + ? const Color(0xFF0368FF) + : Colors.white, + border: Border(top: Constants.GreyBorderSide), + ), + alignment: Alignment.center, + child: Text( + item['value'], + textScaleFactor: 1.0, + style: TextStyle( + color: _selectTempFirstLevelIndex == index + ? Colors.white + : Constants.BlackTextColor, + ), + ))); + }).toList(), + ), + ), + Expanded( + child: Container( + width: double.infinity, + decoration: + BoxDecoration(border: Border(left: Constants.GreyBorderSide)), + child: ListView( + children: secondLevels.map((item) { + return buildRow(item); + }).toList(), + ), + ), + ) + ], + )); + } + + _buildConditionListWidget(items, void itemOnTap(sortCondition)) { + return ListView.separated( + shrinkWrap: true, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + itemCount: items.length, + // item 的个数 + separatorBuilder: (BuildContext context, int index) => + Divider(height: 1.0), + // 添加分割线 + itemBuilder: (BuildContext context, int index) { + SortCondition goodsSortCondition = items[index]; + return InkWell( + onTap: () { + for (var value in items) { + value.isSelected = false; + } + goodsSortCondition.isSelected = true; + + itemOnTap(goodsSortCondition); + }, + child: Container( + height: 50, + width: double.infinity, + alignment: Alignment.center, + child: Text( + goodsSortCondition.name, + textScaleFactor: 1.0, + style: TextStyle( + color: goodsSortCondition.isSelected + ? const Color(0xFF0368FF) + : Constants.BlackTextColor, + ), + )), + ); + }, + ); + } +} diff --git a/lib/home/PravicySettingPage.dart b/lib/home/PravicySettingPage.dart new file mode 100644 index 0000000..019c083 --- /dev/null +++ b/lib/home/PravicySettingPage.dart @@ -0,0 +1,414 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/FullWithButton.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import 'package:oktoast/oktoast.dart'; +import '../data/UserData.dart'; +import '../utils/TokenMgr.dart'; +import 'WhiteAndBlackList.dart'; + +enum userDetail { + open, + pay, + apply, +} + +class PravicySettingPage extends StatefulWidget { + PravicySettingPage({Key key}) : super(key: key); + + _PravicySettingPageState createState() => _PravicySettingPageState(); +} + +class _PravicySettingPageState extends State { + int _socialType = 0; + bool parkHidden = false; + bool distanceHidden = false; + bool msgHidden = false; + bool strangerHidden = false; + String money; + bool isLoadingFish = false; + setUserDetailData(type, statu, mon, callback) async { + var data = { + "userid": UserData().basicInfo.userId, + "type": type, + "statu": statu, + }; + data['sign'] = TokenMgr().getSign(data); + data["price"] = mon; + try { + Response res = + await HttpUtil().post('user/setting/userprivacy', data: data); + Map resData = res.data; + if (resData['code'] == 0) { + callback(); + } else { + showToast(resData['msg']); + } + } catch (e) {} + } + + @override + void initState() { + super.initState(); + + print('PravicySettingPage initState'); + + getSettingInfo(); + } + + void getSettingInfo() async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + Response res = await HttpUtil().post('user/get/privacy', + data: data, failback: () => Navigator.of(context).pop()); + Map resData = res.data; + print(resData); + if (resData['code'] == 0 && resData['data'] != null) { + _socialType = resData['data']['Details']; + parkHidden = resData['data']['Invisible'] == 1; + distanceHidden = resData['data']['Distance'] == 1; + msgHidden = resData['data']['Chat'] == 1; + strangerHidden = resData['data']['StrangerNews'] == 1; + Future.delayed(Duration(milliseconds: Constants.CloseLoaindTime), () { + isLoadingFish = true; + setState(() {}); + }); + setState(() {}); + } + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + I18n.of(context).setting, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ); + + Widget content = Scaffold( + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + )), + appBar: appBar, + ); + return CustomUI.buildPageLoading(context, content, !isLoadingFish); + } + + Widget _buildBody() { + return new ListView( + children: [ + _userDetail(), + _buildSwitchButtom( + I18n.of(context).hide_me, I18n.of(context).hide_me, parkHidden, () { + setUserDetailData(4, !parkHidden ? 1 : 0, 0, () { + setState(() { + parkHidden = !parkHidden; + }); + }); + }), + _buildSwitchButtom(I18n.of(context).hide_distance, + I18n.of(context).hide_distance, distanceHidden, () { + setUserDetailData(5, !distanceHidden ? 1 : 0, 0, () { + setState(() { + distanceHidden = !distanceHidden; + }); + }); + }), + _buildSwitchButtom( + I18n.of(context).chat_setting, I18n.of(context).chat_me, msgHidden, + () { + setUserDetailData(7, !msgHidden ? 1 : 0, 0, () { + setState(() { + msgHidden = !msgHidden; + }); + }); + }), + _buildSwitchButtom(I18n.of(context).stranger, + I18n.of(context).receive_stranger, strangerHidden, () { + setUserDetailData(8, !strangerHidden ? 1 : 0, 0, () { + setState(() { + strangerHidden = !strangerHidden; + }); + }); + }), + _buildBlackList(), + ], + ); + } + + Widget _buildBlackList() { + //版本 + return Container( + margin: EdgeInsets.only(top: 20, bottom: 20), + padding: EdgeInsets.symmetric(horizontal: 5), + child: FullWidthButton( + showRightIcon: true, + title: I18n.of(context).blacklist2, + showDivider: false, + onPressed: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return WhiteAndBlackPage( + isWhite: false, + ); + }, + ), + ); + }, + ), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, bottom: Constants.GreyBorderSide)), + ); + } + + //下划线 + Widget _buildDivider() { + return new Container( + margin: EdgeInsets.zero, + padding: EdgeInsets.zero, + decoration: + BoxDecoration(border: Border(bottom: Constants.GreyBorderSide)), + height: 1, + width: MediaQuery.of(context).size.width, + ); + } + + Widget _buildRadioButtom(str, radio, callback) { + Widget left = new Text( + str, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 13, color: Constants.BlackTextColor), + ); + Widget right = new Expanded( + child: new Align( + alignment: Alignment.centerRight, + child: radio, + )); + return InkWell( + onTap: () { + callback(); + }, + child: Container( + padding: EdgeInsets.only(left: 15), + child: new Row( + children: [left, right], + ), + ), + ); + } + + //个人详情 + Widget _userDetail() { + Widget tip = CustomUI.buildTopTip(15, I18n.of(context).personal_details); + openCallback() { + setUserDetailData(1, 1, 0, () { + setState(() { + _socialType = userDetail.open.index; + }); + }); + } + + payCallback() { + if (UserData().picNum == 0) { + showToast(UserData().haveReview + ? I18n.of(context).have_picture_view + : I18n.of(context).first_upload); + return; + } + + var callback = () { + Navigator.of(context).pop(); + int minMoney = 10; + var confirm = + CustomUI.buildConfirmBotton(I18n.of(context).determine, () { + if (money == null || money == "" || int.parse(money) < minMoney) { + showToast(I18n.of(context) + .little_min + .replaceFirst('/s1', minMoney.toString())); + return; + } + + setUserDetailData(2, 1, money, () { + Navigator.of(context).pop(); + money = ''; + setState(() { + _socialType = userDetail.pay.index; + }); + }); + }); + var tip = Column( + children: [ + Container( + margin: EdgeInsets.only(top: 20), + child: Text( + I18n.of(context).set_amount1, + style: TextStyle(color: Constants.BlackTextColor, fontSize: 16), + ), + ), + Container( + margin: EdgeInsets.only(top: 23, bottom: 25), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.all(Radius.circular(8))), + child: TextField( + keyboardAppearance: Brightness.light, + textAlign: TextAlign.center, + textInputAction: TextInputAction.search, + style: TextStyle( + textBaseline: TextBaseline.alphabetic, fontSize: 14), + decoration: InputDecoration( + hintText: I18n.of(context).enter_amount, + filled: true, + contentPadding: EdgeInsets.only(top: 10, bottom: 10), + fillColor: Colors.transparent, + border: InputBorder.none, + ), + keyboardType: TextInputType.phone, + maxLines: 1, + inputFormatters: [ + WhitelistingTextInputFormatter(RegExp("^([1-9][0-9]*)\$")), + WhitelistingTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(3) + ], + onChanged: (str) { + money = str; + }, + ), + ) + ], + ); + // var tip = Container( + // margin: EdgeInsets.only(top: 20, bottom: 10), + // child: TextField( + // textAlign: TextAlign.center, + // style: TextStyle( + // textBaseline: TextBaseline.alphabetic, fontSize: 14), + // decoration: InputDecoration( + // hintText: I18n.of(context).enter_amount, + // hintStyle: TextStyle(fontSize: 14), + // contentPadding: EdgeInsets.all(10.0), + // border: OutlineInputBorder( + // borderRadius: BorderRadius.circular(5.0), + // ), + // ), + // keyboardType: TextInputType.phone, + // maxLines: 1, + // inputFormatters: [ + // WhitelistingTextInputFormatter(RegExp("^([1-9][0-9]*)\$")), + // WhitelistingTextInputFormatter.digitsOnly, + // LengthLimitingTextInputFormatter(3) + // ], + // onChanged: (str) { + // money = str; + // }, + // )); + var content = CustomUI.buildConfirmContent(tip, confirm); + CustomUI.buildTip(context, '', content); + }; + CustomUI.buildOneConfirm(context, I18n.of(context).must_pay, + I18n.of(context).determine, callback); + } + + applyCallback() { + var callback = () { + setUserDetailData(3, 1, 0, () { + Navigator.of(context).pop(); + setState(() { + _socialType = userDetail.apply.index; + }); + }); + }; + CustomUI.buildOneConfirm(context, I18n.of(context).permission_choose, + I18n.of(context).determine, callback); + } + + Widget radio1 = new Radio( + value: userDetail.open.index, + groupValue: _socialType, //当value和groupValue一致的时候则选中 + onChanged: (T) { + openCallback(); + }); + Widget radio2 = new Radio( + value: userDetail.pay.index, + groupValue: _socialType, //当value和groupValue一致的时候则选中 + onChanged: (T) { + payCallback(); + }); + Widget radio3 = new Radio( + value: userDetail.apply.index, + groupValue: _socialType, //当value和groupValue一致的时候则选中 + onChanged: (T) { + applyCallback(); + }); + + List basicList = [ + _buildRadioButtom(I18n.of(context).public, radio1, openCallback), + _buildDivider(), + _buildRadioButtom(I18n.of(context).paid_album, radio2, payCallback), + _buildDivider(), + _buildRadioButtom( + I18n.of(context).need_permission, radio3, applyCallback), + ]; + var socialCard = new Container( + color: Colors.white, + child: new Column( + children: basicList, + ), + ); + return new Column( + children: [tip, socialCard], + ); + } + + Widget _buildSwitchButtom(title, str, value, callback) { + Widget tip = CustomUI.buildTopTip(15, title); + Widget left = Expanded( + child: Text( + str, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 13, color: Constants.BlackTextColor), + )); + Widget right = Container( + child: new Align( + alignment: Alignment.centerRight, + child: new Switch( + value: value, + activeTrackColor: Constants.ConfrimButtonColor.withOpacity(0.3), + onChanged: (bool val) { + callback(); + }, + ))); + var socialCard = new Container( + color: Colors.white, + padding: EdgeInsets.only(left: 15), + height: 53, + child: new Row( + children: [left, right], + ), + ); + return new Column( + children: [tip, socialCard], + ); + } +} diff --git a/lib/home/ProfilePage.dart b/lib/home/ProfilePage.dart new file mode 100644 index 0000000..a4a805e --- /dev/null +++ b/lib/home/ProfilePage.dart @@ -0,0 +1,2682 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:chat/home/InfoList.dart'; +import 'package:chat/home/fans_page.dart'; +import 'package:chat/home/goddess_hot.dart'; +import 'package:chat/home/rich_title.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/models/voucher_change.dart'; +import 'package:chat/photo/entity/options.dart'; +import 'package:chat/photo/photo.dart'; +import 'package:chat/utils/ChargeMoney.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/blacklist_mgr.dart'; +import 'package:chat/utils/conversation_table.dart'; +import 'package:chat/utils/friend_list_mgr.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sp_utils.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/InformUser.dart'; +import 'package:chat/home/MoneyPage.dart'; +import 'package:chat/home/Myprogram.dart'; +import 'package:chat/home/VideoPage.dart'; +import 'package:chat/home/VipPage.dart'; +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TutorialOverlay.dart'; +import 'package:chat/utils/UserCard.dart'; +import 'package:chat/utils/UserChips.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/services.dart'; +import 'package:image_cropper/image_cropper.dart'; + +import 'package:image_picker/image_picker.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:photo_manager/photo_manager.dart'; +import 'package:provider/provider.dart'; +import 'package:share/share.dart'; +import '../utils/FullWithButton.dart'; +import '../home/EditData.dart'; +import '../home/SystemEditPage.dart'; +import '../data/UserData.dart'; +import '../utils/TokenMgr.dart'; +import 'package:dio/dio.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'VerificationCenter.dart'; +import 'WhiteAndBlackList.dart'; +import "package:chat/utils/PicSwiper.dart"; + +import 'add_friend.dart'; +import 'apply_content_view.dart'; +import 'daily_bonus_page.dart'; +import 'money_picture_view.dart'; + +var cardWidth; + +var greyColor = const Color(0xFFB2B2B2); + +class ProfilePage extends StatefulWidget { + @required + final userId; + final int fromWhere; + final int addMode; + final int applyId; //好友申请id + + ProfilePage( + {Key key, + this.userId, + this.fromWhere, + this.addMode = 0, + this.applyId = 0}) + : super(key: key); + + _ProfilePageState createState() => _ProfilePageState(); +} + +class _ProfilePageState extends State + with TickerProviderStateMixin { + static const Separate_Size = 10.0; + GlobalKey registKey = new GlobalKey(); + UserInfo userInfo = new UserInfo(); + + TextEditingController nickNameController = new TextEditingController(); + + // AnimationController animationController; + // Animation movement; + + bool isMyself = false; + + List imgList = []; + + bool isCanWatch = false; + + bool isMan = true; + bool isAttestation = false; + + bool isBuyPicture = false; + + bool isVip = false; + + bool isSvip = false; + + bool isApplying = false; //是否申请中 + + //约会节目 + String dateItem = ''; + +//期待对象 + String lovePeople = ''; + +//约会范围 + String dateRange = ''; + +//生日 + String birthday = ''; + +//身高数据 + String heightStr = ''; + +//体重数据 + String weightStr = ''; + + //个人介绍 + String myMsg = ''; + + Map wealthData = { + 'CoinValue': 0, + 'IsMember': 0, + }; + + int myselfImg = 0; + + String endTime = ''; + + bool isLoadingFish = false; + + String firstDyImg = ''; //第一条动态的图片 + + int programId = 0; //是否有一条活跃的节目 + + bool isblack = false; + + bool isAuthority = false; //是否有聊天和查看用户资料的权限 + + getUserInfo({mymsg = ''}) async { + if (mymsg != '' && mymsg != null) { + UserData().basicInfo.ownMsg = mymsg; + } + HttpUtil().getUserInfo( + widget.userId, + (data) async { + print('getUserInfo $data'); + if (isMyself) { + saveLocalData(data); + } + userInfo = UserInfo.fromJson(data); + initValues(); + isLoadingFish = true; + showMyMsgDialog(); + if (mounted) { + setState(() {}); + } + }, + _buildJoinVip, + () { + if (!isMyself) { + Future.delayed(Duration(milliseconds: 500), () { + Navigator.of(context).pop(); + }); + } + }); + getImg(); + if (isMyself) { + HttpUtil().getWealth(context, (data) { + wealthData = data; + endTime = data['MemberEnd']; + if (mounted) { + Provider.of(context) + .initMoney(data['CoinValue']); + Provider.of(context) + .initVoucher(data['Voucher']); + } + }); + } else { + // getFirstDy(); + // getFirstProgram(); + } + } + + saveLocalData(data) { + UserData().basicInfo = UserInfo.fromJson(data); + SPUtils.saveString( + Constants.LocalUsrInfo, jsonEncode(UserData().toJson()).toString()); + } + + initLocalData() async { + if (isMyself && await SPUtils.get(Constants.LocalUsrInfo) != null) { + isLoadingFish = true; + userInfo = UserData().basicInfo; + initValues(); + showMyMsgDialog(); + } + } + + showMyMsgDialog() { + if (!UserData().isFirstTip && + (UserData().basicInfo.ownMsg == '' || + UserData().basicInfo.ownMsg == null) && + UserData().homemainIndex == 4) { + UserData().isFirstTip = true; + + CustomUI.buildOneConfirm( + context, I18n.of(context).personal, I18n.of(context).white_now, () { + Navigator.pop(context); + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return EditPage( + isEditPage: true, + ); + }, + ), + ); + }); + } + } + + initValues() { + isMan = userInfo.sex == 1; + isAttestation = userInfo.isAttestation == null || userInfo.isAttestation; + isVip = userInfo.isMember > 0; + isSvip = userInfo.isMember == 2; + isCanWatch = userInfo.infoAut == 0 || userInfo.applyStatus == 1; + isApplying = userInfo.applyStatus == 0; + isblack = userInfo.isBlackList; + isBuyPicture = + (isMyself || userInfo.photoAut == 0 || userInfo.payStatus == 1); + + dateItem = + userInfo.program == null ? "" : WebData().getProgram(userInfo.program); + + lovePeople = userInfo.hopeObject == null + ? "" + : WebData().getLovePeople(userInfo.hopeObject); + + dateRange = WebData().getDateRange(userInfo.meetPlace); + + birthday = userInfo.birthday == null ? '' : userInfo.birthday; + isAuthority = userInfo.isAuthority || + (!UserData().isMan() && UserData().basicInfo.isAttestation) || + userInfo.distince < 200; + myMsg = userInfo.ownMsg; + } + + // getFirstDy() async { + // var data = { + // "userId": UserData().basicInfo.userId, + // "visitUserId": widget.userId, + // "type": 2, + // }; + // data['sign'] = TokenMgr().getSign(data); + // data['page'] = 1; + // data['rows'] = 1; + // Response res = await HttpUtil().post('station/gain/program', data: data); + // var resData = res.data; + // if (resData['code'] == 0 && resData['data'] != null) { + // var imgUrl = resData['data'][0]['ImgUrl']; + // if (imgUrl != '') { + // firstDyImg = imgUrl.split('|')[0]; + // if (mounted) { + // setState(() {}); + // } + // } + // } + // } + + // getFirstProgram() async { + // var data = { + // "userId": UserData().basicInfo.userId, + // "visitUserId": widget.userId, + // //"type": 1, + // }; + // data['sign'] = TokenMgr().getSign(data); + // data['page'] = 1; + // data['rows'] = 1; + // Response res = await HttpUtil().post('station/gain/program', data: data); + // var resData = res.data; + // if (resData['code'] == 0 && + // resData['data'] != null && + // resData['data'][0]['Status'] == 0) { + // if (mounted) { + // setState(() { + // programId = resData['data'][0]['Id']; + // }); + // } + // } + // } + + @override + void initState() { + super.initState(); + + print('ProfilePage initState'); + + isMyself = widget.userId == UserData().basicInfo.userId; + messageOn(); + initLocalData(); + getUserInfo(); + initAnimation(); + } + + initAnimation() { + // animationController = AnimationController( + // duration: Duration(milliseconds: 600), + // vsync: this, + // ); + // movement = + // Tween(begin: EdgeInsets.only(right: 0), end: EdgeInsets.only(right: 10)) + // .animate(animationController) + // ..addListener(() { + // setState(() {}); + // }); + // animationController.repeat(); + } + + void initMyController() {} + + void _buildJoinVip() { + isLoadingFish = true; + CustomUI.buildOneConfirm( + context, I18n.of(context).only_see, I18n.of(context).joinvip, () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return VipPage(); + }, + ), + ); + }, failcallbak: () { + Navigator.of(context).pop(); + }); + } + + msgBuyVip(data) { + HttpUtil().getWealth(context, (data) { + wealthData = data; + endTime = data['MemberEnd']; + if (mounted) { + Provider.of(context).initMoney(data['CoinValue']); + } + }); + } + + msgRefreshPhoto(data) { + getImg(); + } + + msgUpdateData(data) { + print('msgUpdateData $data'); + getUserInfo(mymsg: data); + } + + msgInformSucess(data) { + if (!isMyself) + CustomUI.buildOneConfirm( + context, I18n.of(context).waiting_results, I18n.of(context).ok, () { + Navigator.of(context).pop(); + }); + } + + msgListDelete(data) { + if (userInfo.dynamicNum > 0) { + if (mounted) { + setState(() { + userInfo.dynamicNum--; + }); + } + } + } + + void messageOn() { + MessageMgr().on('inform_sucess', msgInformSucess); + MessageMgr().on('refresh_money', msgBuyVip); + MessageMgr().on('refresh_photo', msgRefreshPhoto); + MessageMgr().on('update_data', msgUpdateData); + MessageMgr().on('delete_program', msgListDelete); + MessageMgr().on('post_add_friend', msgAddFriend); + MessageMgr().on('refresh_love_list', msgRefreshLoveList); + MessageMgr().on('refresh_fans_num', msgRefreshFansNum); + } + + void messageOff() { + MessageMgr().off('inform_sucess', msgInformSucess); + MessageMgr().off('refresh_money', msgBuyVip); + MessageMgr().off('refresh_photo', msgRefreshPhoto); + MessageMgr().off('update_data', msgUpdateData); + MessageMgr().off('delete_program', msgListDelete); + MessageMgr().off('post_add_friend', msgAddFriend); + MessageMgr().off('refresh_love_list', msgRefreshLoveList); + MessageMgr().off('refresh_fans_num', msgRefreshFansNum); + } + + msgRefreshFansNum(data) { + setState(() { + if (data['UserId'] == userInfo.userId && userInfo.fans < data['nums']) { + userInfo.fans = data['nums']; + } + }); + } + + msgRefreshLoveList(data) { + setState(() { + if (data['flag'] == 0) { + isMyself ? userInfo.followNum++ : userInfo.fans++; + } else { + isMyself ? userInfo.followNum-- : userInfo.fans--; + } + }); + } + + msgAddFriend(data) { + setState(() { + userInfo.isAddFriends = 0; + }); + } + + @override + void dispose() { + messageOff(); + registKey = null; + //animationController?.dispose(); + nickNameController.dispose(); + super.dispose(); + } + + void getImg() async { + var data = { + "visitUserId": UserData().basicInfo.userId, + "userId": widget.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('user/personal/album', data: data); + Map resData = res.data; + if (resData['code'] == 0) { + imgList = resData['data'] == null ? [] : resData['data']; + if (isMyself) { + UserData().picNum = 0; + for (int i = 0; i < imgList.length; i++) { + if (imgList[i]['Status'] == 1) { + UserData().picNum++; + } + if (imgList[i]['Status'] == 0 || imgList[i]['Status'] == 2) { + UserData().haveReview = true; + } + } + } + if (mounted) { + setState(() {}); + } + } + } + +//上传相册 + void _uploadPhoto() async { + // if (await CustomUI.showPhotoPermissionSetting(context)) { + // var tempFile = await ImagePicker.pickImage(source: ImageSource.gallery); + // if (tempFile != null) { + // //选择焚烧 + // Navigator.of(context).push( + // new MaterialPageRoute( + // builder: (context) { + // return UploadPicture( + // img: tempFile, + // ); + // }, + // ), + // ); + // } + // } + var photos = await PhotoPicker.pickAsset( + context: context, + themeColor: Color(0xFFF0F0F0), + textColor: Color(0xFF3F3F3F), + pickType: PickType.onlyImage); + + if (photos != null && photos.length > 0) { + List fileList = []; + for (var i = 0; i < photos.length; i++) { + AssetEntity photoEntity = photos[i]; + fileList.add(await photoEntity.file); + } + Map data = {"type": 2, "userId": UserData().basicInfo.userId}; + data['sign'] = TokenMgr().getSign(data); + data['sex'] = UserData().basicInfo.sex; + data['isBurn'] = 0; + Response res = await HttpUtil().uploadFiles( + fileList, data, 'upload/post/postfiles', 'image', + isShowLoading: true); + var resData = res.data; + + if (resData['code'] == 0) { + if (resData['data']['msg'] != '' && resData['data']['msg'] != null) { + showToast(resData['data']['msg']); + } + resData['Type'] = 0; + MessageMgr().emit('refresh_photo'); + } + } + } + + void _sendPicture() async { + if (await CustomUI.showPhotoPermissionSetting(context)) { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return LoadingDialog( + text: "", + ); + }); + var tempFile = await ImagePicker.pickImage(source: ImageSource.gallery); + Navigator.of(context).pop(); + if (tempFile != null) { + _cropPicture(tempFile); + } + } + } + + void _cropPicture(tempFile) async { + File croppedFile = await ImageCropper.cropImage( + sourcePath: tempFile.path, + aspectRatio: CropAspectRatio(ratioX: 1, ratioY: 1), + ); + + if (croppedFile != null) { + Map data = {"type": 1, "userId": userInfo.userId}; + data['sign'] = TokenMgr().getSign(data); + Response res = await HttpUtil() + .uploadFile(croppedFile, data, 'upload/file/postflie', 'image'); + var resData = res.data; + if (resData['code'] == 0) { + userInfo.headimgurl = resData['msg']; + + if (mounted) { + setState(() {}); + } + } + } + } + + Widget _buildHeadView() { + cardWidth = MediaQuery.of(context).size.width; + + Color buttonColor = Colors.grey; + return Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border(bottom: Constants.GreyBorderSide)), + child: Stack( + children: [ + Container( + decoration: BoxDecoration( + color: Colors.white, + ), + width: MediaQuery.of(context).size.width, + padding: EdgeInsets.only(top: 20), + child: Column( + children: [ + _buildHeadImg(), + _buildUserName(), + _buildUserChips(), + _buildResientCity(), + //_buildProgram(), + _buildAttestation(), + _buildFans(), + ], + ), + ), + _buildLoveButton(buttonColor), + ], + )); + } + + //认证相关 + Widget _buildAttestation() { + return Container( + margin: EdgeInsets.only(top: 7, bottom: 7), + alignment: Alignment.center, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + isAttestation + ? Icon(Icons.check_circle_outline, + size: 12, color: Constants.BlueTextColor) + : Padding( + padding: EdgeInsets.only(bottom: 0.5), + child: Icon(IconData(0xe63a, fontFamily: 'iconfont'), + size: 16, color: const Color(0xFFA9A9A9))), + SizedBox(width: 3), + Text( + isAttestation + ? isMyself + ? (isMan + ? (userInfo.isVipAttestation + ? I18n.of(context).by_paying + : I18n.of(context).incode_passed) + : I18n.of(context).certified) + : (isMan + ? (userInfo.isVipAttestation + ? I18n.of(context).pay_join + : I18n.of(context).passed_review) + : I18n.of(context).passed_video) + : isMyself + ? I18n.of(context).not_certified + : (isMan ? '' : I18n.of(context).not_video), + textScaleFactor: 1.0, + style: TextStyle(fontSize: 11, color: Constants.GreyTextColor)) + ], + )); + // return Stack( + // children: [ + // Container( + // margin: EdgeInsets.only(top: 3), + // alignment: Alignment.center, + // child: Row( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // isAttestation + // ? Icon(Icons.check_circle_outline, + // size: 12, color: Constants.BlueTextColor) + // : Padding( + // padding: EdgeInsets.only(bottom: 0.5), + // child: Icon(IconData(0xe63a, fontFamily: 'iconfont'), + // size: 16, color: const Color(0xFFA9A9A9))), + // SizedBox(width: 3), + // Text( + // isAttestation + // ? isMyself + // ? (isMan + // ? (userInfo.isVipAttestation + // ? I18n.of(context).by_paying + // : I18n.of(context).incode_passed) + // : I18n.of(context).certified) + // : (isMan + // ? (userInfo.isVipAttestation + // ? I18n.of(context).pay_join + // : I18n.of(context).passed_review) + // : I18n.of(context).passed_video) + // : isMyself + // ? I18n.of(context).not_certified + // : (isMan ? '' : I18n.of(context).not_video), + // textScaleFactor: 1.0, + // style: + // TextStyle(fontSize: 11, color: Constants.GreyTextColor)) + // ], + // )), + // !isMan && isAttestation + // ? Container( + // padding: EdgeInsets.only(top: 17), + // alignment: Alignment.centerRight, + // child: InkWell( + // onTap: () { + // Navigator.of(context).push( + // new MaterialPageRoute( + // builder: (context) { + // return VideoPage( + // userId: userInfo.userId, + // ); + // }, + // ), + // ); + // }, + // child: Padding( + // padding: EdgeInsets.only(right: 17), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.end, + // children: [ + // Text('${I18n.of(context).certified_video}', + // textScaleFactor: 1.0, + // style: TextStyle( + // fontSize: 11, color: Colors.grey)), + // Icon( + // IconData(0xe63c, fontFamily: 'iconfont'), + // size: 18.0, + // color: Color(AppColors.TabIconNormal), + // ), + // ], + // )))) + // : Container(), + // ], + // ); + } + + Widget _buildFansButton(int nums, String text, callback, + {bool isShowDot = false}) { + return InkWell( + onTap: callback, + child: Container( + width: Screen.width / 3, + child: Column( + children: [ + SizedBox(height: 8), + Stack( + children: [ + Padding( + padding: EdgeInsets.only(left: 4, right: 4), + child: Text( + nums < 0 ? "0" : nums.toString(), + style: TextStyle( + fontSize: 13, + //color: isMyself ? Constants.BlackTextColor : greyColor), + color: Constants.BlackTextColor), + )), + isShowDot + ? Positioned( + top: 2, + right: 0, + child: CircleAvatar( + radius: 2, + backgroundColor: const Color(0xFFE50000), + ), + ) + : Container( + width: 0, + ) + ], + ), + SizedBox(height: 4), + Text( + text, + style: TextStyle( + fontSize: 11, + //color: isMyself ? Constants.BlackTextColor : greyColor), + color: greyColor), + ), + SizedBox(height: 8), + ], + )), + ); + } + + //关注列表 + Widget _buildFans() { + return Container( + decoration: + BoxDecoration(border: Border(top: Constants.GreyBorderSide)), + child: Row( + //mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildFansButton( + userInfo.fans, + I18n.of(context).fans, + isMyself + ? () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return FansPage(); + }, + ), + ); + } + : null), + _buildFansButton( + userInfo.followNum, + I18n.of(context).attention, + isMyself + ? () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return WhiteAndBlackPage( + isWhite: true, + ); + }, + ), + ); + } + : null), + _buildFansButton(userInfo.dynamicNum, I18n.of(context).dynamics, + () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return MyProgramPage( + userId: userInfo.userId, + isMan: isMan, + ); + }, + ), + ); + }, isShowDot: userInfo.dynamicNum > 0), + ], + )); + } + + // //约会节目按钮 + // Widget _buildProgram() { + // return programId != 0 + // ? InkWell( + // onTap: () { + // Navigator.of(context).push( + // new MaterialPageRoute( + // builder: (context) { + // return ProgramDetailPage( + // programId: programId, + // ); + // }, + // ), + // ); + // }, + // child: Container( + // decoration: BoxDecoration( + // borderRadius: BorderRadius.all( + // Radius.circular(Constants.LittleButtonRadius)), + // gradient: LinearGradient(colors: [ + // const Color(0xFF6D6AEC), + // const Color(0xFF1795FF), + // ])), + // height: 31, + // alignment: Alignment.center, + // width: Screen.width, + // margin: + // EdgeInsets.only(left: 32.5, right: 32.5, top: 5, bottom: 3), + // child: Stack( + // alignment: Alignment.center, + // children: [ + // Container( + // alignment: Alignment.center, + // height: 31, + // child: Text( + // isMan + // ? I18n.of(context).his_appointment + // : I18n.of(context).her_appointment, + // style: TextStyle(color: Colors.white, fontSize: 14), + // )), + // Positioned( + // right: 30, + // child: Container( + // //padding: movement.value, + // child: Image.asset( + // 'assets/images/hand.png', + // width: 20, + // )), + // ) + // ], + // ))) + // : Container(); + // } + + //常驻城市 + Widget _buildResientCity() { + return isMyself + ? Container( + padding: EdgeInsets.only(top: 5), + child: Text( + userInfo.userId == null + ? '' + : '${I18n.of(context).Resident_city}:${UserData().hasLocationPermission ? WebData().getDateRange(userInfo.meetPlace) : I18n.of(context).unknown}', + textScaleFactor: 1.0, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 12), + )) + : userInfo.userId == null + ? Container() + : Padding( + padding: EdgeInsets.only(top: 5), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + InfoTile( + icon: IconData(0xe630, + fontFamily: Constants.IconFontFamily), + title: WebData() + .getDistanceString(userInfo.distince.toDouble()), + titleColor: greyColor, + isDivider: true), + InfoTile( + title: userInfo.onlineStatus == 1 + ? I18n.of(context).online + : WebData() + .getLoginTime(context, userInfo.loginDate), + titleColor: greyColor, + isDivider: + userInfo.photoAut == 1 || userInfo.infoAut == 1), + userInfo.infoAut == 1 + ? InfoTile( + icon: IconData(0xe645, fontFamily: 'iconfont'), + iconHeight: 22, + title: I18n.of(context).application_view, + titleColor: greyColor, + isDivider: false, + onTap: () {}) + : Container(), + userInfo.photoAut == 1 + ? InfoTile( + icon: IconData(0xe632, + fontFamily: Constants.IconFontFamily), + title: I18n.of(context).paid_photo, + titleColor: greyColor, + isDivider: false, + onTap: () {}) + : Container(), + ], + )); + } + + //用户chips + Widget _buildUserChips() { + var age = 0; + if (userInfo.birthday != null) { + age = DateTime.now().year - int.parse(userInfo.birthday.split('-')[0]); + } + return Container( + margin: EdgeInsets.only(top: 10), + alignment: Alignment.center, + width: cardWidth, + child: userInfo.userId == null + ? Container() + : UserChips( + bgColor: const Color(0xFFF2F2F2), + fontStyle: + TextStyle(fontSize: 12, color: const Color(0xFF807B95)), + isCenter: true, + city: UserData().hasLocationPermission + ? WebData().getCity(userInfo.city) + : I18n.of(context).unknown, + age: age, + constellation: + WebData().getConstellation(context, userInfo.constellation), + professional: userInfo.occupation == null + ? '' + : WebData().getProffesionName(userInfo.occupation))); + } + + //用户姓名 + Widget _buildUserName() { + return isMyself + ? InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return EditPage(isEditPage: true); + }, + ), + ); + }, + child: Container( + margin: EdgeInsets.only(top: 10), + alignment: Alignment.center, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + Provider.of(context) + .getRefName(userInfo.userId, userInfo.nickName), + textScaleFactor: 1.0, + style: TextStyle( + color: Constants.BlackTextColor, + fontWeight: FontWeight.w500, + fontSize: 16)), + isAttestation && !isMan + ? Container( + height: 13, + margin: EdgeInsets.only(left: 5), + padding: EdgeInsets.only(left: 5, right: 5), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Constants.PurpleBackgroundColor, + ), + child: Text( + 'Real', + textScaleFactor: 1.0, + style: + TextStyle(fontSize: 9, color: Colors.white), + )) + : Text(''), + isVip && isMan + ? Container( + margin: EdgeInsets.only(left: 5), + child: + isSvip ? Constants.svipIcon : Constants.vipIcon) + : Text(''), + Container( + padding: EdgeInsets.only(left: 5), + alignment: Alignment.center, + child: new InkWell( + child: Icon( + IconData(0xe6e5, fontFamily: 'iconfont'), + color: Colors.grey, + size: 16, + ), + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return EditPage(isEditPage: true); + }, + ), + ); + }, + ), + ) + ], + ))) + : Container(); + } + + //用户头像 + Widget _buildHeadImg() { + bool needSign = UserData().sign == 1 && isMyself; + + return Container( + width: MediaQuery.of(context).size.width, + child: Stack( + children: [ + Center( + child: InkWell( + onTap: isMyself + ? _sendPicture + : () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return PicSwiper( + id: 0, + pics: [ + PicSwiperItem(userInfo.headimgurl, id: 0) + ], + ); + }, + ), + ); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2.0), + boxShadow: [ + BoxShadow( + color: Colors.grey[200], + offset: Offset(0, 6), + blurRadius: 5, + ) + ]), + width: 110, + height: 110, + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: userInfo.headimgurl == null || + userInfo.headimgurl == '' + ? Image.asset(Constants.DefaultHeadImgUrl, + height: 110, width: 110) + : CachedNetworkImage( + imageUrl: userInfo.headimgurl, + placeholder: (context, url) => Image.asset( + Constants.DefaultHeadImgUrl, + height: 110, + width: 110, + ), + fit: BoxFit.cover, + ), + ))), + ), + + ///签到功能入口 + needSign + ? Positioned.fill( + child: GestureDetector( + onTap: () { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) { + return DailyBonusPage(); + }, + )); + }, + child: Container( + alignment: Alignment.centerRight, + child: Container( + margin: EdgeInsets.only(right: 23), + width: 48, + height: 48, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(30)), + boxShadow: [ + BoxShadow( + color: Color(0x739f9f9f), + offset: Offset(0.3, 0.5), + blurRadius: 2.0, + spreadRadius: 1.0), +// BoxShadow( +// color: Color(0x9900FF00), offset: Offset(1.0, 1.0)), +// BoxShadow(color: Color(0xFF0000FF)) + ]), + child: ClipOval( + child: Container( + color: Colors.white, + child: Column( + children: [ + SizedBox( + height: 8, + ), + Icon( + IconData(0xe65c, + fontFamily: Constants.IconFontFamily), + size: 20, + color: Color(0xFF0D68FF), + ), + SizedBox( + height: 2, + ), + Text( + I18n.of(context).signin, + style: TextStyle( + color: Color(0xFF0D68FF), fontSize: 10), + ) + ], + ), + ), + ), + ), + ), + ), + ) + : Container() + ], + ), + ); + } + + //收藏按钮 + Widget _buildLoveButton(Color buttonColor) { + return isMyself || userInfo.sex == UserData().basicInfo.sex + ? Container() + : Positioned( + right: 10, + top: 20, + child: InkWell( + onTap: () async { + if (!userInfo.isLike) { + HttpUtil().setLove(userInfo.userId, () { + MessageMgr().emit('refresh_love_list', + {'UserId': userInfo.userId, 'flag': 0}); + setState(() { + userInfo.isLike = true; + }); + }); + } else { + HttpUtil().cancleLove(userInfo.userId, () { + MessageMgr().emit('refresh_love_list', + {'UserId': userInfo.userId, 'flag': 2}); + setState(() { + userInfo.isLike = false; + }); + }); + } + }, + child: Container( + child: Row( + children: [ + Icon( + IconData(userInfo.isLike ? 0xe623 : 0xe625, + fontFamily: Constants.IconFontFamily), + size: 14, + color: userInfo.isLike + ? const Color(0xFFFF7777) + : buttonColor, + ), + SizedBox(width: 2), + Text( + I18n.of(context).like, + style: TextStyle(color: buttonColor, fontSize: 11), + ) + ], + ), + padding: EdgeInsets.symmetric(horizontal: 8, vertical: 5), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey[300]), + borderRadius: BorderRadius.circular(5))))); + } + + Widget _buildMyPicture() { + var pisc = imgList + .map((f) => PicSwiperItem( + f['ImgUrl'], + id: f['Id'], + type: f['Type'], + isWatch: f['IsCheck'] == 1, + userId: userInfo.userId, + isBuy: f['PayStatus'] == 1, + )) + .toList(); + var list = imgList.map((data) { + var width = MediaQuery.of(context).size.width / 4 - 15; + bool isWatch = data['IsCheck'] == 1; + double raduis = 10; + return CustomUI.buildImgCover(data['Id'], pisc, data['ImgUrl'], width, + raduis, isWatch, context, data['Type'], + isMyself: isMyself, + payStatus: data['PayStatus'], + state: isMan ? 1 : data['Status']); + }).toList(); + if (!isBuyPicture && list.length > 4) { + list.length = 4; + } + + TitleItem title; + if (!isMan) { + title = UserData().isVip + ? TitleItem( + title: I18n.of(context).unlock_user, + name: Provider.of(context) + .getRefName(userInfo.userId, userInfo.nickName), + ) + : TitleItem( + title: I18n.of(context).free_unlock, + name: userInfo.price.toString() + I18n.of(context).mask_coin); + } else { + title = TitleItem( + title: I18n.of(context).pay_unlock, name: userInfo.price.toString()); + } + //我的相册 + return Container( + alignment: Alignment.center, + margin: EdgeInsets.only(top: Separate_Size), + padding: EdgeInsets.symmetric(horizontal: 10), + width: isMyself ? Screen.width : cardWidth, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + FullWidthButton( + title: (isMyself + ? I18n.of(context).my_album + : (isMan + ? I18n.of(context).his_photo + : I18n.of(context).her_photo)), + //+'(${I18n.of(context).visit_you.replaceFirst('/s1', userInfo.accessNum.toString())})', + description: isMyself ? I18n.of(context).upload : '', + descriptionColor: Constants.BlueTextColor, + showDivider: true, + showRightIcon: false, + onPressed: isMyself ? _uploadPhoto : () {}, + ), + list.length == 0 + ? (isMyself + ? InkWell( + onTap: _uploadPhoto, + child: Container( + height: 100, + alignment: Alignment.center, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(I18n.of(context).first_photo, + textScaleFactor: 1.0), + Text( + isMan + ? I18n.of(context).have_picture + : I18n.of(context).no_photo, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 12, color: Colors.grey)) + ], + ))) + : Container( + alignment: Alignment.center, + height: 120, + child: Text( + isMan + ? I18n.of(context).not_up_man + : I18n.of(context).not_up_women, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14), + ), + )) + : (isBuyPicture + ? Container( + //alignment: Alignment.center, + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: list, + )) + : Container( + alignment: Alignment.center, + child: Stack( + //alignment: Alignment.center, + children: [ + Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: list, + ), + Opacity( + opacity: 0.96, + child: Container( + decoration: BoxDecoration(color: Colors.white), + height: 200, + ), + ), + Container( + height: 200, + alignment: Alignment.center, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/suo.png', + width: 35, + color: Colors.grey[700], + ), + Container( + margin: EdgeInsets.only(top: 10), + alignment: Alignment.center, + child: Text( + isMan + ? I18n.of(context).set_lock + : I18n.of(context).set_lock2, + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.grey[700], + fontSize: 15), + ), + ), + Container( + margin: EdgeInsets.only(top: 8), + alignment: Alignment.center, + child: RichText( + text: TextSpan( + children: RichTitle.getRichText(title, + titleStyle: TextStyle( + color: Colors.grey[700], + fontSize: 13), + nameStyle: TextStyle( + color: Colors.red, + fontSize: 13))), + ), + ), + InkWell( + onTap: buyPhoto, + child: Container( + margin: EdgeInsets.only(top: 10), + padding: + EdgeInsets.only(top: 6, bottom: 6), + width: 100, + alignment: Alignment.center, + decoration: Constants + .ConfirmBUttonBoxDecoration, + child: Text( + I18n.of(context).unlock, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white), + ), + )), + ], + )) + ], + ))), + !isMan && isMyself + ? InkWell( + onTap: () { + if (!userInfo.isAttestation) { + _buildNotTrue(); + return; + } + if (imgList.length == 0) { + showToast(I18n.of(context).no_photos); + return; + } + Navigator.of(context) + .push(new MaterialPageRoute(builder: (context) { + return MoneyPicture( + imageList: imgList, + ); + })); + }, + child: Container( + alignment: Alignment.centerRight, + // decoration: BoxDecoration( + // border: + // Border(top: BorderSide(color: Colors.grey[50]))), + margin: EdgeInsets.only(top: 10, right: 10, bottom: 10), + padding: EdgeInsets.only(top: 10), + child: Text( + I18n.of(context).set_photo, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.red), + ), + )) + : Container(), + _buildRset(), + ], + ), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, bottom: Constants.GreyBorderSide)), + ); + } + + void _buildNotTrue() { + CustomUI.buildOneConfirm(context, I18n.of(context).moneyPageTip, + I18n.of(context).authenticate_now, () { + Navigator.pop(context); + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return VerificationCenterPage(); + }, + ), + ); + }); + } + + void _buildConfirmBlack() { + Navigator.of(context).pop(); + CustomUI.buildOneConfirm( + context, I18n.of(context).blacklist_choose, I18n.of(context).determine, + () async { + Navigator.pop(context); + + HttpUtil().blackUser(userInfo.userId, () { + isblack = true; + }); + }); + } + + void _sendMySelfPicture() async { + if (await CustomUI.showPhotoPermissionSetting(context)) { + var tempFile = await ImagePicker.pickImage(source: ImageSource.gallery); + if (tempFile != null) { + Map data = {"type": 6, "userId": UserData().basicInfo.userId}; + data['sign'] = TokenMgr().getSign(data); + data['isBurn'] = 1; + + Response res = await HttpUtil().uploadFile( + tempFile, data, 'upload/file/postflie', 'image', + isShowLoading: true); + var resData = res.data; + if (resData['code'] == 0) { + showToast(I18n.of(context).successfully_submit); + myselfImg = resData['data']['photoId']; + Navigator.of(context).pop(); + _postApply(); + } + } + } + } + + void _postApply() async { + Map data = { + "userId": userInfo.userId, + "imgUrl": myselfImg, + "applyUserId": UserData().basicInfo.userId + }; + + data['sign'] = TokenMgr().getSign(data); + Response res = await HttpUtil() + .post('user/apply/checkcords', data: data, isShowLoading: true); + Map resData = res.data; + if (resData['code'] == 0) { + isApplying = true; + setState(() {}); + } + } + + Widget _buildBody() { + Widget hidden = Container( + alignment: Alignment.center, + width: Screen.width, + height: Screen.height - 372, + color: Colors.white, + margin: EdgeInsets.only(top: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: EdgeInsets.only(bottom: 10), + child: Image.asset('assets/images/login/lock.png', + height: 45, width: 45), + ), + Text( + isMan ? I18n.of(context).view_user : I18n.of(context).view_user2, + textScaleFactor: 1.0, + textAlign: TextAlign.center, + style: TextStyle(color: Constants.GreyTextColor, fontSize: 13.5), + ), + InkWell( + onTap: isApplying + ? null + : () async { + CustomUI.buildOneConfirm( + context, + I18n.of(context).need_photo, + I18n.of(context).choose_photo, + _sendMySelfPicture); + }, + child: Container( + margin: EdgeInsets.only(top: 10, left: 100, right: 100), + padding: EdgeInsets.only(top: 10, bottom: 10), + alignment: Alignment.center, + decoration: BoxDecoration( + color: Constants.ConfrimButtonColor, + borderRadius: BorderRadius.all( + Radius.circular(Constants.LittleButtonRadius))), + child: Text( + isApplying + ? I18n.of(context).already_applied + : I18n.of(context).apply_now, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white), + ), + )), + ], + ), + ); + List child = []; + if (isMyself) { + child.addAll([ + _buildHeadView(), + _buildGoldnessHot(), + _buildMoneyBox(), + _buildMyPicture(), + _buildTips(), + _buildHistory(), + //_buildApplyCode(), + _buildShare(), + ]); + } else if (isCanWatch) { + child.addAll([ + _buildHeadView(), + _buildMyPicture(), + _buildBasicInfo(), + _buildBottomTips(), + ]); + } else if (userInfo.userId != null) { + child.addAll([ + _buildHeadView(), + hidden, + ]); + } else { + child.addAll([ + _buildHeadView(), + ]); + } + return Column( + children: child, + ); + } + + _inviteFdBtn() { + return Container( + width: Screen.width, + child: FlatButton( + child: fixedText(I18n.of(context).add_friends, + fontSize: 16, + color: Colors.blueAccent, + fontWeight: FontWeight.w500), + onPressed: () async { + //已经是好友 + if (FriendListMgr().isMyFriend(userInfo.userId)) { + showToast(I18n.of(context).added); + return; + } + //已申请 + if (userInfo.isAddFriends == 0) { + showToast(I18n.of(context).add_friends_tips); + return; + } + + if (UserData().addFdDistanceSwitch > 0 && userInfo.distince > 200) { + showToast(I18n.of(context).distance_long); + return; + } + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return AddFriendPage( + userId: userInfo.userId, + pageType: SendMessagePageType.AddFriends, + originalName: I18n.of(context) + .i_am + .replaceFirst('/s1', UserData().basicInfo.nickName), + ); + }, + ), + ); + }), + ); + } + + void doFriendApply(state, callback) async { + Map data = { + "id": widget.applyId, + "userId": UserData().basicInfo.userId, + "status": state, + }; + data['sign'] = TokenMgr().getSign(data); + Response res = + await HttpUtil().post('friendship/handler/apply', data: data); + if (res == null) { + return; + } + var resData = res.data; + if (resData['code'] == 0) { + callback(resData['msg']); + } else {} + } + + _dealInvite() { + return Container( + width: Screen.width, + child: Row( + children: [ + Expanded( + child: InkWell( + onTap: () { + doFriendApply(1, (msg) { + showToast(msg); + Navigator.of(context).pop(); + var friendModel = FriendModel.fromServerJson({ + 'UserId': userInfo.userId, + 'ImgUrl': userInfo.headimgurl, + 'UserName': userInfo.nickName + }); + FriendListMgr().addFriend(friendModel); + MessageMgr().emit('do_friend_apply', + {'userId': userInfo.userId, 'state': 1}); + MessageMgr().emit('Add friend'); + }); + }, + child: Container( + color: const Color(0xFF3875E9), + alignment: Alignment.center, + child: Text( + I18n.of(context).agree, + style: TextStyle(fontSize: 18, color: Colors.white), + ), + ), + )), + InkWell( + onTap: () { + doFriendApply(2, (msg) { + showToast(msg); + Navigator.of(context).pop(); + MessageMgr().emit('do_friend_apply', + {'userId': userInfo.userId, 'state': 2}); + }); + }, + child: Container( + alignment: Alignment.center, + color: const Color(0xFFA8D3FF), + width: Screen.width * 0.33, + child: Text( + I18n.of(context).refuse, + style: + TextStyle(fontSize: 18, color: const Color(0xFF007EFF)), + ), + )) + ], + )); + } + + //自定义item + Widget _bottomBorderBox( + String textLeft, String textRight, bool showBorder, callback, + {showIcon: false}) { + Widget left = new Container( + margin: EdgeInsets.only(right: 20), + width: 90, + child: new Text( + textLeft, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14), + )); + + Widget right = new Expanded( + child: Text( + textRight, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 13, color: Constants.GreyTextColor), + ), + ); + return InkWell( + highlightColor: Colors.transparent, + radius: 0.0, + onTap: callback, + child: Column( + children: [ + Container( + height: 53, + margin: EdgeInsets.only(left: 20, bottom: 0, right: 10), + child: Row( + children: [ + left, + right, + showIcon + ? Padding( + padding: EdgeInsets.only(right: 10), + child: Icon( + IconData(0xe63c, fontFamily: 'iconfont'), + size: 22.0, + color: Color(AppColors.TabIconNormal), + )) + : Container() + ], + ), + ), + showBorder ? _buildDivider() : Container(), + ], + )); + } + + //下划线 + Widget _buildDivider() { + return new Container( + margin: EdgeInsets.symmetric(horizontal: 15), + height: 1, + decoration: + BoxDecoration(border: Border(bottom: Constants.GreyBorderSide)), + width: MediaQuery.of(context).size.width, + ); + } + + testChatPermission(callback) { + becomeVip() { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return VipPage(); + }, + ), + ); + } + + payCallback() { + if (Provider.of(context).money < + UserData().accountPrice) { + Navigator.of(context).pop(); + CustomUI.buildOneConfirm(context, I18n.of(context).balance_insufficien, + I18n.of(context).recharge, () { + Navigator.of(context).pop(); + ChargeMoney.showChargeSheet(context, () { + setState(() {}); + }); + }); + return; + } + Navigator.of(context).pop(); + HttpUtil().buyChatAccount( + UserData().accountPrice, userInfo.userId, context, () { + setState(() { + isAuthority = true; + }); + }); + } + + freeTime() { + HttpUtil().userFreeTime(context, userInfo.userId, 2, () { + UserData().basicInfo.usedNum++; + Navigator.of(context).pop(); + setState(() { + isAuthority = true; + }); + }); + } + + // //对方是女性用户,且未认证提示未认证 + // if (userInfo.sex == 2 && !userInfo.isAttestation) { + // showToast(I18n.of(context).not_video); + // return; + // } + + //自己是女性,且未认证,提示去认证 + if (!UserData().isMan() && !UserData().basicInfo.isAttestation) { + CustomUI.buildNotTrue(context); + return; + } + + print('isAuthority $isAuthority'); + var tipStr = ''; + + //没有解锁账号,并且对方禁止陌生人聊天 + if (!isAuthority && !userInfo.isCanStrangerNews) { + tipStr = I18n.of(context).stranger_close; + } else { + tipStr = I18n.of(context).unlock_information; + if (userInfo.sex == 2 && !userInfo.isAttestation) { + tipStr += '(${I18n.of(context).not_true_woman})'; + } + } + if (isAuthority) { + if (callback != null) callback(); + } else { + //如果自己是男性,vip提示免费次数,次数用完或者非vip提示购买 + if (UserData().isMan()) { + if (UserData().isVip) { + UserData().basicInfo.freeNum < UserData().basicInfo.usedNum + ? CustomUI.buildOneConfirm( + context, + tipStr, + I18n.of(context) + .pay_unlock + .replaceFirst('/s1', UserData().accountPrice.toString()), + payCallback) + : CustomUI.buildOneConfirm( + context, + tipStr, + I18n.of(context).unlock_choose, + freeTime, + ); + } else { + CustomUI.buildTowConfirm( + context, + tipStr, + I18n.of(context).become_member, + becomeVip, + I18n.of(context) + .pay_unlock + .replaceFirst('/s1', UserData().accountPrice.toString()), + payCallback); + } + } + } + } + + buyChatAccount() { + if (widget.fromWhere != null && widget.fromWhere == 0) { + ///如果是聊天界面跳转过来的,直接返回 + Navigator.of(context).pop(); + } else { + testChatPermission(() { + int fdId = userInfo.userId; + int sessionId = UserData().getSessionId(fdId); + + MsgHandler.updateActiveSesstion(sessionId); + + AppNavigator.pushChatPage(context, fdId); + }); + } + } + + buyPhoto() { + //女性用户付费,男性用户会员的话免费解锁,非会员付费解锁 + becomeVip() { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return VipPage(); + }, + ), + ); + } + + payCallback() { + if (Provider.of(context).money < userInfo.price) { + Navigator.of(context).pop(); + CustomUI.buildOneConfirm(context, I18n.of(context).balance_insufficien, + I18n.of(context).recharge, () { + Navigator.of(context).pop(); + ChargeMoney.showChargeSheet(context, () { + setState(() {}); + }); + }); + return; + } + Navigator.of(context).pop(); + HttpUtil().buyPictures(userInfo.price, userInfo.userId, context, () { + setState(() { + isBuyPicture = true; + }); + }); + } + + freeTime() { + HttpUtil().userFreeTime(context, userInfo.userId, 1, () { + UserData().basicInfo.usedNum++; + Navigator.of(context).pop(); + setState(() { + isBuyPicture = true; + }); + }); + } + + String title = I18n.of(context).unlock_user.replaceFirst( + '/s1', + Provider.of(context) + .getRefName(userInfo.userId, userInfo.nickName), + ); + + if (!UserData().isMan()) { + CustomUI.buildOneConfirm( + context, + title, + I18n.of(context) + .pay_unlock + .replaceFirst('/s1', userInfo.price.toString()), + payCallback); + } else if (UserData().isVip) { + if (UserData().basicInfo.freeNum < UserData().basicInfo.usedNum) { + CustomUI.buildOneConfirm( + context, + title, + I18n.of(context) + .pay_unlock + .replaceFirst('/s1', userInfo.price.toString()), + payCallback); + } else { + CustomUI.buildOneConfirm( + context, title, I18n.of(context).unlock_choose, freeTime); + } + } else { + CustomUI.buildTowConfirm( + context, + title, + I18n.of(context).become_member, + becomeVip, + I18n.of(context) + .pay_unlock + .replaceFirst('/s1', userInfo.price.toString()), + payCallback); + } + } + + Widget _buildBasicInfo() { + String wechat = ''; + String facebook = ''; + bool isHidden = userInfo.accountStatus == 1; + //隐藏社交账号 + if (isHidden) { + wechat = I18n.of(context).ask_me; + facebook = I18n.of(context).ask_me; + } else { + wechat = isAuthority ? userInfo.wechat : I18n.of(context).filled_in; + facebook = isAuthority ? userInfo.facebook : I18n.of(context).filled_in; + } + + heightStr = (userInfo.height == 0.0 || userInfo.height == null) + ? I18n.of(context).not_show + : '${userInfo.height}M'; + weightStr = (userInfo.weight == 0.0 || userInfo.weight == null) + ? I18n.of(context).not_show + : '${userInfo.weight}KG'; + + List basicList = [ + userInfo.height != null && userInfo.height != 0 + ? _bottomBorderBox(I18n.of(context).height, heightStr, true, () {}) + : Container(), + userInfo.weight != null && userInfo.weight != 0 + ? _bottomBorderBox(I18n.of(context).weight, weightStr, true, () {}) + : Container(), + _bottomBorderBox(I18n.of(context).Resident_city, dateRange, true, () {}), + //_bottomBorderBox(I18n.of(context).program, dateItem, true, () {}), + _bottomBorderBox(I18n.of(context).expect_lover, lovePeople, true, () {}), + (userInfo.wechat != null && userInfo.wechat != '') + ? _bottomBorderBox( + I18n.of(context).wechat_number, wechat, true, buyChatAccount, + showIcon: !isAuthority) + : Container(), + (userInfo.facebook != null && userInfo.facebook != '') + ? _bottomBorderBox( + I18n.of(context).facebook, facebook, true, buyChatAccount, + showIcon: !isAuthority) + : Container(), + userInfo.ownMsg != null && userInfo.ownMsg != '' + ? _bottomBorderBox( + I18n.of(context).self_introduction, myMsg, false, () {}) + : Container(), + ]; + + return Container( + width: cardWidth, + margin: EdgeInsets.only(top: Separate_Size), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, + bottom: Constants.GreyBorderSide)), + child: new Column( + children: basicList, + )); + } + + Widget _buildTips() { + return Container( + margin: EdgeInsets.only(top: 10, bottom: 10, left: 20, right: 20), + child: Text(I18n.of(context).dont, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 12, + color: Colors.grey, + ))); + } + + Widget _buildBottomTips() { + return Container( + margin: EdgeInsets.only(bottom: 10, left: 10, right: 10, top: 10), + width: cardWidth, + alignment: Alignment.center, + child: Text(I18n.of(context).not_illage, + textScaleFactor: 1.0, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 12, color: Colors.grey)), + ); + } + + Widget _buildGoldnessHot() { + //女神热度 + return isMan + ? Container() + : Container( + margin: EdgeInsets.only(top: Separate_Size), + padding: EdgeInsets.symmetric(horizontal: 10), + child: FullWidthButton( + title: I18n.of(context).Goddess_heat, + showDivider: false, + showRightIcon: true, + onPressed: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return GoddessHotPage( + userId: userInfo.userId, + ); + }, + ), + ); + }, + ), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, + bottom: Constants.GreyBorderSide)), + ); + } + + Widget _buildMoneyBox() { + //认证、钱包、隐私连麦设置 + return Container( + margin: EdgeInsets.only(top: Separate_Size), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, bottom: Constants.GreyBorderSide)), + padding: EdgeInsets.all(10), + child: Column( + children: [ + isMan + ? FullWidthButton( + title: I18n.of(context).member, + description: UserData().isVip + ? I18n.of(context) + .expires + .replaceFirst('/s1', endTime.split(' ')[0]) + : I18n.of(context).enjoy_privileges, + showDivider: true, + onPressed: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return VipPage(); + }, + ), + ); + }, + ) + : FullWidthButton( + title: isAttestation + ? I18n.of(context).certified_video + : I18n.of(context).authenticate, + showDivider: true, + onPressed: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return isAttestation + ? VideoPage( + userId: userInfo.userId, + ) + : VerificationCenterPage(); + }, + ), + ); + }, + ), + FullWidthButton( + title: I18n.of(context).wallet, + description: + '${Provider.of(context).money}${I18n.of(context).mask_coin}', + showDivider: false, + onPressed: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return MoneyPage(); + }, + ), + ); + }, + ), + ], + ), + ); + } + + Widget _buildHistory() { + //历史访客 + return Container( + margin: EdgeInsets.only(top: Separate_Size), + padding: EdgeInsets.symmetric(horizontal: 10), + child: FullWidthButton( + title: I18n.of(context).historical_visitor, + description: I18n.of(context) + .visit_you + .replaceFirst('/s1', userInfo.accessNum.toString()), + showDivider: false, + showRightIcon: false, + onPressed: () {}, + ), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, bottom: Constants.GreyBorderSide)), + ); + } + + //恢复焚阅照片 + Widget _buildRset() { + //历史访客 + return isMyself + ? Container( + margin: EdgeInsets.only(top: Separate_Size), + //padding: EdgeInsets.symmetric(horizontal: 10), + child: FullWidthButton( + title: I18n.of(context) + .visit_photo + .replaceFirst('/s1', userInfo.burnNum.toString()), + description: I18n.of(context).recovery_photo, + showDivider: false, + showRightIcon: false, + onPressed: () async { + CustomUI.buildOneConfirm( + context, + I18n.of(context).confrim_recovery, + I18n.of(context).determine, () async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('user/recover/photos', + data: data, isShowLoading: true); + Map resData = res.data; + if (resData['code'] == 0) { + showToast(resData['msg']); + Navigator.of(context).pop(); + userInfo.burnNum = 0; + setState(() {}); + } + }); + }, + ), + decoration: BoxDecoration( + color: Colors.white, + border: Border(top: Constants.GreyBorderSide)), + ) + : Container(); + } + + // Widget _buildApplyCode() { + // //帮朋友申请邀请码 + // return isMan + // ? Container( + // margin: EdgeInsets.only(top: Separate_Size), + // padding: EdgeInsets.symmetric(horizontal: 10), + // child: FullWidthButton( + // title: I18n.of(context).apply_code, + // showDivider: false, + // showRightIcon: false, + // onPressed: () { + // CustomUI.buildOneConfirm(context, I18n.of(context).issue_choose, + // I18n.of(context).determine, () async { + // Map data = { + // "userId": UserData().basicInfo.userId, + // }; + // data['sign'] = TokenMgr().getSign(data); + + // Response res = + // await HttpUtil().post('user/helper/apply', data: data); + // Map resData = res.data; + + // if (resData['code'] == 0) { + // Navigator.of(context).pop(); + // CustomUI.buildOneConfirm( + // context, + // I18n.of(context).receive_incode, + // I18n.of(context).ok, () { + // Navigator.of(context).pop(); + // }); + // } else { + // showToast(resData['msg']); + // } + // }); + // }, + // ), + // decoration: BoxDecoration( + // color: Colors.white, + // border: Border( + // top: Constants.GreyBorderSide, + // bottom: Constants.GreyBorderSide)), + // ) + // : Container(); + // } + + Widget _buildShare() { + //分享 + return Container( + margin: EdgeInsets.only(top: Separate_Size, bottom: Separate_Size), + padding: EdgeInsets.symmetric(horizontal: 10), + child: FullWidthButton( + showRightIcon: false, + title: I18n.of(context).share_app, + showDivider: false, + onPressed: () { + Share.share('https://henho.jphgames.com/'); + }, + ), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, bottom: Constants.GreyBorderSide)), + ); + } + + Widget _buildIcon(code, str, isCanHit, callback, {iconSize = 28.0}) { + var color = isCanHit ? Constants.BlueTextColor : Constants.GreyTextColor; + return InkWell( + onTap: isCanHit + ? callback + : () { + showToast(isMan + ? I18n.of(context).view_user + : I18n.of(context).view_user2); + }, + child: Row( + children: [ + Icon( + IconData( + code, + fontFamily: 'iconfont', + ), + color: color, + size: iconSize, + ), + Padding( + child: Text( + str, + textScaleFactor: 1.0, + style: TextStyle(color: color, fontSize: 12), + ), + padding: EdgeInsets.only(left: 5)) + ], + )); + } + + @override + Widget build(BuildContext context) { + Size screenSize = MediaQuery.of(context).size; + cardWidth = screenSize.width; + Widget appBar = AppBar( +// backgroundColor: AppColors.NewAppbarBgColor, + //automaticallyImplyLeading: !isMyself, + leading: isMyself ? Container() : CustomUI.buildCustomLeading(context), + titleSpacing: isMyself ? -40 : NavigationToolbar.kMiddleSpacing, + title: isMyself + ? Text( + I18n.of(context).me, + textScaleFactor: 1.0, + style: Constants.MainTitleStyle, + ) + : Container( + alignment: Alignment.center, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + WebData().subUserName( + Provider.of(context) + .getRefName(userInfo.userId, userInfo.nickName)), + textScaleFactor: 1.0, + style: TextStyle(color: Constants.BlackTextColor)), + isAttestation && !isMan + ? Container( + height: 13, + margin: EdgeInsets.only(left: 5), + padding: EdgeInsets.only(left: 5, right: 5), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Constants.PurpleBackgroundColor, + ), + child: Text( + 'Real', + textScaleFactor: 1.0, + style: TextStyle(fontSize: 10, color: Colors.white), + )) + : Text(''), + isVip && isMan + ? Container( + margin: EdgeInsets.only(left: 5), + child: + isSvip ? Constants.svipIcon : Constants.vipIcon) + : Text(''), + ], + )), + centerTitle: !isMyself, + elevation: 1, + actions: [ + isMyself + ? Container( + padding: EdgeInsets.only(right: 15), + alignment: Alignment.center, + child: new InkWell( + child: CircleAvatar( + backgroundColor: Constants.GreyBackgroundColor, + radius: 15.75, + child: Icon( + IconData(0xe658, fontFamily: 'iconfont'), + color: Constants.BlackTextColor, + size: 20, + )), + onTap: () { + AppNavigator.pushQrPage(context); + }, + ), + ) + : Container(), + isMyself + ? Container( + padding: EdgeInsets.only(right: 15), + alignment: Alignment.center, + child: new InkWell( + child: CircleAvatar( + backgroundColor: Constants.GreyBackgroundColor, + radius: 15.75, + child: Icon( + Icons.settings, + //IconData(0xe6e5, fontFamily: 'iconfont'), + color: Constants.BlackTextColor, + size: 22, + )), + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return SystemEditPage(); + }, + ), + ); + }, + ), + ) + : Container(), + isMyself + ? Container( + // padding: EdgeInsets.only(right: 10), + // alignment: Alignment.center, + // child: new InkWell( + // child: CircleAvatar( + // backgroundColor: Constants.GreyBackgroundColor, + // radius: 15.75, + // child: Icon( + // IconData(0xe6e5, fontFamily: 'iconfont'), + // color: Constants.BlackTextColor, + // size: 25, + // )), + // onTap: () { + // Navigator.of(context).push( + // new MaterialPageRoute( + // builder: (context) { + // return EditPage(isEditPage: true); + // }, + // ), + // ); + // }, + // ), + ) + : Container( + alignment: Alignment.center, + child: new InkWell( + child: new Padding( + padding: EdgeInsets.only( + right: 15, left: 15, top: 10, bottom: 10), + child: Icon( + IconData( + 0xe621, + fontFamily: 'iconfont', + ), + color: Constants.BlackTextColor, + size: 20, + ), + ), + onTap: () { + showModalBottomSheet( + context: registKey.currentContext, + builder: (BuildContext context) { + return SafeArea( + child: Container( + height: 137, + child: Column( + children: [ + InkWell( + child: Container( + height: 45, + alignment: Alignment.center, + child: Text( + isblack + ? I18n.of(context).remove_blacklist + : I18n.of(context).blacklist, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 18, + color: Constants.BlackTextColor), + ), + ), + onTap: isblack + ? () async { + HttpUtil().cancleBlackUser( + userInfo.userId, () { + Navigator.of(context).pop(); + isblack = false; + }); + } + : _buildConfirmBlack, + ), + Divider(height: 1), + InkWell( + onTap: () async { + Navigator.of(context).pop(); + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return InformUserPage( + isMan: isMan, + userId: userInfo.userId, + ); + }, + ), + ); + }, + child: Container( + alignment: Alignment.center, + height: 45, + child: Text( + I18n.of(context).anonymous_report, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 18, + color: Constants + .BlackTextColor)))), + Divider(height: 1), + InkWell( + onTap: () async { + Navigator.of(context).pop(); + + nickNameController.text = + Provider.of(context) + .getRefName(userInfo.userId, + userInfo.nickName); + + var confirm = CustomUI.buildConfirmBotton( + I18n.of(context).determine, () async { + nickNameController.text = + nickNameController.text.trim(); + if (nickNameController.text == null || + nickNameController.text.length > + 25) { + showToast(I18n.of(context).only1_8); + return; + } + Provider.of( + registKey.currentContext) + .changeRefName(userInfo.userId, + nickNameController.text, () { + Navigator.of(registKey.currentContext) + .pop(); + }); + }); + var tip = Column( + children: [ + Container( + margin: EdgeInsets.only(top: 20), + child: Text( + I18n.of(context).setRemark, + style: TextStyle( + color: + Constants.BlackTextColor, + fontSize: 16), + ), + ), + Container( + margin: EdgeInsets.only( + top: 23, bottom: 25), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.all( + Radius.circular(8))), + child: TextField( + keyboardAppearance: + Brightness.light, + controller: nickNameController, + textAlign: TextAlign.center, + textInputAction: + TextInputAction.search, + style: TextStyle( + textBaseline: + TextBaseline.alphabetic, + fontSize: 14), + decoration: InputDecoration( + hintText: userInfo.nickName, + hintStyle: + TextStyle(fontSize: 12), + filled: true, + contentPadding: EdgeInsets.only( + top: 10, bottom: 10), + fillColor: Colors.transparent, + border: InputBorder.none, + ), + maxLines: 1, + inputFormatters: [ + LengthLimitingTextInputFormatter( + 15) + ], + ), + ) + ], + ); + var content = + CustomUI.buildConfirmContent( + tip, confirm); + CustomUI.buildTip( + registKey.currentContext, + '', + content); + }, + child: Container( + alignment: Alignment.center, + height: 45, + child: Text(I18n.of(context).Remark, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 18, + color: Constants + .BlackTextColor)))), + ], + ), + ), + ); + }, + ).then((val) {}); + }, + ), + ), + ], + ); + Widget content = Container( + color: Colors.white, + child: SafeArea( + child: Scaffold( + bottomNavigationBar: !isMyself + ? Container( + height: 55, + decoration: BoxDecoration( + border: + Border(top: BorderSide(color: Color(0xffeaeaea))), + color: Constants.LightGreyBackgroundColor, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: widget.addMode == 1 + ? [_inviteFdBtn()] + : (widget.addMode == 2 + ? [_dealInvite()] + : [ + _buildIcon( + 0xe633, I18n.of(context).evaluate, true, + () async { + Map data = { + "userid": userInfo.userId, + 'evaluateuserid': + UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post( + 'evaluate/user/info', + data: data, + isShowLoading: true); + + Map resData = res.data; + print(resData); + if (resData['code'] == 0) { + Navigator.of(context).push( + TutorialOverlay( + child: ApplyContent( + userId: userInfo.userId, + isMan: isMan, + userInfo: + resData['data']))); + } else { + showToast(resData['msg']); + } + }), + _buildIcon( + 0xe637, + I18n.of(context).private_chat, + isCanWatch, + isCanWatch ? buyChatAccount : null, + iconSize: 24.0), + _buildIcon(0xe62f, I18n.of(context).chat, + isCanWatch, onAudio) + ]), + ), + ) + : null, + appBar: appBar, + key: registKey, + body: SafeArea( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + color: AppColors.BackgroundColor, + child: SingleChildScrollView( + child: _buildBody(), + ), + )))), + ); + return CustomUI.buildPageLoading(context, content, !isLoadingFish); + } + + //连麦 + onAudio() async { + testChatPermission(() async { + if (userInfo.chatStatus == 0) { + showToast(I18n.of(context).cantt_voice); + return; + } + + if (BlacklistMgr.isBlaklistMe(userInfo.userId)) { + showToast(I18n.of(context).you_are_blaklisted); + return; + } + + if (BlacklistMgr.isInMyblaklist(userInfo.userId)) { + showToast(I18n.of(context).reject_message); + return; + } + + //对方关闭陌生人消息,则提示 + if (!userInfo.isCanStrangerNews) { + showToast(I18n.of(context).stranger_close_tips); + return; + } + + if (await CustomUI.showPermissionSetting(context, + PermissionGroup.microphone, I18n.of(context).video_permission)) { + AppNavigator.pushAudioChatPage(context, userInfo); + } else { + showToast(I18n.of(context).need_record); + } + }); + } +} diff --git a/lib/home/ProgramDetail.dart b/lib/home/ProgramDetail.dart new file mode 100644 index 0000000..36ffc4e --- /dev/null +++ b/lib/home/ProgramDetail.dart @@ -0,0 +1,586 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/InformUser.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/MessageBox.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/PicSwiper.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; +import '../utils/HttpUtil.dart'; +import 'package:dio/dio.dart'; +import "../data/UserData.dart"; +import '../utils/TokenMgr.dart'; + +class ProgramDetailPage extends StatefulWidget { + @required + final int programId; + ProgramDetailPage({Key key, this.programId}) : super(key: key); + + @override + _ProgramDetailPageState createState() => new _ProgramDetailPageState(); +} + +class _ProgramDetailPageState extends State { + GlobalKey registKey = new GlobalKey(); + + List fabulousList = []; + bool isMyself = false; + + List evaluateList = []; + + List enrollList = []; + + bool showAllContent = false; + + bool isMan = false; + + bool isProgram = false; + + Map programInfo = {}; + + bool isLoadingFish = false; + + bool isNonContent = false; + + bool isJoin = false; + + msgRefresh(data) { + getData(); + } + + msgUpdateDy(data) { + setState(() { + isNonContent = data; + }); + } + + @override + void initState() { + super.initState(); + MessageMgr().on('delete_program', msgDeleteProgram); + MessageMgr().on('update_dy', msgUpdateDy); + MessageMgr().on('refresh_list', msgRefreshList); + getData(); + } + + msgRefreshList(data) { + getData(); + } + + msgDeleteProgram(data) { + Navigator.of(context).pop(); + } + + Future getData() async { + Map data = { + "userId": UserData().basicInfo.userId, + "id": widget.programId, + }; + data['sign'] = TokenMgr().getSign(data); + Response res = await HttpUtil().post('station/evaluate/detail', + data: data, failback: () => Navigator.of(context).pop()); + var resData = res.data; + print(resData); + if (resData['code'] == 0) { + if (resData['data']['FabulousList'] != null) + fabulousList = resData['data']['FabulousList']; + if (resData['data']['EvaluateList'] != null) { + evaluateList = resData['data']['EvaluateList']; + } + enrollList = resData['data']['EnrollList']; + isMyself = resData['data']['UserId'] == UserData().basicInfo.userId; + isMan = resData['data']['Sex'] == 1; + isProgram = resData['data']['Type'] == 0; + programInfo = resData['data']; + programInfo['Id'] = widget.programId; + isNonContent = resData['data']['EvaluateStatus'] == 1; + isJoin = resData['data']['IsEnroll'] == 1; + isLoadingFish = true; + setState(() {}); + } else { + showToast(resData['msg']); + } + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + //backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + isProgram + ? I18n.of(context).program_details + : I18n.of(context).dynamic_details, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + elevation: 1, + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ); + var content = new Scaffold( + key: registKey, + appBar: appBar, + //backgroundColor: Colors.white, + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + ), + )); + + return CustomUI.buildPageLoading(context, content, !isLoadingFish); + } + + Widget _buildBottomSheetItem(str, height, callback) { + return InkWell( + child: Container( + height: height, + decoration: + BoxDecoration(border: Border(bottom: Constants.GreyBorderSide)), + alignment: Alignment.center, + child: Text( + str, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 18, color: Constants.BlackTextColor), + ), + ), + onTap: callback, + ); + } + + Widget _buildReply(data) { + const TextColor = Constants.BlackTextColor; + const BlueColor = Constants.GreyTextColor; + bool isWriter = + programInfo['UserId'] == UserData().basicInfo.userId; //是否发布者 + bool isReplyer = data['UserId'] == UserData().basicInfo.userId; //是否评论者 + replay() { + Navigator.of(context).pop(); + CustomUI.showContentDialog( + registKey.currentContext, programInfo['Id'], data['Pid'], 1, (data) { + programInfo['EvaluateNum']++; + evaluateList.add(data); + setState(() {}); + }, + replyUserId: data['UserId'], + replyUserName: Provider.of(context) + .getRefName(data['UserId'], data['NickName']), + isMyself: isMyself); + } + + inform() async { + var resdata = { + "reportuserId": UserData().basicInfo.userId, + "userid": data['UserId'], + }; + resdata['sign'] = TokenMgr().getSign(resdata); + resdata['type'] = 4; + resdata['objectId'] = data['Pid']; + resdata['reason'] = 0; + + resdata["imgurl"] = ''; + resdata["explain"] = ''; + Response res = await HttpUtil().post('report/user/insert', data: resdata); + Map resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + Navigator.of(context).pop(); + } + } + + delete() async { + var resdata = { + "userId": UserData().basicInfo.userId, + "pId": data['Pid'], + }; + resdata['sign'] = TokenMgr().getSign(resdata); + + Response res = await HttpUtil() + .post('station/delete/evaluate', data: resdata, isShowLoading: true); + Map resData = res.data; + if (resData['code'] == 0) { + Navigator.of(context).pop(); + programInfo['EvaluateNum']--; + getData(); + } + } + + double fontSize = 14; + + //1.不是发布者 + //1.1是评论者则没有选项 + //1.2不是评论者则有回复和举报 + //2.是发布者 + //2.1是评论者则有删除 + //2.2不是评论者则有删除,回复和举报 + return InkWell( + onTap: !isWriter && isReplyer + ? null + : () { + double height = 50.0; + List list = []; + if (!isWriter && !isReplyer) + list = [ + _buildBottomSheetItem( + I18n.of(context).reply, height, replay), + _buildBottomSheetItem( + I18n.of(context).report, height, inform), + ]; + if (isWriter && isReplyer) + list = [ + _buildBottomSheetItem( + I18n.of(context).delete, height, delete), + ]; + if (isWriter && !isReplyer) + list = [ + _buildBottomSheetItem( + I18n.of(context).delete, height, delete), + _buildBottomSheetItem( + I18n.of(context).reply, height, replay), + _buildBottomSheetItem( + I18n.of(context).report, height, inform), + ]; + + //回复不能回复自己 ,只有发布者才能删除评论 + showModalBottomSheet( + context: registKey.currentContext, + builder: (BuildContext context) { + return new Container( + height: height * list.length, + child: Column( + children: list, + ), + ); + }, + ).then((val) {}); + }, + child: Container( + padding: EdgeInsets.only(bottom: 3), + child: RichText( + text: TextSpan( + children: data['ReplyUserId'] == 0 + ? [ + TextSpan( + text: Provider.of(context) + .getRefName(data['UserId'], data['NickName']), + style: TextStyle( + fontSize: fontSize, + textBaseline: TextBaseline.alphabetic, + color: BlueColor, + fontWeight: FontWeight.w500), + ), + TextSpan( + text: ': ${data['Content']}', + style: TextStyle( + color: TextColor, + textBaseline: TextBaseline.alphabetic, + fontSize: fontSize), + ) + ] + : [ + TextSpan( + text: Provider.of(context) + .getRefName(data['UserId'], data['NickName']), + style: TextStyle( + fontSize: fontSize, + textBaseline: TextBaseline.alphabetic, + color: BlueColor, + fontWeight: FontWeight.w500), + ), + TextSpan( + text: ' ${I18n.of(context).reply} ', + style: TextStyle( + fontSize: fontSize, + textBaseline: TextBaseline.alphabetic, + color: TextColor, + fontWeight: FontWeight.w500), + ), + TextSpan( + text: data['ReplyNickName'], + style: TextStyle( + fontSize: fontSize, + textBaseline: TextBaseline.alphabetic, + color: BlueColor, + fontWeight: FontWeight.w500), + ), + TextSpan( + text: ': ${data['Content']}', + style: TextStyle( + color: TextColor, + textBaseline: TextBaseline.alphabetic, + fontSize: fontSize), + ) + ]), + ), + )); + } + + Widget _buildJoinItem(data) { + Widget basicInfo = Row(children: [ + Padding( + padding: EdgeInsets.only(left: 10, right: 5), + child: Stack( + children: [ + Padding( + padding: EdgeInsets.only(right: 10), + child: ClipRRect( + borderRadius: BorderRadius.circular(6.0), + child: CachedNetworkImage( + height: 45, + width: 45, + imageUrl: + data['Headimgurl'] == null ? "" : data['Headimgurl'], + placeholder: CustomUI.buildImgLoding, + fit: BoxFit.cover, + ), + ), + ), + Positioned( + right: 5, + bottom: 0, + child: Container( + padding: EdgeInsets.only(bottom: 1.3, left: 0.5), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(20))), + child: Icon( + IconData( + !isMan ? 0xe639 : 0xe638, + fontFamily: 'iconfont', + ), + color: !isMan + ? const Color(0xff0072ff) + : const Color(0xffff0486), + size: 12, + ), + )) + ], + )), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: RichText( + text: TextSpan(children: [ + TextSpan( + text: Provider.of(context) + .getRefName(data['UserId'], data['NickName']), + style: + TextStyle(fontSize: 14, color: Constants.BlackTextColor)), + TextSpan( + text: I18n.of(context).signed_up.replaceFirst('/s1', ''), + style: + TextStyle(fontSize: 13, color: Constants.GreyTextColor)), + ])), + ), + Text( + '${data['CreateTime']}', + textScaleFactor: 1.0, + style: TextStyle(color: Constants.LightGreyTextColor, fontSize: 12), + ), + ], + )), + InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return InformUserPage( + isMan: !isMan, + userId: data['UserId'], + ); + }, + ), + ); + }, + child: Container( + padding: EdgeInsets.only(left: 10, right: 10, bottom: 10), + alignment: Alignment.topRight, + child: Text( + I18n.of(context).report, + textScaleFactor: 1.0, + style: TextStyle(color: Constants.BlackTextColor), + ))) + ]); + + Widget img = Container( + child: Row( + children: [ + InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return PicSwiper( + id: 0, pics: [PicSwiperItem(data['ImgUrl'], id: 0)]); + }, + ), + ); + }, + child: Container( + margin: EdgeInsets.only(top: 10, left: 60), + height: 80, + width: 100, + decoration: + BoxDecoration(borderRadius: BorderRadius.circular(2.0)), + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: CachedNetworkImage( + imageUrl: data['ImgUrl'] == null ? "" : data['ImgUrl'], + placeholder: CustomUI.buildImgLoding, + fit: BoxFit.cover, + ), + ))), + Expanded( + child: Container( + height: 90, + alignment: Alignment.bottomRight, + child: InkWell( + child: Container( + margin: EdgeInsets.only(right: 10), + decoration: BoxDecoration( + color: const Color(0xFF547CFF), + borderRadius: BorderRadius.all(Radius.circular(5))), + padding: + EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5), + child: Text( + !isMan + ? I18n.of(context).talk_him + : I18n.of(context).contact_her, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white, fontSize: 13), + ), + ), + onTap: () { + int fdId = data['UserId']; + int sessionId = UserData().getSessionId(fdId); + + MsgHandler.updateActiveSesstion(sessionId); + AppNavigator.pushChatPage(context, fdId); + }, + ), + ), + ) + ], + ), + ); + + return Container( + padding: EdgeInsets.only(top: 10, bottom: 10), + decoration: BoxDecoration( + color: Colors.grey[100], + borderRadius: BorderRadius.all(Radius.circular(10))), + margin: EdgeInsets.only(top: 10), + width: MediaQuery.of(context).size.width * 0.95, + child: Column( + children: [basicInfo, img], + )); + } + + Widget _buildJoinList() { + if (enrollList == null || enrollList.length == 0) { + return Container(); + } + return isMyself + ? Container( + child: Column( + children: enrollList.map((data) { + return _buildJoinItem(data); + }).toList(), + ), + ) + : Container(); + } + + Widget _buildContent() { + if (evaluateList == null || evaluateList.length == 0) { + return Container(); + } + const maxNum = 2; + + Widget button = InkWell( + highlightColor: Colors.transparent, + radius: 0, + onTap: () { + setState(() { + showAllContent = !showAllContent; + }); + }, + child: Padding( + padding: EdgeInsets.only(top: 5, bottom: 5), + child: Row( + children: [ + Text( + !showAllContent + ? I18n.of(context).expand + : I18n.of(context).collapse, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 12, color: Colors.grey), + ), + Icon( + !showAllContent + ? Icons.keyboard_arrow_down + : Icons.keyboard_arrow_up, + size: 18, + color: Colors.grey, + ) + ], + ), + ), + ); + List list = []; + + int showNum = evaluateList.length; + if (evaluateList.length >= maxNum && !showAllContent) { + showNum = maxNum; + } + + for (int i = 0; i < showNum; i++) { + var data = evaluateList[i]; + list.add(_buildReply(data)); + } + if (evaluateList.length > maxNum) { + list.add(button); + } + return Container( + padding: EdgeInsets.only(left: 23, top: 10, right: 8, bottom: 10), + color: Colors.white, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: list, + )); + } + + Widget _buildBody() { + return new ListView( + children: isLoadingFish + ? [ + MessageBox(isDetail: true, programInfo: programInfo), + // _buildBigImg(programInfo), + // _buildImgList(), + _buildContent(), + _buildJoinList(), + ] + : [], + ); + } + + @override + void dispose() { + registKey = null; + MessageMgr().off('update_dy', msgUpdateDy); + MessageMgr().off('delete_program', msgDeleteProgram); + MessageMgr().off('refresh_list', msgRefreshList); + super.dispose(); + } +} diff --git a/lib/home/Registerpage.dart b/lib/home/Registerpage.dart new file mode 100644 index 0000000..b13a803 --- /dev/null +++ b/lib/home/Registerpage.dart @@ -0,0 +1,491 @@ +import 'dart:async'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:wifi_info_plugin/wifi_info_plugin.dart'; + +import 'package:oktoast/oktoast.dart'; +import '../utils/OtherLogin.dart'; + +const RATE_NUM = 0.82; + +const BlueColor = Constants.BlueTextColor; + +enum PageType { + register, + changePWD, + bindPhone, +} + +class RegisterPage extends StatefulWidget { + @required + final int type; + RegisterPage({Key key, this.type}); + + _RegisterPageState createState() => _RegisterPageState(); +} + +class _RegisterPageState extends State { + String _phoneNumber = ''; + + String _selectType = UserData().language == LanguageType.Vietnamese + ? phone.keys.toList()[1] + : phone.keys.toList()[0]; + + String _verifyCode = ''; + + String _passWorld = ''; + // String _rePassWorld = ''; + + bool isChangePWD = false; + + int _seconds = 0; + + String _verifyStr = ''; + + Timer _timer; + + @override + void initState() { + super.initState(); + isChangePWD = widget.type == PageType.changePWD.index; + } + + @override + void dispose() { + _cancelTimer(); + super.dispose(); + } + + _startTimer() { + _seconds = 60 * 5; + _timer = new Timer.periodic(new Duration(seconds: 1), (timer) { + _seconds--; + _verifyStr = '$_seconds(s)'; + setState(() {}); + if (_seconds == 0) { + _verifyStr = I18n.of(context).send_again; + _cancelTimer(); + } + }); + } + + _cancelTimer() { + _timer?.cancel(); + } + + @override + Widget build(BuildContext context) { + String title = I18n.of(context).number_registration; + if (widget.type == PageType.changePWD.index) { + title = I18n.of(context).change_password; + } else if (widget.type == PageType.bindPhone.index) { + title = I18n.of(context).bind_phone1; + } + + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + title, + style: TextStyle(color: AppColors.NewAppbarTextColor), + textScaleFactor: 1.0, + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ); + return Scaffold( + appBar: appBar, + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + )), + resizeToAvoidBottomPadding: false, + ); + } + + Widget _buildBody() { + return new Column( + children: [ + _buildAcountInput(), + _buildSecurityInput(), + _buildPasswordInput(), + _buildLoginButton(), + widget.type == PageType.register.index + ? _buildOtherLogin() + : Container(), + ], + ); + } + + //构建底部第三方登陆 + Widget _buildOtherLogin() { + return new Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + new Container( + alignment: Alignment.bottomCenter, + child: OtherLogin().builder(context), + ) + ], + ), + ); + } + + //账号输入框 + Widget _buildAcountInput() { + double height = 54.5; + return new Container( + alignment: Alignment.center, + margin: EdgeInsets.only(top: 8.5), + height: height, + padding: EdgeInsets.only(left: 17), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, + bottom: Constants.GreyBorderSide)), + child: Stack( + children: [ + Container( + width: Screen.width, + height: height, + alignment: Alignment.centerLeft, + child: Icon( + Icons.phone_android, + color: BlueColor, + size: Constants.TextFieldIconSize, + ), + ), + Positioned( + left: 46, + child: Container( + padding: EdgeInsets.only(top: 5), + margin: EdgeInsets.all(0), + alignment: Alignment.centerLeft, + child: new DropdownButtonHideUnderline( + child: new DropdownButton( + items: phone.keys.map((key) { + return DropdownMenuItem( + child: new Text(key, textScaleFactor: 1.0), + value: key, + ); + }).toList(), + onChanged: (value) { + setState(() { + _selectType = value; + }); + }, + value: _selectType, + elevation: 24, //设置阴影的高度 + style: new TextStyle( + //设置文本框里面文字的样式 + color: Constants.BlackTextColor, + fontSize: 12, + ), + iconSize: 25.0, + )), + ), + ), + Positioned( + left: 90, + child: Container( + alignment: Alignment.center, + width: Screen.width - 90, + height: height, + child: TextField( + keyboardAppearance: Brightness.light, + decoration: new InputDecoration( + hintText: I18n.of(context).enter_number, + hintStyle: TextStyle(fontSize: 14), + border: InputBorder.none, + ), + maxLines: 1, + style: TextStyle(textBaseline: TextBaseline.alphabetic), + inputFormatters: [ + WhitelistingTextInputFormatter.digitsOnly, + ], + onChanged: (str) { + _phoneNumber = str; + setState(() {}); + }, + keyboardType: TextInputType.phone, + ), + ), + ) + ], + )); + } + + //验证码 + Widget _buildSecurityInput() { + Widget verifyCodeEdit = new TextField( + keyboardAppearance: Brightness.light, + decoration: new InputDecoration( + hintText: I18n.of(context).enter_code, + hintStyle: TextStyle(fontSize: 14), + icon: new Icon( + Icons.security, + color: BlueColor, + size: Constants.TextFieldIconSize, + ), + border: InputBorder.none, + ), + maxLines: 1, + keyboardType: TextInputType.number, + style: TextStyle(textBaseline: TextBaseline.alphabetic), + inputFormatters: [ + WhitelistingTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(6) + ], + onChanged: (str) { + _verifyCode = str; + setState(() {}); + }, + ); + + void getSms() async { + var data = { + "mobile": phone[_selectType] + _phoneNumber, + "type": 0, + "language": UserData().language, + }; + data['sign'] = TokenMgr().getSign(data); + + try { + Response res = await HttpUtil() + .post('user/send/sms', data: data, isShowLoading: true); + var resData = res.data; + if (resData['code'] == 0) { + setState(() { + _startTimer(); + }); + } else { + showToast(resData['msg']); + } + } catch (e) {} + } + + Widget verifyCodeBtn = new InkWell( + onTap: (_seconds == 0) + ? () { + if (_phoneNumber == null || _phoneNumber == "") { + showToast(I18n.of(context).enter_number); + return; + } + getSms(); + } + : null, + child: new Container( + margin: EdgeInsets.only(right: 21.5), + padding: EdgeInsets.symmetric(vertical: 4, horizontal: 6), + decoration: BoxDecoration( + border: Border.all(color: BlueColor), + borderRadius: BorderRadius.all(Radius.circular(15))), + alignment: Alignment.center, + child: new Text( + '${_verifyStr == '' ? I18n.of(context).send_code : _verifyStr}', + textScaleFactor: 1.0, + style: new TextStyle(fontSize: 11.34, color: BlueColor), + ), + ), + ); + return new Container( + alignment: Alignment.center, + height: 54.5, + padding: EdgeInsets.only(left: 17), + decoration: BoxDecoration( + color: Colors.white, + border: Border(bottom: Constants.GreyBorderSide)), + child: new Stack( + alignment: Alignment.center, + children: [ + verifyCodeEdit, + Positioned( + right: 0, + child: verifyCodeBtn, + ) + ], + ), + ); + } + + //密码 + Widget _buildPasswordInput() { + return new Container( + alignment: Alignment.center, + height: 54.5, + padding: EdgeInsets.only(left: 17), + decoration: BoxDecoration( + color: Colors.white, + border: Border(bottom: Constants.GreyBorderSide)), + child: new TextField( + keyboardAppearance: Brightness.light, + decoration: new InputDecoration( + hintText: I18n.of(context).set_password2, + hintStyle: TextStyle(fontSize: 14), + icon: new Icon( + Icons.lock, + color: BlueColor, + size: Constants.TextFieldIconSize, + ), + border: InputBorder.none, + ), + maxLines: 1, + inputFormatters: [LengthLimitingTextInputFormatter(20)], + obscureText: true, + style: TextStyle(textBaseline: TextBaseline.alphabetic), + onChanged: (str) { + _passWorld = str; + setState(() {}); + }, + ), + ); + } + + // //密码 + // Widget _buildRePasswordInput() { + // return new Container( + // child: new TextField( + // decoration: new InputDecoration( + // hintText: '请重新输入登陆密码', + // icon: new Icon(Icons.lock), + // border: InputBorder.none, + // ), + // maxLines: 1, + // obscureText: true, + // onChanged: (str) { + // _rePassWorld = str; + // setState(() {}); + // }, + // ), + // width: MediaQuery.of(context).size.width * RATE_NUM, + // ); + // } + + //下一步按钮 + Widget _buildLoginButton() { + Text text = new Text(I18n.of(context).submit, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: Constants.ShaderButtonFontSize, color: Colors.white)); + + void postRegister(phoneNum) async { + var type = 0; + if (widget.type == PageType.register.index) { + type = 0; + } else if (widget.type == PageType.bindPhone.index) { + type = 1; + } else { + return; + } + + var data = { + "mobile": phoneNum, + "code": _verifyCode, + "pwd": _passWorld, + "cPwd": _passWorld, + "type": type, + "language": UserData().language, + }; + data['sign'] = TokenMgr().getSign(data); + data['userid'] = UserData().basicInfo.userId; + data['lng'] = UserData().longitude; + data['lat'] = UserData().latitude; + + try { + WifiInfoWrapper wifiObject = await WifiInfoPlugin.wifiDetails; + if (wifiObject != null) { + data['routerName'] = wifiObject.ssid; + data['mac'] = wifiObject.bssId; + } + } catch (e) { + print(e); + } + try { + Response res = await HttpUtil() + .post('user/binding/mobile', data: data, isShowLoading: true); + var resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + UserData().mobile = int.parse(phoneNum); + if (widget.type == PageType.register.index) { + HttpUtil().login(phoneNum, _passWorld, context); + } + if (widget.type == PageType.bindPhone.index) { + Navigator.of(context).pop(); + } + } + } catch (e) {} + } + + void postChangePwd(phoneNum) async { + var data = { + "mobile": phoneNum, + "code": _verifyCode, + "newpassword": _passWorld, + "confirmPassword": _passWorld, + }; + data['sign'] = TokenMgr().getSign(data); + try { + Response res = await HttpUtil() + .post('password/setting/password', data: data, isShowLoading: true); + var resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + Navigator.of(context).pop(); + } + } catch (e) {} + } + + callback() { + if (_phoneNumber == null || _phoneNumber == "") { + showToast(I18n.of(context).enter_number); + return; + } + if (_verifyCode == null || _verifyCode == "" || _verifyCode.length != 6) { + showToast(I18n.of(context).enter_code); + return; + } + if (_passWorld == null || _passWorld == "") { + showToast(I18n.of(context).enter_password); + return; + } + if (_passWorld.length < 6) { + showToast(I18n.of(context).password_limit); + return; + } + var phoneNum = phone[_selectType] + _phoneNumber; + !isChangePWD ? postRegister(phoneNum) : postChangePwd(phoneNum); + } + + return InkWell( + onTap: callback, + child: Container( + margin: EdgeInsets.only(top: 60), + alignment: Alignment.center, + height: Constants.ShaderButtonHeight, + width: Screen.width * RATE_NUM, + decoration: BoxDecoration( + color: Constants.ConfrimButtonColor, + border: + Border.all(color: AppColors.NewAppbarTextColor.withAlpha(140)), + borderRadius: + BorderRadius.all(Radius.circular(Constants.BigButtonRadius))), + child: text, + ), + ); + } +} diff --git a/lib/home/SearchPage.dart b/lib/home/SearchPage.dart new file mode 100644 index 0000000..e110fc1 --- /dev/null +++ b/lib/home/SearchPage.dart @@ -0,0 +1,255 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/UserCard.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; + +class SearchPage extends StatefulWidget { + @override + _SearchPageState createState() => _SearchPageState(); +} + +class _SearchPageState extends State { + RefreshController _refreshController = + RefreshController(initialRefresh: false); + TextEditingController _txtCtrl = new TextEditingController(); + List list = new List(); //列表要展示的数据 + int _page = 1; //加载的页数 + int rows = 20; + bool isLoading = false; //是否正在加载数据 + + bool _hasdeleteIcon = false; + + @override + void initState() { + super.initState(); + MessageMgr().on('refresh_love_list', msgRefreshLoveList); + } + + msgRefreshLoveList(data) { + for (int i = 0; i < list.length; i++) { + var item = list[i]; + if (item['UserId'] == data['UserId']) { + item['Follow'] = data['flag']; + break; + } + } + setState(() {}); + } + + //获取新的数据 + void getNewData() { + _page = 1; + getData((data) { + list.clear(); + if (data != null) { + list.addAll(data); + } + setState(() {}); + }); + } + + void getMoreData() { + _page++; + getData((data) { + data == null || data.length == 0 ? _page-- : list.addAll(data); + setState(() {}); + }); + } + + void getData(callback) async { + var data = { + "userId": UserData().basicInfo.userId, + "language": UserData().language, + "value": _txtCtrl.text, + }; + data['sign'] = TokenMgr().getSign(data); + data['lng'] = UserData().longitude; + data['lat'] = UserData().latitude; + data['page'] = _page; + data['rows'] = rows; + data['sex'] = UserData().basicInfo.sex; + Response res = await HttpUtil().post('user/search/userList', data: data); + isLoading = false; + _refreshController.refreshCompleted(); + var resData = res.data; + print(resData); + if (resData['code'] == 0) { + callback(resData['data']); + } + } + + @override + void dispose() { + _refreshController.dispose(); + _txtCtrl.dispose(); + MessageMgr().off('refresh_love_list', msgRefreshLoveList); + super.dispose(); + } + + searchUser() {} + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + titleSpacing: 0, + leading: CustomUI.buildCustomLeading(context), + title: Container( + alignment: Alignment.center, + margin: const EdgeInsets.only(top: 20, bottom: 20, right: 20), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.all(Radius.circular(10))), + child: new TextField( + keyboardAppearance: Brightness.light, + keyboardType: TextInputType.text, + textInputAction: TextInputAction.search, + controller: _txtCtrl, + maxLines: 1, + style: TextStyle( + textBaseline: TextBaseline.alphabetic, + fontSize: 14, + color: AppColors.NewAppbarTextColor), + autofocus: true, + inputFormatters: [ + LengthLimitingTextInputFormatter(50), + ], + decoration: InputDecoration( + hintText: I18n.of(context).search_user, + hintStyle: TextStyle(fontSize: 14, color: Colors.grey), + suffixIcon: Padding( + padding: EdgeInsetsDirectional.only( + start: 2.0, end: _hasdeleteIcon ? 20.0 : 0), + child: _hasdeleteIcon + ? new InkWell( + onTap: (() { + setState(() { + WidgetsBinding.instance.addPostFrameCallback( + (_) => _txtCtrl.clear()); + _hasdeleteIcon = false; + }); + }), + child: Icon( + Icons.clear, + size: 18.0, + color: Constants.BlackTextColor, + )) + : new Text('')), + filled: true, + contentPadding: + EdgeInsets.only(left: 20, top: 14, bottom: 14), + fillColor: Colors.transparent, + border: InputBorder.none, + ), + onChanged: (str) { + setState(() { + if (str.isEmpty) { + _hasdeleteIcon = false; + } else { + _hasdeleteIcon = true; + } + }); + }, + onEditingComplete: () { + setState(() { + isLoading = true; + getNewData(); + }); + }), + ), + ), + body: SafeArea( + child: Stack( + children: [ + SmartRefresher( + enablePullDown: list.length > 0, + enablePullUp: true, + header: MaterialClassicHeader(), + footer: CustomUI.buildLoadingFooter(), + controller: _refreshController, + onRefresh: _onRefresh, + onLoading: _onLoading, + child: + (_refreshController.headerStatus == RefreshStatus.completed && + list.length == 0) + ? CustomUI.buildNoData(context) + : ListView.builder( + itemBuilder: _renderRow, + itemCount: list.length, + ), + ), + isLoading ? CustomUI.buildLoaingAnim(context) : Container(), + ], + ))); + } + + Widget _renderRow(BuildContext context, int index) { + if (index < list.length) { + var userInfo = list[index]; + var refName = Provider.of(context) + .getRefName(userInfo['UserId'], userInfo['NickName']); + + return UserCard( + key: UniqueKey(), + nameSize: 14, + userName: refName == userInfo['NickName'] + ? userInfo['NickName'] + : WebData().subUserName(refName, size: 4) + + '(${WebData().subUserName(userInfo['NickName'], size: 2)})', + city: WebData().getCountry( + userInfo['Country']), //WebData().getCity(userInfo['City']), + headUrl: userInfo['Headimgurl'], + isReal: userInfo['IsAttestation'] == 1, + constellation: + WebData().getConstellation(context, userInfo['Constellation']), + distance: userInfo['Distance'].toDouble(), + age: userInfo['Age'], + professional: WebData().getProffesionName(userInfo['Occupation']), + isOnline: userInfo['OnlineStatus'] == 1 + ? I18n.of(context).online + : WebData().getLoginTime(context, userInfo['LoginDate']), + sex: userInfo['Sex'], + hiddenDistince: userInfo['DistanceStatus'] == 1, + isLove: userInfo['Follow'] == 0, + isBalck: userInfo['Follow'] == 1, + userId: userInfo['UserId'], + payImg: userInfo['PhotoAut'] == 1, + isHidden: userInfo['InfoAut'] == 1, + member: userInfo['IsMember'], + imgNum: userInfo['PhotoNum'], + ); + } + return Container(); + } + + Future _onRefresh() async { + getNewData(); + } + + Future _onLoading() async { + _page++; + getData((data) { + if (data == null || data.length == 0) { + _page--; + _refreshController.loadNoData(); + } else { + list.addAll(data); + _refreshController.loadComplete(); + } + setState(() {}); + }); + } +} diff --git a/lib/home/SelectPage.dart b/lib/home/SelectPage.dart new file mode 100644 index 0000000..a724fae --- /dev/null +++ b/lib/home/SelectPage.dart @@ -0,0 +1,183 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:flutter/material.dart'; + +import 'package:oktoast/oktoast.dart'; + +//自定义 地址选择 +class SelectPage extends StatefulWidget { + @required + final String title; + @required + final dataId; + final str; + final callback; + final provinces; + final cities; + final isSingle; + final int mostNum; + SelectPage( + {Key key, + this.str, + this.title, + this.dataId, + this.callback, + this.provinces, + this.cities, + this.isSingle, + this.mostNum}) + : super(key: key); + _SelectPageState createState() => _SelectPageState(); +} + +class _SelectPageState extends State { + String leftSelection; + Set tempRankId = new Set(); + @override + void initState() { + super.initState(); + leftSelection = widget.provinces.keys.first; + tempRankId = widget.dataId.toSet(); + } + + @override + void dispose() { + tempRankId.clear(); + + super.dispose(); + } + + List _buildLeftSelection() { + List result = []; + widget.provinces.forEach((k, v) => result.add(_buildItem(k, v, true))); + return result; + } + + List _buildRightSelection() { + List result = []; + widget.cities[leftSelection].forEach( + (k, v) => result.add(_buildItem('$leftSelection-$k', v, false))); + return result; + } + + Widget _buildItem(key, value, isLeft) { + return InkWell( + onTap: () { + if (isLeft) { + setState(() { + leftSelection = key; + }); + } else { + setState(() { + // //常驻城市不能跨国家选中 + if (!widget.isSingle && + tempRankId.length > 0 && + tempRankId.first.split('-')[0] != leftSelection) { + showToast('常驻城市不能跨国家'); + return; + } + if (tempRankId.contains(key)) { + if (!widget.isSingle) tempRankId.remove(key); + } else { + if (tempRankId.length >= widget.mostNum) { + showToast(I18n.of(context) + .most + .replaceFirst('/s1', widget.mostNum.toString())); + return; + } + tempRankId.add(key); + } + }); + //单选直接关闭 + if (widget.isSingle) { + if (widget.dataId.length != 0 && tempRankId.length >= 2) { + tempRankId.remove(widget.dataId.first); + } + widget.callback(tempRankId); + } + } + }, + highlightColor: Colors.transparent, + radius: 0.0, + child: new Container( + height: 50, + child: new Align( + alignment: Alignment.center, + child: new Text( + value, + textScaleFactor: 1.0, + style: isLeft + ? TextStyle( + color: leftSelection == key + ? Colors.white + : Constants.BlackTextColor) + : TextStyle( + color: tempRankId.contains(key) + ? Constants.BlueTextColor + : Constants.BlackTextColor), + ), + ), + decoration: BoxDecoration( + color: + leftSelection == key ? Constants.BlueTextColor : Colors.white, + border: Border(top: BorderSide(color: Colors.grey, width: 0.5)), + ), + )); + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + title: new Text(widget.title, textScaleFactor: 1.0), + elevation: 0, + leading: CustomUI.buildCustomLeading(context), + actions: [ + new Container( + alignment: Alignment.center, + child: new InkWell( + child: new Padding( + padding: + EdgeInsets.only(right: 15, left: 15, top: 10, bottom: 10), + child: new Text(I18n.of(context).determine, + textScaleFactor: 1.0, style: Constants.AppBarActionTextStyle), + ), + onTap: () { + widget.callback(tempRankId); + }, + ), + ) + ], + centerTitle: true, + ); + return Scaffold( + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: Row( + children: [ + Container( + width: MediaQuery.of(context).size.width * 0.5, + child: ListView( + children: _buildLeftSelection(), + ), + decoration: BoxDecoration( + border: + Border(right: BorderSide(color: Colors.grey, width: 1)), + )), + Container( + width: MediaQuery.of(context).size.width * 0.5, + child: ListView( + children: _buildRightSelection(), + ), + ), + ], + ), + ), + )), + appBar: appBar, + ); + } +} diff --git a/lib/home/SelectSexPage.dart b/lib/home/SelectSexPage.dart new file mode 100644 index 0000000..d11854c --- /dev/null +++ b/lib/home/SelectSexPage.dart @@ -0,0 +1,379 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/IndexPage.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/TutorialOverlay.dart'; +import 'package:flutter/material.dart'; +import '../utils/ShadowButton.dart'; +import '../home/EditData.dart'; +import '../data/UserData.dart'; +import '../utils/TokenMgr.dart'; +import 'package:dio/dio.dart'; +import '../utils/HttpUtil.dart'; + +double opacityRate = 0.4; + +class SelectSex extends StatefulWidget { + SelectSex({Key key}) : super(key: key); + + _SelectSexState createState() => _SelectSexState(); +} + +class _SelectSexState extends State { + int boyFlag = 1; + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + title: new Text(I18n.of(context).who, textScaleFactor: 1.0), + centerTitle: true, + elevation: 0, + // leading: IconButton( + // onPressed: () { + // HttpUtil().clearCacheData(); + // Navigator.of(context).pushAndRemoveUntil(new MaterialPageRoute( + // builder: (context) { + // return IndexPage(); + // }, + // ), (route) => route == null); + // }, + // icon: Icon(Icons.arrow_back), + // ), + leading: CustomUI.buildCustomLeading(context, onTap: () { + HttpUtil().clearCacheData(); + Navigator.of(context).pushAndRemoveUntil(new MaterialPageRoute( + builder: (context) { + return IndexPage(); + }, + ), (route) => route == null); + }), + ); + return Scaffold( + backgroundColor: Colors.white, + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + )), + appBar: appBar, + ); + } + + Widget _buildBody() { + return new Column( + children: [ + _buildTips(), + _buildSex(), + _buildRegisterButton(), + ], + ); + } + + Widget _buildTips() { + return new Container( + alignment: Alignment.center, + child: new Text( + I18n.of(context).cannot_modified, + textScaleFactor: 1.0, + style: TextStyle(color: const Color(0xFF787878), fontSize: 14), + ), + ); + } + + postSexSetting() async { + var sex = this.boyFlag; + Map data = { + "userid": UserData().basicInfo.userId, + "sex": sex, + }; + data['sign'] = TokenMgr().getSign(data); + try { + Response res = await HttpUtil().post('user/setting/sex', data: data); + var resData = res.data; + if (resData['code'] == 0) { + UserData().basicInfo.sex = sex; + Navigator.of(context).pushReplacement(MaterialPageRoute( + builder: (context) => EditPage( + isEditPage: false, + ))); + } else {} + } catch (e) {} + } + + Widget _buildRegisterButton() { + Text text = new Text(I18n.of(context).determine, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 15, color: Colors.white)); + + LinearGradient gradientColor = new LinearGradient(colors: [ + Constants.ConfrimButtonColor, + Constants.ConfrimButtonColor, + ]); + + return new Container( + margin: EdgeInsets.only(top: 10), + height: 44, + width: MediaQuery.of(context).size.width * 0.6, + child: ShadowButton().builder(gradientColor, text, () { + Navigator.of(context).push(TutorialOverlay( + child: Align( + child: Container( + height: 192, + decoration: BoxDecoration( + color: Colors.white, borderRadius: BorderRadius.circular(10)), + alignment: Alignment.center, + width: 298, + child: Column( + children: [ + Align( + alignment: Alignment.centerRight, + child: InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + padding: EdgeInsets.only( + bottom: 10, right: 14, top: 10, left: 14), + child: Icon( + IconData( + 0xe679, + fontFamily: 'iconfont', + ), + size: 17, + color: Colors.grey[400] //const Color(0xFF939393), + )), + ), + ), + Container( + padding: EdgeInsets.only(left: 20, right: 20, top: 12), + child: Text( + I18n.of(context).cannot_modified, + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18), + ), + ), + Container( + margin: EdgeInsets.only(top: 40), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: const Color(0xFF2D81FF)), + borderRadius: BorderRadius.all( + Radius.circular( + Constants.LittleButtonRadius))), + height: 36.5, + width: 93.5, + alignment: Alignment.center, + child: Text( + I18n.of(context).cancel, + style: TextStyle( + fontSize: 15, + color: const Color(0xFF2D81FF), + ), + )), + ), + InkWell( + onTap: postSexSetting, + child: Container( + decoration: Constants.ConfirmBUttonBoxDecoration, + height: 36.5, + width: 93.5, + alignment: Alignment.center, + child: Text( + I18n.of(context).determine, + style: TextStyle( + fontSize: 15, + color: Colors.white, + ), + )), + ), + ], + )) + ], + ), + ), + ))); + // CustomUI.buildOneConfirm(context, I18n.of(context).cannot_modified, + // I18n.of(context).determine, postSexSetting); + }), + ); + } + + Widget _buildPostion(flag, color) { + return Positioned( + right: 0, + top: 10, + child: flag + ? Container( + padding: EdgeInsets.zero, + margin: EdgeInsets.zero, + decoration: BoxDecoration(shape: BoxShape.circle, color: color), + child: Icon( + Icons.check, + color: Colors.white, + size: 20, + )) + : Container(), + ); + } + + Widget _buildSex() { + Widget pictureMan = new Align( + alignment: Alignment.centerLeft, + child: Image.asset( + 'assets/images/login/xzxb_male.png', + width: MediaQuery.of(context).size.width * 0.53, + ), + ); + Widget pictureWomen = new Align( + alignment: Alignment.centerRight, + child: Image.asset( + 'assets/images/login/xzxb_female.png', + width: MediaQuery.of(context).size.width * 0.53, + ), + ); + Widget manBox = new Align( + alignment: Alignment.center, + child: Stack( + children: [ + Container( + height: 100, + width: 100, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + boxShadow: boyFlag == 1 + ? [ + BoxShadow( + color: const Color(0xBF045080), + offset: Offset(0, 2.5), + blurRadius: 4, + ) + ] + : [], + border: new Border.all(color: Color(0xFF0767A4), width: 3), + ), + child: new InkWell( + onTap: () { + setState(() { + boyFlag = 1; + }); + }, + highlightColor: Colors.transparent, + radius: 0.0, + child: new Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + new Text( + I18n.of(context).boy, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 30, color: const Color(0xFF0767A4)), + ), + UserData().language == LanguageType.English + ? Container() + : new Text( + 'Male', + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 11, color: const Color(0xFF0767A4)), + ) + ], + )), + ), + _buildPostion(boyFlag == 1, const Color(0xFF0767A4)) + ], + )); + + Widget womanBox = Align( + alignment: Alignment.center, + child: Stack(children: [ + InkWell( + onTap: () { + setState(() { + boyFlag = 2; + }); + }, + highlightColor: Colors.transparent, + radius: 0.0, + child: Container( + alignment: Alignment.center, + height: 100, + width: 100, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + boxShadow: boyFlag == 2 + ? [ + BoxShadow( + color: const Color(0xBF720041), + offset: Offset(0, 2.5), + blurRadius: 4, + ) + ] + : [], + border: Border.all(color: Color(0xFFE80D89), width: 3), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + I18n.of(context).girl, + textScaleFactor: 1.0, + style: + TextStyle(fontSize: 30, color: const Color(0xFFE80D89)), + ), + UserData().language == LanguageType.English + ? Container() + : Text( + 'Female', + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 11, color: const Color(0xFFE80D89)), + ) + ], + )), + ), + _buildPostion(boyFlag == 2, const Color(0xFFE80D89)) + ]), + ); + + return new Stack( + children: [ + Opacity( + opacity: boyFlag == 1 ? 1.0 : opacityRate, + child: pictureMan, + ), + Opacity( + opacity: boyFlag == 2 ? 1 : opacityRate, + child: pictureWomen, + ), + new Column( + children: [ + SizedBox(height: MediaQuery.of(context).size.height * 0.68 * 0.2), + Opacity( + opacity: boyFlag == 1 ? 1 : opacityRate, + child: manBox, + ), + SizedBox(height: MediaQuery.of(context).size.height * 0.68 * 0.14), + Opacity( + opacity: boyFlag == 2 ? 1 : opacityRate, + child: womanBox, + ), + ], + ) + ], + ); + } +} diff --git a/lib/home/SystemEditPage.dart b/lib/home/SystemEditPage.dart new file mode 100644 index 0000000..87470c2 --- /dev/null +++ b/lib/home/SystemEditPage.dart @@ -0,0 +1,533 @@ +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/BindCode.dart'; +import 'package:chat/home/UserAgreement.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/local_notification_util.dart'; +import 'package:chat/utils/receive_share_file.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sound_util.dart'; +import 'package:chat/utils/sp_utils.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import '../utils/FullWithButton.dart'; +import '../data/UserData.dart'; +import '../utils/HttpUtil.dart'; +import '../home/Registerpage.dart'; +import '../home/MessagePushPage.dart'; +import 'package:flutter_cache_manager/flutter_cache_manager.dart'; + +import 'PravicySettingPage.dart'; + +var cardWidth; +Map language = { + "0": "English", + "1": "Tiếng việt", + "2": "繁體中文", + "3": "简体中文", + "4": "한국어", + "5": "日本語" +}; +BoxDecoration getCardDecoration() { + return new BoxDecoration( + color: Colors.white, + ); +} + +class SystemEditPage extends StatefulWidget { + SystemEditPage({Key key}) : super(key: key); + + _SystemEditPageState createState() => _SystemEditPageState(); +} + +class _SystemEditPageState extends State { + static const Separate_Size = 15.0; + String _selectType = UserData().language.toString(); + bool soundPlayMode = false; + + @override + void initState() { + super.initState(); + getDefaultSetting(); + } + + void getDefaultSetting() async { + bool soundPlayMode = + (await SPUtils.getBool(Constants.SOUND_PLAY_MODE)) ?? false; + setState(() { + this.soundPlayMode = soundPlayMode; + }); + } + + @override + Widget build(BuildContext context) { + Size screenSize = MediaQuery.of(context).size; + cardWidth = screenSize.width; + + return Scaffold( + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + I18n.of(context).setting2, + style: TextStyle(color: AppColors.NewAppbarTextColor), + textScaleFactor: 1.0, + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ), + body: SafeArea( + child: Container( + color: AppColors.BackgroundColor, + height: MediaQuery.of(context).size.height, + child: SingleChildScrollView( + child: _buildBody(), + )))); + } + + Widget _buildBody() { + return Column( + children: [ + SizedBox(height: Separate_Size), + _buildPravice(), + SizedBox(height: Separate_Size), + _buildMsgSetting(), + SizedBox(height: Separate_Size), + _buildBasicSetting(), + SizedBox(height: Separate_Size), + _clearPictureSetting(), + _soundPlayModeSetting(), + SizedBox(height: Separate_Size), + _buildUserAgreement(), + _buildBindCode(), + _buildMyEvaluation(), + _buildVersion(), + _buildHelp(), + SizedBox(height: Separate_Size), + _buildLogout(), + SizedBox(height: Separate_Size), + ], + ); + } + + //有问题需要帮助 + Widget _buildHelp() { + return Container( + margin: EdgeInsets.only(top: Separate_Size), + padding: EdgeInsets.symmetric(horizontal: 10), + child: FullWidthButton( + showRightIcon: false, + title: I18n.of(context).need_help, + description: I18n.of(context).need_help2, + showDivider: false, + onPressed: () { + AppNavigator.pushServicePage(context); + }, + ), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, bottom: Constants.GreyBorderSide)), + ); + } + + Widget _buildVersion() { + //版本 + return Container( + margin: EdgeInsets.only(top: Separate_Size), + padding: EdgeInsets.symmetric(horizontal: 10), + child: FullWidthButton( + showRightIcon: false, + title: '${I18n.of(context).current_version} ', + description: Constants.versionName, + showDivider: false, + onPressed: () { +// VersionUtils.versionUpdate(context, fromProfileNeedShow: true); + }, + ), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, bottom: Constants.GreyBorderSide)), + ); + } + + Widget _buildMyEvaluation() { + //版本 + return Container( + margin: EdgeInsets.only(top: Separate_Size), + padding: EdgeInsets.symmetric(horizontal: 10), + child: FullWidthButton( + showRightIcon: true, + title: I18n.of(context).my_evaluation, + showDivider: false, + onPressed: () async { + Map data = { + "userid": UserData().basicInfo.userId, + "evaluateuserid": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil() + .post('evaluate/user/info', data: data, isShowLoading: true); + + Map resData = res.data; + if (resData['code'] == 0) { + _buildMyEvaluate(resData['data']); + } + }, + ), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, bottom: Constants.GreyBorderSide)), + ); + } + + void _buildMyEvaluate(data) { + bool isMan = UserData().isMan(); + var content = Container( + margin: EdgeInsets.only(top: 10.5), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CustomUI.buildBox( + data['Friendly'], + isMan + ? I18n.of(context).courtesy + : I18n.of(context).friendly), + CustomUI.buildBox( + data['Interesting'], I18n.of(context).interesting), + CustomUI.buildBox(data['Refreshing'], I18n.of(context).readily), + ], + ), + SizedBox( + height: 5, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CustomUI.buildBox(data['Patience'], + isMan ? I18n.of(context).generous : I18n.of(context).patient), + CustomUI.buildBox(data['Hello'], + isMan ? I18n.of(context).lie : I18n.of(context).indifferent), + CustomUI.buildBox( + data['Unfriendly'], + isMan + ? I18n.of(context).unfriendly + : I18n.of(context).bad_temper), + ], + ) + ], + ), + ); + CustomUI.buildTip(context, I18n.of(context).your_evaluation, content); + } + + Widget _buildPravice() { + return Container( + padding: EdgeInsets.symmetric(horizontal: 10), + width: cardWidth, + child: FullWidthButton( + title: I18n.of(context).setting, + showDivider: false, + onPressed: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return PravicySettingPage(); + }, + ), + ); + }, + ), + decoration: getCardDecoration(), + ); + } + + //消息通知设置 + Widget _buildMsgSetting() { + return Container( + padding: EdgeInsets.symmetric(horizontal: 10), + width: cardWidth, + child: FullWidthButton( + title: I18n.of(context).push_setting2, + showDivider: false, + onPressed: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return MessagePushPage(); + }, + ), + ); + }, + ), + decoration: getCardDecoration(), + ); + } + + //手机号码·修改密码 + Widget _buildBasicSetting() { + Widget telePhoneSetting = FullWidthButton( + title: I18n.of(context).phone_number, + description: (UserData().mobile == 0 || UserData().mobile == null) + ? '' + : UserData().mobile.toString(), + showDivider: true, + onPressed: () { + if (UserData().mobile != null && UserData().mobile != 0) { + CustomUI.buildOneConfirm(context, I18n.of(context).modify_choose, + I18n.of(context).determine, () { + Navigator.of(context).pop(); + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return RegisterPage( + type: PageType.bindPhone.index, + ); + }, + ), + ); + }); + return; + } + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return RegisterPage( + type: PageType.bindPhone.index, + ); + }, + ), + ); + }, + ); + + Widget changePwd = FullWidthButton( + title: I18n.of(context).change_password, + showDivider: true, + onPressed: () { + if (UserData().mobile == null || UserData().mobile == 0) { + showToast(I18n.of(context).first_bind); + return; + } + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return RegisterPage( + type: PageType.changePWD.index, + ); + }, + ), + ); + }, + ); + + Widget changeLang = Container( + padding: EdgeInsets.only(left: 10), + height: 50, + child: Row( + children: [ + Text(I18n.of(context).language_set, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.normal)), + Expanded( + child: Container(), + ), + Container( + padding: EdgeInsets.all(0), + margin: EdgeInsets.all(0), + child: new DropdownButtonHideUnderline( + child: new DropdownButton( + items: language.keys.map((key) { + return DropdownMenuItem( + child: new Text(language[key], textScaleFactor: 1.0), + value: key, + ); + }).toList(), + onChanged: (value) { + setState(() { + _selectType = value; + changeLanguage(); + }); + }, + value: _selectType, + elevation: 24, //设置阴影的高度 + style: new TextStyle( + //设置文本框里面文字的样式 + color: Constants.BlackTextColor, + fontSize: 12, + ), + iconSize: 25.0, + )), + ) + ], + )); + return Container( + padding: EdgeInsets.symmetric(horizontal: 10), + width: cardWidth, + child: Column( + children: [ + telePhoneSetting, + changePwd, + changeLang, + ], + ), + decoration: getCardDecoration(), + ); + } + + //修改语言 + void changeLanguage() async { + HttpUtil().changeLanguage(context, _selectType, () async { + UserData().language = int.parse(_selectType); + WebData().changeLoaction(UserData().language); + //将用户信息存到本地 + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setInt(Constants.Language, int.parse(_selectType)); + WebData().getAllData(); + Navigator.of(context) + .pushNamedAndRemoveUntil('/main', (route) => route == null); + }, true); + + setStatusBar(); + + } + + //清楚图片缓存 + Widget _clearPictureSetting() { + return Container( + padding: EdgeInsets.symmetric(horizontal: 10), + width: cardWidth, + child: FullWidthButton( + title: I18n.of(context).clear_cache, + showDivider: false, + onPressed: () { + DefaultCacheManager().emptyCache(); + showToast(I18n.of(context).success); + }, + ), + decoration: getCardDecoration(), + ); + } + + ///切换听筒模式-或外放 + Widget _soundPlayModeSetting() { + Widget left = new Text( + I18n.of(context).play_model, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.normal), + ); + Widget right = new Expanded( + child: new Align( + alignment: Alignment.centerRight, + child: new Switch( + value: soundPlayMode, + activeTrackColor: Colors.blue.withOpacity(0.3), + onChanged: (bool val) { + setState(() { + soundPlayMode = val; + }); + SoundUtils.instance.savePlayModeConfig(soundPlayMode); + print('目前: soundPlayMode $soundPlayMode'); +// setDisableScreenshots(); + }, + ))); + return new Container( + decoration: BoxDecoration( + color: Colors.white, + ), + margin: EdgeInsets.only(top: 15, bottom: 0), + padding: EdgeInsets.only(left: 20), + height: 53, + child: new Row( + children: [left, right], + ), + ); + } + + //用户协议 + Widget _buildUserAgreement() { + return Container( + padding: EdgeInsets.symmetric(horizontal: 10), + width: cardWidth, + child: FullWidthButton( + title: I18n.of(context).user_agreement, + showDivider: false, + showRightIcon: false, + onPressed: () async { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return UserAgreement(); + }, + ), + ); + }, + ), + decoration: getCardDecoration(), + ); + } + + //绑定邀请码 + Widget _buildBindCode() { + return Container( + margin: EdgeInsets.only(top: Separate_Size), + padding: EdgeInsets.symmetric(horizontal: 10), + width: cardWidth, + child: FullWidthButton( + title: I18n.of(context).bind_code, + description: + UserData().agentId == 0 ? '' : UserData().agentId.toString(), + showDivider: false, + onPressed: UserData().agentId == 0 + ? () { + if (!UserData().basicInfo.isAttestation) { + CustomUI.buildNotTrue(context); + return; + } + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return BindCodePage(); + }, + ), + ); + } + : () {}, + ), + decoration: getCardDecoration(), + ); + } + + void _buildConfirmLogout() { + CustomUI.buildOneConfirm( + context, I18n.of(context).exit, I18n.of(context).determine, () { + LocalNotificationUtil().removeAlias(); + HttpUtil().postLoginOut(context); + ReceiveShareFile.dispose(); + }); + } + + //退出登陆 + Widget _buildLogout() { + return Container( + padding: EdgeInsets.symmetric(horizontal: 10), + width: cardWidth, + child: FullWidthButton( + showRightIcon: false, + title: I18n.of(context).sign_out, + showDivider: false, + onPressed: _buildConfirmLogout, + ), + decoration: getCardDecoration(), + ); + } +} diff --git a/lib/home/UserAgreement.dart b/lib/home/UserAgreement.dart new file mode 100644 index 0000000..eb3560d --- /dev/null +++ b/lib/home/UserAgreement.dart @@ -0,0 +1,144 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; + +class UserAgreement extends StatefulWidget { + UserAgreement({Key key}) : super(key: key); + + _UserAgreementState createState() => _UserAgreementState(); +} + +class _UserAgreementState extends State { + Widget _buildTitle(str) { + return Container( + margin: EdgeInsets.only(top: 20, bottom: 0), + alignment: Alignment.center, + width: Screen.width, + child: Text( + str, + style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600), + ), + ); + } + + Widget _buildH1(str) { + return Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + alignment: Alignment.centerLeft, + width: Screen.width, + child: Text( + str, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600), + ), + ); + } + + Widget _buildFoot(str) { + return Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + alignment: Alignment.centerRight, + width: Screen.width, + child: Text( + str, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600), + ), + ); + } + + Widget _buildContent(str) { + return Container( + alignment: Alignment.centerLeft, + width: Screen.width, + child: Text( + ' ' + str, + style: TextStyle(fontSize: 14, height: 1.35), + ), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + I18n.of(context).user_agreement, + style: TextStyle(color: AppColors.NewAppbarTextColor), + //I18n.of(context).UG_LINE0, + textScaleFactor: 1.0, + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ), + body: SafeArea( + child: Container( + padding: EdgeInsets.only(left: 5, right: 5), + color: Colors.white, + height: MediaQuery.of(context).size.height, + child: SingleChildScrollView( + child: Column( + children: [ + _buildTitle(I18n.of(context).UG_LINE0), + _buildH1(I18n.of(context).UG_LINE1), + _buildContent(I18n.of(context).UG_LINE2), + _buildContent(I18n.of(context).UG_LINE3), + _buildH1(I18n.of(context).UG_LINE4), + _buildContent(I18n.of(context).UG_LINE5), + _buildContent(I18n.of(context).UG_LINE6), + _buildContent(I18n.of(context).UG_LINE7), + _buildContent(I18n.of(context).UG_LINE8), + _buildContent(I18n.of(context).UG_LINE9), + _buildContent(I18n.of(context).UG_LINE10), + _buildContent(I18n.of(context).UG_LINE11), + _buildContent(I18n.of(context).UG_LINE12), + _buildContent(I18n.of(context).UG_LINE13), + _buildContent(I18n.of(context).UG_LINE14), + _buildContent(I18n.of(context).UG_LINE15), + _buildContent(I18n.of(context).UG_LINE16), + _buildContent(I18n.of(context).UG_LINE17), + _buildContent(I18n.of(context).UG_LINE18), + _buildContent(I18n.of(context).UG_LINE19), + _buildContent(I18n.of(context).UG_LINE20), + _buildContent(I18n.of(context).UG_LINE21), + _buildContent(I18n.of(context).UG_LINE22), + _buildContent(I18n.of(context).UG_LINE23), + _buildContent(I18n.of(context).UG_LINE24), + _buildContent(I18n.of(context).UG_LINE25), + _buildContent(I18n.of(context).UG_LINE26), + _buildContent(I18n.of(context).UG_LINE27), + _buildContent(I18n.of(context).UG_LINE28), + _buildContent(I18n.of(context).UG_LINE29), + _buildH1(I18n.of(context).UG_LINE30), + _buildContent(I18n.of(context).UG_LINE31), + _buildH1(I18n.of(context).UG_LINE32), + _buildContent(I18n.of(context).UG_LINE33), + _buildH1(I18n.of(context).UG_LINE34), + _buildContent(I18n.of(context).UG_LINE35), + _buildContent(I18n.of(context).UG_LINE36), + _buildContent(I18n.of(context).UG_LINE37), + _buildContent(I18n.of(context).UG_LINE38), + _buildContent(I18n.of(context).UG_LINE39), + _buildContent(I18n.of(context).UG_LINE40), + _buildContent(I18n.of(context).UG_LINE41), + _buildContent(I18n.of(context).UG_LINE42), + _buildH1(I18n.of(context).UG_LINE43), + _buildContent(I18n.of(context).UG_LINE44), + _buildContent(I18n.of(context).UG_LINE45), + _buildContent(I18n.of(context).UG_LINE46), + _buildContent(I18n.of(context).UG_LINE47), + _buildContent(I18n.of(context).UG_LINE48), + _buildContent(I18n.of(context).UG_LINE49), + _buildContent(I18n.of(context).UG_LINE50), + _buildH1(I18n.of(context).UG_LINE51), + _buildContent(I18n.of(context).UG_LINE52), + _buildContent(I18n.of(context).UG_LINE53), + _buildContent(I18n.of(context).UG_LINE54), + _buildContent(I18n.of(context).UG_LINE55), + _buildFoot(I18n.of(context).UG_LINE56) + ], + ), + )))); + } +} diff --git a/lib/home/VerificationCenter.dart b/lib/home/VerificationCenter.dart new file mode 100644 index 0000000..f100f9d --- /dev/null +++ b/lib/home/VerificationCenter.dart @@ -0,0 +1,390 @@ +import 'dart:io'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:flutter/material.dart'; + +import 'package:image_picker/image_picker.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:video_player/video_player.dart'; +import '../data/UserData.dart'; +import '../utils/TokenMgr.dart'; +import "package:dio/dio.dart"; +import '../utils/HttpUtil.dart'; +import '../utils/ShadowButton.dart'; + +var cardWidth; + +class VerificationCenterPage extends StatefulWidget { + VerificationCenterPage({Key key}) : super(key: key); + + _VerificationCenterPageState createState() => _VerificationCenterPageState(); +} + +class _VerificationCenterPageState extends State { + String code = ''; + String videoUrl = ''; + String buttonStr = ''; + File videoFile; + int state = 3; + bool isPostVideo = false; + bool isShowPlayButton = true; + VideoPlayerController _controller; + static const Separate_Size = 17.0; + + bool isLoadingFish = false; + + @override + void initState() { + super.initState(); + getInfo(); + } + + @override + void dispose() { + if (_controller != null) { + _controller.dispose(); + } + + super.dispose(); + } + + getInfo() async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + // 0=审核中,1=申请成功,2=申请失败,3未申请 + Response res = await HttpUtil().post('user/female/authInfo', + data: data, failback: () => Navigator.of(context).pop()); + Map resData = res.data; + if (resData['code'] == 0) { + code = resData['data']['Code']; + state = resData['data']['Status']; + if (state == 0 || state == 1) { + isPostVideo = true; + videoUrl = resData['data']['AttestationValue']; + _controller = VideoPlayerController.network(videoUrl) + ..initialize().then((_) { + setState(() {}); + }); + _controller.addListener(() { + if (_controller.value.position >= _controller.value.duration) { + isShowPlayButton = true; + setState(() {}); + } + }); + buttonStr = I18n.of(context).under_review; + } + isLoadingFish = true; + setState(() {}); + } + } + + @override + Widget build(BuildContext context) { + Size screenSize = MediaQuery.of(context).size; + cardWidth = screenSize.width; + + Widget content = Scaffold( + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + I18n.of(context).certification_center, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + elevation: 0, + ), + body: SafeArea( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 10), + color: const Color(0xFFF4F4F4), + height: MediaQuery.of(context).size.height, + child: SingleChildScrollView( + child: _buildBody(), + )))); + return CustomUI.buildPageLoading(context, content, !isLoadingFish); + } + + BoxDecoration getCardDecoration() { + return new BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(230, 230, 230, 1), + offset: Offset(0, 10), + blurRadius: 8, + ) + ], + borderRadius: BorderRadius.all(Radius.circular(10))); + } + + Widget _buildBody() { + return Column( + children: [ + _buildVideo(), + _buildTip1(), + SizedBox(height: Separate_Size), + _buildTip2(), + SizedBox(height: Separate_Size), + _buildTip3(), + SizedBox(height: Separate_Size), + _buildRegisterButton(), + Container( + margin: EdgeInsets.only(top: 10.5, bottom: Separate_Size), + child: Text( + I18n.of(context).after_authentication, + style: TextStyle(fontSize: 12, color: Constants.GreyTextColor), + ), + ), + ], + ); + } + + Widget _buildVideo() { + Widget stack = Stack( + children: [ + Container( + height: 230, + alignment: Alignment.center, + child: _controller != null && _controller.value.initialized + ? AspectRatio( + aspectRatio: _controller.value.aspectRatio, + child: VideoPlayer(_controller), + ) + : Container(), + ), + InkWell( + highlightColor: Colors.transparent, + radius: 0, + onTap: () { + setState(() { + if (!_controller.value.isPlaying) { + _controller.seekTo(Duration()); + _controller.play(); + isShowPlayButton = false; + setState(() {}); + } + }); + }, + child: Container( + height: 230, + alignment: Alignment.center, + child: Container( + color: Colors.black38, + child: Icon( + Icons.play_arrow, + size: _controller != null && _controller.value.isPlaying + ? 0 + : 50, + color: Colors.white, + ), + ))) + ], + ); + Widget img = Container( + child: Image.asset( + 'assets/images/login/rzzx.png', + height: 230, + ), + ); + return (videoUrl == '') ? img : stack; + } + + Widget _buildTip1() { + return Container( + alignment: Alignment.center, + padding: EdgeInsets.only(top: 15, left: 20, right: 20, bottom: 15), + width: cardWidth, + child: Column( + children: [ + Container( + padding: EdgeInsets.only(bottom: 10), + alignment: Alignment.centerLeft, + child: Text( + I18n.of(context).certification_conditions, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Constants.BlackTextColor), + )), + Container( + padding: EdgeInsets.only(bottom: 5), + alignment: Alignment.centerLeft, + child: Text(I18n.of(context).conditions1, textScaleFactor: 1.0)), + Align( + alignment: Alignment.centerLeft, + child: Text(I18n.of(context).conditions2, textScaleFactor: 1.0)), + ], + ), + decoration: getCardDecoration(), + ); + } + + Widget _buildTip2() { + return Container( + alignment: Alignment.center, + padding: EdgeInsets.only(top: 15, left: 20, right: 20, bottom: 15), + width: cardWidth, + child: Column( + children: [ + Container( + padding: EdgeInsets.only(bottom: 10), + alignment: Alignment.centerLeft, + child: Text( + I18n.of(context).verification_method, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Constants.BlackTextColor), + )), + Container( + alignment: Alignment.centerLeft, + child: Text(I18n.of(context).method3, textScaleFactor: 1.0)), + Container( + padding: EdgeInsets.only(bottom: 10, top: 10), + alignment: Alignment.center, + child: Text( + code, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 30, + fontWeight: FontWeight.w600, + color: const Color(0xFFFF4523)), + )), + Align( + alignment: Alignment.centerLeft, + child: Text(I18n.of(context).method4, textScaleFactor: 1.0)), + ], + ), + decoration: getCardDecoration(), + ); + } + + Widget _buildTip3() { + var str = ''; + if (state == 0) { + str = I18n.of(context).certificating; + } else if (state == 2) { + str = I18n.of(context).re_upload2; + } else { + str = I18n.of(context).not_authenticate; + } + return Container( + alignment: Alignment.center, + padding: EdgeInsets.only(top: 15, left: 20, right: 20, bottom: 15), + width: cardWidth, + child: Column( + children: [ + Container( + padding: EdgeInsets.only(bottom: 10), + alignment: Alignment.centerLeft, + child: Text( + I18n.of(context).certification_status, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Constants.BlackTextColor), + )), + Container( + padding: EdgeInsets.only(bottom: 5), + alignment: Alignment.centerLeft, + child: Text(str, textScaleFactor: 1.0)), + ], + ), + decoration: getCardDecoration(), + ); + } + + void _sendVideo() async { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return LoadingDialog( + text: "", + ); + }); + videoFile = await ImagePicker.pickVideo(source: ImageSource.camera); + + Navigator.of(context).pop(); + if (videoFile != null) { + var size = await videoFile.length(); + if (size > 104857600) { + showToast(I18n.of(context).video_more_big); + videoFile = null; + return; + } + + Map data = {"type": 5, "userId": UserData().basicInfo.userId}; + data['sign'] = TokenMgr().getSign(data); + Response res = await HttpUtil().uploadFile( + videoFile, data, 'upload/file/postflie', 'video', + isShowLoading: true); + var resData = res.data; + if (resData['code'] == 0) { + showToast(I18n.of(context).success); + videoUrl = resData['msg']; + isPostVideo = true; + _controller = VideoPlayerController.file(videoFile) + ..initialize().then((_) { + // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed. + setState(() {}); + }); + _controller.addListener(() { + if (_controller.value.position >= _controller.value.duration) { + isShowPlayButton = true; + setState(() {}); + } + }); + buttonStr = I18n.of(context).submit; + setState(() {}); + } + } + } + + void postInfo() async { + Map data = { + "userId": UserData().basicInfo.userId, + "videoUrl": WebData().deleteDemain(videoUrl), + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('user/auth/video', data: data); + Map resData = res.data; + if (resData['code'] == 0) { + showToast(resData['msg']); + state = 0; + buttonStr = I18n.of(context).under_review; + setState(() {}); + } + } + + //构建注册按钮 + Widget _buildRegisterButton() { + Text text = new Text( + buttonStr == '' ? I18n.of(context).upload_video : buttonStr, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 15, color: Colors.white)); + + LinearGradient gradientColor = new LinearGradient(colors: [ + Constants.ConfrimButtonColor, + Constants.ConfrimButtonColor, + ]); + return new Container( + margin: EdgeInsets.only(top: 5.5), + height: 44, + width: MediaQuery.of(context).size.width * 0.86, + child: ShadowButton().builder(gradientColor, text, + state == 0 ? () {} : (videoUrl == '' ? _sendVideo : postInfo)), + ); + } +} diff --git a/lib/home/VerificationPage.dart b/lib/home/VerificationPage.dart new file mode 100644 index 0000000..ca9fe0f --- /dev/null +++ b/lib/home/VerificationPage.dart @@ -0,0 +1,149 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import 'package:oktoast/oktoast.dart'; + +class VerificationPage extends StatefulWidget { + final List applyList; + VerificationPage({Key key, this.applyList}) : super(key: key); + _VerificationPageState createState() => _VerificationPageState(); +} + +class _VerificationPageState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + title: new Text( + I18n.of(context).check_incode, + textScaleFactor: 1.0, + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ); + return Scaffold( + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + )), + appBar: appBar, + resizeToAvoidBottomPadding: false, + ); + } + + Widget _buildBody() { + return widget.applyList.length == 0 + ? CustomUI.buildNoData(context) + : ListView( + children: widget.applyList == null + ? [] + : widget.applyList.map((item) { + return item['Status'] == 0 + ? Container() + : _buildResult(item); + }).toList(), + ); + } + + Widget _buildResult(data) { + bool isSucess = data['Status'] == 1; + Widget tip = Container( + margin: EdgeInsets.only(top: 25.5, bottom: 44), + child: Text( + isSucess + ? I18n.of(context).successful_application1 + : I18n.of(context).application_failed1, + textScaleFactor: 1.0, + style: TextStyle( + color: isSucess ? const Color(0xFF2D81FF) : const Color(0xFFFF4523), + fontSize: 22), + ), + ); + Widget success = Column( + children: [ + Container( + margin: EdgeInsets.only(bottom: 22), + width: MediaQuery.of(context).size.width, + alignment: Alignment.center, + child: Text( + I18n.of(context).your_incode, + textScaleFactor: 1.0, + style: TextStyle( + color: Constants.BlackTextColor, + fontSize: 17, + fontWeight: FontWeight.w500), + ), + ), + Container( + decoration: BoxDecoration( + border: Border( + bottom: + BorderSide(width: 1, color: const Color(0xFFFF4523)))), + child: Text( + data['Code'], + textScaleFactor: 1.0, + style: TextStyle(color: const Color(0xFFFF4523), fontSize: 33.36), + ), + ), + InkWell( + onTap: () { + ClipboardData clipboardData = + new ClipboardData(text: data['Code']); + Clipboard.setData(clipboardData); + showToast(I18n.of(context).successful_copy); + }, + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.only(top: 60), + padding: EdgeInsets.only(top: 5, left: 20, right: 20, bottom: 5), + width: 198.05, + height: 32.85, + decoration: BoxDecoration( + color: const Color(0xFF2D81FF), + borderRadius: BorderRadius.all(Radius.circular(30))), + child: Text( + I18n.of(context).copy, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white), + ), + )), + ], + ); + + Widget fail = Align( + child: Padding( + padding: EdgeInsets.only(left: 80, right: 80), + child: Text( + I18n.of(context).application_failed, + textScaleFactor: 1.0, + textAlign: TextAlign.center, + style: TextStyle(color: const Color(0xFFB3B3B3)), + ), + ), + ); + return Stack( + children: [ + Container( + child: Image.asset('assets/images/yqm_bg.png'), + margin: EdgeInsets.only(left: 41, right: 41, top: 20.5), + ), + Container( + margin: EdgeInsets.only(top: 20.5), + child: Column( + children: [tip, isSucess ? success : fail], + )) + ], + ); + } +} diff --git a/lib/home/VideoPage.dart b/lib/home/VideoPage.dart new file mode 100644 index 0000000..1917165 --- /dev/null +++ b/lib/home/VideoPage.dart @@ -0,0 +1,157 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/controller_widget_builder.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_ijkplayer/flutter_ijkplayer.dart'; +import 'package:video_player/video_player.dart'; + +class VideoPage extends StatefulWidget { + final userId; + VideoPage({Key key, @required this.userId}) : super(key: key); + + _VideoPageState createState() => _VideoPageState(); +} + +class _VideoPageState extends State { + VideoPlayerController _controller; + bool isShowPlayButton = true; + + bool isLoadingFish = false; + + IjkMediaController controller = IjkMediaController(); + + @override + void initState() { + super.initState(); + SystemChrome.setEnabledSystemUIOverlays([]); + getInfo(); + } + + @override + void dispose() { + SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values); + _controller.dispose(); + super.dispose(); + } + + getInfo() async { + Map data = { + "userId": widget.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('user/female/authInfo', + data: data, failback: () => Navigator.of(context).pop()); + Map resData = res.data; + print(resData); + if (resData['code'] == 0) { + var videoUrl = resData['data']['AttestationValue']; + if (videoUrl != '' && videoUrl != null) { +// _controller = VideoPlayerController.network(videoUrl) +// ..initialize().then((_) { +// isLoadingFish = true; +// setState(() {}); +// }); +// _controller.addListener(() { +// if (_controller.value.position >= _controller.value.duration) { +// isShowPlayButton = true; +// setState(() {}); +// } +// }); + isLoadingFish = true; + setState(() {}); + WidgetsBinding.instance.addPostFrameCallback((_) { + controller.setNetworkDataSource(videoUrl, autoPlay: false); + }); + } + } + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + I18n.of(context).certified_video, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ); + + Widget content = Scaffold( + backgroundColor: const Color(0xFFF4F4F4), + body: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildVideo(), + ), + ), + appBar: appBar, + resizeToAvoidBottomPadding: false, + ); + return CustomUI.buildPageLoading(context, content, !isLoadingFish); + } + + Widget _buildVideo() { + return IjkPlayer( + controllerWidgetBuilder: (ctl) { + return MyDefaultIJKControllerWidget( + ///按钮修改 + controller: ctl, + hideBackButton: true, + ); + }, + mediaController: controller, + ); + +// Widget stack = Stack( +// alignment: Alignment.center, +// children: [ +// +// Container( +// width: Screen.width, +// child: _controller != null && _controller.value.initialized +// ? AspectRatio( +// aspectRatio: _controller.value.aspectRatio, +// child: VideoPlayer(_controller), +// ) +// : Container(), +// ), +// InkWell( +// highlightColor: Colors.transparent, +// radius: 0, +// onTap: () { +// setState(() { +// if (!_controller.value.isPlaying) { +// _controller.seekTo(Duration()); +// _controller.play(); +// isShowPlayButton = false; +// setState(() {}); +// } +// }); +// }, +// child: Container( +// height: MediaQuery.of(context).size.height, +// color: Colors.black.withOpacity( +// _controller != null && _controller.value.isPlaying ? 0 : 0.5), +// padding: EdgeInsets.only(bottom: 20), +// alignment: Alignment.center, +// child: Image.asset( +// 'assets/images/bofang.png', +// width: +// _controller != null && _controller.value.isPlaying ? 0 : 70, +// ), +// )) +// ], +// ); +// return stack; + } +} diff --git a/lib/home/VipPage.dart b/lib/home/VipPage.dart new file mode 100644 index 0000000..813f41d --- /dev/null +++ b/lib/home/VipPage.dart @@ -0,0 +1,603 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/utils/ChargeMoney.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/ShadowButton.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; + +const double PaddingSize = 8; + +class VipPage extends StatefulWidget { + VipPage({Key key}) : super(key: key); + + _VipPageState createState() => _VipPageState(); +} + +enum PayWay { + wx, + zfb, +} + +class _VipPageState extends State with SingleTickerProviderStateMixin { + TabController tabCtrl; + + List vipData = []; + + int selectId = 0; + + int selectMoney = 0; + + int payWay = PayWay.wx.index; + + bool isLoadingFish = false; + + bool isNormalVip = true; + + int subMoney = 0; + + List goodsList = []; + + Map memberInfo = { + 'CheckNum': 0, + 'PhotoOrAccount': 0, + 'BurnTime': 0, + 'PublishAd': 0, + 'HumanTranslation': 0, + 'ExclusiveCustomer': 0, + 'PremiumUIDisplay': 0, + }; + + @override + void initState() { + super.initState(); + getVipInfo(1); + } + + void getVipInfo(type) async { + Map data = { + "userid": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + data['type'] = type; + Response res = await HttpUtil().post('goods/member/list', + data: data, failback: () => Navigator.of(context).pop()); + Map resData = res.data; + if (resData['code'] == 0 && + resData['data'] != null && + resData['data'].length > 0) { + if (type == 2) subMoney = upgradNum(vipData, resData['data']['list']); + memberInfo = resData['data']['memberInfo']; + vipData = resData['data']['list']; + selectId = vipData[0]['Id']; + selectMoney = vipData[0]['TotalPrice']; + isLoadingFish = true; + isNormalVip = type == 1; + setState(() {}); + } + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + Widget content = Scaffold( + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + I18n.of(context).member_centre, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ), + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + ))); + return CustomUI.buildPageLoading(context, content, !isLoadingFish); + } + + Widget _buildBody() { + return ListView( + children: [ + _buildTips(), + _buildGoodsItemList(), + _buildCommit(), + ], + ); + } + + //构建注册按钮 + Widget _buildCommit() { + Text text = new Text( + UserData().isVip + ? I18n.of(context).renewal_fee + : I18n.of(context).open_immediately, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 17, color: Colors.white)); + + LinearGradient gradientColor = new LinearGradient(colors: [ + Constants.ConfrimButtonColor, + Constants.ConfrimButtonColor, + ]); + callback() { + if (UserData().isSuperVip && isNormalVip) { + showToast(I18n.of(context).cannot_vip); + return; + } + + if (UserData().isVip && !UserData().isSuperVip && !isNormalVip) { + if (subMoney == 0) { + return; + } + CustomUI.buildOneConfirm( + context, + I18n.of(context) + .becomeSvip + .replaceFirst('/s1', subMoney.toString()), + I18n.of(context).determine, () { + HttpUtil().buyVIP(subMoney, 0, 2, context, () { + Navigator.of(context).pop(); + MessageMgr().emit('refresh_money'); + MessageMgr().emit('update_data'); + }); + }); + return; + } + + if (Provider.of(context).money < selectMoney) { + CustomUI.buildOneConfirm(context, I18n.of(context).balance_insufficien, + I18n.of(context).recharge, () { + Navigator.of(context).pop(); + ChargeMoney.showChargeSheet(context, () { + setState(() {}); + }); + }); + return; + } + + CustomUI.buildOneConfirm( + context, + I18n.of(context).confirm_pay + + selectMoney.toString() + + I18n.of(context).mask_coin, + I18n.of(context).determine, () { + HttpUtil().buyVIP(selectMoney, selectId, isNormalVip ? 1 : 2, context, + () { + Navigator.of(context).pop(); + MessageMgr().emit('refresh_money'); + MessageMgr().emit('update_data'); + }); + }); + } + + return Container( + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.only(left: 28), + child: Text( + I18n.of(context).total, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 15.49), + ), + ), + Padding( + padding: EdgeInsets.only(top: 1), + child: Text( + ' $selectMoney', + textScaleFactor: 1.0, + style: TextStyle( + color: const Color(0xFFE30101), + fontSize: 16, + fontWeight: FontWeight.normal), + ), + ), + Padding( + padding: EdgeInsets.only(left: 2, top: 1), + child: Text( + I18n.of(context).mask_coin, + textScaleFactor: 1.0, + style: + TextStyle(color: const Color(0xFFE30101), fontSize: 15), + ), + ), + ], + ), + Container( + margin: EdgeInsets.only(top: 21, left: 31, right: 31, bottom: 20), + height: 44, + child: ShadowButton().builder(gradientColor, text, callback), + ) + ], + ), + ); + } + + // Widget _buildVerText(String str) { + // List child = []; + // List list = str.split(' '); + // list.forEach((str) { + // child.add(Text( + // str, + // style: TextStyle(fontSize: 14, color: Constants.BlackTextColor), + // )); + // }); + // return Column( + // mainAxisAlignment: MainAxisAlignment.center, + // children: child, + // ); + // } + + Widget _buildGoodsItem(month, money, oldMoney, leftTop, value) { + bool isSelect = selectId == value['Id']; + return InkWell( + onTap: () { + setState(() { + selectId = value['Id']; + selectMoney = value['TotalPrice']; + }); + }, + child: Container( + alignment: Alignment.center, + height: 49.25, + margin: EdgeInsets.only(bottom: 15, left: 12.5, right: 12.5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + width: 1, + color: isSelect + ? const Color(0xFF2D81FF) + : const Color(0xFFC9C9C9)), + boxShadow: [ + BoxShadow( + color: isSelect + ? const Color(0x7A2D81FF) + : const Color(0x7ABCBCBC), + offset: Offset(0, 5), + blurRadius: 9, + ) + ], + borderRadius: BorderRadius.all(Radius.circular(10))), + child: Stack( + children: [ + leftTop + ? Positioned( + left: 0, + top: 0, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(9), + bottomRight: Radius.circular(5)), + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFFCE0B0B), + const Color(0xFFFF0000), + ]), + ), + padding: EdgeInsets.only(left: 5, right: 5), + child: Text(I18n.of(context).recommend, + textScaleFactor: 1.0, + style: + TextStyle(fontSize: 13, color: Colors.white)), + )) + : Positioned(left: 0, top: 0, child: Container()), + isSelect + ? Positioned( + right: -1, + bottom: 0, + child: Image.asset( + 'assets/images/login/vip_rect2.png', + + ), + width: 25, + ) + : Positioned( + right: 0, + bottom: 0, + child: Container(), + ), + Container( + height: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Expanded( + child: Container( + alignment: Alignment.center, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('$money', + textScaleFactor: 1.0, + style: TextStyle( + color: const Color(0xFFE30101), + fontSize: 22, + fontWeight: FontWeight.normal)), + Text('${I18n.of(context).mask_coin}', + textScaleFactor: 1.0, + style: TextStyle( + color: const Color(0xFFE30101), + fontSize: 20, + fontWeight: FontWeight.normal)), + ], + )), + ), + Image.asset( + 'assets/images/login/vip_rect3.png', + height: 25, + color: Colors.grey, + ), + Container( + width: 110, + alignment: Alignment.center, + child: Text(month, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 15, color: Constants.BlackTextColor)), + ), + ], + ), + ) + ], + ))); + } + + Widget buildSelectContainer(str, bool isSelect, bool isNormalVip) { + var color = Constants.BlackTextColor; + return Container( + alignment: Alignment.center, + padding: EdgeInsets.only(bottom: isSelect ? 9 : 12), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + bottom: BorderSide( + color: + isSelect ? const Color(0xFF2D81FF) : Colors.transparent, + width: isSelect ? 4 : 1))), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.only(top: 0), + child: Image.asset( + isNormalVip + ? 'assets/images/vip/hy_hy.png' + : 'assets/images/vip/hy_cjhy.png', + width: 18, + ), + ), + SizedBox(width: 5), + Text(str, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 16, color: color)) + ], + ), + ); + } + + Widget _buildGoodsItemList() { + Widget tip = Container( + color: Colors.white, + margin: EdgeInsets.only(bottom: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + InkWell( + onTap: isNormalVip + ? null + : () { + getVipInfo(1); + }, + child: buildSelectContainer( + I18n.of(context).member, isNormalVip, true)), + InkWell( + onTap: !isNormalVip + ? null + : () { + getVipInfo(2); + }, + child: buildSelectContainer( + I18n.of(context).svip, !isNormalVip, false)), + ], + )); + List list = [tip]; + vipData.forEach((k) { + var name = k['MonthValue'] == 0.5 + ? I18n.of(context).half_month + : I18n.of(context) + .month2 + .replaceFirst('/s1', k['MonthValue'].toInt().toString()); + list.add(_buildGoodsItem( + name, k['TotalPrice'], 72, vipData.indexOf(k) == 0, k)); + }); + list.add(Container( + height: 1, + color: const Color(0xFFDADADA), + margin: EdgeInsets.only(left: 14, right: 14, bottom: 13), + )); + return Container( + child: Wrap( + alignment: WrapAlignment.spaceEvenly, + children: list, + ), + ); + } + + double subNum(data) { + return data['MonthPrice'] / 30; + } + +//补差价 + int upgradNum(vipList, sVipList) { + if (UserData().memberEndTime == '') { + return 0; + } + int day = 0; + const moneyDay = 30; + try { + DateTime endTime = DateTime.parse(UserData().memberEndTime); + day = endTime.difference(DateTime.now()).inDays; + if (day < 0) { + return 0; + } + //小于最小天数按最小天数补 + if (day < vipList[0]['MonthValue'] * moneyDay) { + return (day * (subNum(sVipList[0]) - subNum(vipList[0]))).ceil(); + } + + //大于最大天数按最大天数补 + if (day > vipList[vipList.length - 1]['MonthValue'] * moneyDay) { + return (day * + (subNum(sVipList[vipList.length - 1]) - + subNum(vipList[vipList.length - 1]))) + .ceil(); + } + for (int i = 0; i < vipList.length; i++) { + int standDay = (vipList[i]['MonthValue'] * moneyDay).ceil(); + + if (day < standDay) { + return (day * (subNum(sVipList[i - 1]) - subNum(vipList[i - 1]))) + .ceil(); + } + } + } catch (e) {} + return 0; + } + + Widget _buildTipItem(leftStr, rightStr, {isShow = true}) { + var color = isShow ? Colors.white : Colors.white.withOpacity(0); + return Container( + margin: EdgeInsets.only(left: 39, right: 5), + child: Row( + children: [ + Container( + margin: EdgeInsets.only(right: 20.5), + child: Text( + leftStr, + textScaleFactor: 1.0, + style: TextStyle( + color: color, fontSize: 11.44, fontWeight: FontWeight.w600), + ), + ), + Expanded( + child: Container( + padding: EdgeInsets.only(right: 5), + child: Text( + rightStr, + textScaleFactor: 1.0, + style: TextStyle( + color: color, + fontSize: 10.4, + ), + ), + )), + ], + ), + ); + } + + Widget _buildTips() { + Widget tip = Container( + margin: EdgeInsets.only(left: PaddingSize, right: PaddingSize), + padding: EdgeInsets.only(top: 9, left: 12, bottom: 10), + child: Row( + children: [ + Image.asset( + 'assets/images/vip/hy_tq.png', + width: 16, + ), + Text( + I18n.of(context).members_privilege, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white, fontSize: 13.54), + ), + ], + )); + return Container( + color: Colors.white, + width: Screen.width, + child: Stack( + children: [ + Container( + color: Colors.white, + margin: EdgeInsets.only(left: PaddingSize, right: PaddingSize), + alignment: Alignment.center, + child: Image.asset( + 'assets/images/vip/hy_bg.png', + fit: BoxFit.fitWidth, + ), + ), +// Container( +// height: 150, +// margin: EdgeInsets.only(top:5,left: PaddingSize, right: PaddingSize), +// alignment: Alignment.center, +// child: Text(''), +// decoration: BoxDecoration( +// borderRadius: BorderRadius.circular(12), +// gradient: LinearGradient( +// begin: Alignment.centerLeft, +// end: Alignment.centerRight, +// colors: [Color(0xffff9186), Color(0xffff5599)], +// +// )), +// ), + Positioned( + child: Container( + height: (Screen.width - PaddingSize * 2) / 2.18, + padding: EdgeInsets.only(bottom: 15), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + tip, + _buildTipItem(I18n.of(context).see_more, + I18n.of(context).unlimited_see), + _buildTipItem( + I18n.of(context).see_cheaper, + I18n.of(context).free10.replaceFirst('/s1', + memberInfo['PhotoOrAccount'].toString())), + _buildTipItem( + I18n.of(context).see_longer, + I18n.of(context).towto6.replaceFirst('/s1', + (memberInfo['BurnTime'] + 2).toString())), + _buildTipItem( + I18n.of(context).see_better, + I18n.of(context).free_program.replaceFirst( + '/s1', memberInfo['PublishAd'].toString())), + _buildTipItem(I18n.of(context).right5, + I18n.of(context).free_translate, + isShow: !isNormalVip), + _buildTipItem(I18n.of(context).right6, + I18n.of(context).personalTraff, + isShow: !isNormalVip), + ], + ))), + ], + )); + } +} diff --git a/lib/home/WelcomePage.dart b/lib/home/WelcomePage.dart new file mode 100644 index 0000000..6998c42 --- /dev/null +++ b/lib/home/WelcomePage.dart @@ -0,0 +1,541 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/IndexPage.dart'; +import 'package:chat/home/VipPage.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:flutter/material.dart'; + +import 'package:oktoast/oktoast.dart'; +import '../utils/ShadowButton.dart'; +import '../home/EditData.dart'; +import 'package:flutter/services.dart'; +import '../home/VerificationPage.dart'; +import '../data/UserData.dart'; +import '../utils/TokenMgr.dart'; +import 'package:dio/dio.dart'; +import '../utils/HttpUtil.dart'; +import 'GetRegisterCodePage.dart'; +import '../utils/MessageMgr.dart'; + +import 'package:chat/models/money_change.dart'; +import 'package:provider/provider.dart'; + +class WelcomePage extends StatefulWidget { + WelcomePage({Key key, bool flag}) : super(key: key); + + _WelcomePageState createState() => _WelcomePageState(); +} + +class _WelcomePageState extends State { + List registerList = []; + String registerCode = ''; + bool isCanApplay = true; + @override + void initState() { + super.initState(); + getNewData(null); + MessageMgr().on('register_code', getNewData); + MessageMgr().on('refresh_money', msgBuyVip); + } + + msgBuyVip(data) { + HttpUtil().getWealth(context, (data) { + if (mounted) { + Provider.of(context).initMoney(data['CoinValue']); + + } + }); + } + + initList(resData) { + if (resData != null) { + registerList = resData; + } + isCanApplay = true; + for (int i = 0; i < registerList.length; i++) { + if (registerList[i]['Status'] == 0 || registerList[i]['Status'] == 1) { + isCanApplay = false; + break; + } + } + setState(() {}); + } + + void getNewData(data) { + getRegisterState(initList); + } + + @override + void dispose() { + MessageMgr().off('register_code', getNewData); + MessageMgr().off('refresh_money', msgBuyVip); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + elevation: 1, + // leading: IconButton( + // onPressed: () { + // HttpUtil().clearCacheData(); + // Navigator.of(context).pushAndRemoveUntil(new MaterialPageRoute( + // builder: (context) { + // return IndexPage(); + // }, + // ), (route) => route == null); + // }, + // icon: Icon(Icons.arrow_back), + // ), + leading: CustomUI.buildCustomLeading(context, onTap: () { + HttpUtil().clearCacheData(); + Navigator.of(context).pushAndRemoveUntil(new MaterialPageRoute( + builder: (context) { + return IndexPage(); + }, + ), (route) => route == null); + }), + title: new Text( + I18n.of(context).welcome, + textScaleFactor: 1.0, + ), + centerTitle: true, + ); + return Scaffold( + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildBody(), + ), + )), + appBar: appBar, + resizeToAvoidBottomPadding: false, + ); + } + + Widget _buildBody() { + return SingleChildScrollView( + child: Column( + children: [ + Container( + margin: EdgeInsets.only(top: 10), + width: double.infinity, + color: Colors.white, + child: Column( + children: [ + _buildTopTips(), + _buildInput(), + _buildRegisterButton(), + ], + ), + ), + Container( + margin: EdgeInsets.only(top: 59, bottom: 8.5), + child: Text( + I18n.of(context).how_get, + style: TextStyle(fontSize: 11.59, color: Constants.GreyTextColor), + ), + ), + _buildBottom(), + ], + ), + ); + } + + void getRegisterState(callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + try { + Response res = await HttpUtil().post('user/apply/records', data: data); + var resData = res.data; + print(resData); + if (resData['code'] == 0) { + callback(resData['data']); + } else { + showToast(resData['msg']); + } + } catch (e) {} + } + + Widget _buildTopTips() { + return Container( + margin: EdgeInsets.only(top: 22), + child: Column( + children: [ + Text( + I18n.of(context).enter_incode, + textScaleFactor: 1.0, + style: TextStyle(fontWeight: FontWeight.normal, fontSize: 16), + ), + SizedBox(height: 8), + Text( + I18n.of(context).must_incode, + textScaleFactor: 1.0, + style: TextStyle(color: const Color(0xFFC3C3C3), fontSize: 11.53), + ) + ], + ), + ); + } + + Widget _buildRegisterButton() { + Text text = new Text(I18n.of(context).determine, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 15, color: Colors.white)); + + LinearGradient gradientColor = new LinearGradient(colors: [ + Constants.ConfrimButtonColor, + Constants.ConfrimButtonColor, + ]); + callback() async { + if (registerCode == null || registerCode == '') { + showToast(I18n.of(context).enter_incode); + return; + } + var data = { + "UserId": UserData().basicInfo.userId, + "Code": registerCode, + }; + data['sign'] = TokenMgr().getSign(data); + try { + Response res = await HttpUtil().post('user/register/code', data: data); + var resData = res.data; + print(resData); + if (resData['code'] == 0) { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return EditPage( + isEditPage: false, + ); + }, + ), + ); + } else { + showToast(resData['msg']); + } + } catch (e) {} + } + + return new Container( + margin: EdgeInsets.only(top: 36, left: 34, right: 34, bottom: 50), + height: 42.7, + child: ShadowButton().builder(gradientColor, text, callback), + ); + } + + Widget _buildInput() { + return Container( + margin: EdgeInsets.only(top: 34, left: 34, right: 34), + child: TextField( + keyboardAppearance: Brightness.light, + onChanged: (str) { + registerCode = str; + }, + textAlign: TextAlign.center, + inputFormatters: [ + WhitelistingTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(6) + ], + style: TextStyle(textBaseline: TextBaseline.alphabetic), + decoration: InputDecoration( + hintText: I18n.of(context).your_incode, + hintStyle: TextStyle(fontSize: 19.21, color: const Color(0xFFB4B4B4)), + contentPadding: EdgeInsets.all(10.0), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(30.0), + ), + ), + ), + ); + } + + Widget _buildBottom() { + return Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + _buildBottomItemFirst(), + _buildBottomItemSecond(), + ], + ), + ); + } + + Widget _buildBottomItemFirst() { + double leftPadding = 30; + register() async { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return GetRegisterCodePage(); + }, + ), + ); + } + + var color = isCanApplay ? const Color(0xFF2D81FF) : Colors.grey; + Widget left = Container( + padding: EdgeInsets.only(left: leftPadding), + width: MediaQuery.of(context).size.width * 0.6, + child: Column( + children: [ + Container( + padding: EdgeInsets.only(top: 10), + alignment: Alignment.centerLeft, + child: Text( + I18n.of(context).free, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Constants.BlackTextColor), + ), + ), + Container( + padding: EdgeInsets.only(top: 4), + alignment: Alignment.centerLeft, + child: Text( + I18n.of(context).so_get, + textScaleFactor: 1.0, + style: TextStyle(color: const Color(0xFF949494), fontSize: 13), + ), + ), + ], + ), + ); + Widget right = new Container( + padding: EdgeInsets.only(top: 10), + width: MediaQuery.of(context).size.width * 0.4, + child: Column( + children: [ + InkWell( + onTap: isCanApplay ? register : null, + child: Container( + padding: + EdgeInsets.only(top: 5, left: 20, right: 20, bottom: 5), + decoration: BoxDecoration( + border: Border.all(color: color, width: 1), + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(30))), + child: Text( + isCanApplay + ? I18n.of(context).apply_now + : I18n.of(context).already_applied, + textScaleFactor: 1.0, + style: TextStyle(color: color), + ), + )), + InkWell( + onTap: () { + getRegisterState((data) { + initList(data); + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return VerificationPage( + applyList: data == null ? [] : data, + ); + }, + ), + ); + }); + }, + child: Align( + child: Container( + padding: EdgeInsets.only(right: 25, top: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + I18n.of(context).check_incode, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.red, fontSize: 13), + ), + Icon( + IconData(0xe63c, fontFamily: 'iconfont'), + size: 18.0, + color: Colors.red, + //color: const Color(0xFF2D81FF), + ), + ], + ), + ), + ), + ) + ], + ), + ); + + return Container( + padding: EdgeInsets.only(bottom: 20), + margin: EdgeInsets.only(bottom: 10), + color: Colors.white, + child: Column( + children: [ + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only(left: leftPadding, top: 2, bottom: 2), + width: double.infinity, + child: Text( + I18n.of(context).method1, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w500, + color: Constants.BlackTextColor), + ), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(color: const Color(0xFFF3F3F3)))), + ), + Row( + children: [left, right], + ), + ], + )); + } + + Widget _buildBottomItemSecond() { + double leftPadding = 30; + Widget left = Container( + padding: EdgeInsets.only(left: leftPadding), + width: MediaQuery.of(context).size.width * 0.6, + child: Column( + children: [ + Container( + padding: EdgeInsets.only(top: 10), + alignment: Alignment.centerLeft, + child: Text( + I18n.of(context).joinvip, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Constants.BlackTextColor), + ), + ), + Container( + padding: EdgeInsets.only(top: 4), + alignment: Alignment.centerLeft, + child: Text( + I18n.of(context).join_odds, + textScaleFactor: 1.0, + style: TextStyle(color: const Color(0xFF949494), fontSize: 13), + ), + ), + ], + ), + ); + Widget right = new Container( + width: MediaQuery.of(context).size.width * 0.4, + child: Column( + children: [ + InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return UserData().isVip + ? EditPage( + isEditPage: false, + ) + : VipPage(); + }, + ), + ); + }, + child: Container( + padding: + EdgeInsets.only(top: 5, left: 15, right: 15, bottom: 5), + decoration: BoxDecoration( + border: + Border.all(color: const Color(0xFF2D81FF), width: 1), + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(30))), + child: Text( + UserData().isVip + ? I18n.of(context).joined + : I18n.of(context).join_now, + textScaleFactor: 1.0, + style: TextStyle(color: const Color(0xFF2D81FF)), + ), + )), + // UserData().isVip + // ? InkWell( + // onTap: () { + // Navigator.of(context).push( + // new MaterialPageRoute( + // builder: (context) { + // return EditPage( + // isEditPage: false, + // ); + // }, + // ), + // ); + // }, + // child: Align( + // child: Container( + // padding: EdgeInsets.only( + // right: MediaQuery.of(context).size.width * 0.1, + // top: 10), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.end, + // children: [ + // Text( + // I18n.of(context).joined, + // textScaleFactor: 1.0, + // style: TextStyle( + // color: const Color(0xFFB4B4B4), fontSize: 13), + // ), + // Text( + // '>', + // textScaleFactor: 1.0, + // style: TextStyle(color: const Color(0xFFF6C5CC)), + // ) + // ], + // ), + // ), + // ), + // ) + // : Container( + // height: 13, + // ), + Container( + height: 13, + ) + ], + ), + ); + + return Container( + padding: EdgeInsets.only(bottom: 20), + margin: EdgeInsets.only(bottom: 10), + color: Colors.white, + child: Column( + children: [ + Container( + alignment: Alignment.centerLeft, + padding: EdgeInsets.only(left: leftPadding, top: 2, bottom: 2), + width: double.infinity, + child: Text( + I18n.of(context).method2, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w500, + color: Constants.BlackTextColor), + ), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(color: const Color(0xFFF3F3F3)))), + ), + Row( + children: [left, right], + ), + ], + )); + } +} diff --git a/lib/home/WhiteAndBlackList.dart b/lib/home/WhiteAndBlackList.dart new file mode 100644 index 0000000..4a902c2 --- /dev/null +++ b/lib/home/WhiteAndBlackList.dart @@ -0,0 +1,271 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/UserCard.dart'; +import 'package:flutter/material.dart'; + +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; +import '../utils/HttpUtil.dart'; +import 'package:dio/dio.dart'; +import "../data/UserData.dart"; +import '../utils/TokenMgr.dart'; +import 'ProfilePage.dart'; + +class WhiteAndBlackPage extends StatefulWidget { + final bool isWhite; + WhiteAndBlackPage({Key key, this.isWhite = true}) : super(key: key); + + @override + _WhiteAndBlackPageState createState() => new _WhiteAndBlackPageState(); +} + +class _WhiteAndBlackPageState extends State { + List list = new List(); //列表要展示的数据 + RefreshController _refreshController = + RefreshController(initialRefresh: true); + int _page = 1; //加载的页数 + int rows = 20; + + @override + void initState() { + super.initState(); + MessageMgr().on('refresh_love_list', msgRefreshLoveList); + } + + msgRefreshLoveList(data) { + for (int i = 0; i < list.length; i++) { + var item = list[i]; + if (item['FollowUserId'] == data['UserId'] && data['flag'] != 0) { + list.removeAt(i); + break; + } + } + setState(() {}); + } + + Future getData(type, callback) async { + var data = { + "userid": UserData().basicInfo.userId, + "type": type, + }; + data['sign'] = TokenMgr().getSign(data); + data['lng'] = UserData().longitude; + data['lat'] = UserData().latitude; + data['page'] = _page; + data['rows'] = rows; + Response res = await HttpUtil().post('userfollow/follow/user', + data: data, failback: () => Navigator.of(context).pop()); + _refreshController.refreshCompleted(); + var resData = res.data; + if (resData['code'] == 0) { + callback(resData['data']); + } else { + showToast(resData['msg']); + } + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + widget.isWhite ? I18n.of(context).i_like : I18n.of(context).blacklist2, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ); + + return Scaffold( + appBar: appBar, + body: SafeArea( + child: SmartRefresher( + enablePullDown: true, + enablePullUp: true, + header: MaterialClassicHeader(), + footer: CustomUI.buildLoadingFooter(), + controller: _refreshController, + onRefresh: _onRefresh, + onLoading: _onLoading, + child: + (_refreshController.headerStatus == RefreshStatus.completed && + list.length == 0) + ? CustomUI.buildNoData(context) + : ListView.builder( + itemBuilder: _renderRow, + itemCount: list.length, + ), + ), + )); + } + + Widget _renderRow(BuildContext context, int index) { + if (index < list.length) { + var userInfo = list[index]; + print(userInfo); + var whiteItem = UserCard( + key: UniqueKey(), + userName: Provider.of(context) + .getRefName(userInfo['UserId'], userInfo['NickName']), + city: WebData().getCountry( + userInfo['Country']), // WebData().getCity(userInfo['City']), + headUrl: userInfo['Headimgurl'], + isReal: userInfo['IsAttestation'] == 1, + constellation: + WebData().getConstellation(context, userInfo['constellation']), + distance: userInfo['Distance'].toDouble(), + age: + DateTime.now().year - int.parse(userInfo['Birthday'].split('-')[0]), + professional: WebData().getProffesionName(userInfo['Occupation']), + isOnline: userInfo['OnlineStatus'] == 1 + ? I18n.of(context).online + : WebData().getLoginTime(context, userInfo['LoginDate']), + hiddenDistince: userInfo['DistanceStatus'] == 1, + sex: userInfo['Sex'], + isLove: true, + isBalck: false, + userId: userInfo['FollowUserId'], + payImg: userInfo['PhotoAut'] == 1, + isHidden: userInfo['InfoAut'] == 1, + member: userInfo['IsMember'], + imgNum: userInfo['PhotoNum'], + ); + var blackItem = Container( + padding: EdgeInsets.all(10), + margin: EdgeInsets.symmetric(horizontal: 10, vertical: 4), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(0, 0, 0, 248), + offset: Offset(0, 6), + blurRadius: 6, + ) + ], + borderRadius: BorderRadius.all(Radius.circular(10))), + child: Row( + children: [ + _buildImg(userInfo['FollowUserId'], userInfo['Headimgurl']), + Padding( + padding: EdgeInsets.only(left: 10), + child: Text( + WebData().subUserName(userInfo['NickName']), + textScaleFactor: 1.0, + style: + TextStyle(fontSize: 15, color: Constants.BlackTextColor), + )), + Expanded(child: Container()), + InkWell( + onTap: () async { + HttpUtil().cancleBlackUser(userInfo.userId, () { + for (int i = 0; i < list.length; i++) { + if (list[i]['FollowUserId'] == userInfo['FollowUserId']) { + setState(() { + list.removeAt(i); + }); + break; + } + } + }); + }, + child: Container( + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 10.5), + decoration: BoxDecoration( + color: Constants.ConfrimButtonColor, + borderRadius: BorderRadius.all(Radius.circular(5))), + alignment: Alignment.center, + child: Text( + I18n.of(context).cancel_shield, + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.white, + fontSize: 13.5, + ), + )), + ) + ], + ), + ); + return widget.isWhite + ? (index == 0 + ? Padding(padding: EdgeInsets.only(top: 10), child: whiteItem) + : whiteItem) + : blackItem; + } + return Container(); + } + + Widget _buildImg(userId, url) { + return InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: userId, + ); + }, + ), + ); + }, + child: Container( + decoration: BoxDecoration(borderRadius: BorderRadius.circular(2.0)), + width: 70.6, + height: 70.6, + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: url == '' || url == null + ? Image.asset( + Constants.DefaultHeadImgUrl, + ) + : CachedNetworkImage( + imageUrl: url, + placeholder: (context, url) => Image.asset( + Constants.DefaultHeadImgUrl, + width: 55, + height: 55, + ), + fit: BoxFit.cover, + ), + ))); + } + + Future _onRefresh() async { + _page = 1; + getData(widget.isWhite == true ? 0 : 1, (data) { + if (data != null) { + list.clear(); + list.addAll(data); + setState(() {}); + } + }); + } + + Future _onLoading() async { + _page++; + getData(widget.isWhite == true ? 0 : 1, (data) { + if (data == null || data.length == 0) { + _page--; + _refreshController.loadNoData(); + } else { + list.addAll(data); + _refreshController.loadComplete(); + } + setState(() {}); + }); + } + + @override + void dispose() { + _refreshController.dispose(); + MessageMgr().off('refresh_love_list', msgRefreshLoveList); + super.dispose(); + } +} diff --git a/lib/home/add_friend.dart b/lib/home/add_friend.dart new file mode 100644 index 0000000..78e9101 --- /dev/null +++ b/lib/home/add_friend.dart @@ -0,0 +1,201 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class AddFriendPage extends StatefulWidget { + final int userId; + final int pageType; + final String originalName; + AddFriendPage( + {Key key, + @required this.userId, + @required this.pageType, + @required this.originalName}) + : super(key: key); + + @override + _AddFriendPageState createState() => new _AddFriendPageState(); +} + +class _AddFriendPageState extends State { + bool _hasdeleteIcon = false; + TextEditingController _txtCtrl = new TextEditingController(); + + @override + void initState() { + super.initState(); + + print('AddFriendPage init'); + _txtCtrl.text = widget.originalName; + } + + @override + Widget build(BuildContext context) { + String title = ''; + switch (widget.pageType) { + case SendMessagePageType.AddFriends: + title = I18n.of(context).friend_verification; + break; + case SendMessagePageType.ChangeGroupName: + title = I18n.of(context).change_group_name; + break; + case SendMessagePageType.ChangeGroupNickName: + title = I18n.of(context).my_group_nickname; + break; + default: + } + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + title, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + actions: [ + InkWell( + onTap: () { + var content = _txtCtrl.text; + if (_txtCtrl.text.length == 0) { + content = widget.originalName; + } + switch (widget.pageType) { + case SendMessagePageType.AddFriends: + HttpUtil().addFriends(context, widget.userId, content, () { + Navigator.of(context).pop(); + MessageMgr().emit('post_add_friend', widget.userId); + }); + break; + case SendMessagePageType.ChangeGroupName: + + Navigator.of(context).pop(); + MsgHandler.updateGroupName(widget.userId, content); + break; + case SendMessagePageType.ChangeGroupNickName: + Navigator.of(context).pop(); + MsgHandler.updateMemberRefName(widget.userId, content); + break; + default: + } + }, + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.only(top: 15, bottom: 15, right: 20), + height: 20, + padding: EdgeInsets.only(left: 18,right: 18,bottom: 1), + decoration: BoxDecoration( + color: Constants.ConfrimButtonColor, borderRadius: BorderRadius.circular(4.5)), + child: Text( + widget.pageType == SendMessagePageType.AddFriends + ? I18n.of(context).send + : I18n.of(context).determine, + style: TextStyle( + color: Colors.white , fontSize: 14), + textScaleFactor: 1.0, + ), + ), + ) + ], + ); + + return Scaffold(appBar: appBar, body: SafeArea(child: _buildBody())); + } + + Widget _buildBody() { + return Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildTips(), + _buildInput(), + ], + ), + ); + } + + Widget _buildInput() { + return Container( + height: 36.5, + color: Colors.white, + child: TextField( + keyboardAppearance: Brightness.light, + controller: _txtCtrl, + style: TextStyle( + fontSize: 16, + color: Constants.BlackTextColor, + textBaseline: TextBaseline.alphabetic), + decoration: InputDecoration( + contentPadding: + EdgeInsets.only(right: 10, left: 15, top: 10, bottom: 10), + hintText: widget.originalName, + hintStyle: TextStyle(fontSize: 16, color: Colors.grey), + border: InputBorder.none, + suffixIcon: Padding( + padding: EdgeInsetsDirectional.only( + start: 2.0, end: _hasdeleteIcon ? 20.0 : 0), + child: _hasdeleteIcon + ? InkWell( + onTap: (() { + setState(() { + WidgetsBinding.instance + .addPostFrameCallback((_) => _txtCtrl.clear()); + _hasdeleteIcon = false; + }); + }), + child: Icon( + Icons.cancel, + size: 18.0, + color: const Color(0xFFDBDBDB), + )) + : Text('')), + ), + maxLines: 1, + inputFormatters: [LengthLimitingTextInputFormatter(15)], + onChanged: (str) async { + setState(() { + if (str.isEmpty) { + _hasdeleteIcon = false; + } else { + _hasdeleteIcon = true; + } + }); + }, + ), + ); + } + + Widget _buildTips() { + String title = ''; + switch (widget.pageType) { + case SendMessagePageType.AddFriends: + title = I18n.of(context).added_friends_tips; + break; + case SendMessagePageType.ChangeGroupName: + title = I18n.of(context).change_group_name; + break; + case SendMessagePageType.ChangeGroupNickName: + title = I18n.of(context).my_group_nickname_tips; + break; + default: + } + return Container( + margin: EdgeInsets.only(top: 20.5, left: 15, bottom: 6), + child: Text( + title, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 11), + ), + ); + } + + @override + void dispose() { + super.dispose(); + } +} diff --git a/lib/home/address_book.dart b/lib/home/address_book.dart new file mode 100644 index 0000000..e901e7c --- /dev/null +++ b/lib/home/address_book.dart @@ -0,0 +1,396 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/add_friend.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/conversation_table.dart'; +import 'package:dio/dio.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import 'ProfilePage.dart'; + +class _ContactItem extends StatelessWidget { + _ContactItem( + {@required this.avatar, + @required this.title, + @required this.userId, + this.groupTitle, + this.onPressed, + this.gradient, + this.iconCode, + this.isShowDivder: true, + this.state}); + final int userId; + final int iconCode; + final String avatar; + final String title; + final String groupTitle; + final VoidCallback onPressed; + final Gradient gradient; + final bool isShowDivder; + final int state; + + static const double MARGIN_VERTICAL = 10.0; + static const double GROUP_TITLE_HEIGHT = 24.0; + + @override + Widget build(BuildContext context) { + Widget _avatarIcon; + if (iconCode == null) { + _avatarIcon = ClipRRect( + borderRadius: BorderRadius.circular(6), + child: CachedNetworkImage( + imageUrl: this.avatar, + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + )); + } else { + _avatarIcon = Container( + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + decoration: BoxDecoration( + gradient: gradient, borderRadius: BorderRadius.circular(6)), + child: Icon( + IconData(this.iconCode, fontFamily: Constants.IconFontFamily), + color: Colors.white, + ), + ); + } + + Widget _button = Container( + padding: const EdgeInsets.symmetric( + vertical: MARGIN_VERTICAL, horizontal: 16.0), + decoration: BoxDecoration(color: Colors.white), + child: Row( + children: [ + _avatarIcon, + SizedBox(width: 10.0), + Expanded(child: Text(title)), + state == 1 + ? InkWell( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 21, vertical: 7), + child: Text( + I18n.of(context).added, + textScaleFactor: 1.0, + style: TextStyle(color: const Color(0xFF8A8B8B)), + ), + ), + ) + : (state == 0 + ? InkWell( + child: Container( + padding: + EdgeInsets.symmetric(horizontal: 21, vertical: 7), + child: Text( + I18n.of(context).already_applied, + textScaleFactor: 1.0, + style: TextStyle(color: const Color(0xFF8A8B8B)), + ), + ), + ) + : InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return AddFriendPage( + userId: this.userId, + pageType: SendMessagePageType.AddFriends, + originalName: I18n.of(context) + .i_am + .replaceFirst( + '/s1', UserData().basicInfo.nickName), + ); + }, + ), + ); + }, + child: Container( + padding: + EdgeInsets.symmetric(horizontal: 21, vertical: 7), + decoration: BoxDecoration( + color: const Color(0xFF3875E9), + borderRadius: BorderRadius.circular(5)), + child: Text( + I18n.of(context).add, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white), + ), + ), + )), + ], + ), + ); + + //分组标签 + Widget _itemBody; + if (this.groupTitle != null) { + _itemBody = Column( + children: [ + Container( + height: GROUP_TITLE_HEIGHT, + padding: EdgeInsets.only(left: 16.0, right: 16.0), + color: const Color(AppColors.ContactGroupTitleBgColor), + alignment: Alignment.centerLeft, + child: Text(this.groupTitle, + textScaleFactor: 1.0, style: AppStyles.GroupTitleItemTextStyle), + ), + _button, + ], + ); + } else { + _itemBody = _button; + } + + return InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: userId, + ); + }, + ), + ); + }, + child: Container( + color: Colors.white, + child: Column( + children: [ + _itemBody, + isShowDivder + ? Container( + height: 1, + color: const Color(0xFFF3F3F3), + margin: EdgeInsets.only( + left: 26 + Constants.ContactAvatarSize), + ) + : Container() + ], + ))); + } +} + +class ContactsPage extends StatefulWidget { + @override + _ContactsPageState createState() => _ContactsPageState(); +} + +class _ContactsPageState extends State { + String _currentLetter = ''; + ScrollController _scrollController; + TextEditingController _txtCtrl = new TextEditingController(); + FocusNode editFocus = FocusNode(); + bool _hasdeleteIcon = false; + + List searchList = []; + + List friendList = []; + + @override + void initState() { + print('ContactsPage initState'); + super.initState(); + getFriendList(); + _scrollController = new ScrollController(); + MessageMgr().on('post_add_friend', msgAddFriend); + } + + msgAddFriend(data) { + for (int i = 0; i < friendList.length; i++) { + if (friendList[i].friendId == data) { + setState(() { + friendList[i].state = 0; + }); + break; + } + } + } + + getFriendList() async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('maillist/user/get', data: data); + Map resData = res.data; + print(resData['data']); + if (resData['code'] == 0 && resData['data'] != null) { + resData['data'].forEach((f) { + var friend = FriendModel.fromServerJson(f); + if (friend.friendId != UserData().basicInfo.userId) + friendList.add(friend); + }); + setState(() {}); + } + } + + @override + void dispose() { + _scrollController.dispose(); + editFocus.dispose(); + MessageMgr().off('post_add_friend', msgAddFriend); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final List _body = []; + + if (!_hasdeleteIcon) { + friendList.sort((a, b) => a.nameTag.compareTo(b.nameTag)); + _body.add(ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + int _contactIndex = index; + bool _isGroupTitle = true; + FriendModel _contact = friendList[_contactIndex]; + + if (_contactIndex >= 1 && + _contact.nameTag == friendList[_contactIndex - 1].nameTag) { + _isGroupTitle = false; + } + + return _ContactItem( + userId: _contact.friendId, + avatar: _contact.avatar, + title: _contact.name, + state: _contact.state, + isShowDivder: _isGroupTitle, + groupTitle: _isGroupTitle ? _contact.nameTag : null); + }, + itemCount: friendList.length, + )); + } else { + _body.add(ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + FriendModel _contact = searchList[index]; + + return _ContactItem( + userId: _contact.friendId, + avatar: _contact.avatar, + title: _contact.name, + state: _contact.state, + isShowDivder: true, + groupTitle: null); + }, + itemCount: searchList.length, + )); + } + + if (_currentLetter != null && + _currentLetter.isNotEmpty && + !_hasdeleteIcon) { + _body.add(Center( + child: Container( + width: Constants.IndexLetterBoxSize, + height: Constants.IndexLetterBoxSize, + decoration: BoxDecoration( + color: AppColors.IndexLetterBoxBgColor, + borderRadius: BorderRadius.all( + Radius.circular(Constants.IndexLetterBoxRadius)), + ), + child: Center( + child: Text(_currentLetter, + textScaleFactor: 1.0, style: AppStyles.IndexLetterBoxTextStyle), + ), + ), + )); + } + + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + I18n.of(context).contact_add, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + elevation: 1, + bottom: PreferredSize( + preferredSize: Size.fromHeight(49), + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.only(bottom: 14, left: 12.5, right: 12.5), + height: 35, + decoration: BoxDecoration( + color: const Color(0xFFEEEEEE), + borderRadius: BorderRadius.all(Radius.circular(8))), + child: TextField( + keyboardAppearance: Brightness.light, + keyboardType: TextInputType.text, + textInputAction: TextInputAction.search, + controller: _txtCtrl, + focusNode: editFocus, + maxLines: 1, + style: TextStyle( + textBaseline: TextBaseline.alphabetic, fontSize: 14.5), + autofocus: false, + inputFormatters: [ + LengthLimitingTextInputFormatter(50), + ], + decoration: InputDecoration( + hintText: I18n.of(context).search, + hintStyle: TextStyle(fontSize: 14.5), + prefixIcon: Icon( + IconData( + 0xe664, + fontFamily: Constants.IconFontFamily, + ), + color: const Color(0xFFA0A0A0), + size: 18, + ), + suffixIcon: Padding( + padding: EdgeInsetsDirectional.only( + start: 2.0, end: _hasdeleteIcon ? 20.0 : 0), + child: _hasdeleteIcon + ? new InkWell( + onTap: (() { + setState(() { + WidgetsBinding.instance + .addPostFrameCallback( + (_) => _txtCtrl.clear()); + _hasdeleteIcon = false; + }); + }), + child: Icon( + Icons.clear, + size: 18.0, + color: Constants.BlackTextColor, + )) + : new Text('')), + filled: true, + fillColor: Colors.transparent, + border: InputBorder.none, + ), + onChanged: (str) async { + setState(() { + if (str.isEmpty) { + _hasdeleteIcon = false; + } else { + _hasdeleteIcon = true; + searchList = CustomUI().getSearchResult( + str, friendList == null ? [] : friendList); + } + }); + }, + onEditingComplete: () {}), + )), + ), + body: Stack( + children: _body, + )); + } +} diff --git a/lib/home/address_search.dart b/lib/home/address_search.dart new file mode 100644 index 0000000..b244227 --- /dev/null +++ b/lib/home/address_search.dart @@ -0,0 +1,165 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/models/friends_info.dart'; +import 'package:flutter/material.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/conversation_table.dart'; +import 'package:chat/utils/friend_list_mgr.dart'; +import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; + +class AddressSearchPage extends StatefulWidget { + @override + _AddressSearchPageState createState() => _AddressSearchPageState(); +} + +class _AddressSearchPageState extends State { + ScrollController _scrollController; + TextEditingController _txtCtrl = new TextEditingController(); + bool _hasdeleteIcon = false; + + List searchList = []; + + List friendList = []; + + FocusNode focusNode; + //var _contactsFuture; + @override + void initState() { + super.initState(); + focusNode = new FocusNode(); + _scrollController = new ScrollController(); + getFriendList(); + } + + getFriendList() async { + friendList = await FriendListMgr().getFriendList(); + + if (mounted) { + setState(() {}); + } + } + + @override + void dispose() { + _scrollController.dispose(); + focusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final List _body = []; + + _body.add(ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + FriendModel _contact = searchList[index]; + + return FriendsInfo( + userId: _contact.friendId, + avatar: _contact.avatar, + title: Provider.of(context) + .getRefName(_contact.friendId, _contact.name), + isShowDivder: true, + groupTitle: null); + }, + itemCount: searchList.length, + )); + + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text(I18n.of(context).search, + textScaleFactor: 1.0, style: Constants.MainTitleStyle), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + elevation: 1, + bottom: PreferredSize( + preferredSize: Size.fromHeight(49), + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.only(bottom: 14, left: 12.5, right: 12.5), + height: 35, + decoration: BoxDecoration( + color: const Color(0xFFEEEEEE), + borderRadius: BorderRadius.all(Radius.circular(8))), + child: TextField( + keyboardType: TextInputType.text, + textInputAction: TextInputAction.search, + controller: _txtCtrl, + focusNode: focusNode, + cursorColor: Constants.BlueTextColor, + maxLines: 1, + style: TextStyle( + textBaseline: TextBaseline.alphabetic, fontSize: 14.5), + autofocus: true, + inputFormatters: [ + LengthLimitingTextInputFormatter(50), + ], + decoration: InputDecoration( + hintText: I18n.of(context).search, + hintStyle: TextStyle(fontSize: 14.5), + contentPadding: EdgeInsets.only( + left: 20, + top: (UserData().language == LanguageType.English || + UserData().language == + LanguageType.Vietnamese) + ? 3 + : 10.5, + bottom: 10.5), + prefixIcon: Icon( + IconData( + 0xe664, + fontFamily: Constants.IconFontFamily, + ), + color: const Color(0xFFA0A0A0), + size: 18, + ), + suffixIcon: Padding( + padding: EdgeInsetsDirectional.only( + start: 2.0, end: _hasdeleteIcon ? 20.0 : 0), + child: _hasdeleteIcon + ? new InkWell( + onTap: (() { + setState(() { + WidgetsBinding.instance + .addPostFrameCallback( + (_) => _txtCtrl.clear()); + _hasdeleteIcon = false; + }); + }), + child: Icon( + Icons.clear, + size: 18.0, + color: Constants.BlackTextColor, + )) + : new Text('')), + filled: true, + fillColor: Colors.transparent, + border: InputBorder.none, + ), + onChanged: (str) async { + setState(() { + if (str.isEmpty) { + _hasdeleteIcon = false; + } else { + _hasdeleteIcon = true; + searchList = CustomUI().getSearchResult( + str, friendList == null ? [] : friendList); + } + }); + }, + onEditingComplete: () { + FocusScope.of(context).requestFocus(FocusNode()); + }), + )), + ), + body: Stack( + children: _body, + )); + } +} diff --git a/lib/home/alter_select_view.dart b/lib/home/alter_select_view.dart new file mode 100644 index 0000000..6eee0fa --- /dev/null +++ b/lib/home/alter_select_view.dart @@ -0,0 +1,442 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/group_member_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class _MemberItem extends StatelessWidget { + _MemberItem({ + @required this.avatar, + @required this.title, + @required this.userId, + this.groupTitle, + this.onPressed, + this.gradient, + this.iconCode, + this.isShowDivder: true, + }); + final int userId; + final int iconCode; + final String avatar; + final String title; + final String groupTitle; + final VoidCallback onPressed; + final Gradient gradient; + final bool isShowDivder; + + static double _height(bool hasGroupTitle) { + final _buttonHeight = MARGIN_VERTICAL * 2 + + Constants.ContactAvatarSize + + Constants.DividerWidth; + if (hasGroupTitle) { + return _buttonHeight + GROUP_TITLE_HEIGHT; + } else { + return _buttonHeight; + } + } + + @override + Widget build(BuildContext context) { + Widget _avatarIcon; + if (iconCode == null) { + _avatarIcon = ClipRRect( + borderRadius: BorderRadius.circular(6), + child: CachedNetworkImage( + imageUrl: this.avatar, + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + )); + } else { + _avatarIcon = Container( + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + decoration: BoxDecoration( + gradient: gradient, borderRadius: BorderRadius.circular(6)), + child: Icon( + IconData(this.iconCode, fontFamily: Constants.IconFontFamily), + color: Colors.white, + ), + ); + } + + Widget _button = Container( + padding: const EdgeInsets.symmetric( + vertical: MARGIN_VERTICAL, horizontal: 16.0), + decoration: BoxDecoration(color: Colors.white), + child: Row( + children: [ + _avatarIcon, + SizedBox(width: 10.0), + Text(title), + ], + ), + ); + + //分组标签 + Widget _itemBody; + if (this.groupTitle != null) { + _itemBody = Column( + children: [ + Container( + height: GROUP_TITLE_HEIGHT, + padding: EdgeInsets.only(left: 16.0, right: 16.0), + color: const Color(AppColors.ContactGroupTitleBgColor), + alignment: Alignment.centerLeft, + child: + Text(this.groupTitle, style: AppStyles.GroupTitleItemTextStyle), + ), + _button, + ], + ); + } else { + _itemBody = _button; + } + + return InkWell( + onTap: onPressed, + child: Container( + color: Colors.white, + child: Column( + children: [ + _itemBody, + isShowDivder + ? Container( + height: 1, + color: const Color(0xFFF3F3F3), + margin: EdgeInsets.only( + left: 26 + Constants.ContactAvatarSize), + ) + : Container() + ], + ))); + } +} + +class AlterSelectPage extends StatefulWidget { + final GroupInfoModel groupInfoModel; + AlterSelectPage(this.groupInfoModel); + @override + _AlterSelectPageState createState() => _AlterSelectPageState(); + + static Future pickAlterUser( + BuildContext context, GroupInfoModel groupInfoModel) async { + var results = await Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) { + return AlterSelectPage(groupInfoModel); + }, + ), + ); + + return results; + } +} + +class _AlterSelectPageState extends State { + List members = []; //除自己外的其他成员 + bool _hasdeleteIcon = false; //是否在搜索状态 + TextEditingController _txtCtrl = TextEditingController(); + ScrollController _scrollController = ScrollController(); + List searchList = []; + final Map _letterPosMap = {INDEX_BAR_WORDS[0]: 0.0}; + + FocusNode focusNode = FocusNode(); + + String _currentLetter = ''; + + @override + void initState() { + super.initState(); + print('AlterSelectPage initState'); + var myId = UserData().basicInfo.userId; + for (var member in widget.groupInfoModel.members) { + if (member.memberId != myId && member.inGroup > 0) { + member.getNameTag(); + members.add(member); + } + } + } + + @override + void dispose() { + + focusNode.unfocus(); + _scrollController.dispose(); + _txtCtrl.dispose(); + super.dispose(); + } + + updateIndexPos(List friendList) { + //计算用于 IndexBar 进行定位的关键通讯录列表项的位置 + double _totalPos = 0.0; + for (var i = 0; i < friendList.length; i++) { + bool _hasGroupTitle = true; + if (i > 0 && + friendList[i].nameTag.compareTo(friendList[i - 1].nameTag) == 0) { + _hasGroupTitle = false; + } + + if (_hasGroupTitle) { + _letterPosMap[friendList[i].nameTag] = _totalPos; + } + _totalPos += _MemberItem._height(_hasGroupTitle); + } + } + + Widget _buildAvatar(url) { + return ClipRRect( + borderRadius: BorderRadius.circular(6), + child: CachedNetworkImage( + imageUrl: url, + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + )); + } + + String getLetter(BuildContext context, double tileHeight, Offset globalPos) { + RenderBox _box = context.findRenderObject(); + var local = _box.globalToLocal(globalPos); + int index = (local.dy ~/ tileHeight).clamp(0, INDEX_BAR_WORDS.length - 1); + return INDEX_BAR_WORDS[index]; + } + + void _jumpToIndex(String letter) { + if (_letterPosMap.isNotEmpty) { + final _pos = _letterPosMap[letter]; + if (_pos != null) { + _scrollController.animateTo(_letterPosMap[letter], + curve: Curves.easeInOut, duration: Duration(microseconds: 200)); + } + } + } + + Widget _buildIndexBar(BuildContext context, BoxConstraints constraints) { + final List _letters = INDEX_BAR_WORDS.map((String word) { + return Expanded( + child: Container( + margin: EdgeInsets.only(right: 5), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: + _currentLetter == word ? Colors.blue : Colors.transparent, + ), + alignment: Alignment.center, + padding: EdgeInsets.all(2), + width: 20, + child: Text( + word, + style: TextStyle( + fontSize: 10, + color: + _currentLetter == word ? Colors.white : Colors.black), + ))); + }).toList(); + + final _totalHeight = constraints.biggest.height; + final _tileHeight = _totalHeight / _letters.length; + return GestureDetector( + onVerticalDragDown: (DragDownDetails details) { + setState(() { + _currentLetter = + getLetter(context, _tileHeight, details.globalPosition); + _jumpToIndex(_currentLetter); + }); + }, + onVerticalDragEnd: (DragEndDetails details) { + setState(() { + //_indexBarBgColor = Colors.transparent; + _currentLetter = null; + }); + }, + onVerticalDragCancel: () { + setState(() { + //_indexBarBgColor = Colors.transparent; + _currentLetter = null; + }); + }, + onVerticalDragUpdate: (DragUpdateDetails details) { + setState(() { + //var _letter = getLetter(context, _tileHeight, details.globalPosition); + _currentLetter = + getLetter(context, _tileHeight, details.globalPosition); + _jumpToIndex(_currentLetter); + }); + }, + child: Column( + children: _letters, + ), + ); + } + + @override + Widget build(BuildContext context) { + final List _body = []; + + if (!_hasdeleteIcon) { + + members.sort((a, b) => a.nameTag.compareTo(b.nameTag)); + + updateIndexPos(members); + _body.addAll([ + ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + bool _isGroupTitle = true; + GroupMemberModel _contact = members[index]; + + if (index >= 1 && + _contact.nameTag == members[index - 1].nameTag) { + _isGroupTitle = false; + } + + return _MemberItem( + userId: _contact.memberId, + avatar: _contact.avtar, + title: _contact.refName, + isShowDivder: _isGroupTitle, + onPressed: () { + Navigator.of(context).pop(_contact); + }, + groupTitle: _isGroupTitle ? _contact.nameTag : null); + }, + itemCount: members.length), + Positioned( + width: Constants.IndexBarWidth, + right: 0.0, + top: 0.0, + bottom: 0.0, + child: Container( + child: LayoutBuilder( + builder: _buildIndexBar, + ), + ), + ) + ]); + } else { + _body.add(ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + GroupMemberModel _contact = searchList[index]; + + return _MemberItem( + userId: _contact.memberId, + avatar: _contact.avtar, + title: _contact.refName, + isShowDivder: true, + onPressed: () { + Navigator.of(context).pop(_contact); + }, + groupTitle: null); + }, + itemCount: searchList.length, + )); + } + + if (_currentLetter != null && + _currentLetter.isNotEmpty && + !_hasdeleteIcon) { + _body.add(Center( + child: Container( + width: Constants.IndexLetterBoxSize, + height: Constants.IndexLetterBoxSize, + decoration: BoxDecoration( + color: AppColors.IndexLetterBoxBgColor, + borderRadius: BorderRadius.all( + Radius.circular(Constants.IndexLetterBoxRadius)), + ), + child: Center( + child: + Text(_currentLetter, style: AppStyles.IndexLetterBoxTextStyle), + ), + ), + )); + } + + return Scaffold( + resizeToAvoidBottomPadding: false, + backgroundColor: AppColors.NewAppbarBgColor, + appBar: AppBar( + title: Text(I18n.of(context).select_notice_people), + centerTitle: true, + elevation: 1, + leading: CustomUI.buildCustomLeading(context), + bottom: PreferredSize( + preferredSize: Size.fromHeight(49), + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.only(bottom: 14, left: 12.5, right: 12.5), + height: 35, + decoration: BoxDecoration( + color: const Color(0xFFEEEEEE), + borderRadius: BorderRadius.all(Radius.circular(8))), + child: TextField( + keyboardAppearance: Brightness.light, + keyboardType: TextInputType.text, + textInputAction: TextInputAction.search, + controller: _txtCtrl, + cursorColor: Constants.BlueTextColor, + maxLines: 1, + style: TextStyle( + textBaseline: TextBaseline.alphabetic, fontSize: 14.5), + autofocus: false, + inputFormatters: [ + LengthLimitingTextInputFormatter(50), + ], + focusNode: focusNode, + decoration: InputDecoration( + hintText: I18n.of(context).search, + hintStyle: TextStyle(fontSize: 14.5), + prefixIcon: Icon( + IconData( + 0xe664, + fontFamily: Constants.IconFontFamily, + ), + color: const Color(0xFFA0A0A0), + size: 18, + ), + suffixIcon: Padding( + padding: EdgeInsetsDirectional.only( + start: 2.0, end: _hasdeleteIcon ? 20.0 : 0), + child: _hasdeleteIcon + ? new InkWell( + onTap: (() { + setState(() { + WidgetsBinding.instance + .addPostFrameCallback( + (_) => _txtCtrl.clear()); + _hasdeleteIcon = false; + }); + }), + child: Icon( + Icons.clear, + size: 18.0, + color: Constants.BlackTextColor, + )) + : new Text('')), + filled: true, + fillColor: Colors.transparent, + border: InputBorder.none, + ), + onChanged: (str) async { + setState(() { + if (str.isEmpty) { + _hasdeleteIcon = false; + } else { + _hasdeleteIcon = true; + searchList = CustomUI().getSearchResult( + str, members == null ? [] : members); + } + }); + }, + onEditingComplete: () {}), + )), + ), + body: Stack( + children: _body, + )); + } +} diff --git a/lib/home/apply_content_view.dart b/lib/home/apply_content_view.dart new file mode 100644 index 0000000..597374a --- /dev/null +++ b/lib/home/apply_content_view.dart @@ -0,0 +1,343 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:oktoast/oktoast.dart'; + +import 'InformUser.dart'; + +class ApplyContent extends StatefulWidget { + final userInfo; + final userId; + final bool isMan; + + ApplyContent({Key key, this.userInfo, this.userId, this.isMan = false}) + : super(key: key); + + _ApplyContentState createState() => _ApplyContentState(); +} + +class _ApplyContentState extends State { + int friendly = 0; + int interesting = 0; + int refreshing = 0; + int patience = 0; + int hello = 0; + int unfriendly = 0; + bool isPost = false; + + Set select = new Set(); + + String evilImg1 = ''; //恶意差评1 + String evilImg2 = ''; //恶意差评2 + + @override + Widget build(BuildContext context) { + String tip = isPost + ? I18n.of(context).anonymous_evaluation + : (widget.isMan + ? I18n.of(context).his_evaluation + : I18n.of(context).her_evaluation); + return CustomUI.buildTipContent( + context, tip, _buildContent(widget.userInfo)); + } + + @override + void initState() { + super.initState(); + friendly = widget.userInfo['Friendly']; + interesting = widget.userInfo['Interesting']; + refreshing = widget.userInfo['Refreshing']; + patience = widget.userInfo['Patience']; + hello = widget.userInfo['Hello']; + unfriendly = widget.userInfo['Unfriendly']; + } + + void doContext(callback) async { + Map data = { + "userid": widget.userId, + "evaluateuserid": UserData().basicInfo.userId, + }; + String str = ''; + select.forEach((s) { + str += (str == '' ? s : '|$s'); + }); + if (str == '') { + showToast(I18n.of(context).click_select); + return; + } + data['sign'] = TokenMgr().getSign(data); + data['value'] = str; + data['evilImg'] = '$evilImg1|$evilImg2'; + Response res = await HttpUtil().post('evaluate/user/insert', data: data); + var resData = res.data; + if (resData['code'] == 0) { + select.forEach((s) { + switch (s) { + case 'Friendly': + friendly++; + break; + case 'Interesting': + interesting++; + break; + case 'Refreshing': + refreshing++; + break; + case 'Patience': + patience++; + break; + case 'Hello': + hello++; + break; + case 'Unfriendly': + unfriendly++; + break; + default: + } + }); + showToast(resData['msg']); + callback(); + } else { + showToast(resData['msg']); + } + } + + void _sendPicture(callback) async { + if (await CustomUI.showPhotoPermissionSetting(context)) { + var tempFile = await ImagePicker.pickImage(source: ImageSource.gallery); + if (tempFile != null) { + Map data = {"type": 4, "userId": UserData().basicInfo.userId}; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().uploadFile( + tempFile, data, 'upload/file/postflie', 'image', + isShowLoading: true); + + var resData = res.data; + if (resData['code'] == 0) { + Navigator.of(context).pop(); + callback(WebData().deleteDemain(resData['msg'])); + } + } + } + } + + Widget _buildBox(str, value, callback) { + bool isSelect = select.contains(value); + return InkWell( + onTap: callback, + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.only(top: 10, bottom: 21, left: 5, right: 5), + width: (Screen.width - 70) / 3, + height: 28, + decoration: BoxDecoration( + color: isSelect ? Colors.blue : Colors.grey[200], + borderRadius: + BorderRadius.circular(Constants.LittleButtonRadius)), + child: Text( + str, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 14, + color: isSelect ? Colors.white : Constants.BlackTextColor), + ), + )); + } + + Widget _buildContext(nums, str) { + return InkWell( + onTap: () { + if (widget.userInfo['Statu'] == 1) { + showToast(I18n.of(context).has_eva); + return; + } + if (widget.userInfo['IsComment'] == 0) { + showToast(!widget.isMan + ? I18n.of(context).cant_evaluate + : I18n.of(context).cant_evaluate2); + return; + } + setState(() { + isPost = !isPost; + }); + }, + child: CustomUI.buildBox(nums, str)); + } + + Widget _buildContent(data) { + var evaluation1 = + widget.isMan ? I18n.of(context).courtesy : I18n.of(context).friendly; + + var evaluation2 = I18n.of(context).interesting; + var evaluation3 = I18n.of(context).readily; + var evaluation4 = + widget.isMan ? I18n.of(context).generous : I18n.of(context).patient; + var evaluation5 = + widget.isMan ? I18n.of(context).lie : I18n.of(context).indifferent; + var evaluation6 = widget.isMan + ? I18n.of(context).unfriendly + : I18n.of(context).bad_temper; + + return Container( + padding: EdgeInsets.only(top: 10), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + isPost + ? _buildBox(evaluation1, 'Friendly', () { + select.contains('Friendly') + ? select.remove('Friendly') + : select.add('Friendly'); + setState(() {}); + }) + : _buildContext(friendly, evaluation1), + isPost + ? _buildBox(evaluation2, 'Interesting', () { + select.contains('Interesting') + ? select.remove('Interesting') + : select.add('Interesting'); + setState(() {}); + }) + : _buildContext(interesting, evaluation2), + isPost + ? _buildBox(evaluation3, 'Refreshing', () { + select.contains('Refreshing') + ? select.remove('Refreshing') + : select.add('Refreshing'); + setState(() {}); + }) + : _buildContext(refreshing, evaluation3), + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + isPost + ? _buildBox(evaluation4, 'Patience', () { + select.contains('Patience') + ? select.remove('Patience') + : select.add('Patience'); + setState(() {}); + }) + : _buildContext(patience, evaluation4), + isPost + ? _buildBox(evaluation5, 'Hello', () { + if (select.contains('Hello')) { + select.remove('Hello'); + evilImg1 = ''; + setState(() {}); + } else { + CustomUI.buildOneConfirm( + context, + I18n.of(context).bad_evaluate, + I18n.of(context).determine, () { + _sendPicture((url) { + evilImg1 = url; + select.add('Hello'); + setState(() {}); + }); + }); + } + }) + : _buildContext(hello, evaluation5), + isPost + ? _buildBox(evaluation6, 'Unfriendly', () { + if (select.contains('Unfriendly')) { + select.remove('Unfriendly'); + evilImg2 = ''; + setState(() {}); + } else { + CustomUI.buildOneConfirm( + context, + I18n.of(context).bad_evaluate, + I18n.of(context).determine, () { + _sendPicture((url) { + evilImg2 = url; + select.add('Unfriendly'); + setState(() {}); + }); + }); + } + }) + : _buildContext(unfriendly, evaluation6), + ], + ), + InkWell( + onTap: () { + if (!isPost && widget.userInfo['Statu'] == 1) { + showToast(I18n.of(context).has_eva); + return; + } + if (widget.userInfo['IsComment'] == 0) { + showToast(!widget.isMan + ? I18n.of(context).cant_evaluate + : I18n.of(context).cant_evaluate2); + return; + } + if (isPost) { + doContext(() { + isPost = !isPost; + widget.userInfo['Statu'] = 1; + setState(() {}); + }); + } else { + isPost = !isPost; + setState(() {}); + } + }, + child: Container( + margin: EdgeInsets.only(top: 20, left: 80, right: 80), + width: double.infinity, + alignment: Alignment.center, + padding: EdgeInsets.only(top: 8, bottom: 8), + decoration: BoxDecoration( + border: + Border.all(color: const Color(0xFF2D81FF), width: 1), + color: const Color(0xFF2D81FF), + borderRadius: BorderRadius.all( + Radius.circular(Constants.LittleButtonRadius))), + child: Text( + isPost + ? I18n.of(context).submit + : I18n.of(context).anonymous_evaluation, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white), + ), + )), + InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return InformUserPage( + isMan: widget.isMan, + userId: widget.userId, + ); + }, + ), + ); + }, + child: Container( + margin: EdgeInsets.only(top: 5), + child: Text( + I18n.of(context).anonymous_report, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.red, fontSize: 12), + ), + )) + ], + )); + } +} diff --git a/lib/home/audio_chat_view.dart b/lib/home/audio_chat_view.dart new file mode 100644 index 0000000..1586427 --- /dev/null +++ b/lib/home/audio_chat_view.dart @@ -0,0 +1,768 @@ +import 'dart:async'; +import 'dart:ui'; + +import 'package:agora_rtc_engine/agora_rtc_engine.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/chat/gift_page.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/models/gift_item_model.dart'; +import 'package:chat/models/gift_select_provider.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/ChargeMoney.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/anim_effect_overlay.dart'; +import 'package:chat/utils/counter_overlay.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sound_util.dart'; +import 'package:chat/utils/sp_utils.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; + +class AudioChatPage extends StatefulWidget { + final UserInfo userInfo; + final bool isReplay; + + AudioChatPage({this.userInfo, this.isReplay = false}); + @override + _AudioChatPageState createState() => _AudioChatPageState(); +} + +class _AudioChatPageState extends State { + //是否启用扬声器 + bool speakPhone = false; + + int friendId; + + bool isReply; //是否应答模式 + + bool isChating = false; //是否通话中 + + //超时挂断 + Timer offTimer; + Timer callingTimer; + + String channelName; + + //打赏礼物信息 + List giftList; + final _controller = new PageController(); + + //礼物数量 + int curGiftValue = 1; + + bool isQuit = false; + + @override + void initState() { + super.initState(); + + friendId = widget.userInfo.userId; + isReply = widget.isReplay; + + MsgHandler.isAudioConnect = true; + + getGiftList(); + initAgoreSdk(); + getDefaultSetting(); + //事件监听回调 + setAgoreEventListener(); + + //礼物打赏 + MessageMgr().on('Receive Gift', receiveGift); + + MessageMgr().on('AudioChat Failed', closeChat); + + MessageMgr().on('AudioChat State', refuseAnswer); + } + + void getDefaultSetting() async { + bool soundPlayMode = + (await SPUtils.getBool(Constants.SOUND_PLAY_MODE)) ?? false; + setState(() { + speakPhone = soundPlayMode; + }); + AgoraRtcEngine.setEnableSpeakerphone(speakPhone); + } + + closeChat(args) { + showToast(I18n.of(context).not_online); + _onExit(context); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + print('test didChangeDependencies'); + } + + refuseAnswer(args) { + var fdId = args['fdId']; + var isAnswer = args['isAnswer']; + if (fdId == friendId && !isAnswer) { + // showToast('对方暂时无法接听'); + _onExit(context); + } + } + + receiveGift(gift) { + int giftId = gift.giftId; + int amount = gift.giftAmount; + int total = gift.money; + + print(DateTime.now()); + + var giftModel = giftList[giftId - 1]; + print('收到礼物金额:$total'); + UserData().incomeMoney += total; + //Provider.of(context, listen: false).addMoney(total); + AnimEffect.showEffect(context, giftId); + AnimEffect.showDashangEffect(context, false, amount, giftModel.name); + } + + //本页面即将销毁 + @override + void dispose() { + _controller.dispose(); + MessageMgr().off('AudioChat State', refuseAnswer); + MessageMgr().off('AudioChat Failed', closeChat); + MessageMgr().off('Receive Gift', receiveGift); + MsgHandler.isAudioConnect = false; + + offTimer?.cancel(); + + callingTimer?.cancel(); + SoundUtils().stop(); + AgoraRtcEngine.leaveChannel(); + //sdk资源释放 + AgoraRtcEngine.destroy(); + super.dispose(); + } + + void initAgoreSdk() { + //初始化引擎 + AgoraRtcEngine.create(Constants.Agore_appId); + //设置视频为可用 启用音频模块 + AgoraRtcEngine.enableAudio(); + //每次需要原生视频都要调用_createRendererView + if (!isReply) { + int myId = UserData().basicInfo.userId; + + _createRendererView(myId); + } + } + + void getGiftList() async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('prop/get/list', data: data); + + if (res == null) { + return; + } + print(res); + Map resData = res.data; + + if (resData['code'] == 0) { + //领取成功 + giftList = resData['data'] + .map((v) => GiftItemModel.fromJson(v)) + .toList(); + + print('giftList length : ${giftList.length}'); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: Stack( + children: [ + ConstrainedBox( + constraints: BoxConstraints.expand(), + child: CachedNetworkImage( + imageUrl: widget.userInfo.headimgurl, + fit: BoxFit.fill, + placeholder: CustomUI.buildImgLoding)), + BackdropFilter( + filter: new ImageFilter.blur( + sigmaX: Screen.width / 8, sigmaY: Screen.width / 8), + child: Container( + color: Colors.black.withOpacity(0.5), + ), + ), + SafeArea( + child: Padding( + padding: EdgeInsets.symmetric(vertical: 40), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _viewAudio(), + isReply ? _replayToolBar() : _bottomToolBar(), + ], + ))) + ], + ))); + } + + _viewAudio() { + var url = widget.userInfo.headimgurl; + + print('url : $url'); + print(url.length); + var userName = Provider.of(context) + .getRefName(widget.userInfo.userId, widget.userInfo.nickName); + var local = WebData().getCity(widget.userInfo.city); + + var profession = WebData().getProffesionName(widget.userInfo.occupation); + + var birth = widget.userInfo.birthday; + print('birth : $birth'); + + var birthDay = DateTime.parse(birth); + print(birthDay); + var today = DateTime.now(); + + var testAge = today.difference(birthDay); + print(testAge.inDays); + + var age = testAge.inDays ~/ 365; + + var connectTip; + + if (isChating) { + connectTip = I18n.of(context).chatting; + } else { + if (isReply) { + connectTip = I18n.of(context).voice_msg.replaceFirst('/s1', userName); + } else { + connectTip = I18n.of(context).waitting_answer; + } + } + + return Container( + child: Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(0), + child: url.length == 0 + ? SizedBox( + height: 100, + width: 100, + child: Image.asset(R.assetsImagesDefaultNorAvatar)) + : CachedNetworkImage( + width: 100, + height: 100, + imageUrl: url, + placeholder: (context, url) => Padding( + padding: EdgeInsets.all(5), + child: CircularProgressIndicator( + valueColor: + AlwaysStoppedAnimation(Constants.BlueTextColor)), + ), + fit: BoxFit.cover, + ), + ), + SizedBox(height: 5), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + fixedText(userName, fontSize: 20, color: Colors.white70), + fixedText('$age', fontSize: 20, color: Colors.white70) + ], + ), + SizedBox(height: 5), + Text( + '$local', + style: TextStyle(fontSize: 16, color: Colors.white70), + textScaleFactor: 1.0, + textAlign: TextAlign.center, + ), + SizedBox(height: 5), + Text( + '$profession', + style: TextStyle(fontSize: 16, color: Colors.white70), + textScaleFactor: 1.0, + textAlign: TextAlign.center, + ), + SizedBox(height: 20), + Text( + connectTip, + maxLines: 1, + style: TextStyle(fontSize: 20, color: Colors.white70), + textScaleFactor: 1.0, + textAlign: TextAlign.center, + ), + ], + ), + ); + } + + _replayToolBar() { + return Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + //接听按钮 + RawMaterialButton( + onPressed: () { + MsgHandler.stopAudioRing(); + int myId = UserData().basicInfo.userId; + MsgHandler.sendReplyAudioChatReq(friendId, true); + _createRendererView(myId); + }, + child: Icon( + Icons.call, + color: Colors.white, + size: 35.0, + ), + shape: CircleBorder(), + elevation: 2.0, + fillColor: Colors.greenAccent, + padding: const EdgeInsets.all(15.0), + ), + //挂断按钮 + RawMaterialButton( + onPressed: () { + _onExit(context); + MsgHandler.stopAudioRing(); + MsgHandler.sendReplyAudioChatReq(friendId, false); + }, + child: Icon( + Icons.call_end, + color: Colors.white, + size: 35.0, + ), + shape: CircleBorder(), + elevation: 2.0, + fillColor: Colors.redAccent, + padding: const EdgeInsets.all(15.0), + ) + ])); + } + + _bottomToolBar() { + List showWidgets = [ + Text(I18n.of(context).voicing, + style: TextStyle(fontSize: 11, color: Colors.white24), + textAlign: TextAlign.center), + SizedBox(height: 10), + Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ + Offstage( + offstage: !isChating, + child: UserData().giftSwitch > 0 + ? RawMaterialButton( + onPressed: _showGiftSheet, + child: Icon( + IconData(0xe64e, fontFamily: Constants.IconFontFamily), + color: Colors.blueAccent, + size: 20.0, + ), + shape: CircleBorder(), + elevation: 2.0, + fillColor: Colors.white, + padding: const EdgeInsets.all(12.0), + ) + : SizedBox(width: 36, height: 36)), + + //挂断按钮 + RawMaterialButton( + onPressed: () { + MsgHandler.sendReplyAudioChatReq(friendId, false); + _onExit(context); + }, + child: Icon( + Icons.call_end, + color: Colors.white, + size: 35.0, + ), + shape: CircleBorder(), + elevation: 2.0, + fillColor: Colors.redAccent, + padding: const EdgeInsets.all(15.0), + ), + + //是否外放 + Offstage( + offstage: !isChating, + child: RawMaterialButton( + onPressed: _isSpeakPhone, + child: new Icon( + speakPhone ? Icons.volume_up : Icons.volume_down, + color: Colors.blueAccent, + size: 20.0, + ), + shape: new CircleBorder(), + elevation: 2.0, + fillColor: Colors.white, + padding: const EdgeInsets.all(12.0), + )) + ]) + ]; + + if (isChating) { + showWidgets.insert( + 0, + Container( + alignment: Alignment.center, + height: 80, + width: 200, + child: CounterOverlay(), + )); + } + return Container( + child: Column(children: showWidgets), + ); + } + + //创建渲染视图 + void _createRendererView(int uId) { + //增加音频会话对象 为了音频布局需要(通过uid和容器信息) + //加入频道 第一个参数是 token 第二个是频道id 第三个参数 频道信息 一般为空 第四个 用户id + int myId = UserData().basicInfo.userId; + setState(() { + print('加入聊天房间'); + var channelName = UserData().getSessionId(friendId).toString(); + + AgoraRtcEngine.joinChannel(null, channelName, null, myId); + }); + } + + //设置事件监听 + void setAgoreEventListener() { + //成功加入房间 + AgoraRtcEngine.onJoinChannelSuccess = + (String channel, int uid, int elapsed) { + print("加入成功id为:$uid elapsed:$elapsed"); + if (isReply) { + //回应 + setState(() { + isReply = false; + isChating = true; + }); + } else { + MsgHandler.sendAudioChatReq(widget.userInfo.userId); + + callingTimer = Timer.periodic(Duration(milliseconds: 2200), (timer) { + SoundUtils().play( + 'http://testcyhd.chengyouhd.com/Upload/Audio/even_wheat_sound.mp3', + isLocal: false); + }); + + //30没人接就自动挂断 + offTimer = Timer(Duration(seconds: 30), () { + MsgHandler.sendReplyAudioChatReq(friendId, false); + _onExit(context); + }); + } + }; + + //监听是否有新用户加入 + AgoraRtcEngine.onUserJoined = (int uid, int elapsed) { + print("新用户所加入的id为:$uid elapsed:$elapsed"); + + setState(() { + //更新UI布局 + SoundUtils().stop(); + callingTimer?.cancel(); + isChating = true; + offTimer?.cancel(); + }); + }; + + //监听用户是否离开这个房间 + AgoraRtcEngine.onUserOffline = (int uid, int reason) { + print("用户离开的id为:$uid"); + _onExit(context); + }; + + AgoraRtcEngine.onError = (dynamic errCode) { + print('通话异常'); + // _onExit(context); + }; + + //监听用户是否离开这个频道 + AgoraRtcEngine.onLeaveChannel = () { + print("用户离开"); + }; + } + + void _showGiftSheet() { + showModalBottomSheet( + context: context, + elevation: 2.0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), topRight: Radius.circular(20))), + backgroundColor: Colors.transparent, + builder: (BuildContext context) { + return StatefulBuilder( + builder: (BuildContext context, setBottomSheetState) { + return Container( + height: 400, + width: Screen.width, + decoration: BoxDecoration( + color: Colors.white, + ), + child: giftList == null + ? Center(child: Text(I18n.of(context).no_gift)) + : Column( + children: [ + Container( + // decoration: BoxDecoration( + // color: Colors.orangeAccent, + // borderRadius: borderRadius + // ), + padding: EdgeInsets.symmetric( + vertical: 10, horizontal: 20), + child: Row( + children: [ + Text(I18n.of(context).sent_gift, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Constants.BlackTextColor)), + Expanded( + child: SizedBox(), + ), + Image.asset( + R.assetsImagesCoin, + scale: 2, + ), + SizedBox( + width: 5, + ), + fixedText( + I18n.of(context) + .available_balance + .replaceFirst('/s1', ''), + color: Constants.GreyTextColor), + Consumer( + builder: (context, + MoneyChangeProvider counter, + child) => + fixedText(counter.money.toString(), + color: Color(0xFFDB305D)), + ), + fixedText(I18n.of(context).mask_coin, + color: Color(0xFFDB305D)), + ], + ), + ), + Container( + alignment: Alignment.topCenter, + padding: EdgeInsets.all(10), + height: 230, + child: GiftPage(giftList, 0), + ), + Expanded(child: SizedBox()), + Padding( + padding: EdgeInsets.symmetric( + vertical: 5, horizontal: 20), + child: Row( + children: [ + Expanded( + child: SizedBox( + height: 36, + child: RaisedButton( + padding: + EdgeInsets.symmetric(horizontal: 5), + child: Text( + I18n.of(context).recharge, + textScaleFactor: 1.0, + maxLines: 1, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold), + ), + elevation: 2.0, + color: Colors.orangeAccent, + textColor: Colors.white, + onPressed: () { + ChargeMoney.showChargeSheet(context, + () { + setState(() {}); + }); + }, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(20)), + ), + ), + )), + SizedBox(width: 20), + Expanded( + flex: 2, + child: Container( + height: 36, + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + blurRadius: 2.0, + color: Colors.white24) + ], + borderRadius: BorderRadius.all( + Radius.circular(20)), + border: Border.all( + color: Colors.red)), + child: Row( + children: [ + Expanded( + child: DropdownButton( + isExpanded: true, + underline: Container(), + value: curGiftValue, + style: TextStyle(fontSize: 16), + iconEnabledColor: + Colors.redAccent, + onChanged: (newValue) { + setBottomSheetState(() { + curGiftValue = newValue; + }); + }, + items: [1, 6, 8, 66] + .map((v) => DropdownMenuItem( + value: v, + child: Container( + padding: + EdgeInsets.only( + left: 20), + child: fixedText( + v.toString(), + color: v == curGiftValue + ? Colors + .redAccent + : Colors + .black)))) + .toList(), + )), + Expanded( + child: InkWell( + child: Container( + decoration: BoxDecoration( + color: Color(0xFFFD6E8F), + borderRadius: + BorderRadius.only( + topRight: Radius + .circular(20), + bottomRight: + Radius.circular( + 20)), + ), + height: 36, + alignment: Alignment.center, + child: Text( + I18n.of(context).give, + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: + FontWeight.bold), + ), + ), + onTap: () { + _sendGift(context); + }, + )) + ], + ))) + ], + ), + ) + ], + )); + }, + ); + }); + } + + _sendGift(BuildContext context) async { + int curSelectIndex = + Provider.of(context).curSelectIndex; + var curGift = giftList[curSelectIndex]; + + int price = curGift.price; + int giftId = curGift.id; + int total = curGiftValue * price; + if (total > Provider.of(context).money) { + showToast(I18n.of(context).not_enough); + return; + } + + int buyCount = 0; + if (curGiftValue > curGift.amount) { + buyCount = curGiftValue - curGift.amount; + } + Map data = { + "userId": UserData().basicInfo.userId, + "rUserId": friendId, + "id": giftId, + "price": price, + "amount": curGiftValue, + "totalPrice": total, + "payNum": buyCount + }; + + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('reward/gift', data: data); + if (res == null) { + return; + } + Map resData = res.data; + + //showToast(resData['msg']); + + if (resData['code'] == 0) { + //赠送成功 + print('赠送金额:${resData['data']}'); + + int receiveAmount = resData['data']; + Navigator.pop(context); + + Provider.of(context, listen: false).subMoney(total); + AnimEffect.showEffect(context, giftId); + AnimEffect.showDashangEffect(context, true, curGiftValue, curGift.name); + MsgHandler.sendGiftTo(friendId, giftId, curGiftValue, receiveAmount); + + setState(() {}); + } + } + + //是否开启扬声器 + void _isSpeakPhone() { + setState(() { + speakPhone = !speakPhone; + }); + AgoraRtcEngine.setEnableSpeakerphone(speakPhone); + } + + //退出频道 退出本页面 + void _onExit(BuildContext context) { + if (!isQuit) { + if (Navigator.canPop(context)) { + isQuit = true; + Navigator.of(context).pop(); + SoundUtils().stop(); + callingTimer?.cancel(); + } + } + } +} diff --git a/lib/home/create_group_view.dart b/lib/home/create_group_view.dart new file mode 100644 index 0000000..ea157bf --- /dev/null +++ b/lib/home/create_group_view.dart @@ -0,0 +1,671 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/chat/group_chat_view.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/models/group_list_provider.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/conversation_table.dart'; +import 'package:chat/utils/friend_list_mgr.dart'; +import 'package:chat/utils/group_member_model.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; + +Widget _createAvatar(avatar) { + return ClipRRect( + borderRadius: BorderRadius.circular(6), + child: CachedNetworkImage( + imageUrl: avatar, + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + )); +} + +class FriendSelectItem extends StatefulWidget { + final FriendModel friendModel; + final String groupTitle; + final bool isShowDivder; + final bool isSingle; + final bool isSelected; + FriendSelectItem( + {this.friendModel, + this.groupTitle, + this.isShowDivder = true, + this.isSelected = false, + this.isSingle = false}); + + @override + _FriendSelectItemState createState() => _FriendSelectItemState(); +} + +class _FriendSelectItemState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + var selectProvider = Provider.of(context); + bool isSelect = selectProvider.isSelect(widget.friendModel); + // print('是否选择 ${widget.friendModel.name} $isSelect'); + var _avatarIcon = _createAvatar(widget.friendModel.avatar); + Widget _button = Container( + padding: const EdgeInsets.symmetric( + vertical: MARGIN_VERTICAL, horizontal: 16.0), + decoration: BoxDecoration(color: Colors.white), + child: Row( + children: [ + widget.isSelected + ? Container( + width: 20, + height: 20, + decoration: BoxDecoration( + color: Colors.grey[400], + shape: BoxShape.circle, + border: Border.all( + color: const Color(0xFF707070), width: 0.2)), + child: Icon(Icons.check, size: 15, color: Colors.white), + ) + : (isSelect + ? Container( + width: 20, + height: 20, + decoration: BoxDecoration( + color: const Color(0xFF2685FA), + shape: BoxShape.circle, + border: Border.all( + color: const Color(0xFF707070), width: 0.2)), + child: Icon(Icons.check, size: 15, color: Colors.white), + ) + : Container( + width: 20, + height: 20, + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + border: Border.all(color: const Color(0xFF707070))), + )), + SizedBox(width: 10), + _avatarIcon, + SizedBox(width: 10.0), + Text(widget.friendModel.getTitle()), + ], + ), + ); + + //分组标签 + Widget _itemBody; + if (widget.groupTitle != null) { + _itemBody = Column( + children: [ + Container( + height: GROUP_TITLE_HEIGHT, + padding: EdgeInsets.only(left: 16.0, right: 16.0), + color: const Color(AppColors.ContactGroupTitleBgColor), + alignment: Alignment.centerLeft, + child: Text(widget.groupTitle, + style: AppStyles.GroupTitleItemTextStyle), + ), + _button, + ], + ); + } else { + _itemBody = _button; + } + + return InkWell( + onTap: widget.isSelected + ? null + : () { + if (widget.isSingle) { + selectProvider.curSelectFriendList.clear(); + if (isSelect) { + selectProvider.removeFriend(widget.friendModel); + } else { + selectProvider.addFriend(widget.friendModel); + MessageMgr().emit('jump_top'); + } + } else { + if (isSelect) { + selectProvider.removeFriend(widget.friendModel); + } else { + selectProvider.addFriend(widget.friendModel); + MessageMgr().emit('jump_top'); + } + } + }, + child: Container( + color: Colors.white, + child: Column( + children: [ + _itemBody, + widget.isShowDivder + ? Container( + height: 1, + color: const Color(0xFFF3F3F3), + margin: EdgeInsets.only( + left: 26 + Constants.ContactAvatarSize), + ) + : Container() + ], + ))); + } +} + +class CreateGroupPage extends StatefulWidget { + final int pageType; + final List originalList; + final int groupId; + CreateGroupPage(this.pageType, this.originalList, this.groupId); + @override + _CreateGroupPageState createState() => _CreateGroupPageState(); +} + +class _CreateGroupPageState extends State { + String _currentLetter = ''; + ScrollController _scrollController; + ScrollController _headScrollCtrl = ScrollController(); + TextEditingController _txtCtrl = new TextEditingController(); + bool _hasdeleteIcon = false; + + bool isSingle = false; + + bool isCreating = false; + + List friendList = []; + + List searchList = []; + + Set originalUserIdSet = new Set(); + + GroupSelectProvider _groupSelectProvider = GroupSelectProvider(); + final Map _letterPosMap = {INDEX_BAR_WORDS[0]: 0.0}; + + double _groupHeight(bool hasGroupTitle) { + final _buttonHeight = MARGIN_VERTICAL * 2 + + Constants.ContactAvatarSize + + Constants.DividerWidth; + if (hasGroupTitle) { + return _buttonHeight + GROUP_TITLE_HEIGHT; + } else { + return _buttonHeight; + } + } + + @override + void initState() { + super.initState(); + + print('CreateGroupPage initState'); + + getFriendList(); + isSingle = widget.pageType == GroupOperatingPageType.SelectGroupOwner; + MessageMgr().on('jump_top', animateToTop); + } + + @override + void dispose() { + MessageMgr().off('jump_top', animateToTop); + super.dispose(); + } + + animateToTop(data) { + // _scrollController.animateTo( + // 0.0, + // curve: Curves.easeOut, + // duration: const Duration(milliseconds: 300), + // ); + _headScrollCtrl.jumpTo(0); + } + + getFriendList() async { + for (var item in widget.originalList) { + originalUserIdSet.add(item.memberId); + } + if (widget.pageType == GroupOperatingPageType.AddMember || + widget.pageType == GroupOperatingPageType.CreateGroup) { + friendList = await FriendListMgr().getFriendList(); + setState(() {}); + } + if (widget.pageType == GroupOperatingPageType.DeleteMember || + widget.pageType == GroupOperatingPageType.SelectGroupOwner) { + for (var item in widget.originalList) { + if (item.memberId != UserData().basicInfo.userId) { + FriendModel friend = new FriendModel( + friendId: item.memberId, + avatar: item.avtar, + name: item.nickName, + refName: item.refName); + friendList.add(friend); + } + } + setState(() {}); + } + } + + Widget _createSearch() { + return Container( + alignment: Alignment.center, + height: 45, + child: TextField( + keyboardAppearance: Brightness.light, + keyboardType: TextInputType.text, + textInputAction: TextInputAction.search, + controller: _txtCtrl, + maxLines: 1, + style: + TextStyle(textBaseline: TextBaseline.alphabetic, fontSize: 14.5), + autofocus: false, + inputFormatters: [ + LengthLimitingTextInputFormatter(50), + ], + decoration: InputDecoration( + contentPadding: EdgeInsets.symmetric(vertical: 14), + hintText: I18n.of(context).search, + hintStyle: TextStyle(fontSize: 14.5), + prefixIcon: Consumer( + builder: (context, counter, child) => Icon( + IconData( + 0xe664, + fontFamily: Constants.IconFontFamily, + ), + color: const Color(0xFFA0A0A0), + size: 18, + )), + filled: true, + fillColor: Colors.transparent, + border: InputBorder.none, + ), + onChanged: (str) async { + setState(() { + if (str.isEmpty) { + _hasdeleteIcon = false; + } else { + _hasdeleteIcon = true; + searchList = CustomUI() + .getSearchResult(str, friendList == null ? [] : friendList); + } + }); + }, + onEditingComplete: () {}), + ); + } + + updateIndexPos(List friendList) { + //计算用于 IndexBar 进行定位的关键通讯录列表项的位置 + double _totalPos = 0.0; + for (var i = 0; i < friendList.length; i++) { + bool _hasGroupTitle = true; + if (i > 0 && + friendList[i].nameTag.compareTo(friendList[i - 1].nameTag) == 0) { + _hasGroupTitle = false; + } + + if (_hasGroupTitle) { + _letterPosMap[friendList[i].nameTag] = _totalPos; + } + _totalPos += _groupHeight(_hasGroupTitle); + } + } + + String getLetter(BuildContext context, double tileHeight, Offset globalPos) { + RenderBox _box = context.findRenderObject(); + var local = _box.globalToLocal(globalPos); + int index = (local.dy ~/ tileHeight).clamp(0, INDEX_BAR_WORDS.length - 1); + return INDEX_BAR_WORDS[index]; + } + + void _jumpToIndex(String letter) { + if (_letterPosMap.isNotEmpty) { + final _pos = _letterPosMap[letter]; + if (_pos != null) { + _scrollController.animateTo(_letterPosMap[letter], + curve: Curves.easeInOut, duration: Duration(microseconds: 200)); + } + } + } + + Widget _buildIndexBar(BuildContext context, BoxConstraints constraints) { + final List _letters = INDEX_BAR_WORDS.map((String word) { + return Expanded( + child: Container( + margin: EdgeInsets.only(right: 5), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: + _currentLetter == word ? Colors.blue : Colors.transparent, + ), + alignment: Alignment.center, + padding: EdgeInsets.all(2), + width: 20, + child: Text( + word, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 10, + color: + _currentLetter == word ? Colors.white : Colors.black), + ))); + }).toList(); + + final _totalHeight = constraints.biggest.height; + final _tileHeight = _totalHeight / _letters.length; + return GestureDetector( + onVerticalDragDown: (DragDownDetails details) { + setState(() { + _currentLetter = + getLetter(context, _tileHeight, details.globalPosition); + _jumpToIndex(_currentLetter); + }); + }, + onVerticalDragEnd: (DragEndDetails details) { + setState(() { + //_indexBarBgColor = Colors.transparent; + _currentLetter = null; + }); + }, + onVerticalDragCancel: () { + setState(() { + //_indexBarBgColor = Colors.transparent; + _currentLetter = null; + }); + }, + onVerticalDragUpdate: (DragUpdateDetails details) { + setState(() { + //var _letter = getLetter(context, _tileHeight, details.globalPosition); + _currentLetter = + getLetter(context, _tileHeight, details.globalPosition); + _jumpToIndex(_currentLetter); + }); + }, + child: Column( + children: _letters, + ), + ); + } + + @override + Widget build(BuildContext context) { + if (friendList == null) { + return Scaffold( + appBar: AppBar( + leading: CustomUI.buildCustomLeading(context), + ), + body: Center(child: CircularProgressIndicator())); + } + + final List _body = []; + + if (!_hasdeleteIcon) { + friendList.sort((a, b) => a.nameTag.compareTo(b.nameTag)); + updateIndexPos(friendList); + _body.addAll([ + ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + bool _isGroupTitle = true; + FriendModel _contact = friendList[index]; + + if (index >= 1 && + _contact.nameTag == friendList[index - 1].nameTag) { + _isGroupTitle = false; + } + + return FriendSelectItem( + friendModel: _contact, + isShowDivder: _isGroupTitle, + isSingle: isSingle, + isSelected: originalUserIdSet.contains(_contact.friendId) && + widget.pageType == GroupOperatingPageType.AddMember, + groupTitle: _isGroupTitle ? _contact.nameTag : null); + }, + itemCount: friendList.length, + ), + Positioned( + width: Constants.IndexBarWidth, + right: 0.0, + top: 0.0, + bottom: 0.0, + child: Container( + child: LayoutBuilder( + builder: _buildIndexBar, + ), + ), + ) + ]); + } else { + _body.add(ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + FriendModel _contact = searchList[index]; + + return FriendSelectItem( + isSingle: isSingle, + friendModel: _contact, + isShowDivder: true, + isSelected: originalUserIdSet.contains(_contact.friendId) && + widget.pageType == GroupOperatingPageType.AddMember, + groupTitle: null); + }, + itemCount: searchList.length, + )); + } + + if (_currentLetter != null && + _currentLetter.isNotEmpty && + !_hasdeleteIcon) { + _body.add(Center( + child: Container( + width: Constants.IndexLetterBoxSize, + height: Constants.IndexLetterBoxSize, + decoration: BoxDecoration( + color: AppColors.IndexLetterBoxBgColor, + borderRadius: BorderRadius.all( + Radius.circular(Constants.IndexLetterBoxRadius)), + ), + child: Center( + child: + Text(_currentLetter, style: AppStyles.IndexLetterBoxTextStyle), + ), + ), + )); + } + + String title = ''; + switch (widget.pageType) { + case GroupOperatingPageType.AddMember: + case GroupOperatingPageType.CreateGroup: + title = I18n.of(context).add_member; + break; + case GroupOperatingPageType.DeleteMember: + title = I18n.of(context).delete_member; + break; + case GroupOperatingPageType.SelectGroupOwner: + title = I18n.of(context).choose_group_owner; + break; + default: + } + + return ChangeNotifierProvider( + create: (_) => _groupSelectProvider, + child: Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + title, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + elevation: 0, + actions: [ + InkWell( + child: Padding( + padding: EdgeInsets.only(right: 12, top: 14, bottom: 14), + child: Consumer( + builder: (context, counter, child) => Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4.5), + color: _groupSelectProvider + .curSelectFriendList.length == + 0 + ? Colors.grey[350] + : (widget.pageType == + GroupOperatingPageType + .DeleteMember + ? Colors.red + : const Color(0xFF3875E9)), + ), + padding: EdgeInsets.symmetric(horizontal: 10), + alignment: Alignment.center, + child: fixedText( + (widget.pageType == + GroupOperatingPageType + .DeleteMember + ? I18n.of(context).delete + : I18n.of(context).determine) + + "(${_groupSelectProvider.curSelectFriendList.length})", + color: Colors.white, + fontSize: 12.67), + ))), + onTap: () async { + if (_groupSelectProvider.curSelectFriendList.length == 0) + return; + + switch (widget.pageType) { + case GroupOperatingPageType.CreateGroup: + createGroup(); + break; + case GroupOperatingPageType.AddMember: + addMember(); + break; + case GroupOperatingPageType.DeleteMember: + deleteMember(); + break; + case GroupOperatingPageType.SelectGroupOwner: + selectGroupOwner(); + break; + default: + } + }, + ) + ], + bottom: PreferredSize( + preferredSize: Size.fromHeight(49), + child: Container( + color: Colors.white, + child: Column( + children: [ + Container( + height: 6, + color: const Color(0xFFE9E9E9), + ), + Row( + children: [ + Consumer( + builder: (context, counter, child) { + return Container( + margin: EdgeInsets.only(left: 10), + constraints: BoxConstraints( + maxWidth: Screen.width - 100), + height: 45, + width: (Constants.ContactAvatarSize + 3) * + counter.curSelectFriendList.length, + child: ListView( + reverse: true, + controller: _headScrollCtrl, + scrollDirection: Axis.horizontal, + children: counter.curSelectFriendList.reversed + .map((friend) => InkWell( + onTap: () { + var selectProvider = Provider.of< + GroupSelectProvider>(context); + bool isSelect = + selectProvider.isSelect(friend); + if (isSelect) { + selectProvider + .removeFriend(friend); + } else { + selectProvider.addFriend(friend); + } + }, + child: Container( + margin: EdgeInsets.only(right: 3), + child: _createAvatar( + friend.avatar)))) + .toList(), + ), + ); + }), + Expanded( + child: _createSearch(), + ) + ], + ) + ], + ), + )), + ), + body: Stack( + children: _body, + ))); + } + + deleteMember() { + List members = []; + for (var i = 0; i < _groupSelectProvider.curSelectFriendList.length; i++) { + var fdInfo = _groupSelectProvider.curSelectFriendList[i]; + members.add(fdInfo.friendId); + } + MsgHandler.removeGroupMember(widget.groupId, members); + Navigator.of(context).pop(); + } + + addMember() { + List members = []; + for (var i = 0; i < _groupSelectProvider.curSelectFriendList.length; i++) { + var fdInfo = _groupSelectProvider.curSelectFriendList[i]; + members.add(fdInfo.friendId); + } + MsgHandler.addGroupMember(widget.groupId, members); + Navigator.of(context).pop(); + } + + selectGroupOwner() { + FriendModel fdInfo = _groupSelectProvider.curSelectFriendList[0]; + MsgHandler.updateGroupHoster(widget.groupId, fdInfo.friendId); + Navigator.of(context).pop('close'); + } + + createGroup() { + //创建群 + print('创建群:成员数${_groupSelectProvider.curSelectFriendList.length}'); + var myId = UserData().basicInfo.userId; + var members = [myId]; + for (var i = 0; i < _groupSelectProvider.curSelectFriendList.length; i++) { + var fdInfo = _groupSelectProvider.curSelectFriendList[i]; + members.add(fdInfo.friendId); + } + + if (isCreating) { + showToast(I18n.of(context).creating_group); + return; + } + isCreating = true; + + MsgHandler.createGroup(members, (GroupInfoModel groupInfoModel) { + Navigator.of(context).pushReplacement(MaterialPageRoute( + builder: (context) => GroupChatPage( + key: Key('GroupChat'), groupInfoModel: groupInfoModel))); + }); + } +} diff --git a/lib/home/daily_bonus_page.dart b/lib/home/daily_bonus_page.dart new file mode 100644 index 0000000..8492317 --- /dev/null +++ b/lib/home/daily_bonus_page.dart @@ -0,0 +1,577 @@ +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/daily_bonus.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:percent_indicator/linear_percent_indicator.dart'; + +class DailyBonusPage extends StatefulWidget { + @override + State createState() { + return DailyBouusState(); + } +} + +class DailyBouusState extends State with SingleTickerProviderStateMixin { + bool isLoadingFish = false; + + int score = 0; + List goods = []; + + DailyBonusBean dailyBonusBean; + int addScore = 0; + double progress1 = 0; + double progress2 = 0; + double progress3 = 0; + + AnimationController controller; + Animation animation; + AnimationStatusListener statusListener; + + @override + void dispose() { + animation.removeStatusListener(statusListener); + animation = null; + + controller.dispose(); + controller = null; + super.dispose(); + } + + @override + void initState() { + super.initState(); + dailyBonusBean = new DailyBonusBean(); + + controller = new AnimationController( + duration: const Duration(milliseconds: 800), vsync: this); + animation = Tween(begin: 0.95, end: 1.1).animate(controller); + + animation.addStatusListener(statusListener = (status) { + if (status == AnimationStatus.completed) { + controller.reverse(from: 1.0); + } else if (status == AnimationStatus.dismissed) { + controller.forward(); + } + }); + + controller.addListener(() { + setState(() {}); +// print(animation.value); + }); + controller.forward(); + + WidgetsBinding.instance.addPostFrameCallback((_) { + initDailyInfo(); + }); + } + + initDailyInfo() async { + var daily = await HttpUtil().getDailyBonus(); + if (daily != null) { + dailyBonusBean = daily; + setState(() { + goods = dailyBonusBean.goods; + print('dailyBonusBean goods length:${dailyBonusBean.goods.length}'); + score = dailyBonusBean.score; + + int currentDay = dailyBonusBean.isSignIn == 0 + ? dailyBonusBean.currentDay + 1 + : dailyBonusBean.currentDay; + addScore = currentDay * dailyBonusBean.addScore; + setProgress(); + isLoadingFish = true; + }); + } + } + + setProgress() { + int currentPart = 0; + double tempProgress = 0; + for (int k = 0; k < dailyBonusBean.goods.length; k++) { + GoodsBean bean = dailyBonusBean.goods[k]; + + if (score <= bean.s) { + currentPart = k; + break; + } + } + print('tempProgress: $tempProgress'); + print('currentPart: $currentPart'); + if (currentPart == 0) { + GoodsBean bean = dailyBonusBean.goods[0]; + print('GGG $score ${bean.s} ${dailyBonusBean.goods.length}'); + tempProgress = score / bean.s; + progress1 = tempProgress; + progress2 = 0; + progress3 = 0; + if (progress1 > 1) { + progress1 = 1; + } + } else if (currentPart == 1) { + int s = dailyBonusBean.goods[currentPart].s - + dailyBonusBean.goods[currentPart - 1].s; + int current = (score - dailyBonusBean.goods[currentPart - 1].s); + + double p = current / s; + progress1 = 1; + progress2 = p; + print('WWW $s $current $progress2 '); + progress3 = 0; + if (progress2 > 1) { + progress2 = 1; + } + } else if (currentPart == 2) { + int s = dailyBonusBean.goods[currentPart].s - + dailyBonusBean.goods[currentPart - 1].s; + int current = (score - dailyBonusBean.goods[currentPart - 1].s); + + double p = current / s; + progress1 = 1; + progress2 = 1; + progress3 = p; + if (progress3 > 1) { + progress3 = 1; + } + print('WWW $s $progress3 '); + } + +// print('progress: $progress'); + +// GoodsBean bean = dailyBonusBean.goods[currentPart]; +// print('currentPart:$currentPart'); +// int max = bean.s; +// double maxProgress = currentPart/(dailyBonusBean.goods.length); +// +// progress = score/max*maxProgress; + } + + @override + Widget build(BuildContext context) { + List signStr = I18n.of(context).today_score.split('/s1'); + int signTotalDay = dailyBonusBean != null ? dailyBonusBean.currentDay : 0; + String rules = '''${I18n.of(context).sign_tips}'''; + Widget content = Material( + child: Stack( + children: [ + Container( + height: MediaQuery.of(context).size.height, + color: Color(0xffF0F0F0), + ), + Container( + child: Image.asset( + 'assets/images/daily_bg_1.png', + width: MediaQuery.of(context).size.width, + height: 200, + fit: BoxFit.cover, + ), + ), + Scaffold( + appBar: AppBar( + title: Text( + I18n.of(context).sign_in, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + backgroundColor: Colors.transparent, + iconTheme: IconThemeData(color: Colors.white), + ), + backgroundColor: Colors.transparent, + body: SafeArea( + child: SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Stack( + children: [ + Image.asset(R.assetsImagesDailyBg2, fit: BoxFit.cover), + Container( + padding: EdgeInsets.only(left: 30, right: 20), + height: 150, + alignment: Alignment.center, + child: Row( + children: [ + Expanded( + flex: 4, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + SizedBox( + height: 50, + ), + Text( + I18n.of(context).my_score, + textScaleFactor: 1.0, + style: TextStyle( + color: Color(0xff6D6D6E), + fontSize: 16), + ), + Text( + '$score', + textScaleFactor: 1.0, + style: TextStyle( + color: Color(0xff0060FF), + fontSize: 33), + ), + ], + )), + Expanded( + flex: 6, + child: Container( + padding: EdgeInsets.only(left: 20), + child: Column( + children: [ + SizedBox( + height: 50, + ), + GestureDetector( + child: Container( + alignment: Alignment.center, + constraints: BoxConstraints( + minHeight: 38, + minWidth: 113, + maxWidth: 150), + child: Text( + I18n.of(context).signin_now, + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.white, + fontSize: 16), + ), + decoration: BoxDecoration( + color: Color( + dailyBonusBean.isSignIn == 0 + ? 0xff2D81FF + : 0xffB5B5B5), + borderRadius: + BorderRadius.circular(6)), + ), + onTap: () { + signInBouus(); + }, + ), + SizedBox( + height: 10, + ), + RichText( + maxLines: 3, + textAlign: TextAlign.center, + text: TextSpan(children: [ + TextSpan( + text: signStr[0], + style: TextStyle( + color: Color(0xff6D6D6E), + fontSize: 10)), + TextSpan( + text: '$addScore', + style: TextStyle( + color: Color(0xffFF0000), + fontSize: 10)), + TextSpan( + text: signStr[1], + style: TextStyle( + color: Color(0xff6D6D6E), + fontSize: 10)), + ])) + ], + ), + )) + ], + ), + ) + ], + ), + ), + SizedBox( + height: 15, + ), + Container( + ///签到进度 + height: 118, + + width: MediaQuery.of(context).size.width, + margin: EdgeInsets.symmetric(horizontal: 17), + child: Column( + children: [ + Container( + alignment: Alignment.center, + height: 105, + width: 360, + child: Stack( + children: [ + Container( + alignment: Alignment.center, + child: Padding( + padding: EdgeInsets.only(left: 10, top: 12), + child: Row( + children: [ + LinearPercentIndicator( + width: 51, + lineHeight: 10, + percent: progress1, + padding: null, + progressColor: Color(0xff008AFF), + backgroundColor: Color(0xffD3D3D3), + ), + SizedBox( + width: 15, + ), + LinearPercentIndicator( + width: 94, + lineHeight: 10, + percent: progress2, + padding: null, + progressColor: Color(0xff008AFF), + backgroundColor: Color(0xffD3D3D3), + ), + SizedBox( + width: 23, + ), + LinearPercentIndicator( + width: 94, + lineHeight: 10, + percent: progress3, + padding: null, + progressColor: Color(0xff008AFF), + backgroundColor: Color(0xffD3D3D3), + ), + ], + ), + ), + ), + getGoods() + ], + ), + ), + ], + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(6)), + ), + SizedBox( + height: 22, + ), + Container( + ///签到天数 + constraints: BoxConstraints(minHeight: 420), + width: MediaQuery.of(context).size.width, + margin: EdgeInsets.symmetric(horizontal: 17), + child: Column( + children: [ + Container( + alignment: Alignment.center, + height: 46, + margin: EdgeInsets.all(20), + child: Row( + children: [ + Image.asset(R.assetsImagesDailyIcon), + Expanded( + child: Text( + I18n.of(context).sign_in_day.replaceFirst( + '/s1', signTotalDay.toString()), + textAlign: TextAlign.center, + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.white, fontSize: 13), + )) + ], + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(23), + gradient: LinearGradient( + colors: [Color(0xff8683EA), Color(0xff4BAAFB)], + )), + ), + + ///签到天数表格 + Container( + height: 246, + padding: EdgeInsets.only(left: 20, right: 20), + child: GridView.builder( + physics: NeverScrollableScrollPhysics(), + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 7, + crossAxisSpacing: 15.0, + mainAxisSpacing: 13.0), + itemBuilder: (context, index) { + bool isCheck = index < dailyBonusBean.currentDay; + return ClipOval( + child: Container( + alignment: Alignment.center, + color: + Color(isCheck ? 0xff2D81FF : 0xffD3D3D3), + child: isCheck + ? Icon( + Icons.check, + color: Colors.white, + ) + : Text( + '${index + 1}', + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white), + ), + ), + ); + }, + itemCount: dailyBonusBean.days, + padding: EdgeInsets.all(5.0), + ), + ), + Padding( + padding: EdgeInsets.fromLTRB(18, 0, 18, 18), + child: Text( + rules, + style: TextStyle( + color: Color(0xffFF0000), fontSize: 12), + ), + ) + ], + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(6)), + ), + SizedBox( + height: 22, + ), + ], + ), + )), + ) + ], + ), + ); + return CustomUI.buildPageLoading(context, content, !isLoadingFish); + } + + Widget getGoods() { + return goods.length < 3 + ? Container() + : Container( + width: 400, + height: 105, + child: Row( + children: [ + SizedBox( + width: 46, + ), + getGoodsItem(goods[0], 0), + SizedBox( + width: 39, + ), + getGoodsItem(goods[1], 1), + SizedBox( + width: 38, + ), + getGoodsItem(goods[2], 2), + ], + ), + ); + } + + getGoodsItem(GoodsBean bean, int index) { + bool isEnough = score >= bean.s; + + bool needAnimate = isEnough && bean.state == 0; + + return GestureDetector( + onTap: () { + exchangeBonus(index); + }, + child: Column( + children: [ + Container( + alignment: Alignment.center, + margin: EdgeInsets.only(top: 12, bottom: 5), + constraints: BoxConstraints(minWidth: 61), + padding: EdgeInsets.fromLTRB(3, 1, 3, 1), + decoration: BoxDecoration( + color: Color(isEnough ? 0xff2D81FF : 0xffCBCBCB), + borderRadius: BorderRadius.circular(8)), + child: Text( + bean.state == 1 + ? I18n.of(context).have_get + : '${bean.h}${I18n.of(context).daily_translate_voucher}', + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white, fontSize: 12), + ), + ), + Stack( + children: [ +// Container(width: 49,), + Positioned( + top: 48, + child: Text('${bean.s}', + textScaleFactor: 1.0, + style: TextStyle( + color: Color(isEnough ? 0xff2D81FF : 0xffCBCBCB), + fontSize: 13))), + Container( + margin: EdgeInsets.only(bottom: 25), + alignment: Alignment.center, + width: 40, + height: 40, + child: Container( + alignment: Alignment.center, + width: 37, + height: 37, + child: Image.asset( + R.assetsImagesImgFyj, + width: needAnimate ? animation.value * 17 : 17, + height: needAnimate ? animation.value * 17 : 17, + ), + decoration: BoxDecoration( + color: Color(isEnough ? 0xff2D81FF : 0xffCBCBCB), + borderRadius: BorderRadius.circular(30))), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(30)), + ), + ], + ), + ], + ), + ); + } + + signInBouus() async { + if (dailyBonusBean.isSignIn == 0) { + int addScore = (dailyBonusBean.currentDay + 1) * dailyBonusBean.addScore; + bool isSuccess = await HttpUtil().signInBounus(addScore); + if (isSuccess) { + setState(() { + score = score + addScore; + dailyBonusBean.isSignIn = 1; + dailyBonusBean.currentDay = dailyBonusBean.currentDay + 1; + }); + } + } + } + + exchangeBonus(int index) async { + GoodsBean goodsBean = goods[index]; + if (score >= goodsBean.s && goodsBean.state == 0) { +// int addScore= (dailyBonusBean.currentDay+1)*dailyBonusBean.addScore; + bool isSuccess = await HttpUtil().signInExchange(goodsBean); + if (isSuccess) { + setState(() { + score = score - goodsBean.s; + goods[index].state = 1; + setProgress(); + }); + MessageMgr().emit('refresh_money'); + + ///兑换成功后加了金币刷新余额 + } + } + } +} diff --git a/lib/home/fans_page.dart b/lib/home/fans_page.dart new file mode 100644 index 0000000..b84d9dd --- /dev/null +++ b/lib/home/fans_page.dart @@ -0,0 +1,164 @@ +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/UserCard.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; +import '../utils/HttpUtil.dart'; +import 'package:dio/dio.dart'; +import "../data/UserData.dart"; +import '../utils/TokenMgr.dart'; + +class FansPage extends StatefulWidget { + FansPage({Key key}) : super(key: key); + + @override + _FansPageState createState() => new _FansPageState(); +} + +class _FansPageState extends State { + List list = new List(); //列表要展示的数据 + RefreshController _refreshController = + RefreshController(initialRefresh: true); + int _page = 1; //加载的页数 + int rows = 20; + + @override + void initState() { + super.initState(); + } + + Future getData(callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + data['lng'] = UserData().longitude; + data['lat'] = UserData().latitude; + data['page'] = _page; + data['rows'] = rows; + Response res = await HttpUtil().post('userfollow/fans/list', + data: data, failback: () => Navigator.of(context).pop()); + _refreshController.refreshCompleted(); + var resData = res.data; + if (resData['code'] == 0) { + callback(resData['data']); + } else { + showToast(resData['msg']); + } + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + leading: CustomUI.buildCustomLeading(context), + title: new Text( + I18n.of(context).fans_list, + style: TextStyle(color: AppColors.NewAppbarTextColor), + textScaleFactor: 1.0, + ), + centerTitle: true, + ); + + return Scaffold( + appBar: appBar, + body: SafeArea( + child: SmartRefresher( + enablePullDown: true, + enablePullUp: true, + header: MaterialClassicHeader(), + footer: CustomUI.buildLoadingFooter(), + controller: _refreshController, + onRefresh: _onRefresh, + onLoading: _onLoading, + child: + (_refreshController.headerStatus == RefreshStatus.completed && + list.length == 0) + ? CustomUI.buildNoData(context) + : ListView.builder( + itemBuilder: _renderRow, + itemCount: list.length, + ), + ), + )); + } + + Widget _renderRow(BuildContext context, int index) { + if (index < list.length) { + var userInfo = list[index]; + print(userInfo); + var whiteItem = UserCard( + key: UniqueKey(), + userName: Provider.of(context) + .getRefName(userInfo['UserId'], userInfo['NickName']), + city: WebData().getCountry( + userInfo['Country']), // WebData().getCity(userInfo['City']), + headUrl: userInfo['Headimgurl'], + isReal: userInfo['IsAttestation'] == 1, + constellation: + WebData().getConstellation(context, userInfo['constellation']), + distance: userInfo['Distance'].toDouble(), + age: + DateTime.now().year - int.parse(userInfo['Birthday'].split('-')[0]), + professional: WebData().getProffesionName(userInfo['Occupation']), + isOnline: userInfo['OnlineStatus'] == 1 + ? I18n.of(context).online + : WebData().getLoginTime(context, userInfo['LoginDate']), + hiddenDistince: userInfo['DistanceStatus'] == 1, + sex: userInfo['Sex'], + isLove: userInfo['Follow'] == 0, + isBalck: userInfo['Follow'] == 1, + userId: userInfo['FollowUserId'], + payImg: userInfo['PhotoAut'] == 1, + isHidden: userInfo['InfoAut'] == 1, + member: userInfo['IsMember'], + imgNum: userInfo['PhotoNum'], + ); + + return (index == 0 + ? Padding(padding: EdgeInsets.only(top: 10), child: whiteItem) + : whiteItem); + } + return Container(); + } + + Future _onRefresh() async { + _page = 1; + getData((data) { + if (data != null) { + list.clear(); + list.addAll(data); + MessageMgr().emit('refresh_fans_num', + {"UserId": UserData().basicInfo.userId, "nums": list.length}); + setState(() {}); + } + }); + } + + Future _onLoading() async { + _page++; + getData((data) { + if (data == null || data.length == 0) { + _page--; + _refreshController.loadNoData(); + } else { + list.addAll(data); + _refreshController.loadComplete(); + } + setState(() {}); + }); + } + + @override + void dispose() { + _refreshController.dispose(); + super.dispose(); + } +} diff --git a/lib/home/find_page.dart b/lib/home/find_page.dart new file mode 100644 index 0000000..9891e65 --- /dev/null +++ b/lib/home/find_page.dart @@ -0,0 +1,236 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/DiscoverPage.dart'; +import 'package:chat/home/ParkPage.dart'; +import 'package:chat/home/follow_user_dynamic.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:flutter/material.dart'; +import 'package:location_permissions/location_permissions.dart'; +import 'package:oktoast/oktoast.dart'; + +class FindPage extends StatefulWidget { + FindPage({Key key}) : super(key: key); + + @override + _FindPageState createState() => new _FindPageState(); +} + +class _FindPageState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text(I18n.of(context).find, + textScaleFactor: 1.0, style: Constants.MainTitleStyle), + centerTitle: false, + elevation: 1, + ); + return SafeArea( + child: Scaffold( + appBar: appBar, + body: _buildBody(), + )); + } + + _buildBody() { + return Column( + children: [ + _buildRadioButton(), + _buildMyProgramButton(), + _buildNearButton(), + _buildScanButton(), + ], + ); + } + + _buildIconButton(Widget icon, Gradient gradient, String text, callback, + {double marginTop: 12, bool showDivder: false}) { + return InkWell( + onTap: callback, + child: Container( + margin: EdgeInsets.only(top: marginTop), + padding: EdgeInsets.only(left: 16.5, right: 20, top: 9, bottom: 9), + decoration: BoxDecoration( + color: Colors.white, + border: + showDivder ? Border(top: Constants.GreyBorderSide) : null), + child: Row( + children: [ + Stack( + alignment: Alignment.center, + children: [ + Container( + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + decoration: BoxDecoration( + gradient: gradient, + borderRadius: BorderRadius.circular(4)), + ), + icon + ], + ), + Expanded( + child: Container( + margin: EdgeInsets.only(left: 15), + child: Text( + text, + style: TextStyle(fontSize: 16), + ), + ), + ), + Icon( + IconData(0xe63c, fontFamily: 'iconfont'), + size: 25.0, + color: Color(AppColors.TabIconNormal), + ) + ], + ))); + } + + _buildRadioButton() { + Widget icon = Positioned( + // left: 4.5, + top: 5, + child: Icon( + IconData(0xe66b, fontFamily: Constants.IconFontFamily), + color: Colors.white, + )); + + var gradient = LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFFFBD25C), + const Color(0xFFF57723), + ]); + + return _buildIconButton(icon, gradient, I18n.of(context).radio, () { + if (!UserData().stationOpenSwitch) { + showToast(I18n.of(context).system_not_open); + return; + } + if (!UserData().hasLocationPermission) { + CustomUI.buildOneConfirm( + context, I18n.of(context).get_location, I18n.of(context).determine, + () { + Navigator.of(context).pop(); + LocationPermissions().openAppSettings(); + }); + return; + } + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ParkPage(); + }, + ), + ); + }); + } + + _buildMyProgramButton() { + Widget icon = Icon( + IconData(0xe66d, fontFamily: Constants.IconFontFamily), + color: Colors.white, + ); + + var gradient = LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFFF87354), + const Color(0xFFF23D6B), + ]); + + return _buildIconButton( + icon, + gradient, + UserData().isMan() + ? I18n.of(context).woman_gold + : I18n.of(context).man_gold, () { + if (!UserData().myProgramOpenSwitch) { + showToast(I18n.of(context).system_not_open); + return; + } + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return FollowUserPage(); + }, + ), + ); + }, marginTop: 0, showDivder: true); + } + + _buildNearButton() { + Widget icon = Icon( + IconData(0xe665, fontFamily: Constants.IconFontFamily), + color: Colors.white, + ); + + var gradient = LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFFB678FF), + const Color(0xFF6760FC), + ]); + + return _buildIconButton(icon, gradient, I18n.of(context).nearby, () { + if (!UserData().nearbyOpenSwitch) { + showToast(I18n.of(context).system_not_open); + return; + } + + if (!UserData().hasLocationPermission) { + CustomUI.buildOneConfirm( + context, I18n.of(context).get_location, I18n.of(context).determine, + () { + Navigator.of(context).pop(); + LocationPermissions().openAppSettings(); + }); + return; + } + + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return DisCoverPage(); + }, + ), + ); + }); + } + + _buildScanButton() { + Widget icon = Positioned( + top: 5, + child: Icon( + IconData(0xe666, fontFamily: Constants.IconFontFamily), + color: Colors.white, + )); + + var gradient = LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFF48DFF2), + const Color(0xFF0080FF), + ]); + + return _buildIconButton(icon, gradient, I18n.of(context).scan, () { + CustomUI().goScanPage(context); + }); + } + + @override + void dispose() { + super.dispose(); + } +} diff --git a/lib/home/follow_user_dynamic.dart b/lib/home/follow_user_dynamic.dart new file mode 100644 index 0000000..b153720 --- /dev/null +++ b/lib/home/follow_user_dynamic.dart @@ -0,0 +1,167 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/MessageBox.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; +import '../utils/HttpUtil.dart'; +import 'package:dio/dio.dart'; +import "../data/UserData.dart"; +import '../utils/TokenMgr.dart'; + +class FollowUserPage extends StatefulWidget { + FollowUserPage({Key key}) : super(key: key); + + @override + _FollowUserPageState createState() => new _FollowUserPageState(); +} + +class _FollowUserPageState extends State { + List list = new List(); //列表要展示的数据 + RefreshController _refreshController = + RefreshController(initialRefresh: true); + int _page = 1; //加载的页数 + int rows = 20; + + @override + void initState() { + super.initState(); + MessageMgr().on('love_program', msgListLove); + MessageMgr().on('refresh_list', msgRefreshList); + MessageMgr().on('refresh_list_when_no_data', msgRefreshListWhenNoData); + MessageMgr().on('join_program', msgJoinList); + } + + msgJoinList(data) { + for (int i = 0; i < list.length; i++) { + if (list[i]['Id'] == data) { + list[i]['EnrollNum']++; + list[i]['IsEnroll']++; + setState(() {}); + break; + } + } + } + + msgRefreshListWhenNoData(data) { + if (list.length == 0) _onRefresh(); + } + + msgRefreshList(data) { + _onRefresh(); + } + + msgListLove(data) { + print('msgListLove $data'); + for (int i = 0; i < list.length; i++) { + if (list[i]['Id'] == data) { + list[i]['FabulousNum']++; + list[i]['IsFabulous']++; + setState(() {}); + break; + } + } + } + + Future getData(callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + data['page'] = _page; + data['rows'] = rows; + Response res = await HttpUtil().post('userfollow/dynamic/follow', + data: data, failback: () => Navigator.of(context).pop()); + var resData = res.data; + _refreshController.refreshCompleted(); + print(resData); + if (resData['code'] == 0) { + callback(resData['data']); + } else { + showToast(resData['msg']); + } + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + leading: CustomUI.buildCustomLeading(context), + title: new Text( + I18n.of(context).i_like, + textScaleFactor: 1.0, + style: Constants.MainTitleStyle, + ), + centerTitle: true, + elevation: 1, + ); + + Widget content = Scaffold( + appBar: appBar, + body: SafeArea( + child: SafeArea( + child: SmartRefresher( + enablePullDown: true, + enablePullUp: true, + header: MaterialClassicHeader(), + footer: CustomUI.buildLoadingFooter(), + controller: _refreshController, + onRefresh: _onRefresh, + onLoading: _onLoading, + child: + (_refreshController.headerStatus == RefreshStatus.completed && + list.length == 0) + ? CustomUI.buildNoData(context) + : ListView.builder( + itemBuilder: _renderRow, + itemCount: list.length, + ), + ), + ))); + return content; + } + + Future _onLoading() async { + _page++; + getData((data) { + if (data == null || data.length == 0) { + _page--; + _refreshController.loadNoData(); + } else { + list.addAll(data); + _refreshController.loadComplete(); + } + setState(() {}); + }); + } + + Widget _renderRow(BuildContext context, int index) { + if (index < list.length) { + var userInfo = list[index]; + return MessageBox(programInfo: userInfo); + } + return Container(); + } + + Future _onRefresh() async { + _page = 1; + getData((data) { + list.clear(); + list.addAll(data == null ? [] : data); + setState(() {}); + }); + } + + @override + void dispose() { + _refreshController.dispose(); + MessageMgr().off('love_program', msgListLove); + MessageMgr().off('refresh_list', msgRefreshList); + MessageMgr().off('join_program', msgJoinList); + MessageMgr().off('refresh_list_when_no_data', msgRefreshListWhenNoData); + super.dispose(); + } +} diff --git a/lib/home/friend_page.dart b/lib/home/friend_page.dart new file mode 100644 index 0000000..7afc52f --- /dev/null +++ b/lib/home/friend_page.dart @@ -0,0 +1,533 @@ +import 'dart:io'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/home/global_search.dart'; +import 'package:chat/home/new_friends.dart'; +import 'package:chat/home/search_newfriend.dart'; +import 'package:chat/models/friends_info.dart'; +import 'package:flutter/material.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/conversation_table.dart'; +import 'package:chat/utils/friend_list_mgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'address_book.dart'; + +List showUserList = []; + +bool isHaveNewFriends() { + return showUserList.length > 0; +} + +class FriendPage extends StatefulWidget { + @override + _FriendPageState createState() => _FriendPageState(); +} + +class _FriendPageState extends State { + String _currentLetter = ''; + ScrollController _scrollController; + + List friendList = []; + + List _functionButtons = []; + final Map _letterPosMap = {INDEX_BAR_WORDS[0]: 0.0}; + + Set userIdSet = new Set(); + + //var _contactsFuture; + @override + void initState() { + super.initState(); + + print('FriendPage initState'); + initNewFriendsList([]); + + getFriendList(); + getNewFriendList(null); + _scrollController = new ScrollController(); + MessageMgr().on('Add friend', msgAddfrend); + MessageMgr().on('Delete friend', msgDeletefrend); + MessageMgr().on('do_friend_apply', messageApply); + MessageMgr().on('goto_new_friends', messageNew); + } + + messageApply(data) { + getNewFriendList(data); + } + + messageNew(data) { + gotoNewFriendsPage(); + } + + gotoNewFriendsPage() async { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return NewFriendsPage(); + }, + ), + ); + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setStringList(Constants.NewFriendsList, userIdSet.toList()); + showUserList = []; + initNewFriendsList([]); + setState(() {}); + } + + Widget _buildNewFriends(list) { + if (list.length == 0) { + return FriendsInfo( + avatar: '', + userId: 0, + iconCode: 0xe66c, + title: I18n.of(LoadingManage.context).new_friends, + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFF58B7F5), + const Color(0xFF1874C9), + ]), + onPressed: gotoNewFriendsPage); + } else { + return _buildFriendsItem(list); + } + } + + Widget _buildAvatar(url) { + return ClipRRect( + borderRadius: BorderRadius.circular(6), + child: CachedNetworkImage( + imageUrl: url, + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + )); + } + + Widget _buildFriendsItem(list) { + Widget unreadRedDot = Container( + margin: EdgeInsets.only(right: 15), + width: Constants.UnReadMsgNotifyDotSize, + height: Constants.UnReadMsgNotifyDotSize, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(Constants.UnReadMsgNotifyDotSize / 2.0), + color: Color(0xFFFF5454), + ), + child: Text(list.length > 99 ? "99+" : list.length.toString(), + textScaleFactor: 1.0, style: AppStyles.UnreadMsgCountDotStyle), + ); + + var left; + if (list.length == 1) { + left = Row( + children: [ + _buildAvatar(list[0]['ApplyUrl']), + SizedBox(width: 10.0), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(list[0]['ApplyName'], style: TextStyle(fontSize: 12.66)), + SizedBox( + height: 5, + ), + Text(I18n.of(context).apply_fro_friends, + style: + TextStyle(fontSize: 10, color: const Color(0xFF6A6A6A))), + ], + )), + unreadRedDot, + ], + ); + } else { + left = Row( + children: [ + Expanded( + child: Container( + height: Constants.ContactAvatarSize, + constraints: BoxConstraints(maxWidth: Screen.width - 100), + child: ListView( + scrollDirection: Axis.horizontal, + children: list + .map((f) => Container( + child: _buildAvatar(f['ApplyUrl']), + margin: EdgeInsets.only(right: 5), + )) + .toList(), + ))), + unreadRedDot, + ], + ); + } + + return InkWell( + onTap: gotoNewFriendsPage, + child: Container( + padding: const EdgeInsets.symmetric( + vertical: MARGIN_VERTICAL, horizontal: 16.0), + decoration: BoxDecoration(color: Colors.white), + child: left, + )); + } + + showPermission() async { + if (await CustomUI.showPermissionSetting( + LoadingManage.context, + PermissionGroup.contacts, + I18n.of(LoadingManage.context).contact_permission)) { + MessageMgr().emit('PostContact'); + Navigator.push(LoadingManage.context, + MaterialPageRoute(builder: (BuildContext context) { + return ContactsPage(); + })); + } + } + + getFriendList() async { + friendList = await FriendListMgr().getFriendList(); + + if (mounted) { + setState(() {}); + } + } + + getNewFriendList(userdata) async { + Map data = { + "userId": UserData().basicInfo.userId, + "type": 1, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = + await HttpUtil().post('friendship/newFriends/record', data: data); + var resData = res.data; + if (resData['code'] == 0) { + if (resData['data'] != null) { + SharedPreferences prefs = await SharedPreferences.getInstance(); + List list = prefs.getStringList(Constants.NewFriendsList); + if (list != null) { + userIdSet = new Set.from(list); + } else { + userIdSet = new Set(); + } + + if (userdata != null && userIdSet.contains(userdata['userId'])) { + userIdSet.remove(userdata['userId']); + } + showUserList = []; + + for (int i = 0; i < resData['data'].length; i++) { + if (!userIdSet + .contains(resData['data'][i]['ApplyUserId'].toString())) { + showUserList.add(resData['data'][i]); + userIdSet.add(resData['data'][i]['ApplyUserId'].toString()); + } + } + + initNewFriendsList(showUserList); + if (mounted) { + setState(() {}); + } + } + } else { + showToast(resData['msg']); + } + } + + initNewFriendsList(showUserList) { + _functionButtons = [ + FriendsInfo( + avatar: '', + userId: 0, + iconCode: 0xe659, + title: I18n.of(LoadingManage.context).scan, + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFF6171F1), + const Color(0xFF3441C1), + ]), + onPressed: () { + CustomUI().goScanPage(LoadingManage.context); + }), + FriendsInfo( + avatar: '', + userId: 0, + iconCode: 0xe67a, + isShowDivder: true, + title: I18n.of(LoadingManage.context).contact_add, + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFF1AC59E), + const Color(0xFF088E76), + ]), + onPressed: () async { + final PermissionStatus addStatus = await PermissionHandler() + .checkPermissionStatus(PermissionGroup.contacts); + if ((addStatus == PermissionStatus.unknown || + addStatus == PermissionStatus.denied) && + Platform.isIOS) { + CustomUI.buildContacts(context, I18n.of(context).privacyAgreement, + I18n.of(context).determine, () { + Navigator.of(context).pop(); + showPermission(); + }, title: I18n.of(context).tip); + } else { + showPermission(); + } + }), + FriendsInfo( + avatar: '', + userId: 0, + iconCode: 0xe662, + isShowDivder: true, + title: I18n.of(LoadingManage.context).add_friends, + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFF9E58E5), + const Color(0xFF6118A6), + ]), + onPressed: () async { + Navigator.push(LoadingManage.context, + MaterialPageRoute(builder: (BuildContext context) { + return SearchNewFriendsPage(); + })); + }), + ]; + _functionButtons.insert(0, _buildNewFriends(showUserList)); + } + + msgAddfrend(data) { + // setState(() { + // _contactsFuture = FriendListMgr().getFriendList(); + // }); + getFriendList(); + } + + msgDeletefrend(data) { + // setState(() { + // _contactsFuture = FriendListMgr().getFriendList(); + // }); + getFriendList(); + } + + updateIndexPos(List friendList) { + //计算用于 IndexBar 进行定位的关键通讯录列表项的位置 + var _totalPos = _functionButtons.length * FriendsInfo.height(false); + for (var i = 0; i < friendList.length; i++) { + bool _hasGroupTitle = true; + if (i > 0 && + friendList[i].nameTag.compareTo(friendList[i - 1].nameTag) == 0) { + _hasGroupTitle = false; + } + + if (_hasGroupTitle) { + _letterPosMap[friendList[i].nameTag] = _totalPos; + } + _totalPos += FriendsInfo.height(_hasGroupTitle); + } + } + + @override + void dispose() { + _scrollController.dispose(); + + print('FriendPage dispose'); + + MessageMgr().off('Add friend', msgAddfrend); + MessageMgr().off('Delete friend', msgDeletefrend); + MessageMgr().off('do_friend_apply', messageApply); + MessageMgr().off('goto_new_friends', messageNew); + super.dispose(); + } + + String getLetter(BuildContext context, double tileHeight, Offset globalPos) { + RenderBox _box = context.findRenderObject(); + var local = _box.globalToLocal(globalPos); + int index = (local.dy ~/ tileHeight).clamp(0, INDEX_BAR_WORDS.length - 1); + return INDEX_BAR_WORDS[index]; + } + + void _jumpToIndex(String letter) { + if (_letterPosMap.isNotEmpty) { + final _pos = _letterPosMap[letter]; + if (_pos != null) { + _scrollController.animateTo(_letterPosMap[letter], + curve: Curves.easeInOut, duration: Duration(microseconds: 200)); + } + } + } + + Widget _buildIndexBar(BuildContext context, BoxConstraints constraints) { + final List _letters = INDEX_BAR_WORDS.map((String word) { + return Expanded( + child: Container( + margin: EdgeInsets.only(right: 5), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: + _currentLetter == word ? Colors.blue : Colors.transparent, + ), + alignment: Alignment.center, + padding: EdgeInsets.all(2), + width: 20, + child: Text( + word, + style: TextStyle( + fontSize: 10, + color: + _currentLetter == word ? Colors.white : Colors.black), + ))); + }).toList(); + + final _totalHeight = constraints.biggest.height; + final _tileHeight = _totalHeight / _letters.length; + return GestureDetector( + onVerticalDragDown: (DragDownDetails details) { + setState(() { + _currentLetter = + getLetter(context, _tileHeight, details.globalPosition); + _jumpToIndex(_currentLetter); + }); + }, + onVerticalDragEnd: (DragEndDetails details) { + setState(() { + //_indexBarBgColor = Colors.transparent; + _currentLetter = null; + }); + }, + onVerticalDragCancel: () { + setState(() { + //_indexBarBgColor = Colors.transparent; + _currentLetter = null; + }); + }, + onVerticalDragUpdate: (DragUpdateDetails details) { + setState(() { + //var _letter = getLetter(context, _tileHeight, details.globalPosition); + _currentLetter = + getLetter(context, _tileHeight, details.globalPosition); + _jumpToIndex(_currentLetter); + }); + }, + child: Column( + children: _letters, + ), + ); + } + + @override + Widget build(BuildContext context) { + final List _body = []; + + friendList.sort((a, b) => a.nameTag.compareTo(b.nameTag)); + updateIndexPos(friendList); + _body.addAll([ + ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + if (index < _functionButtons.length) { + if (index == 0) { + return Padding( + padding: EdgeInsets.only(top: 7), + child: _functionButtons[index], + ); + } else { + return _functionButtons[index]; + } + } + int _contactIndex = index - _functionButtons.length; + bool _isGroupTitle = true; + FriendModel _contact = friendList[_contactIndex]; + + if (_contactIndex >= 1 && + _contact.nameTag == friendList[_contactIndex - 1].nameTag) { + _isGroupTitle = false; + } + + return FriendsInfo( + userId: _contact.friendId, + avatar: _contact.avatar, + title: Provider.of(context) + .getRefName(_contact.friendId, _contact.name), + isShowDivder: _isGroupTitle, + groupTitle: _isGroupTitle ? _contact.nameTag : null); + }, + itemCount: friendList.length + _functionButtons.length, + ), + Positioned( + width: Constants.IndexBarWidth, + right: 0.0, + top: 0.0, + bottom: 0.0, + child: Container( + //color: _indexBarBgColor, + child: LayoutBuilder( + builder: _buildIndexBar, + ), + ), + ) + ]); + + if (_currentLetter != null && _currentLetter.isNotEmpty) { + _body.add(Center( + child: Container( + width: Constants.IndexLetterBoxSize, + height: Constants.IndexLetterBoxSize, + decoration: BoxDecoration( + color: AppColors.IndexLetterBoxBgColor, + borderRadius: BorderRadius.all( + Radius.circular(Constants.IndexLetterBoxRadius)), + ), + child: Center( + child: + Text(_currentLetter, style: AppStyles.IndexLetterBoxTextStyle), + ), + ), + )); + } + + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text(I18n.of(context).contact, + textScaleFactor: 1.0, style: Constants.MainTitleStyle), + centerTitle: false, + elevation: 1, + bottom: CustomUI.buildSearchButton(context, () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return GlobalSearchPage( + type: GlobalSearchPageType.SearchMyFriends, + ); + }, + ), + ); + })), + body: Stack( + children: _body, + )); + } +} diff --git a/lib/home/global_search.dart b/lib/home/global_search.dart new file mode 100644 index 0000000..7c27c9a --- /dev/null +++ b/lib/home/global_search.dart @@ -0,0 +1,291 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/models/friends_info.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/conversation_table.dart'; +import 'package:chat/utils/friend_list_mgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:flutter/services.dart'; +import 'ProfilePage.dart'; +import 'group_item_widget.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:provider/provider.dart'; + +class GlobalSearchPage extends StatefulWidget { + final int type; + GlobalSearchPage({Key key, @required this.type}) : super(key: key); + @override + _GlobalSearchPageState createState() => _GlobalSearchPageState(); +} + +class _GlobalSearchPageState extends State { + ScrollController _scrollController = ScrollController(); + TextEditingController _txtCtrl = new TextEditingController(); + bool _hasdeleteIcon = false; + FocusNode focusNode; + List searchList = []; + String searchStr = ''; + + @override + void initState() { + super.initState(); + _scrollController = new ScrollController(); + focusNode = new FocusNode(); + } + + @override + void dispose() { + _scrollController.dispose(); + focusNode.dispose(); + super.dispose(); + } + + //群搜索结果 + Widget _buildSearchGroupBody() { + return ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + GroupInfoModel _contact = searchList[index]; + + return GroupItem(Key('Item${_contact.sessionId}'), + groupInfoModel: _contact); + }, + itemCount: searchList.length, + ); + } + + //好友搜索结果 + Widget _buildSearchMyfriendsBody() { + return ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + FriendModel _contact = searchList[index]; + + return FriendsInfo( + userId: _contact.friendId, + avatar: _contact.avatar, + title: Provider.of(context) + .getRefName(_contact.friendId, _contact.name), + isShowDivder: true, + groupTitle: null); + }, + itemCount: searchList.length, + ); + } + + //通过手机号搜索新用户结果 + Widget _buildSearchNewfriendsBody() { + if (searchStr == '') return Container(); + return InkWell( + onTap: () { + HttpUtil().searchNewFrindsByPhone(searchStr, (int userId) { + if (userId == null || userId == 0) { + CustomUI.buildOneConfirm(context, I18n.of(context).not_have_user, + I18n.of(context).determine, () { + Navigator.of(context).pop(); + }); + return; + } + if (userId == UserData().basicInfo.userId) { + CustomUI.buildOneConfirm(context, I18n.of(context).not_add_Myself, + I18n.of(context).determine, () { + Navigator.of(context).pop(); + }); + return; + } + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage(userId: userId, addMode: 1); + }, + ), + ); + }); + }, + child: Container( + margin: EdgeInsets.only(top: 9), + height: 55.1, + width: Screen.width, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: EdgeInsets.only(right: 13), + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFF58B7F5), + const Color(0xFF1874C9), + ]), + borderRadius: BorderRadius.circular(6)), + child: Icon( + IconData(0xe662, fontFamily: Constants.IconFontFamily), + color: Colors.white, + ), + ), + Text('${I18n.of(context).search_phone}: ', + style: TextStyle(fontSize: 16.23)), + Text(searchStr, + style: TextStyle(fontSize: 16.23, color: Color(0xFF008AFF))) + ], + ), + color: Colors.white)); + } + + Widget buildBody() { + Widget result = Container(); + switch (widget.type) { + case GlobalSearchPageType.SearchGroup: + result = _buildSearchGroupBody(); + break; + case GlobalSearchPageType.SearchMyFriends: + result = _buildSearchMyfriendsBody(); + break; + case GlobalSearchPageType.SearchNewFriends: + result = _buildSearchNewfriendsBody(); + break; + default: + } + return result; + } + + //开始搜索群 + _beginSearchGroup(String str) { + Map refMap = Provider.of(context).refMap; + List groupList = GroupInfoMgr().groupInfoList; + searchList = CustomUI() + .getGroupSearchResult(str, groupList == null ? [] : groupList, refMap); + } + + //开始搜索自己好友 + _beginSearchMyFriends(String str) async { + List friendList = []; + friendList = await FriendListMgr().getFriendList(); + searchList = + CustomUI().getSearchResult(str, friendList == null ? [] : friendList); + } + + beginSearch(String str) { + switch (widget.type) { + case GlobalSearchPageType.SearchGroup: + _beginSearchGroup(str); + break; + case GlobalSearchPageType.SearchMyFriends: + _beginSearchMyFriends(str); + break; + default: + } + } + + @override + Widget build(BuildContext context) { + final List _body = []; + + _body.add(buildBody()); + + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text(I18n.of(context).search, + textScaleFactor: 1.0, style: Constants.MainTitleStyle), + centerTitle: true, + elevation: 1, + leading: CustomUI.buildCustomLeading(context), + bottom: PreferredSize( + preferredSize: Size.fromHeight(49), + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.only(bottom: 14, left: 12.5, right: 12.5), + height: 35, + decoration: BoxDecoration( + color: const Color(0xFFEEEEEE), + borderRadius: BorderRadius.all(Radius.circular(8))), + child: TextField( + keyboardType: TextInputType.text, + cursorColor: Constants.BlueTextColor, + textInputAction: TextInputAction.search, + controller: _txtCtrl, + maxLines: 1, + focusNode: focusNode, + style: TextStyle( + textBaseline: TextBaseline.alphabetic, fontSize: 14.5), + autofocus: true, + inputFormatters: + widget.type == GlobalSearchPageType.SearchNewFriends + ? [ + WhitelistingTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(15), + ] + : [ + LengthLimitingTextInputFormatter(50), + ], + decoration: InputDecoration( + hintText: I18n.of(context).search, + hintStyle: TextStyle(fontSize: 14.5), + contentPadding: EdgeInsets.only( + left: 20, + top: (UserData().language == LanguageType.English || + UserData().language == + LanguageType.Vietnamese) + ? 3 + : 10.5, + bottom: 10.5), + prefixIcon: Icon( + IconData( + 0xe664, + fontFamily: Constants.IconFontFamily, + ), + color: const Color(0xFFA0A0A0), + size: 18, + ), + suffixIcon: Padding( + padding: EdgeInsetsDirectional.only( + start: 2.0, end: _hasdeleteIcon ? 20.0 : 0), + child: _hasdeleteIcon + ? new InkWell( + onTap: (() { + setState(() { + WidgetsBinding.instance + .addPostFrameCallback( + (_) => _txtCtrl.clear()); + _hasdeleteIcon = false; + }); + }), + child: Icon( + Icons.clear, + size: 18.0, + color: Constants.BlackTextColor, + )) + : new Text('')), + ), + onChanged: (str) async { + setState(() { + searchStr = str; + if (str.isEmpty) { + _hasdeleteIcon = false; + } else { + _hasdeleteIcon = true; + beginSearch(str); + } + }); + }, + onEditingComplete: () { + FocusScope.of(context).requestFocus(FocusNode()); + }), + )), + ), + body: Stack( + children: _body, + )); + } +} diff --git a/lib/home/goddess_hot.dart b/lib/home/goddess_hot.dart new file mode 100644 index 0000000..0edd5d5 --- /dev/null +++ b/lib/home/goddess_hot.dart @@ -0,0 +1,148 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/models/gift_item_model.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:oktoast/oktoast.dart'; + +class GoddessHotPage extends StatefulWidget { + final int userId; + + GoddessHotPage({Key key, this.userId}) : super(key: key); + + @override + State createState() { + return GoddessHotPageState(); + } +} + +class GoddessHotPageState extends State { + List giftList = []; + + @override + void initState() { + super.initState(); + getGiftInfo(); + } + + Future getGiftInfo() async { + Map data = { + "userId": widget.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('reward/user/stage', + data: data, failback: () => Navigator.of(context).pop()); + var resData = res.data; + print(resData); + if (resData['code'] == 0) { + giftList = resData['data'] + .map((json) => GiftItemModel.havedFromJson(json)) + .toList(); + setState(() {}); + } else { + showToast(resData['msg']); + } + } + + Widget _buildTips() { + return Container( + margin: EdgeInsets.only(left: 12, top: 15), + child: Text(I18n.of(context).Goddess_heat_tips, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 13, color: Constants.BlackTextColor)), + ); + } + + Widget _buildGift(int id, String name, int nums) { + return Container( + child: Column( + children: [ + Stack( + children: [ + Container( + width: 63, + height: 71, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6), + border: Border.all( + color: nums == 0 + ? Colors.transparent + : const Color(0xFFFD5E83))), + alignment: Alignment.center, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Image.asset( + "assets/images/gift_$id.png", + width: 30, + )), + Text( + name, + style: TextStyle( + fontSize: 10, color: const Color(0xFF777777)), + ), + SizedBox(height: 9), + ], + ), + ), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6), + color: nums == 0 + ? Colors.black.withOpacity(0.45) + : Colors.transparent, + ), + width: 63, + height: 71, + ) + ], + ), + SizedBox(height: 9), + Text( + nums.toString() + I18n.of(context).one, + style: TextStyle(fontSize: 12.5, color: const Color(0xFF515151)), + ), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + elevation: 1, + title: new Text( + I18n.of(context).Goddess_heat, + textScaleFactor: 1.0, + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ); + + return Scaffold( + appBar: appBar, + backgroundColor: Colors.white, + body: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildTips(), + SizedBox(height: 22.5), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: giftList + .map((gift) => _buildGift(gift.id, gift.name, gift.amount)) + .toList(), + ) + ], + ), + ), + ); + } +} diff --git a/lib/home/group_all_member.dart b/lib/home/group_all_member.dart new file mode 100644 index 0000000..18836a3 --- /dev/null +++ b/lib/home/group_all_member.dart @@ -0,0 +1,255 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/group_member_model.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../data/constants.dart'; +import '../utils/CustomUI.dart'; +import '../utils/app_navigator.dart'; +import 'create_group_view.dart'; + +class GroupAllMember extends StatefulWidget { + final GroupInfoModel groupInfoModel; + + GroupAllMember({Key key, this.groupInfoModel}) : super(key: key); + + @override + State createState() { + return GroupAllMemberState(); + } +} + +class GroupAllMemberState extends State { + static const Separate_Size = 15.0; + bool isHost; + + + ///是否是群主 + @override + void initState() { + super.initState(); + MessageMgr().on('Update Group Info', updateGroupInfo); + isHost = widget.groupInfoModel.hosterId == UserData().basicInfo.userId; + + + + } + + updateGroupInfo(args) async { + if (mounted) { + print('群设置 - 更新群信息2222'); + setState(() {}); + } + } + + @override + void dispose() { + + super.dispose(); + MessageMgr().off('Update Group Info', updateGroupInfo); + } + + @override + Widget build(BuildContext context) { + + + + + + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + I18n.of(context).group_memeber, + style: TextStyle(color: AppColors.NewAppbarTextColor), + textScaleFactor: 1.0, + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ); + + return Scaffold( + appBar: appBar, + body: SafeArea( + child: ListView( + children: [ + SizedBox( + height: 12, + ), + + ///群成员 + buildMember( + () { + ///添加成员 + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return CreateGroupPage( + GroupOperatingPageType.AddMember, + widget.groupInfoModel.getMembersInGroup(), + widget.groupInfoModel.sessionId); + }, + ), + ); + }, + () { + ///删除成员 + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return CreateGroupPage( + GroupOperatingPageType.DeleteMember, + widget.groupInfoModel.getMembersInGroup(), + widget.groupInfoModel.sessionId); + }, + ), + ); + }, + ), + ], + ), + ), + ); + } + + Widget buildMember(Function addMember, Function deleteMember) { +// List members = widget.groupInfoModel.members; + + List members = []; + + for (int k = 0; k < widget.groupInfoModel.members.length; k++) { + //只加入存在群的 + GroupMemberModel mo = widget.groupInfoModel.members[k]; + if (mo.inGroup == 1) { + print('id ${mo.memberId} name ${mo.refName} avatar ${mo.avtar}'); + members.add(mo); + } + } + + members.sort((GroupMemberModel left, GroupMemberModel right) => + right.identity.compareTo(left.identity)); + + double size = Screen.width / 5; + + List list = []; + for (int index = 0; index < members.length; index++) { + var member = members[index]; + var refName = Provider.of(context) + .getGroupRefName(widget.groupInfoModel.sessionId, member.memberId); + list.add(GestureDetector( + child: Container( + child: Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(8.0)), + child: CachedNetworkImage( + imageUrl: member.avtar, + placeholder: CustomUI.buildImgLoding, + width: size - 30, + height: size - 30, + )), + SizedBox( + height: 5, + ), + + SizedBox( + width: size - 30, + child: Text( + refName, + style: TextStyle(fontSize: 11, color: Color(0xff818181)), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + width: size, + height: size, + ), + behavior: HitTestBehavior.translucent, + onTap: () { + if (member.memberId != UserData().basicInfo.userId) { + AppNavigator.pushProfileInfoPage(context, member.memberId, + fromWhere: 2,addMode: 1); + } + }, + )); + } + + list.add(GestureDetector( + onTap: addMember, + child: Container( + width: size, + height: size, + child: Column( + children: [ + Container( + alignment: Alignment.center, + width: size - 30, + height: size - 30, + child: Text( + '+', + textScaleFactor: 1.0, + style: TextStyle(fontSize: 30, color: Color(0xffB1B1B1)), + ), + decoration: BoxDecoration( +// color: Colors.black, + border: Border.all(color: Color(0xffC3C3C3), width: 1.0), + borderRadius: BorderRadius.all(Radius.circular(6))), + ) + ], + ), + ), + )); + if (isHost) { + list.add(Container( + width: size, + height: size, + child: Column( + children: [ +// SizedBox(height: 5,), + GestureDetector( + onTap: deleteMember, + child: Container( + alignment: Alignment.center, + width: size - 30, + height: size - 30, + child: Container( + color: Color(0xffB1B1B1), + width: 20, + height: 2.6, + ), + decoration: BoxDecoration( + border: Border.all(color: Color(0xffC3C3C3), width: 1.0), + borderRadius: BorderRadius.all(Radius.circular(6))), + ), + ) + ], + ), + )); + } + + return Container( + color: Color(0xffFAFAFA), + //height: Screen.height-100, + child: Column( + children: [ + SizedBox( + height: 10, + ), + Wrap( + children: list, + crossAxisAlignment: WrapCrossAlignment.start, + alignment: WrapAlignment.start, + ), + ], + ), + ); + } +} diff --git a/lib/home/group_announcement.dart b/lib/home/group_announcement.dart new file mode 100644 index 0000000..f4a353e --- /dev/null +++ b/lib/home/group_announcement.dart @@ -0,0 +1,214 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/group_member_model.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; + +class GroupAnnouncementPage extends StatefulWidget { + final GroupInfoModel groupInfoModel; + GroupAnnouncementPage({Key key, @required this.groupInfoModel}) + : super(key: key); + + @override + _GroupAnnouncementPageState createState() => + new _GroupAnnouncementPageState(); +} + +class _GroupAnnouncementPageState extends State { + TextEditingController _txtCtrl = new TextEditingController(); + bool isGroupOwner = false; + + @override + void initState() { + super.initState(); + + print('GroupAnnouncementPage initState'); + _txtCtrl.text = widget.groupInfoModel.describe; + isGroupOwner = + widget.groupInfoModel.hosterId == UserData().basicInfo.userId; + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + I18n.of(context).group_announcement, + style: TextStyle(color: AppColors.NewAppbarTextColor), + textScaleFactor: 1.0, + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + actions: [ + isGroupOwner + ? InkWell( + onTap: () { + var content = _txtCtrl.text; + + MsgHandler.updateGroupNotice( + widget.groupInfoModel.sessionId, content); + Navigator.of(context).pop(); + }, + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.only(top: 15, bottom: 15, right: 20), + height: 20, + width: 60, + padding: EdgeInsets.symmetric(horizontal: 5), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4.5)), + child: Text( + I18n.of(context).determine, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Constants.ConfrimButtonColor, fontSize: 12.6), + ), + ), + ) + : Container() + ], + ); + + return Scaffold( + appBar: appBar, + backgroundColor: Colors.white, + body: SafeArea( + child: _buildBody(), + )); + } + + Widget _buildBody() { + return Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildGroupOwner(), + _buildLine(), + _buildInput(), + Expanded( + child: SizedBox(), + ), + _buildTips(), + ], + ), + ); + } + + Widget _buildLine() { + return Container( + width: Screen.width, + decoration: + BoxDecoration(border: Border(bottom: Constants.GreyBorderSide)), + margin: EdgeInsets.only(left: 20, right: 20), + ); + } + + Widget _buildTips() { + return isGroupOwner + ? Container() + : Container( + width: Screen.width, + margin: EdgeInsets.only(bottom: 60), + child: Row( + children: [ + Expanded( + child: Container( + margin: EdgeInsets.only(left: 30, right: 10), + decoration: BoxDecoration( + border: Border(top: Constants.GreyBorderSide)), + ), + ), + Text( + I18n.of(context).only_host, + style: TextStyle(color: Colors.grey[350]), + ), + Expanded( + child: Container( + margin: EdgeInsets.only(right: 30, left: 10), + decoration: BoxDecoration( + border: Border(top: Constants.GreyBorderSide)), + ), + ), + ], + ), + ); + } + + Widget _buildGroupOwner() { + GroupMemberModel memberModel = widget.groupInfoModel.getHoster(); + + var refName = Provider.of(context) + .getGroupRefName(widget.groupInfoModel.sessionId, memberModel.memberId); + return Container( + height: 62.5, + child: Row( + children: [ + SizedBox(width: 20), + ClipRRect( + borderRadius: BorderRadius.circular(6), + child: CachedNetworkImage( + imageUrl: memberModel.avtar, + width: 45, + height: 45, + )), + SizedBox(width: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + refName, + style: TextStyle(fontSize: 16), + ), + SizedBox(height: 6.5), + ], + ) + ], + ), + ); + } + + Widget _buildInput() { + return isGroupOwner + ? Container( + child: TextField( + keyboardAppearance: Brightness.light, + controller: _txtCtrl, + style: TextStyle( + fontSize: 17, + color: Constants.BlackTextColor, + textBaseline: TextBaseline.alphabetic), + decoration: InputDecoration( + contentPadding: + EdgeInsets.only(right: 20, left: 20, top: 10, bottom: 10), + hintText: I18n.of(context).fill_out, + hintStyle: TextStyle(fontSize: 16, color: Colors.grey), + border: InputBorder.none, + ), + autofocus: true, + maxLines: 5, + inputFormatters: [LengthLimitingTextInputFormatter(100)], + onChanged: (str) async {}, + ), + ) + : Container( + //color: Colors.white, + padding: EdgeInsets.only(right: 20, left: 20, top: 10, bottom: 10), + child: Text(widget.groupInfoModel.describe), + ); + } + + @override + void dispose() { + super.dispose(); + } +} diff --git a/lib/home/group_chat_page.dart b/lib/home/group_chat_page.dart new file mode 100644 index 0000000..5f90eda --- /dev/null +++ b/lib/home/group_chat_page.dart @@ -0,0 +1,163 @@ +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/home/global_search.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'create_group_view.dart'; +import 'group_item_widget.dart'; + +class GroupChatListPage extends StatefulWidget { + @override + _GroupChatListPageState createState() => _GroupChatListPageState(); +} + +class _GroupChatListPageState extends State { + ScrollController _scrollController = ScrollController(); + List searchList = []; + + @override + void initState() { + super.initState(); + + print('GroupChatListPage initState'); + MessageMgr().on('Quit Group', quitGroup); + + MessageMgr().on('Update Group List', updateGroupLastMsg); + } + + updateGroupLastMsg(args) async { + await GroupInfoMgr().sortGroupList(); + if (mounted) { + setState(() {}); + } + } + + @override + void dispose() { + _scrollController.dispose(); + + MessageMgr().off('Update Group List', updateGroupLastMsg); + + MessageMgr().off('Quit Group', quitGroup); + super.dispose(); + } + + quitGroup(args) { + if (mounted) { + setState(() { + print('更新群列表'); + }); + } + } + + Widget _buildCreateButton() { + List groupList = GroupInfoMgr().groupInfoList; + Widget _avatarIcon = ClipRRect( + borderRadius: BorderRadius.circular(GroupRadius), + child: Container( + color: const Color(0xFFF2F2F2), + height: AvatarSize, + width: AvatarSize, + child: Icon( + IconData(0xe66f, fontFamily: Constants.IconFontFamily), + color: Constants.BlueTextColor, + size: 35, + ), + )); + + Widget _button = InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return CreateGroupPage( + GroupOperatingPageType.CreateGroup, [], null); + }, + ), + ); + }, + child: Container( + height: ItemHeight, + margin: EdgeInsets.only(top: 6.5, bottom: 16), + decoration: BoxDecoration(color: Colors.white), + child: Row( + children: [ + SizedBox(width: LeftPadding), + _avatarIcon, + SizedBox(width: 14.0), + Text( + I18n.of(context).create_group_chat, + style: TextStyle(fontSize: 15.5), + ), + ], + ), + )); + + Widget tips = Container( + alignment: Alignment.centerLeft, + width: Screen.width, + height: 33.5, + padding: EdgeInsets.only(left: LeftPadding), + decoration: BoxDecoration( + color: Colors.white, + border: Border(bottom: Constants.GreyBorderSide)), + child: Text(I18n.of(context).group_chat + '(${groupList.length})'), + ); + + return Column( + children: [ + _button, + tips, + ], + ); + } + + @override + Widget build(BuildContext context) { + List groupList = GroupInfoMgr().groupInfoList; + print('build group chat Page 群数量${groupList.length}'); + final List _body = []; + + _body.add( + ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + if (index == 0) { + return _buildCreateButton(); + } else { + var info = groupList[index - 1]; + return GroupItem(ValueKey(info), groupInfoModel: info); + } + }, + itemCount: groupList.length + 1, + ), + ); + + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text(I18n.of(context).group_chat, + textScaleFactor: 1.0, style: Constants.MainTitleStyle), + centerTitle: false, + elevation: 1, + bottom: CustomUI.buildSearchButton(context, () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return GlobalSearchPage( + type: GlobalSearchPageType.SearchGroup, + ); + }, + ), + ); + })), + body: Stack( + children: _body, + )); + } +} diff --git a/lib/home/group_item_widget.dart b/lib/home/group_item_widget.dart new file mode 100644 index 0000000..604fe5a --- /dev/null +++ b/lib/home/group_item_widget.dart @@ -0,0 +1,196 @@ +import 'dart:ui'; + +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/send_msg_state.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/models/last_msg_description.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/image_util.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:provider/provider.dart'; +import 'last_unread_dot.dart'; + +const double AvatarSize = 60; +const double GroupRadius = 6.5; +const double LeftPadding = 15; +const double ItemHeight = 83.5; + +class GroupItem extends StatefulWidget { + GroupItem( + Key key, { + @required this.groupInfoModel, + this.onPressed, + this.isShowDivder: true, + this.enterType=0,this.enterContent + + }) : super(key: key); + + final GroupInfoModel groupInfoModel; + final VoidCallback onPressed; + final bool isShowDivder; + final int enterType; // 0默认 1图片 + final dynamic enterContent; + @override + _GroupItemState createState() => _GroupItemState(); +} + +class _GroupItemState extends State { + @override + void initState() { + super.initState(); + } + + GlobalKey key = GlobalKey(); + + @override + Widget build(BuildContext context) { + Widget _avatarIcon = + WidgetUtil.getAvatarNew(widget.groupInfoModel, key, (String path) { + widget.groupInfoModel.image = path; + }); + + List _rightArea = [ + SizedBox(height: 4), + Align( + alignment: Alignment.topCenter, + child: widget.groupInfoModel.lastMsg == null + ? Container() + : Text( + Constants.getShowTime( + widget.groupInfoModel.lastMsg.updateAt, context), + textScaleFactor: 1.0, + style: AppStyles.DescStyle), + ), + Expanded( + child: Align( + alignment: Alignment.bottomCenter, + child: widget.groupInfoModel.lastMsg == null + ? Container() + : (widget.groupInfoModel.messageFree == 1 + ? Icon( + IconData(0xe673, fontFamily: Constants.IconFontFamily), + color: Colors.grey[400], + size: 20, + ) + : UnreadCountDot( + sessionId: widget.groupInfoModel.lastMsg.sessionId, + unreadCount: ChatDataMgr() + .groupUnreadProvider + .getUnreadCount( + widget.groupInfoModel.lastMsg.sessionId))), + )) + ]; + + Map refMap = Provider.of(context).refMap; + return InkWell( + child: Container( + padding: const EdgeInsets.only( + left: LeftPadding, right: LeftPadding, top: 13.5, bottom: 13.5), + height: ItemHeight, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(widget.groupInfoModel.topTag == 1 + ? 0xfff5f6f9 + : AppColors.ConversationItemBgColor), + border: Border(bottom: Constants.GreyBorderSide)), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Stack( + children: [ + _avatarIcon, + Positioned( + right: 0, + top: 0, + child: Offstage( + offstage: !(widget.groupInfoModel.lastMsg != null && + widget.groupInfoModel.messageFree == 1 && + ChatDataMgr().groupUnreadProvider.getUnreadCount( + widget.groupInfoModel.lastMsg.sessionId) > + 0), + child: CircleAvatar( + radius: 4, + backgroundColor: Colors.red, + ))) + ], + ), + Container(width: 10.0), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(height: 3), + Text(widget.groupInfoModel.getGroupName(refMap), + textScaleFactor: 1.0, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 15, + color: Colors.black, + )), + Expanded(child: SizedBox()), + Row( + children: [ + widget.groupInfoModel.lastMsg == null + ? Container() + : SendMsgState( + sessionId: + widget.groupInfoModel.lastMsg.sessionId, + time: widget.groupInfoModel.lastMsg.updateAt), + widget.groupInfoModel.lastMsg == null + ? Container() + : Row( + children: [ + Text( + widget.groupInfoModel.lastMsg != null && + widget.groupInfoModel.messageFree == + 1 && + ChatDataMgr() + .groupUnreadProvider + .getUnreadCount(widget + .groupInfoModel + .lastMsg + .sessionId) > + 0 + ? '[${ChatDataMgr().groupUnreadProvider.getUnreadCount(widget.groupInfoModel.lastMsg.sessionId)}${I18n.of(context).article}] ' + : "", + style: AppStyles.DescStyle), + Container( + constraints: BoxConstraints( + maxWidth: Screen.width - 160), + child: LastMsgDescription( + Key(widget.groupInfoModel.sessionId + .toString()), + widget.groupInfoModel.lastMsg)) + ], + ) + ], + ), + SizedBox(height: 7) + ], + ), + ), + SizedBox(width: 10), + SizedBox( + height: Constants.ConversationAvatarSize, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _rightArea, + ), + ) + ], + ), + ), + onTap: () { + AppNavigator.pushGroupChatPage(context, widget.groupInfoModel,enterType: widget.enterType,enterContent: widget.enterContent); + }, + ); + } +} diff --git a/lib/home/group_manage_page.dart b/lib/home/group_manage_page.dart new file mode 100644 index 0000000..0083179 --- /dev/null +++ b/lib/home/group_manage_page.dart @@ -0,0 +1,136 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/FullWithButton.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:flutter/material.dart'; +import 'create_group_view.dart'; + +class GroupManagePage extends StatefulWidget { + final GroupInfoModel groupInfoModel; + GroupManagePage({Key key, @required this.groupInfoModel}) : super(key: key); + + @override + _GroupManagePageState createState() => new _GroupManagePageState(); +} + +class _GroupManagePageState extends State { + bool invite = false; //消息提示 + + @override + void initState() { + super.initState(); + invite = widget.groupInfoModel.askSwitch == 1; + } + + Widget _buildSettingWithSwitch( + bool switchValue, String title, Function onchang) { + Widget left = new Text( + title, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.normal), + ); + Widget right = new Expanded( + child: new Align( + alignment: Alignment.centerRight, + child: new Switch( + value: switchValue, + activeTrackColor: Constants.ConfrimButtonColor.withOpacity(0.3), + onChanged: onchang, + ))); + return new Container( + decoration: BoxDecoration( + color: Colors.white, + ), + padding: EdgeInsets.only(left: 20), + height: 53, + child: new Row( + children: [left, right], + ), + ); + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + I18n.of(context).group_setting, + style: TextStyle(color: AppColors.NewAppbarTextColor), + textScaleFactor: 1.0, + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ); + + return Scaffold( + appBar: appBar, + body: SafeArea( + child: _buildBody(), + )); + } + + Widget _buildBody() { + return Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 7, + ), + + ///群聊邀请确认 + _buildSettingWithSwitch(invite, I18n.of(context).group_invite, + (bool val) { + setState(() { + invite = val; + MsgHandler.setGroupSwitch( + widget.groupInfoModel.sessionId, invite); + }); + }), + _buildTips(), + Container( + color: Colors.white, + padding: EdgeInsets.only(left: 10), + height: 53, + child: FullWidthButton( + title: I18n.of(context).change_group_owner, + showDivider: false, + showRightIcon: true, + onPressed: () async { + String str = await Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return CreateGroupPage( + GroupOperatingPageType.SelectGroupOwner, + widget.groupInfoModel.members, + widget.groupInfoModel.sessionId); + }, + ), + ); + if (str == 'close') { + Navigator.pop(context); + } + }, + )) + ], + ), + ); + } + + Widget _buildTips() { + return Container( + margin: EdgeInsets.only(top: 10, bottom: 10, left: 15, right: 15), + child: Text( + I18n.of(context).group_setting_tips, + style: TextStyle(fontSize: 10.5, color: Constants.GreyTextColor), + ), + ); + } + + @override + void dispose() { + super.dispose(); + } +} diff --git a/lib/home/group_qr_view.dart b/lib/home/group_qr_view.dart new file mode 100644 index 0000000..a119743 --- /dev/null +++ b/lib/home/group_qr_view.dart @@ -0,0 +1,124 @@ +import 'dart:convert'; + +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/image_util.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:provider/provider.dart'; + +class GroupQrPage extends StatelessWidget { + final GroupInfoModel groupInfoModel; + + GroupQrPage(this.groupInfoModel); + + @override + Widget build(BuildContext context) { + print('groupInfoModel.askSwitch ${groupInfoModel.askSwitch}'); + DateTime today = DateTime.now(); + DateTime fiftyDaysFromNow = today.add(new Duration(days: 7)); + String dayTips = I18n.of(context).group_qr_code_tips; + dayTips = dayTips.replaceAll('/s1', fiftyDaysFromNow.month.toString()); + dayTips = dayTips.replaceAll('/s2', fiftyDaysFromNow.day.toString()); + + return Scaffold( + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + I18n.of(context).group_qr_code, + style: TextStyle(color: AppColors.NewAppbarTextColor), + textScaleFactor: 1.0, + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ), + body: Center( + child: Container( + margin: EdgeInsets.fromLTRB(28, 0, 28, 0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(6), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _head(context), + _qrImg(context), + Container( + padding: EdgeInsets.all(20), + child: Text( + dayTips, + style: TextStyle(fontSize: 9), + ), + ) + ], + ), + ))); + } + + _qrImg(context) { + //var headImg = UserData().basicInfo.headimgurl; + final size = Screen.width * 0.7; + var dayAfter = + new DateTime.now().add(new Duration(days: 7)).millisecondsSinceEpoch; + print('groupInfoModel.sessionId ${groupInfoModel.sessionId}'); + final groupIdAndTime = + 'type=1&sessionId=${groupInfoModel.sessionId}&expirationTime=$dayAfter'; + + var encodeStr = base64Encode(utf8.encode(groupIdAndTime)); + + return Stack( + children: [ + QrImage( + data: 'https://henho.jphgames.com/?$encodeStr', + version: QrVersions.auto, + size: size, + ), + groupInfoModel.askSwitch == 0 + ? Positioned.fill(child: Container()) + : Positioned.fill( + child: Container( + // height: size, + padding: EdgeInsets.only(left: 20, right: 20), + alignment: Alignment.center, + color: Color(0xf7FFFFFF), + child: Text( + I18n.of(context).group_open_verification, + style: TextStyle(color: Color(0xff696969), fontSize: 20), + ), + )) + ], + ); + } + + _head(BuildContext context) { + Map refMap = Provider.of(context).refMap; + var name = groupInfoModel.getGroupName(refMap); + + return Container( + padding: EdgeInsets.all(20), + child: Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(10), + child: WidgetUtil.getAvatarNew(groupInfoModel, key, (path) { + groupInfoModel.image = path; + })), + SizedBox(width: 10), + Expanded( + child: Text(name, + textScaleFactor: 1.0, + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Constants.BlackTextColor, + fontWeight: FontWeight.w500, + fontSize: 16))) + ], + )); + } +} diff --git a/lib/home/group_setting.dart b/lib/home/group_setting.dart new file mode 100644 index 0000000..34ee06f --- /dev/null +++ b/lib/home/group_setting.dart @@ -0,0 +1,671 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/home/add_friend.dart'; +import 'package:chat/home/group_announcement.dart'; +import 'package:chat/home/group_manage_page.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/group_member_model.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; + +import '../data/constants.dart'; +import '../generated/i18n.dart'; +import '../utils/CustomUI.dart'; +import '../utils/FullWithButton.dart'; +import '../utils/app_navigator.dart'; +import 'create_group_view.dart'; + +class GroupSetting extends StatefulWidget { + final GroupInfoModel groupInfoModel; + + GroupSetting({Key key, this.groupInfoModel}) : super(key: key); + + @override + State createState() { + return GroupSettingState(); + } +} + +class GroupSettingState extends State { + static const Separate_Size = 15.0; + + bool notice = true; //消息提示 + bool stickyChat = false; //置顶聊天 + bool showGroupFriendNickname = true; //显示群成员昵称 + + bool isHost; + + ///是否是群主 + + @override + void initState() { + super.initState(); + + stickyChat = widget.groupInfoModel.topTag > 0; + MessageMgr().on('Update Group Info', updateGroupInfo); + notice = widget.groupInfoModel.messageFree == 1; + showGroupFriendNickname = widget.groupInfoModel.isShowName > 0; + + print( + ' widget.groupInfoModel.hosterId : ${widget.groupInfoModel.hosterId}'); + } + + @override + void dispose() { + MessageMgr().off('Update Group Info', updateGroupInfo); + super.dispose(); + } + + updateGroupInfo(args) { + print('群设置 - 更新群信息'); + if (mounted) { + setState(() {}); + } + } + + quitGroup() { + print('退出所有页面'); + GroupInfoMgr().deleteGroup(widget.groupInfoModel.sessionId); + MessageMgr().emit('Quit Group', widget.groupInfoModel.sessionId); + Navigator.of(context).popUntil(ModalRoute.withName('/main')); + } + +//清空聊天记录 + clearRecord() { + //清楚最后一条数据 + widget.groupInfoModel.lastMsg = null; + + //清空聊天数据 + ChatDataMgr().deleteMsg(widget.groupInfoModel.sessionId, true); + } + + @override + Widget build(BuildContext context) { + isHost = widget.groupInfoModel.hosterId == UserData().basicInfo.userId; + print(widget.groupInfoModel.myName); + Widget appBar = AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + I18n.of(context).chat_news + + '(${widget.groupInfoModel.getMembersInGroup().length})', + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ); + + var groupName = + (widget.groupInfoModel.name == '' || widget.groupInfoModel.name == null) + ? I18n.of(context).undefine_name + : widget.groupInfoModel.name; + + return Scaffold( + appBar: appBar, + body: SafeArea( + child: ListView( + children: [ + SizedBox( + height: 12, + ), + + ///群成员 + buildMember( + () { + ///添加成员 + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return CreateGroupPage( + GroupOperatingPageType.AddMember, + widget.groupInfoModel.getMembersInGroup(), + widget.groupInfoModel.sessionId); + }, + ), + ); + }, + () { + ///删除成员 + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return CreateGroupPage( + GroupOperatingPageType.DeleteMember, + widget.groupInfoModel.getMembersInGroup(), + widget.groupInfoModel.sessionId); + }, + ), + ); + }, + () { + /// 查看更多成员 + AppNavigator.pushGroupAllMember(context, widget.groupInfoModel); + }, + ), + + SizedBox( + height: 12, + ), + + ///群聊名称 + _buildSetting(I18n.of(context).group_chat_name, groupName, () { + if (widget.groupInfoModel.canAlterGroupName()) { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return AddFriendPage( + userId: widget.groupInfoModel.sessionId, + pageType: SendMessagePageType.ChangeGroupName, + originalName: groupName, + ); + }, + ), + ); + } else { + showToast('权限不足'); + } + }), + + ///群二维码 + UserData().groupQRCode == 0 + ? Container() + : _buildSetting(I18n.of(context).group_qr, '', () { + AppNavigator.pushGroupQrPage( + context, widget.groupInfoModel); + }, + extendWidget: Icon( + IconData(0xe658, fontFamily: 'iconfont'), + size: 20.0, + color: Color(AppColors.TabIconNormal), + )), + + ///群公告 + groupAnnounce(), + + ///群管理 + widget.groupInfoModel.hosterId == UserData().basicInfo.userId + ? _buildSetting(I18n.of(context).group_setting, '', () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return GroupManagePage( + groupInfoModel: widget.groupInfoModel, + ); + }, + ), + ); + }, showDivider: false) + : Container(), + SizedBox( + height: 11, + ), + + ///消息免打扰 + _buildSettingWithSwitch(notice, I18n.of(context).close_news_notice, + (bool val) { + setState(() { + notice = val; + MsgHandler.updateMemberMsgFreeReq( + widget.groupInfoModel.sessionId, notice); + }); + }), + Container( + height: 0.5, + color: Colors.white, + child: Container( + color: Color(0xffE5E5E5), + ), + padding: EdgeInsets.symmetric(horizontal: 20), + ), + + ///置顶聊天 + _buildSettingWithSwitch(stickyChat, I18n.of(context).set_chat_top, + (bool val) { + setState(() { + stickyChat = val; + widget.groupInfoModel.updateTopTag(stickyChat); + MessageMgr().emit('Update Group List'); + }); + }), + SizedBox( + height: 11, + ), + + ///我在本群的昵称 + _buildSetting( + I18n.of(context).my_group_nickname, + widget.groupInfoModel.myName == null + ? UserData().basicInfo.nickName + : widget.groupInfoModel.myName, () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return AddFriendPage( + userId: widget.groupInfoModel.sessionId, + pageType: SendMessagePageType.ChangeGroupNickName, + originalName: widget.groupInfoModel.myName, + ); + }, + ), + ); + }), + + ///显示群成员昵称 + _buildSettingWithSwitch(showGroupFriendNickname, + I18n.of(context).show_group_member_name, (bool val) { + setState(() { + showGroupFriendNickname = val; + widget.groupInfoModel.updateShowNameSwitch(val); + }); + }), + + SizedBox( + height: 11, + ), + + ///清除聊天记录 + _buildSettingWithConfirm(I18n.of(context).group_clean_chat_record, + I18n.of(context).group_clean_chat_record, () { + clearRecord(); + Navigator.of(context).pop(); + }), + Padding( + padding: EdgeInsets.symmetric(horizontal: Separate_Size), + child: Divider( + color: Color(0xffE5E5E5), + height: 0.6, + ), + ), + + ///退出并删除按钮 + _buildSettingWithConfirm(I18n.of(context).quit_and_delete, + I18n.of(context).quit_group_tips, () { + print('退出群聊'); + quitGroup(); + MsgHandler.quitGroup(widget.groupInfoModel.sessionId); + }), + ], + ), + ), + ); + } + + Widget _buildSetting(String title, String desc, Function func, + {showRightIcon = true, showDivider = true, extendWidget}) { + //版本 + + return Container( + padding: EdgeInsets.symmetric(horizontal: 10), + child: FullWidthButton( + showRightIcon: showRightIcon, + title: title, + description: desc, + extendWidget: extendWidget, + showDivider: showDivider, + onPressed: func, + ), + decoration: BoxDecoration( + color: Colors.white, + ), + ); + } + + Widget _buildSettingWithSwitch( + bool switchValue, String title, Function onchang) { + Widget left = new Text( + title, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.normal), + ); + Widget right = new Expanded( + child: new Container( + alignment: Alignment.centerRight, + padding: EdgeInsets.only(right: 8), + child: new Switch( + value: switchValue, + activeTrackColor: Constants.ConfrimButtonColor.withOpacity(0.3), + onChanged: onchang, + ))); + return new Container( + decoration: BoxDecoration( + color: Colors.white, + ), + padding: EdgeInsets.only(left: 20), + height: 53, + child: new Row( + children: [left, right], + ), + ); + } + + Widget _buildSettingWithConfirm( + String title, String dialogTips, Function function) { + return Container( + color: Colors.white, + padding: EdgeInsets.only(top: 11, bottom: 11), + child: InkWell( + onTap: () { + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + builder: (BuildContext context) { + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(13), + topRight: Radius.circular(13))), + height: 225, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.fromLTRB(15, 15, 15, 13), + child: Text( + dialogTips, + style: + TextStyle(fontSize: 12, color: Color(0xff777777)), + ), + ), + Divider( + color: Color(0xffE5E5E5), + ), + InkWell( + onTap: function, + child: Container( + height: 60, + alignment: Alignment.center, + child: Text(I18n.of(context).determine, + style: TextStyle( + fontSize: 18, + color: Constants.ConfrimButtonColor)), + ), + ), + Container( + color: Color(0xffF2F2F2), + height: 4, + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + height: 60, + alignment: Alignment.center, + child: Text(I18n.of(context).cancel, + style: TextStyle( + fontSize: 18, color: Color(0xff4B4B4B))), + ), + ) + ], + ), + ); + }, + ); + }, + child: Container( + height: 40, + margin: EdgeInsets.symmetric(horizontal: 40), + alignment: Alignment.center, + child: Text( + title, + style: + TextStyle(color: Constants.ConfrimButtonColor, fontSize: 15), + ), + ), + )); + } + + ///群公告 + Widget groupAnnounce() { + return InkWell( + onTap: () { + if (widget.groupInfoModel.describe == '' && !isHost) { + showToast(I18n.of(context).only_host); + return; + } + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return GroupAnnouncementPage( + groupInfoModel: widget.groupInfoModel, + ); + }, + ), + ); + }, + child: Container( + color: Colors.white, + child: Column( + children: [ + Container( + padding: EdgeInsets.symmetric( + horizontal: Separate_Size, vertical: 12), + color: Colors.white, + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(top: 0, left: 4), + child: Text( + I18n.of(context).group_announcement, + style: TextStyle( + color: Colors.black, fontSize: 14), + ), + ), + widget.groupInfoModel.describe == null || + widget.groupInfoModel.describe == "" + ? Container() + : Container( + width: Screen.width - 55, + padding: EdgeInsets.only(top: 3, left: 4), + child: Text( + widget.groupInfoModel.describe, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Color(0xff818181), + fontSize: 11), + ), + ), + ]), + Expanded( + child: SizedBox(), + ), + Padding( + padding: EdgeInsets.only(bottom: 0), + child: Icon( + IconData(0xe63c, fontFamily: 'iconfont'), + size: 20.0, + color: Color(AppColors.TabIconNormal), + )) + ], + )), + Container( + margin: EdgeInsets.symmetric(horizontal: 15), + decoration: BoxDecoration( + border: Border( + bottom: Constants.GreyBorderSide, + ), + ), + ) + ], + ))); + } + + ///群成员显示 + Widget buildMember( + Function addMember, Function deleteMember, Function seeMoreMember) { +// List members = widget.groupInfoModel.getMembersInGroup(); + + List members = []; + + for (int k = 0; k < widget.groupInfoModel.members.length; k++) { + //只加入存在群的 + GroupMemberModel mo = widget.groupInfoModel.members[k]; + if (mo.inGroup == 1) { + members.add(mo); + } + } + + members.sort((GroupMemberModel left, GroupMemberModel right) => + right.identity.compareTo(left.identity)); + + print('群成员数量- ${members.length}'); + int length = members.length; + int dex = isHost ? 2 : 1; + int shouldShow = length > (10 - dex) ? 10 - dex : length; + + double size = Screen.width / 5; + + List list = []; + for (int index = 0; index < shouldShow; index++) { + var member = members[index]; + var refName = Provider.of(context) + .getGroupRefName(widget.groupInfoModel.sessionId, member.memberId); + list.add(GestureDetector( + child: Container( + child: Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(8.0)), + child: CachedNetworkImage( + imageUrl: member.avtar, + placeholder: CustomUI.buildImgLoding, + width: size - 30, + height: size - 30, + )), + SizedBox( + height: 5, + ), + + SizedBox( + width:size - 30, + child: Text( + refName, + style: TextStyle(fontSize: 11, color: Color(0xff818181)), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ) + + ], + ), + width: size, + height: size, + ), + behavior: HitTestBehavior.translucent, + onTap: () { + if (members[index].memberId != UserData().basicInfo.userId) { + AppNavigator.pushProfileInfoPage(context, members[index].memberId, + fromWhere: 2,addMode: 1); + } + }, + )); + } + + list.add(GestureDetector( + onTap: addMember, + child: Container( + width: size, + height: size, + child: Column( + children: [ + Container( + alignment: Alignment.center, + width: size - 30, + height: size - 30, + child: Text( + '+', + textScaleFactor: 1.0, + style: TextStyle(fontSize: 30, color: Color(0xffB1B1B1)), + ), + decoration: BoxDecoration( + border: Border.all(color: Color(0xffC3C3C3), width: 1.0), + borderRadius: BorderRadius.all(Radius.circular(6))), + ) + ], + ), + ), + )); + if (isHost) { + list.add(Container( + width: size, + height: size, + child: Column( + children: [ + GestureDetector( + onTap: deleteMember, + child: Container( + alignment: Alignment.center, + width: size - 30, + height: size - 30, + child: Container( + color: Color(0xffB1B1B1), + width: 20, + height: 2.6, + ), + decoration: BoxDecoration( + border: Border.all(color: Color(0xffC3C3C3), width: 1.0), + borderRadius: BorderRadius.all(Radius.circular(6))), + ), + ) + ], + ), + )); + } + + return Container( + color: Color(0xffFAFAFA), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 5, + ), + Wrap( + children: list, + crossAxisAlignment: WrapCrossAlignment.start, + alignment: WrapAlignment.start, + ), + length > (10 - dex) + ? GestureDetector( + onTap: seeMoreMember, + child: Container( + height: 35, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + I18n.of(context).show_more_member, + textScaleFactor: 1.0, + style: TextStyle(color: Color(0xff818181)), + ), + Padding( + padding: EdgeInsets.only(bottom: 1.5), + child: Icon( + IconData(0xe63c, fontFamily: 'iconfont'), + size: 20.0, + color: Color(AppColors.TabIconNormal), + )) + ], + ), + ), + ) + : Container(), + ], + ), + ); + } +} diff --git a/lib/home/homeMain.dart b/lib/home/homeMain.dart new file mode 100644 index 0000000..bace6b7 --- /dev/null +++ b/lib/home/homeMain.dart @@ -0,0 +1,463 @@ +import 'dart:async'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/find_page.dart'; +import 'package:chat/home/group_chat_page.dart'; +import 'package:chat/home/unread_dot_widget.dart'; +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/file_transfer_page.dart'; +import 'package:chat/utils/local_notification_util.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/receive_share_file.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sound_util.dart'; +import 'package:chat/utils/version_update_utils.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:chat/home/ConversActionPage.dart'; +import 'package:chat/home/ProfilePage.dart'; +import 'package:flutter/services.dart'; +import 'package:location_permissions/location_permissions.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:chat/utils/my_bottom_navigation_bar.dart' as myBottm; + +import 'friend_page.dart'; + +class NavigationIconView { + final BottomNavigationBarItem item; + + NavigationIconView({ + Key key, + String title, + IconData icon, + int type, + double iconSize = 24, + bool isCenter = false, + bool isShowdot = false, + }) : item = BottomNavigationBarItem( + activeIcon: Stack( + alignment: Alignment.center, + children: [ + isCenter + ? Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: const Color(0x82008DED), + blurRadius: 5.5, + ), + ], + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFF11E6FF), + const Color(0xFF008AFF), + ]), + ), + margin: EdgeInsets.only(bottom: 4), + width: iconSize + 10, + height: iconSize + 10, + ) + : Container(), + Container( + margin: isCenter + ? EdgeInsets.only(bottom: 8, right: 6) + : EdgeInsets.zero, + child: Icon(icon, + size: iconSize, + color: + isCenter ? Colors.white : Constants.BlueTextColor)), + ], + ), + title: Text(''), + backgroundColor: Colors.white, + icon: Stack( + alignment: Alignment.center, + children: [ + isCenter + ? Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: const Color(0x82008DED), + blurRadius: 5.5, + ), + ], + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0xFF11E6FF), + const Color(0xFF008AFF), + ]), + ), + margin: EdgeInsets.only(bottom: 4), + width: iconSize + 10, + height: iconSize + 10, + ) + : Container(), + Container( + margin: isCenter + ? EdgeInsets.only(bottom: 8, right: 6) + : EdgeInsets.zero, + child: isShowdot + ? UnreadDot( + child: Icon(icon, + size: iconSize, + color: Constants.BottomIconGreyColor), + type: type) + : Icon(icon, + size: iconSize, + color: isCenter + ? Colors.white + : Constants.BottomIconGreyColor)) + ], + )); +} + +class HomeMain extends StatefulWidget { + HomeMain({Key key}) : super(key: key); + _HomeMainState createState() => _HomeMainState(); +} + +class _HomeMainState extends State { + List _pages; + int _currentIndex = 0; + List _navigationViews; + List _titles = []; + DateTime lastPopTime; + Timer time; + + @override + void initState() { + MsgHandler.context = context; + + SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light); + super.initState(); + LocalNotificationUtil.instance.initState(context); + HttpUtil().checkReceiptCache(); + HttpUtil().getSettingInfo(); + + MessageMgr().on('Receive AudioChat Request', receiveAudioChatRequest); + MessageMgr().on('Login Out', loginOut); + MessageMgr().on('PostContact', postContact); + MessageMgr().on('Show My Profile', showMyProfile); + MessageMgr().on('test_Permission', msgTestPermission); + MessageMgr().on(MessageMgr.RECEIVE_THIRD_SHARE, goShareInfo); + + ///初始化语音播放是外放还是听筒-默认外放 + SoundUtils.instance.initPlayMode(); + + postContact(null); + postLoaction(); + locationSchedule(); + + WidgetsBinding.instance.addPostFrameCallback((_) { + VersionUtils.versionUpdate(context); + ReceiveShareFile.start(); + }); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + Provider.of(context, listen: false).init(); + } + + showMyProfile(args) { + setState(() { + _currentIndex = _pages.length - 1; + UserData().homemainIndex = _currentIndex; + }); + } + + //三分钟获取一次位置信息 + void locationSchedule() { + time = Timer.periodic(Duration(milliseconds: 180000), (timer) async { + postLoaction(); + }); + } + + postLoaction() async { + if (UserData().hasLocationPermission) { + UserData().getCurrentPosition(callback: (loc) async { + if (UserData().basicInfo.userId != null) { + //传给服务器 + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + data['lat'] = loc.latitude; + data['lon'] = loc.longitude; + Response res = + await HttpUtil().post('location/user/insert', data: data); + if (res == null) { + return; + } + var resData = res.data; + print('location/user/insert $resData'); + } + }); + } + } + + //上传通讯录 + postContact(args) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + int localNum = prefs.getInt(Constants.ContactNum); + if (UserData().contactList.length != 0 && + UserData().contactList.length != localNum && + UserData().basicInfo.userId != null) { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + data['list'] = UserData().contactList; + Response res = await HttpUtil().post('maillist/user/insert', data: data); + if (res == null) { + return; + } + var resData = res.data; + if (resData['code'] == 0) { + prefs.setInt(Constants.ContactNum, UserData().contactList.length); + } + } + } + + @override + void dispose() { + MessageMgr().off('Receive AudioChat Request', receiveAudioChatRequest); + MessageMgr().off('Login Out', loginOut); + MessageMgr().off('PostContact', postContact); + MessageMgr().off('Show My Profile', showMyProfile); + MessageMgr().off('test_Permission', msgTestPermission); + MessageMgr().off(MessageMgr.RECEIVE_THIRD_SHARE, goShareInfo); + LocalNotificationUtil.instance.dispose(); + if (time != null) { + time.cancel(); + } + super.dispose(); + } + + goShareInfo(data) async { + Future.delayed(Duration(milliseconds: 1000), () { + Navigator.of(LoadingManage.context).push( + new MaterialPageRoute( + builder: (context) { + return FileTransferPage(data); + }, + ), + ); + }); + } + + msgTestPermission(data) async { + PermissionStatus status = + await LocationPermissions().checkPermissionStatus(); + if (status == PermissionStatus.granted) { + if (UserData().hasLocationPermission == false) { + UserData().getCurrentPosition(); + } + UserData().hasLocationPermission = true; + } else { + UserData().hasLocationPermission = false; + } + } + + receiveAudioChatRequest(args) { + print('处理连麦消息'); + int friendId = args; + + if (!MsgHandler.isAudioConnect) { + if (LocalNotificationUtil.isBackground) { + print('如果在后台,标记不弹'); + MsgHandler.audioChatRequestFriendId = friendId; + } else { + HttpUtil().getUserInfo(friendId, (data) { + var info = UserInfo.fromJson(data); + AppNavigator.pushAudioChatPage(context, info, true); + }); + } + } + } + + loginOut(args) { + HttpUtil().postLoginOut(context); + showToast(I18n.of(context).otherLogin); + } + + initValue() { + _titles = [ + I18n.of(context).park, + I18n.of(context).radio, + I18n.of(context).news, + I18n.of(context).me + ]; + + _navigationViews = [ + NavigationIconView( + title: _titles[2], + icon: IconData( + 0xe60b, + fontFamily: 'iconfont', + ), + isShowdot: true, + type: 3, + iconSize: 25), + NavigationIconView( + title: _titles[0], + isShowdot: true, + type: 5, + icon: IconData( + 0xe663, + fontFamily: 'iconfont', + ), + iconSize: 26.5), + NavigationIconView( + title: _titles[1], + icon: IconData( + 0xe656, + fontFamily: 'iconfont', + ), + isCenter: true, + iconSize: 31), + NavigationIconView( + title: _titles[1], + isShowdot: true, + icon: IconData( + 0xe66e, + fontFamily: 'iconfont', + ), + type: 4, + iconSize: 26.5), + NavigationIconView( + title: _titles[3], + icon: IconData( + 0xe648, + fontFamily: 'iconfont', + ), + iconSize: 26.5), + ]; + + _pages = [ + ConversActionPage(), + FriendPage(), + FindPage(), + GroupChatListPage(), + ProfilePage( + userId: UserData().basicInfo.userId, + ), + ]; + } + + @override + Widget build(BuildContext context) { + initValue(); + + return WillPopScope( + onWillPop: () async { + if (lastPopTime == null || + DateTime.now().difference(lastPopTime) > Duration(seconds: 2)) { + lastPopTime = DateTime.now(); + showToast(I18n.of(context).confirm_exit); + } else { + lastPopTime = DateTime.now(); + await SystemChannels.platform.invokeMethod('SystemNavigator.pop'); + } + return new Future.value(false); + }, + child: Container( +// color: Colors.white, + color: AppColors.NewAppbarBgColor, + child: Scaffold( + appBar: PreferredSize( + preferredSize: Size.fromHeight(1), + child: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + ), + ), + resizeToAvoidBottomPadding: false, + body: SafeArea( + child: Stack( + alignment: AlignmentDirectional.bottomStart, + children: [ + Container( + padding: EdgeInsets.only(bottom: 48), + color: Constants.LightGreyBackgroundColor, + child: SafeArea( + child: IndexedStack( + index: _currentIndex, + children: _pages, + )), + ), + Positioned( + bottom: 0, + child: Container( + margin: EdgeInsets.only(bottom: 0), + child: Image.asset( + 'assets/images/bg.png', + width: Screen.width, + ), + ), + ), + Positioned( + bottom: 0, + child: Container( + width: Screen.width, + height: 0, + color: Colors.white, + ), + ), + Container( + height: 57, + child: myBottm.BottomNavigationBar( + elevation: 0, + showSelectedLabels: false, + showUnselectedLabels: false, + //iconSize: 23.5, + backgroundColor: Colors + .transparent, //Constants.LightGreyBackgroundColor, + currentIndex: _currentIndex, + type: myBottm.BottomNavigationBarType.fixed, + fixedColor: const Color(AppColors.TabIconActive), + items: + _navigationViews.map((NavigationIconView view) { + return view.item; + }).toList(), + onTap: (int index) { + if (_currentIndex == index) { + //在当前页面点击不刷新 + return; + } + //刷新我的界面数据 + if (index == 4) { + MessageMgr().emit('update_data'); + } + // if (index == 1) { + // MessageMgr().emit('refresh_list_when_no_data'); + // } + MessageMgr().emit('update_system'); + MessageMgr().emit('do_friend_apply'); +// LocalNotificationUtil.instance.cleanAllNotifications(); + setState(() { + _currentIndex = index; + UserData().homemainIndex = _currentIndex; + }); + })), + ], + ))), + )); + } +} diff --git a/lib/home/invite_detail_page.dart b/lib/home/invite_detail_page.dart new file mode 100644 index 0000000..647e33c --- /dev/null +++ b/lib/home/invite_detail_page.dart @@ -0,0 +1,175 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/group_member_model.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; + +class InviteDetailPage extends StatefulWidget { + final List originalList; + final GroupMemberModel opt; + final int groupId; + InviteDetailPage( + {Key key, @required this.originalList, @required this.opt, this.groupId}) + : super(key: key); + + @override + _InviteDetailPageState createState() => new _InviteDetailPageState(); +} + +class _InviteDetailPageState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + title: new Text( + I18n.of(context).invite_detail, + textScaleFactor: 1.0, + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ); + + return Scaffold( + appBar: appBar, + body: SafeArea( + child: _buildBody(), + )); + } + + Widget _buildBody() { + var headImg = Container( + margin: EdgeInsets.only(top: 9), + child: ClipRRect( + borderRadius: BorderRadius.circular(6), + child: CachedNetworkImage( + imageUrl: widget.opt.avtar, + width: 61, + height: 61, + ))); + var name = Container( + margin: EdgeInsets.only(top: 8.5), + alignment: Alignment.center, + width: Screen.width, + child: Text( + widget.opt.nickName, + style: TextStyle(fontSize: 15), + ), + ); + + var tips = Container( + margin: EdgeInsets.only(top: 16, bottom: 20.5), + alignment: Alignment.center, + width: Screen.width, + child: Text( + I18n.of(context) + .invite_members + .replaceFirst('/s1', widget.originalList.length.toString()), + style: TextStyle(fontSize: 15.5), + ), + ); + + var divder = Container( + width: Screen.width, + margin: EdgeInsets.symmetric(horizontal: 16.5), + decoration: BoxDecoration(border: Border(top: Constants.GreyBorderSide)), + ); + + return Container( + color: Colors.white, + width: Screen.width, + margin: EdgeInsets.only(top: 11), + child: ListView( + children: [ + headImg, + name, + tips, + divder, + _buildList(), + + ///确认邀请 + Container( + color: Colors.white, + padding: EdgeInsets.only(top: 11, bottom: 11), + child: GestureDetector( + onTap: () { + List idList = []; + for (int k = 0; k < widget.originalList.length; k++) { + idList.add(widget.originalList[k].memberId); + } + + MsgHandler.agreeMember(widget.groupId, idList); + + Navigator.pop(context); + }, + child: Container( + height: 44.5, + margin: EdgeInsets.symmetric(horizontal: 40, vertical: 40), + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(0xff2685FA), + borderRadius: BorderRadius.all(Radius.circular(6))), + child: Text( + I18n.of(context).determine, + style: TextStyle(color: Colors.white, fontSize: 16), + ), + ), + )), + ], + ), + ); + } + + Widget _buildList() { + List list = []; +// List userList = []; +// for (int i = 0; i < 30; i++) { +// userList.add({ +// 'headImg': UserData().basicInfo.headimgurl, +// 'userName': UserData().basicInfo.nickName +// }); +// } + widget.originalList + .forEach((f) => list.add(_buildUserInfo(f.avtar, f.nickName))); + return Container( + child: Wrap(crossAxisAlignment: WrapCrossAlignment.start, children: list), + ); + } + + Widget _buildUserInfo(String headImg, String username) { + return Container( + width: Screen.width / 5, + child: Column( + children: [ + Container( + margin: EdgeInsets.only(top: 18), + child: ClipRRect( + borderRadius: BorderRadius.circular(6), + child: CachedNetworkImage( + imageUrl: headImg, + width: 42.5, + height: 42.5, + ))), + Container( + margin: EdgeInsets.only(top: 8.5), + child: Text( + username, + style: TextStyle(fontSize: 10.3, color: Constants.GreyTextColor), + ), + ) + ], + ), + ); + } + + @override + void dispose() { + super.dispose(); + } +} diff --git a/lib/home/join_group_confirm.dart b/lib/home/join_group_confirm.dart new file mode 100644 index 0000000..dc043d0 --- /dev/null +++ b/lib/home/join_group_confirm.dart @@ -0,0 +1,137 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/image_util.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:provider/provider.dart'; + +class JoinGroupConfirmPage extends StatefulWidget { + final GroupInfoModel groupInfoModel; + JoinGroupConfirmPage({Key key, @required this.groupInfoModel}) + : super(key: key); + + @override + _JoinGroupConfirmPageState createState() => new _JoinGroupConfirmPageState(); +} + +class _JoinGroupConfirmPageState extends State { + bool isInGroup = false; + @override + void initState() { + super.initState(); + isInGroup = + widget.groupInfoModel.isGroupMember(UserData().basicInfo.userId); + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + title: new Text( + I18n.of(context).join_group, + textScaleFactor: 1.0, + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ); + + return Scaffold( + appBar: appBar, + body: SafeArea( + child: _buildBody(), + )); + } + + GlobalKey key = GlobalKey(); + Widget _buildBody() { + Map refMap = Provider.of(context).refMap; + double width = 52; + var headImg = Container( + margin: EdgeInsets.only(top: 9), + width: width, + height: width, + child: WidgetUtil.getAvatarNew(widget.groupInfoModel, key, (path) { + widget.groupInfoModel.image = path; + })); + var name = Container( + margin: EdgeInsets.only(top: 8.5), + alignment: Alignment.center, + width: Screen.width - 40, + child: Text( + widget.groupInfoModel.getGroupName(refMap), + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 15), + ), + ); + + var tips = Container( + margin: EdgeInsets.only(top: 16, bottom: 20.5), + alignment: Alignment.center, + width: Screen.width, + child: Text( + I18n.of(context).total_members.replaceFirst( + '/s1', widget.groupInfoModel.getMembersInGroup().length.toString()), + style: TextStyle(fontSize: 15.5, color: const Color(0xFF6F6F6F)), + ), + ); + + var divder = Container( + width: Screen.width, + margin: EdgeInsets.symmetric(horizontal: 16.5), + decoration: BoxDecoration(border: Border(top: Constants.GreyBorderSide)), + ); + + return Container( + color: Colors.white, + width: Screen.width, +// margin: EdgeInsets.only(top: 11), + child: SingleChildScrollView( + child: Column( + children: [ + headImg, + + name, + tips, + divder, + + ///确认邀请 + Container( + color: Colors.white, + padding: EdgeInsets.only(top: 11, bottom: 11), + child: GestureDetector( + onTap: isInGroup + ? null + : () { + MsgHandler.joinGroup(widget.groupInfoModel.sessionId); + }, + child: Container( + height: 44.5, + margin: EdgeInsets.symmetric(horizontal: 40, vertical: 40), + alignment: Alignment.center, + decoration: BoxDecoration( + color: isInGroup ? Colors.grey : Color(0xff2685FA), + borderRadius: BorderRadius.all(Radius.circular(6))), + child: Text( + isInGroup + ? I18n.of(context).joined + : I18n.of(context).join_now, + style: TextStyle(color: Colors.white, fontSize: 16), + ), + ), + )), + ], + ), + ), + ); + } + + @override + void dispose() { + super.dispose(); + } +} diff --git a/lib/home/last_chat_item.dart b/lib/home/last_chat_item.dart new file mode 100644 index 0000000..112d3ac --- /dev/null +++ b/lib/home/last_chat_item.dart @@ -0,0 +1,183 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/home/send_msg_state.dart'; +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/models/last_message_model.dart'; +import 'package:chat/models/last_msg_description.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'last_unread_dot.dart'; + +class LastChatItem extends StatefulWidget { + final LastMessageModel lastMessageModel; + final int enterType; // 0默认 1图片 + final dynamic enterContent; + LastChatItem(Key key, this.lastMessageModel, + {this.enterType = 0, this.enterContent}) + : super(key: key); + @override + _LastChatItemState createState() => _LastChatItemState(); +} + +class _LastChatItemState extends State { + LastMessageModel lastMessageModel; + + UserInfo userInfo; + + int retryCount=0; + + @override + void initState() { + super.initState(); + lastMessageModel = widget.lastMessageModel; + + initUserInfo(); +// initUserInfo(); +// initUserInfo(); + MessageMgr().on('UpdateUserInfo', msgUpdateUserInfo); + } + + initUserInfo() async { + print('## xxx ${widget.lastMessageModel.friendId}'); + userInfo = await HttpUtil().getFriendInfo(widget.lastMessageModel.friendId); + setState(() {}); + } + + msgUpdateUserInfo(info) { + if (info.userId == widget.lastMessageModel.friendId) { + userInfo = info; + setState(() {}); + } + } + + @override + void dispose() { + super.dispose(); + MessageMgr().off('UpdateUserInfo', msgUpdateUserInfo); + } + + @override + Widget build(BuildContext context) { + int unreadCount = ChatDataMgr() + .unreadCountProvider + .getUnreadCount(widget.lastMessageModel.sessionId); + print('build lastchatimte 未读消息数$unreadCount'); + + if (userInfo == null ) { + print(('userinfo ==null')); + + + return Container(); + } + Widget avatar = ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(8.0)), + child: CachedNetworkImage( + imageUrl: userInfo.headimgurl, + placeholder: CustomUI.buildImgLoding, + width: Constants.ConversationAvatarSize, + height: Constants.ConversationAvatarSize, + )); + + List _rightArea = [ + Align( + alignment: Alignment.topCenter, + child: Text(Constants.getShowTime(lastMessageModel.updateAt, context), + textScaleFactor: 1.0, style: AppStyles.DescStyle), + ), + Expanded( + child: Align( + alignment: Alignment.bottomCenter, + child: UnreadCountDot( + sessionId: lastMessageModel.sessionId, unreadCount: unreadCount), + )) + ]; + + return InkWell( + child: Container( + padding: const EdgeInsets.all(10.0), + height: 68, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(AppColors.ConversationItemBgColor), + border: Border(bottom: Constants.GreyBorderSide)), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + avatar, + Container(width: 10.0), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + Provider.of(context) + .getRefName(userInfo.userId, userInfo.nickName), + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 15, + color: Colors.black, + )), + Expanded(child: SizedBox()), + Row( + children: [ + SendMsgState( + sessionId: lastMessageModel.sessionId, + time: lastMessageModel.updateAt), + Container( + constraints: + BoxConstraints(maxWidth: Screen.width - 130), + child: LastMsgDescription( + Key("Item$lastMessageModel.sessionId"), + lastMessageModel)) + ], + ), + SizedBox(height: 2) + ], + ), + ), + SizedBox( + height: Constants.ConversationAvatarSize, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _rightArea, + ), + ) + ], + ), + ), + onTap: () { + MsgHandler.updateActiveSesstion(lastMessageModel.sessionId); + AppNavigator.pushChatPage(context, lastMessageModel.friendId, + enterType: widget.enterType, enterContent: widget.enterContent); + }, + ); + + // FutureBuilder( + // future: _friendInfoFuture, + // builder: (BuildContext context, AsyncSnapshot snapshot) { + // if (snapshot.connectionState == ConnectionState.done) { + // if (snapshot.hasError) { + // return Container(); + // } else { + // UserInfo friendInfo = snapshot.data; + // if (friendInfo == null) { + // return Container(); + // } + + // } else { + // return Container(); + // } + // }); + } +} diff --git a/lib/home/last_chat_record_widget.dart b/lib/home/last_chat_record_widget.dart new file mode 100644 index 0000000..4babc33 --- /dev/null +++ b/lib/home/last_chat_record_widget.dart @@ -0,0 +1,272 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/last_chat_item.dart'; +import 'package:chat/models/last_message_model.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:chat/utils/net_state_widget.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sql_util.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; + +class LastChatPage extends StatefulWidget { + final bool needRobot; + final int enterType; // 0默认 1图片 + final dynamic enterContent; + LastChatPage({this.needRobot = true, this.enterType = 0, this.enterContent}); + + @override + _LastChatPageState createState() => _LastChatPageState(); +} + +class _LastChatPageState extends State { + @override + void initState() { + super.initState(); + + MessageMgr().on(MessageMgr.REFRESH_PUSH_PERMISSION, requestPushPermission); + MessageMgr().on('Update LastMsg', updateList); + } + + @override + void dispose() { + MessageMgr().off(MessageMgr.REFRESH_PUSH_PERMISSION, requestPushPermission); + MessageMgr().off('Update LastMsg', updateList); + super.dispose(); + } + + requestPushPermission(args) async { + print('请求推送权限'); + final PermissionStatus status = await PermissionHandler() + .checkPermissionStatus(PermissionGroup.notification); + print('请求推送权限--status:$status'); + if (status == PermissionStatus.denied) { + setState(() { + UserData().needRequestPushPermission = UserData().privatyMsgPushSwitch; + }); + } + if (status == PermissionStatus.granted) { + UserData().needRequestPushPermission = false; + if (mounted) { + setState(() {}); + } + } + } + + updateList(args) { + if (mounted) { + setState(() {}); + } + } + + @override + Widget build(BuildContext context) { + List lastMsgList = ChatDataMgr().lastMsgProvider.lastMsgList; + + print('lastMsgList ${lastMsgList.length}'); + + return Column( + children: [ + UserData().needRequestPushPermission + ? InkWell( + onTap: () { + CustomUI.buildOneConfirm( + context, + I18n.of(context).notice_open, + I18n.of(context).determine, () async { + Navigator.of(context).pop(); + PermissionHandler().openAppSettings(); + }, title: I18n.of(context).open_notice); + }, + child: Container( + height: 25, + alignment: Alignment.center, + width: double.infinity, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + I18n.of(context).not_open, + textScaleFactor: 1, + style: TextStyle( + fontSize: 12.5, color: const Color(0xffab8f60)), + ), + Icon( + Icons.chevron_right, + size: 18, + color: const Color(0xffab8f60), + ) + ], + ), + color: const Color(0xfffaefcf), + )) + : Container(), + NetStateWidget(), + widget.needRobot ? _translateRobot() : Container(), + //_CompanyServer(), + lastMsgList.length == 0 + ? _emptyContent() + : _chatRecordsList(lastMsgList) + ], + ); + } + + Widget _translateRobot() { + return InkWell( + onTap: () { + AppNavigator.pushTranslateRobotPage(context); + }, + child: Container( + padding: const EdgeInsets.all(10.0), + height: 68, + child: Row( + children: [ + ClipRRect( + child: Image.asset(R.assetsImagesRobot), + borderRadius: BorderRadius.circular(5), + ), + SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + fixedText(I18n.of(context).translate_robot, + fontSize: 15, fontWeight: FontWeight.w500), + SizedBox(height: 5), + Text( + I18n.of(context).robot_hello, + textScaleFactor: 1.0, + style: AppStyles.DescStyle, + ), + ], + ) + ], + ), + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(AppColors.ConversationItemBgColor), + border: Border(bottom: Constants.GreyBorderSide)), + )); + } + + Widget _CompanyServer() { + return InkWell( + onTap: () { + AppNavigator.pushCompanyServerPage(context); + }, + child: Container( + padding: const EdgeInsets.all(10.0), + height: 68, + child: Row( + children: [ + ClipRRect( + child: Image.asset(R.assetsImagesServerIcon), + borderRadius: BorderRadius.circular(5), + ), + SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + fixedText('反馈助手', + fontSize: 15, fontWeight: FontWeight.w500), + SizedBox(height: 5), + Text( + '你好,使用过程中遇到任何问题都可以告诉我哦!', + textScaleFactor: 1.0, + style: AppStyles.DescStyle, + ), + ], + ) + ], + ), + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(AppColors.ConversationItemBgColor), + border: Border(bottom: Constants.GreyBorderSide)), + )); + } + + Widget _emptyContent() { + return Expanded( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.only(bottom: 9.5, right: 11), + child: Icon( + IconData( + 0xe640, + fontFamily: 'iconfont', + ), + color: Constants.LightBlueIconColor, + size: 60, + )), + fixedText(I18n.of(context).no_new, + color: Constants.OpacityBlueTextColor, fontSize: 14), + ], + )), + ); + } + + Widget _chatRecordsList(lastMsgList) { + return Expanded( + child: Container( + alignment: Alignment.topCenter, + child: ListView.builder( + shrinkWrap: true, + itemBuilder: (BuildContext context, int index) { + LastMessageModel msg = lastMsgList[index]; + if (msg.sessionId == 10000) { + return Container(); + } + return Dismissible( + key: Key(msg.sessionId.toString()), + child: LastChatItem( + Key(msg.sessionId.toString()), + msg, + enterType: widget.enterType, + enterContent: widget.enterContent, + ), + direction: DismissDirection.endToStart, + background: Container( + color: Colors.red, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + fixedText(I18n.of(context).delete, + color: Colors.white), + Icon( + Icons.delete, + color: Colors.white, + ) + ], + ), + ), + confirmDismiss: (direction) async { + var _confirmContent = I18n.of(context).confirm_delete; + bool isDismiss = await CustomUI.showIosDialog( + context, _confirmContent, () { + lastMsgList.removeAt(index); + SqlUtil.userInfoTable.deleteUser(msg.friendId); + ChatDataMgr().deleteMsg(msg.sessionId, false); + setState(() {}); + Navigator.of(context).pop(true); + }, () { + Navigator.of(context).pop(false); + }); + + return isDismiss; + }); + }, + itemCount: lastMsgList.length, + ))); + } +} diff --git a/lib/home/last_unread_dot.dart b/lib/home/last_unread_dot.dart new file mode 100644 index 0000000..dc1a0ad --- /dev/null +++ b/lib/home/last_unread_dot.dart @@ -0,0 +1,34 @@ +import 'package:chat/data/constants.dart'; +import 'package:flutter/material.dart'; + +class UnreadCountDot extends StatelessWidget { + final int sessionId; + final int unreadCount; + UnreadCountDot({this.sessionId, this.unreadCount}); + + @override + Widget build(BuildContext context) { + + if (unreadCount <= 0) { + return Container(); + } else { + var countStr = unreadCount.toString(); + if (unreadCount > 99) { + countStr = '99+'; + } + + return Container( + width: Constants.UnReadMsgNotifyDotSize, + height: Constants.UnReadMsgNotifyDotSize, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(Constants.UnReadMsgNotifyDotSize / 2.0), + color: Color(AppColors.NotifyDotBgColor), + ), + child: Text(countStr, + textScaleFactor: 1.0, style: AppStyles.UnreadMsgCountDotStyle), + ); + } + } +} \ No newline at end of file diff --git a/lib/home/money_detail.dart b/lib/home/money_detail.dart new file mode 100644 index 0000000..ff9d630 --- /dev/null +++ b/lib/home/money_detail.dart @@ -0,0 +1,432 @@ +import 'dart:async'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/data/conversation.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/InfoList.dart'; +import 'package:chat/home/ProfilePage.dart'; +import 'package:chat/home/rich_title.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart'; + +import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx; +import 'package:oktoast/oktoast.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; + +class _ConversationItem extends StatelessWidget { + const _ConversationItem( + {Key key, + this.conversation, + this.callback, + this.showRight = true, + this.rightButton, + this.showReturn = false, + this.applyInfo, + this.bgColor, + this.isInCome = false, + this.money, + this.title}) + : assert(conversation != null), + super(key: key); + final Widget rightButton; + final Conversation conversation; + final callback; + final int money; + final bool showRight; + final title; + final applyInfo; + final bgColor; + final bool showReturn; + final bool isInCome; + + @override + Widget build(BuildContext context) { + Widget avatar; + double width = 44.55; + if (conversation.isAvatarFromNet()) { + avatar = ClipRRect( + borderRadius: BorderRadius.circular(10), + child: CachedNetworkImage( + imageUrl: conversation.avatar, + placeholder: (context, url) => Image.asset( + Constants.DefaultHeadImgUrl, + width: width, + height: width, + ), + fit: BoxFit.cover, + width: width, + height: width, + )); + } else { + avatar = ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Container( + width: width, + height: width, + alignment: Alignment.center, + decoration: BoxDecoration( + gradient: this.bgColor, + borderRadius: BorderRadius.all(Radius.circular(50))), + child: Image.asset( + conversation.avatar, + height: 27, + ))); + } + + return InkWell( + child: Container( + padding: + const EdgeInsets.only(left: 21, top: 12.5, bottom: 12.5, right: 24.5), + decoration: BoxDecoration( + color: Color(AppColors.ConversationItemBgColor), + border: Border( + bottom: BorderSide( + color: AppColors.DividerColor, + width: Constants.DividerWidth))), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + avatar, + Container(width: 14.0), + Expanded( + child: Container( + padding: EdgeInsets.only(top: 3), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: title == null + ? Text(conversation.title, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 11, + color: Constants.LightGreyTextColor)) + : title), + Container( + padding: EdgeInsets.only(top: 10), + child: Text(conversation.desc, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 11, color: Constants.LightGreyTextColor)), + ) + ], + ), + )), + Container( + height: width, + margin: EdgeInsets.only(left: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '${money > 0 ? '+' : ''}${this.isInCome ? money * 1000 : (money.toString() + I18n.of(context).mask_coin)}', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: + money > 0 ? Color(0xFFFE4624) : Color(0xFF5498FF)), + ), + showReturn + ? Padding( + padding: EdgeInsets.only(top: 3), + child: Text( + I18n.of(context).alreay_back, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.normal, + color: Constants.BlackTextColor), + )) + : Container() + ], + ), + alignment: Alignment.center, + ), + ], + ), + ), + onTap: () { + callback(); + }, + ); + } +} + +class MoneyDetailPage extends StatefulWidget { + final int type; + MoneyDetailPage({Key key, this.type}) : super(key: key); + MoneyDetailPageState createState() => MoneyDetailPageState(); +} + +class MoneyDetailPageState extends State + with SingleTickerProviderStateMixin { + List list = new List(); //列表要展示的数据 + RefreshController _refreshController = + RefreshController(initialRefresh: true); + + int _page = 1; //加载的页数 + int rows = 20; + + TabController tabCtrl; + + var bindAccount; + + @override + void initState() { + super.initState(); + + tabCtrl = TabController(length: 2, vsync: this); + + fluwx.responseFromPayment.listen((data) { + if (data.errCode == 0) { + Navigator.of(context).pop(); + setState(() {}); + showToast(I18n.of(context).payment_successful); + } + }); + } + + void addList(data) { + if (data == null || data.length == 0) { + _page--; + _refreshController.loadNoData(); + } else { + list.addAll(data); + _refreshController.loadComplete(); + } + setState(() {}); + } + + void _onLoading() async { + _page++; + getNewData(addList); + } + + @override + void dispose() { + tabCtrl.dispose(); + _refreshController.dispose(); + if (_conectionSubscription != null) { + _conectionSubscription.cancel(); + _conectionSubscription = null; + } + if (_purchaseUpdatedSubscription != null) { + _purchaseUpdatedSubscription.cancel(); + _purchaseUpdatedSubscription = null; + } + + if (_purchaseErrorSubscription != null) { + _purchaseErrorSubscription.cancel(); + _purchaseErrorSubscription = null; + } + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + Widget content = Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + leading: CustomUI.buildCustomLeading(context), + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + widget.type == 1 + ? I18n.of(context).my_money_info + : I18n.of(context).get_money_detail, + textScaleFactor: 1.0, + ), + centerTitle: true, + ), + body: SafeArea(child: showCoin()), + ); + return content; + //return CustomUI.buildPageLoading(context, content, !isLoadingFish); + } + + Widget showCoin() { + return Scaffold( + body: SafeArea( + child: Center( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: _buildCoinBody(), + ), + ))); + } + + void _onRefresh() async { + _page = 1; + getNewData(initList); + } + + void initList(data) { + list.clear(); + if (data != null) { + list.addAll(data); + } + setState(() {}); + } + + getNewData(callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + 'type': widget.type, + }; + data['sign'] = TokenMgr().getSign(data); + data["page"] = _page; + data['rows'] = rows; + + Response res = await HttpUtil().post('wallet/balance/detail', data: data); + var resData = res.data; + _refreshController.refreshCompleted(); + print(resData); + if (resData['code'] == 0) { + callback(resData['data']); + } else { + showToast(resData['msg']); + } + } + + bool isAdd(int type) { + if (widget.type == 1) { + return type == 1 || + type == 2 || + type == 3 || + type == 12 || + type == 13 || + type == 14; + } else { + return !(type == 1 || type == 2); + } + } + + //钱包通知 + Widget _buildMoneyInfo(data) { + String imgUrl = data['HeadImg'] == null || + data['HeadImg'] == '' || + data['ChangeUserId'] == 0 + ? UserData().basicInfo.headimgurl + : data['HeadImg']; + + return _ConversationItem( + conversation: Conversation( + avatar: imgUrl, + title: '', + desc: WebData().getLoginTime(context, data['CreateTime']), + updateAt: '', + ), + bgColor: Constants.MoneyGradient, + isInCome: widget.type == 2, + money: isAdd(data['DetailType']) ? data['Value'] : -data['Value'], + title: RichTitle.getRichTitleWidget(data, context, + widget.type == 1 ? InfoType.MyMoney : InfoType.IncomeMoney, + titleStyle: TextStyle(fontSize: 12, color: const Color(0XFF7F7F7F)), + nameStyle: TextStyle( + fontWeight: FontWeight.normal, + fontSize: 13, + color: Constants.BlackTextColor)), + callback: () { + if (data['ChangeUserId'] != 0) { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: data['UserId'] == UserData().basicInfo.userId + ? data['ChangeUserId'] + : data['UserId'], + ); + }, + ), + ); + } + }, + ); + } + + Widget _renderRow(BuildContext context, int index) { + if (index < list.length) { + var userInfo = list[index]; + Widget result = _buildMoneyInfo(userInfo); + if (index == 0) { + result = Padding(padding: EdgeInsets.only(top: 10), child: result); + } + + return result; + } + return Container(); + } + + Widget _buildCoinBody() { + return SmartRefresher( + enablePullDown: true, + enablePullUp: true, + header: MaterialClassicHeader(), + footer: CustomUI.buildLoadingFooter(), + controller: _refreshController, + onRefresh: _onRefresh, + onLoading: _onLoading, + child: (_refreshController.headerStatus == RefreshStatus.completed && + list.length == 0) + ? CustomUI.buildNoData(context) + : ListView.builder( + itemBuilder: _renderRow, + itemCount: list.length, + ), + ); + } + + static String currentGoodsId = ''; + static StreamSubscription _conectionSubscription, + _purchaseUpdatedSubscription, + _purchaseErrorSubscription; + + ///ios 内购初始化 + static Future initPayConf(BuildContext context) async { + if (_purchaseErrorSubscription != null) { + return; + } + + // prepare + print('initPayConf -------- start: '); + var result = await FlutterInappPurchase.instance.initConnection; + print('initPayConf -------- result: $result'); + FlutterInappPurchase.instance.clearTransactionIOS(); + + _conectionSubscription = + FlutterInappPurchase.connectionUpdated.listen((connected) { + print('connected: $connected'); + }); + + _purchaseUpdatedSubscription = + FlutterInappPurchase.purchaseUpdated.listen((productItem) { + print('支付成功,成功回调 ------ purchase-updated: $productItem'); +// showToast('支付成功,成功回调 ------ purchase-updated: $productItem'); + if (productItem.transactionReceipt != null && + productItem.transactionReceipt.isNotEmpty) { + HttpUtil().createOrder(currentGoodsId, productItem.transactionReceipt, + productItem.purchaseToken, + context: context); + + showToast(I18n.of(context).payment_successful); + } + Navigator.of(context).pop(); + }); + + _purchaseErrorSubscription = + FlutterInappPurchase.purchaseError.listen((purchaseError) { +// showToast('支付失败回调 -------- purchase-error: $purchaseError'); + FlutterInappPurchase.instance.clearTransactionIOS(); + Navigator.of(context).pop(); + }); + } +} diff --git a/lib/home/money_picture_view.dart b/lib/home/money_picture_view.dart new file mode 100644 index 0000000..ab7d35e --- /dev/null +++ b/lib/home/money_picture_view.dart @@ -0,0 +1,146 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; + +class MoneyPicture extends StatefulWidget { + @required + final List imageList; + + MoneyPicture({Key key, this.imageList}) : super(key: key); + + _MoneyPictureState createState() => _MoneyPictureState(); +} + +class _MoneyPictureState extends State { + int selectId = 0; + + Widget _buildImg(data) { + var width = (MediaQuery.of(context).size.width - 30) / 3; + return InkWell( + onTap: () { + this.setState(() { + if (selectId == data['Id']) { + selectId = 0; + } else { + selectId = data['Id']; + } + }); + }, + child: Stack(children: [ + Container( + decoration: BoxDecoration(borderRadius: BorderRadius.circular(2.0)), + width: width, + height: width, + padding: EdgeInsets.all(5), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: CachedNetworkImage( + imageUrl: data['ImgUrl'] == null ? "" : data['ImgUrl'], + placeholder: CustomUI.buildImgLoding, + fit: BoxFit.cover, + ), + )), + Positioned( + right: 0, + child: Checkbox( + value: data['Id'] == selectId, + activeColor: Colors.blue, + onChanged: (bool val) { + // val 是布尔值 + this.setState(() { + if (selectId == data['Id']) { + selectId = 0; + } else { + selectId = data['Id']; + } + }); + }, + )), + ]), + ); + } + + @override + void initState() { + super.initState(); + + for (int i = 0; i < widget.imageList.length; i++) { + var element = widget.imageList[i]; + if (element['Type'] == PhotoType.money.index || + element['Type'] == PhotoType.destroyMoney.index) { + selectId = element['Id']; + } + } + } + + @override + Widget build(BuildContext context) { + var list = widget.imageList.map((data) { + return _buildImg(data); + }).toList(); + return Scaffold( + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + leading: CustomUI.buildCustomLeading(context), + title: Text( + I18n.of(context).set_photo, + style: TextStyle(color: AppColors.NewAppbarTextColor), + textScaleFactor: 1.0, + ), + actions: [ + Container( + alignment: Alignment.center, + child: new InkWell( + child: new Padding( + padding: + EdgeInsets.only(right: 15, left: 15, top: 10, bottom: 10), + child: new Text(I18n.of(context).determine, + textScaleFactor: 1.0, + style: Constants.AppBarActionTextStyle), + ), + onTap: () async { + Map rdata = { + "userId": UserData().basicInfo.userId, + "Id": selectId, + }; + rdata['sign'] = TokenMgr().getSign(rdata); + + Response res = await HttpUtil().post( + 'user/setting/photosprice', + data: rdata, + isShowLoading: true); + + Map resData = res.data; + if (resData['code'] == 0) { + MessageMgr().emit('refresh_photo'); + Navigator.of(context).pop(); + } + }, + ), + ) + ], + centerTitle: true, + ), + body: SafeArea( + child: Container( + padding: EdgeInsets.only(left: 10, top: 10, bottom: 10), + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + //alignment: Alignment.center, + child: SingleChildScrollView( + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + children: list, + ), + )), + )); + } +} diff --git a/lib/home/my_qr.dart b/lib/home/my_qr.dart new file mode 100644 index 0000000..4e0b7d5 --- /dev/null +++ b/lib/home/my_qr.dart @@ -0,0 +1,127 @@ +import 'dart:convert'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:qr_flutter/qr_flutter.dart'; + +class MyQr extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Container( + alignment: Alignment.center, + margin: EdgeInsets.only(top: 55.5, left: 25, right: 25), + height: 400, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _head(context), + _qrImg(), + Container( + padding: EdgeInsets.all(20), + child: Text( + I18n.of(context).scan_and_add, + style: TextStyle(fontSize: 12.5), + ), + ) + ], + ), + ); + } + + _qrImg() { + //var headImg = UserData().basicInfo.headimgurl; + final size = 205.5; + + var dayAfter = + new DateTime.now().add(new Duration(minutes: 5)).millisecondsSinceEpoch; + var myId = UserData().basicInfo.userId; + final groupIdAndTime = 'type=0&sessionId=$myId&expirationTime=$dayAfter'; + + var encodeStr = base64Encode(utf8.encode(groupIdAndTime)); + + return QrImage( + data: 'https://henho.jphgames.com/?$encodeStr', + version: QrVersions.auto, + size: size, + ); + } + + _head(BuildContext context) { + var userInfo = UserData().basicInfo; + var headImg = userInfo.headimgurl; + + var name = Provider.of(context) + .getRefName(userInfo.userId, userInfo.nickName); + + var isMan = userInfo.sex == 1; + + var city = userInfo.city; + var country = userInfo.country; + return Container( + padding: EdgeInsets.all(20), + child: Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Container( + width: 60, + height: 60, + child: headImg == null || headImg == '' + ? Image.asset(Constants.DefaultHeadImgUrl) + : CachedNetworkImage( + imageUrl: headImg, + placeholder: (context, url) => + Image.asset(Constants.DefaultHeadImgUrl)))), + SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + constraints: BoxConstraints(maxWidth: 170), + child: Text(name, + textScaleFactor: 1.0, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Constants.BlackTextColor, + fontWeight: FontWeight.w500, + fontSize: 16))), + SizedBox(width: 5), + Icon( + IconData( + isMan ? 0xe639 : 0xe638, + fontFamily: 'iconfont', + ), + color: isMan + ? const Color(0xff0072ff) + : const Color(0xffff0486), + size: 13, + ) + ], + ), + //地址 + SizedBox(height: 10), + fixedText( + country == 'China' + ? '${WebData().getCountry(country)}' + : '${WebData().getCountry(country)} ${WebData().getCity(city)}', + fontSize: 11, + color: Constants.GreyTextColor) + ], + ) + ], + )); + } +} diff --git a/lib/home/new_friends.dart b/lib/home/new_friends.dart new file mode 100644 index 0000000..f8a5021 --- /dev/null +++ b/lib/home/new_friends.dart @@ -0,0 +1,382 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/conversation_table.dart'; +import 'package:dio/dio.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import 'ProfilePage.dart'; + +class _ContactItem extends StatelessWidget { + _ContactItem( + {@required this.avatar, + @required this.title, + @required this.userId, + this.groupTitle, + this.onPressed, + this.gradient, + this.iconCode, + this.applyId, + this.isShowDivder: true, + this.state}); + final int userId; + final int iconCode; + final String avatar; + final String title; + final String groupTitle; + final VoidCallback onPressed; + final Gradient gradient; + final bool isShowDivder; + final int state; + final int applyId; + + static const double MARGIN_VERTICAL = 10.0; + static const double GROUP_TITLE_HEIGHT = 24.0; + + @override + Widget build(BuildContext context) { + Widget _avatarIcon; + if (iconCode == null) { + _avatarIcon = ClipRRect( + borderRadius: BorderRadius.circular(6), + child: CachedNetworkImage( + imageUrl: this.avatar, + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + )); + } else { + _avatarIcon = Container( + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + decoration: BoxDecoration( + gradient: gradient, borderRadius: BorderRadius.circular(6)), + child: Icon( + IconData(this.iconCode, fontFamily: Constants.IconFontFamily), + color: Colors.white, + ), + ); + } + + Widget _button = Container( + padding: const EdgeInsets.symmetric( + vertical: MARGIN_VERTICAL, horizontal: 16.0), + decoration: BoxDecoration(color: Colors.white), + child: Row( + children: [ + _avatarIcon, + SizedBox(width: 10.0), + Expanded(child: Text(title)), + state == 1 + ? Container( + padding: EdgeInsets.symmetric(horizontal: 21, vertical: 7), + child: Text( + I18n.of(context).added, + style: TextStyle(color: const Color(0xFF8A8B8B)), + ), + ) + : (state == 0 + ? Container( + padding: + EdgeInsets.symmetric(horizontal: 21, vertical: 7), + child: Text( + I18n.of(context).check, + style: TextStyle(color: Constants.BlueTextColor), + ), + ) + : Container( + padding: + EdgeInsets.symmetric(horizontal: 21, vertical: 7), + child: Text( + I18n.of(context).rejected, + style: TextStyle(color: const Color(0xFF8A8B8B)), + ), + )), + ], + ), + ); + + //分组标签 + Widget _itemBody; + if (this.groupTitle != null) { + _itemBody = Column( + children: [ + Container( + height: GROUP_TITLE_HEIGHT, + padding: EdgeInsets.only(left: 16.0, right: 16.0), + color: const Color(AppColors.ContactGroupTitleBgColor), + alignment: Alignment.centerLeft, + child: + Text(this.groupTitle, style: AppStyles.GroupTitleItemTextStyle), + ), + _button, + ], + ); + } else { + _itemBody = _button; + } + + return InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: userId, + addMode: state == 0 ? 2 : 0, + applyId: applyId, + ); + }, + ), + ); + }, + child: Container( + color: Colors.white, + child: Column( + children: [ + _itemBody, + isShowDivder + ? Container( + height: 1, + color: const Color(0xFFF3F3F3), + margin: EdgeInsets.only( + left: 26 + Constants.ContactAvatarSize), + ) + : Container() + ], + ))); + } +} + +class NewFriendsPage extends StatefulWidget { + @override + _NewFriendsPageState createState() => _NewFriendsPageState(); +} + +class _NewFriendsPageState extends State { + String _currentLetter = ''; + ScrollController _scrollController; + TextEditingController _txtCtrl = new TextEditingController(); + bool _hasdeleteIcon = false; + + List searchList = []; + + List friendList = []; + + @override + void initState() { + super.initState(); + + print('NewFriendsPage initState'); + + getNewFriendList(); + _scrollController = new ScrollController(); + MessageMgr().on('do_friend_apply', messageApply); + } + + messageApply(data) { + for (int i = 0; i < friendList.length; i++) { + if (friendList[i].friendId == data['userId']) { + setState(() { + friendList[i].state = data['state']; + }); + break; + } + } + } + + getNewFriendList() async { + Map data = { + "userId": UserData().basicInfo.userId, + "type": 2, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = + await HttpUtil().post('friendship/newFriends/record', data: data); + Map resData = res.data; + print(resData['data']); + if (resData['code'] == 0 && resData['data'] != null) { + resData['data'].forEach((f) { + var friend = FriendModel.fromApplyServerJson(f); + if (friend.friendId != UserData().basicInfo.userId) + friendList.add(friend); + }); + setState(() {}); + } + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + MessageMgr().off('do_friend_apply', messageApply); + } + + @override + Widget build(BuildContext context) { + final List _body = []; + + if (!_hasdeleteIcon) { + _body.add(ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + int _contactIndex = index; + bool _isGroupTitle = true; + FriendModel _contact = friendList[_contactIndex]; + + bool isThreeDay = WebData().isThreeDayAgo(_contact.creatTime); + + if (_contactIndex >= 1 && + WebData().isThreeDayAgo(_contact.creatTime) == + WebData() + .isThreeDayAgo(friendList[_contactIndex - 1].creatTime)) { + _isGroupTitle = false; + } + + return _ContactItem( + userId: _contact.friendId, + avatar: _contact.avatar, + title: _contact.name, + state: _contact.state, + isShowDivder: true, + applyId: _contact.applyId, + groupTitle: _isGroupTitle + ? (isThreeDay + ? I18n.of(context).before_three_day + : I18n.of(context).after_three_day) + : null); + }, + itemCount: friendList.length, + )); + } else { + _body.add(ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + FriendModel _contact = searchList[index]; + + return _ContactItem( + userId: _contact.friendId, + avatar: _contact.avatar, + title: _contact.name, + state: _contact.state, + isShowDivder: true, + applyId: _contact.applyId, + groupTitle: null); + }, + itemCount: searchList.length, + )); + } + + if (_currentLetter != null && + _currentLetter.isNotEmpty && + !_hasdeleteIcon) { + _body.add(Center( + child: Container( + width: Constants.IndexLetterBoxSize, + height: Constants.IndexLetterBoxSize, + decoration: BoxDecoration( + color: AppColors.IndexLetterBoxBgColor, + borderRadius: BorderRadius.all( + Radius.circular(Constants.IndexLetterBoxRadius)), + ), + child: Center( + child: + Text(_currentLetter, style: AppStyles.IndexLetterBoxTextStyle), + ), + ), + )); + } + + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + I18n.of(context).new_friends, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + elevation: 1, + bottom: PreferredSize( + preferredSize: Size.fromHeight(49), + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.only(bottom: 14, left: 12.5, right: 12.5), + height: 35, + decoration: BoxDecoration( + color: const Color(0xFFEEEEEE), + borderRadius: BorderRadius.all(Radius.circular(8))), + child: TextField( + keyboardAppearance: Brightness.light, + keyboardType: TextInputType.text, + textInputAction: TextInputAction.search, + controller: _txtCtrl, + maxLines: 1, + style: TextStyle( + textBaseline: TextBaseline.alphabetic, fontSize: 14.5), + autofocus: false, + inputFormatters: [ + LengthLimitingTextInputFormatter(50), + ], + decoration: InputDecoration( + hintText: I18n.of(context).search, + hintStyle: TextStyle(fontSize: 14.5), + prefixIcon: Icon( + IconData( + 0xe664, + fontFamily: Constants.IconFontFamily, + ), + color: const Color(0xFFA0A0A0), + size: 18, + ), + suffixIcon: Padding( + padding: EdgeInsetsDirectional.only( + start: 2.0, end: _hasdeleteIcon ? 20.0 : 0), + child: _hasdeleteIcon + ? new InkWell( + onTap: (() { + setState(() { + WidgetsBinding.instance + .addPostFrameCallback( + (_) => _txtCtrl.clear()); + _hasdeleteIcon = false; + }); + }), + child: Icon( + Icons.clear, + size: 18.0, + color: Constants.BlackTextColor, + )) + : new Text('')), + filled: true, + fillColor: Colors.transparent, + border: InputBorder.none, + ), + onChanged: (str) async { + setState(() { + if (str.isEmpty) { + _hasdeleteIcon = false; + } else { + _hasdeleteIcon = true; + searchList = CustomUI().getSearchResult( + str, friendList == null ? [] : friendList); + } + }); + }, + onEditingComplete: () {}), + )), + ), + body: Stack( + children: _body, + )); + } +} diff --git a/lib/home/qr_scanner_overlay.dart b/lib/home/qr_scanner_overlay.dart new file mode 100644 index 0000000..b421d22 --- /dev/null +++ b/lib/home/qr_scanner_overlay.dart @@ -0,0 +1,154 @@ +import 'package:flutter/material.dart'; + +class ScanImageView extends StatefulWidget { + final Widget child; + final Color scanColor; + final Rect scanRect; + + const ScanImageView({Key key, this.child, this.scanRect, this.scanColor}) + : super(key: key); + + @override + _ScanImageViewState createState() => _ScanImageViewState(); +} + +class _ScanImageViewState extends State + with TickerProviderStateMixin { + AnimationController controller; + + @override + void initState() { + super.initState(); + controller = AnimationController( + vsync: this, duration: Duration(milliseconds: 1000)); + + Future.delayed(Duration(milliseconds: 600), () { + controller.repeat(reverse: true); + }); + } + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: controller, + builder: (BuildContext context, Widget child) => CustomPaint( + foregroundPainter: _ScanPainter( + controller.value, widget.scanColor, widget.scanRect), + child: widget.child, + willChange: false, + )); + } +} + +class _ScanPainter extends CustomPainter { + final double value; + final Color scanColor; + final Rect scanRect; + + _ScanPainter(this.value, this.scanColor, this.scanRect); + + Paint _paint; + + @override + void paint(Canvas canvas, Size size) { + if (_paint == null) { + initPaint(); + } + double borderOffset = 3; + double _borderLength = 20; + final cutInnerRect = Rect.fromLTRB( + scanRect.left + borderOffset / 2, + scanRect.top + borderOffset / 2, + scanRect.right - borderOffset / 2, + scanRect.bottom - borderOffset / 2); + + final Path topLeft = Path() + ..moveTo(cutInnerRect.left, cutInnerRect.top + _borderLength) + ..lineTo(cutInnerRect.left, cutInnerRect.top) + ..lineTo(cutInnerRect.left + _borderLength, cutInnerRect.top); + + final Path bottomLeft = Path() + ..moveTo(cutInnerRect.left, cutInnerRect.bottom - _borderLength) + ..lineTo(cutInnerRect.left, cutInnerRect.bottom) + ..lineTo(cutInnerRect.left + _borderLength, cutInnerRect.bottom); + + final Path topRight = Path() + ..moveTo(cutInnerRect.right, cutInnerRect.top + _borderLength) + ..lineTo(cutInnerRect.right, cutInnerRect.top) + ..lineTo(cutInnerRect.right - _borderLength, cutInnerRect.top); + + final Path bottomRight = Path() + ..moveTo(cutInnerRect.right, cutInnerRect.bottom - _borderLength) + ..lineTo(cutInnerRect.right, cutInnerRect.bottom) + ..lineTo(cutInnerRect.right - _borderLength, cutInnerRect.bottom); + + final borderPaint = Paint() + ..color = scanColor + ..style = PaintingStyle.stroke + ..strokeWidth = borderOffset; + + _paint.color = Colors.blueAccent; + _paint.strokeWidth = 1; + final scanLineRect = Rect.fromLTWH( + scanRect.left + 10, + scanRect.top + 10 + (value * (scanRect.height - 20)), + scanRect.width - 20, + 1); + + _paint.shader = LinearGradient(colors: [ + Colors.lightBlue, + Colors.blue, + Colors.lightBlue, + ], stops: [ + 0.0, + 0.5, + 1, + ]).createShader(scanLineRect); + + final backgroundPaint = Paint() + ..color = const Color.fromRGBO(0, 0, 0, 50) + ..style = PaintingStyle.fill; + + final boxPaint = Paint() + ..color = scanColor + ..style = PaintingStyle.fill + ..blendMode = BlendMode.dstOut; + + canvas.saveLayer( + Rect.fromLTWH(0, 0, size.width, size.height), + backgroundPaint, + ); + canvas + ..drawRect( + Rect.fromLTWH(0, 0, size.width, size.height), + backgroundPaint, + ) + ..drawRect(scanRect, boxPaint) + ..drawPath(topLeft, borderPaint) + ..drawPath(bottomLeft, borderPaint) + ..drawPath(topRight, borderPaint) + ..drawPath(bottomRight, borderPaint) + ..drawRect(scanLineRect, _paint) + ..restore(); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return true; + } + + void initPaint() { + _paint = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = 1 + ..isAntiAlias = true + ..strokeCap = StrokeCap.round + ..strokeJoin = StrokeJoin.round; + } +} diff --git a/lib/home/qr_scanner_view.dart b/lib/home/qr_scanner_view.dart new file mode 100644 index 0000000..6772a6e --- /dev/null +++ b/lib/home/qr_scanner_view.dart @@ -0,0 +1,262 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/qr_scanner_overlay.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_qr_reader/flutter_qr_reader.dart'; +import 'package:flutter_qr_reader/qrcode_reader_view.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import 'join_group_confirm.dart'; + +class QrScannerPage extends StatefulWidget { + @override + _QrScannerPageState createState() => _QrScannerPageState(); +} + +class _QrScannerPageState extends State + with SingleTickerProviderStateMixin { + String scanImgPath; + GlobalKey qrViewKey = GlobalKey(); + + AnimationController _animationController; + Animation _animation; + QrReaderViewController qrReaderViewController; + @override + void initState() { + super.initState(); + + _animationController = new AnimationController( + duration: Duration(milliseconds: 600), vsync: this); + + _animation = Tween(begin: 1.0, end: 0.45).animate(_animationController) + ..addListener(() { + //这行如果不写,没有动画效果 + setState(() {}); + }); + + _animationController.forward(); + } + + bool isScan = false; + + @override + void dispose() { + qrReaderViewController = null; + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final Size size = MediaQuery.of(context).size; + final double scanWidth = 250; + final double borderWidth = 5; + final screenRect = Rect.fromLTWH( + size.width / 2 - scanWidth / 2 + borderWidth, + size.height / 2 - + scanWidth / 2 + + borderWidth - + kBottomNavigationBarHeight, + scanWidth - 2 * borderWidth, + scanWidth - 2 * borderWidth, + ); + + return Scaffold( + appBar: AppBar( + leading: IconButton( + iconSize: 22, + icon: Icon( + Icons.arrow_back_ios, + color: Colors.white, + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + backgroundColor: Colors.black, + title: + Text(I18n.of(context).scan, style: TextStyle(color: Colors.white)), + centerTitle: true, + ), + backgroundColor: Colors.black.withOpacity(_animation.value), + body: ScanImageView( + scanColor: Colors.blueAccent, + scanRect: screenRect, + child: Stack( + alignment: Alignment.center, + children: [ + scanImgPath == null + ? QrReaderView( + width: size.width, + height: size.height, + callback: (container) { + qrReaderViewController = container; + + Future.delayed(Duration(milliseconds: 600), () { + qrReaderViewController.startCamera(onQrBack); + }); + }, + ) + : SizedBox.expand( + child: Image.file( + File(scanImgPath), + fit: BoxFit.contain, + )), + Positioned( + left: 0, + right: 0, + bottom: 0, + child: Container( + color: Colors.black, + padding: EdgeInsets.symmetric(vertical: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _iconButton( + IconData(0xe658, + fontFamily: Constants.IconFontFamily), + I18n.of(context).my_qr, () { + AppNavigator.pushQrPage(context); + }), + _iconButton( + IconData(0xe626, + fontFamily: Constants.IconFontFamily), + I18n.of(context).picture, () async { + if (await CustomUI.showPhotoPermissionSetting( + context)) { + _scanImage(); + } + }) + ], + ), + )) + ], + )), + ); + } + + Future _scanImage() async { + stopScan(); + + print('_scanImage 开始'); + + var image = await ImagePicker.pickImage(source: ImageSource.gallery); + if (image == null) { + startScan(); + return; + } + setState(() { + scanImgPath = image.path; + }); + final rest = await FlutterQrReader.imgScan(image); + + print('_scanImage $rest'); + + onScan(rest); + } + + void startScan() { + isScan = false; + qrReaderViewController.startCamera(onQrBack); + } + + void stopScan() { + qrReaderViewController.stopCamera(); + } + + onScan(String result) { + if (result == null || result.length == 0) { + return; + } + print('扫描 $result'); + stopScan(); + Navigator.of(context).pop(); + + if (result.startsWith('https://henho.jphgames.com/')) { + result = result.replaceFirst('https://henho.jphgames.com/?', ''); + result = utf8.decode(base64Decode(result)); + result = 'https://henho.jphgames.com/?' + result; + var url = Uri.parse(result); + var type = int.parse(url.queryParameters['type']); + + int expirationTime = int.parse(url.queryParameters['expirationTime']); + int curTime = DateTime.now().millisecondsSinceEpoch; + print('过期时间$expirationTime'); + + if (curTime > expirationTime) { + showToast(I18n.of(context).qr_outtime); + return; + } + if (type == 1) { + var targetId = int.parse(url.queryParameters['sessionId']); + //群二维码 + print('群二维码'); + GroupInfoMgr().getGroupInfo(targetId, isSave: false).then((groupInfo) { + print('--------------------'); + print(groupInfo); + if (groupInfo == null) { + showToast(I18n.of(context).no_goupr_info); + return; + } + Navigator.push(LoadingManage.context, + MaterialPageRoute(builder: (BuildContext context) { + return JoinGroupConfirmPage( + groupInfoModel: groupInfo, + ); + })); + }); + } else { + //个人二维码 + print('个人二维码'); + + var targetId = int.parse(url.queryParameters['sessionId']); + if (targetId == UserData().basicInfo.userId) { + //我的页面 + MessageMgr().emit('Show My Profile'); + } else { + AppNavigator.pushProfileInfoPage(context, targetId, addMode: 1); + } + } + } else { + //其他的条码 + launch(result); + } + } + + onQrBack(String result, List points) { + print('扫描结果 $result'); + + if (isScan == true) return; + isScan = true; + stopScan(); + onScan(result); + } + + Widget _iconButton(IconData code, String iconName, Function onTap) { + return InkWell( + onTap: onTap, + child: Container( + child: Column(children: [ + Icon( + code, + size: 30, + color: Colors.white, + ), + SizedBox(height: 5), + Text( + iconName, + style: TextStyle(color: Colors.white), + ) + ]))); + } +} diff --git a/lib/home/qr_view.dart b/lib/home/qr_view.dart new file mode 100644 index 0000000..5b7e962 --- /dev/null +++ b/lib/home/qr_view.dart @@ -0,0 +1,23 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/my_qr.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:flutter/material.dart'; + +class QrPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + I18n.of(context).my_qr, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ), + body: MyQr()); + } +} diff --git a/lib/home/record_process.dart b/lib/home/record_process.dart new file mode 100644 index 0000000..950b7a5 --- /dev/null +++ b/lib/home/record_process.dart @@ -0,0 +1,88 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/counter_overlay.dart'; +import 'package:flutter/material.dart'; + +class RecordOverlay { + static String msg; + + static OverlayEntry entry; + + static show(BuildContext context, {String msgs = ''}) { + if (msgs == '') { + msgs = I18n.of(context).up_cancle; + } + msg = msgs; + var overlayState = Overlay.of(context); + OverlayEntry overlayEntry; + overlayEntry = new OverlayEntry(builder: (context) { + return buildToastLayout(); + }); + overlayState.insert(overlayEntry); + + if (entry != null) { + entry.remove(); + } + entry = overlayEntry; + return overlayEntry; + } + + static updateMsg(String newMsg) { + msg = newMsg; + if (entry != null) { + entry.markNeedsBuild(); + } + } + + static hide() { + print('删除overlay'); + entry?.remove(); + entry = null; + } + + static LayoutBuilder buildToastLayout() { + return LayoutBuilder(builder: (context, constraints) { + if (msg == null) { + msg = I18n.of(context).up_cancle; + } + return IgnorePointer( + ignoring: true, + child: Container( + child: Material( + color: Colors.white.withOpacity(0), + child: Container( + width: 200, + height: 120, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + CounterOverlay(), + Container( + child: Text( + "$msg", + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ], + ), + decoration: BoxDecoration( + color: Constants.BlackTextColor.withOpacity(0.8), + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10), + ), + // margin: EdgeInsets.only( + // bottom: constraints.biggest.height * 0.15, + // left: constraints.biggest.width * 0.2, + // right: constraints.biggest.width * 0.2, + // ), + ), + alignment: Alignment.center, + ), + ); + }); + } +} diff --git a/lib/home/rich_title.dart b/lib/home/rich_title.dart new file mode 100644 index 0000000..faf5ad3 --- /dev/null +++ b/lib/home/rich_title.dart @@ -0,0 +1,437 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class InfoType { + static const int Apply = 1; + static const int Evaluation = 2; + static const int System = 3; + static const int Radio = 4; + static const int Money = 5; + static const int IncomeMoney = 6; + static const int MyMoney = 7; +} + +class TitleItem { + String title = ''; + String name = ''; + String value = ''; + TitleItem({this.title, this.name, this.value}); +} + +class RichTitle { + static List getRichText(TitleItem titleItem, + {titleStyle, nameStyle}) { + if (nameStyle == null) { + nameStyle = TextStyle( + fontWeight: FontWeight.w500, color: Constants.BlackTextColor); + } + if (titleStyle == null) { + titleStyle = TextStyle(color: Constants.GreyTextColor); + } + + titleItem.title = titleItem.title == null ? '' : titleItem.title; + List list = titleItem.title.split('/s1'); + titleItem.name = titleItem.name == null ? '' : titleItem.name; + List child; + if (list == null) { + child = [ + TextSpan(text: titleItem.title, style: titleStyle), + ]; + } else { + child = list.length > 1 + ? [ + TextSpan(text: list[0] == '' ? '' : list[0], style: titleStyle), + TextSpan(text: titleItem.name, style: nameStyle), + TextSpan(text: list[1], style: titleStyle), + ] + : [ + TextSpan(text: titleItem.name, style: nameStyle), + TextSpan(text: list[0], style: titleStyle), + ]; + } + return child; + } + + static String getNormalText(TitleItem titleItem) { + List list = titleItem.title.split('/s1'); + titleItem.name = titleItem.name == null ? '' : titleItem.name; + String res = ''; + if (list == null) { + res = titleItem.title; + } else { + list.length > 1 + ? res = (list[0] == '' ? list[0] : list[0]) + titleItem.name + list[1] + : res = titleItem.name + list[0]; + } + return res; + } + + //申请 + static TitleItem _delApplyTitle(userInfo, BuildContext context) { + print(userInfo); + bool isMyself = userInfo['ApplyUserId'] == UserData().basicInfo.userId; + + String name = isMyself + ? Provider.of(context) + .getRefName(userInfo['UserId'], userInfo['UserName']) + : Provider.of(context) + .getRefName(userInfo['ApplyUserId'], userInfo['ApplyName']); + String title = isMyself + ? userInfo['Status'] == 1 + ? I18n.of(context).l15_days + : I18n.of(context).reject_reply + : I18n.of(context).view_application2; + if (userInfo['Type'] == 1) { + title = isMyself + ? I18n.of(context).applyed_friends + : I18n.of(context).apply_friends; + } + + return TitleItem(title: title, name: name); + } + + //评价 + static TitleItem _delEvaluateTitle(userInfo, BuildContext context) { + String name = WebData().getEvaluation(context, userInfo['Value']); + String title = ''; + if (userInfo['Status'] == 2) { + title = I18n.of(context).successful_appeal; + } else if (userInfo['Status'] == 3) { + title = I18n.of(context).successful_appeal1; + } else { + title = UserData().isMan() + ? I18n.of(context).received_evaluation + : I18n.of(context).received_evaluation2; + } + return TitleItem(title: title, name: name); + } + + //电台 + static TitleItem _delRadioTitle(data, BuildContext context) { + bool isProgram = data['ProgramType'] == 0; + String title; + switch (data['Type']) { + case 1: + title = isProgram + ? I18n.of(context).thumbs_up2 + : I18n.of(context).thumbs_up; + break; + case 2: + title = + isProgram ? I18n.of(context).comment2 : I18n.of(context).comment1; + break; + case 3: + title = I18n.of(context).signed_up; + break; + case 4: + title = isProgram + ? I18n.of(context).favorite_user + : I18n.of(context).favorite_user2; + break; + case 5: + title = I18n.of(context).replied_comment; + break; + default: + } + return TitleItem( + title: title, + name: Provider.of(context) + .getRefName(data['UserId'], data['UserName'])); + } + + //系统 + static TitleItem _delSystemTitle(data, BuildContext context) { + bool isMyself = data['UserId'] == UserData().basicInfo.userId; + + bool isPass = data['Status'] == 1; + String title = ''; + String name = Provider.of(context) + .getRefName(data['ReportedUserId'], data['ReportedUserName']); + switch (data['Type']) { + case 1: + title = isPass + ? I18n.of(context).upload_success + : I18n.of(context).re_upload; + break; + case 2: + title = isPass + ? I18n.of(context).successful_authentication + : I18n.of(context).authentication_failed; + break; + case 3: + if (isMyself) { + title = data['Status'] == 1 + ? I18n.of(context).report_success + : I18n.of(context).report_failure; + } else { + title = I18n.of(context).coin_returen; + } + break; + case 4: + title = data['Status'] == 1 + ? I18n.of(context).successful_application + : I18n.of(context).application_failed; + name = data['Status'] == 1 ? data['Content'].toString() : null; + break; + case 5: + title = '代理会员推送相关'; + break; + default: + } + return TitleItem(title: title, name: name); + } + + //钱包 + static TitleItem _delMoneyTitle(data, BuildContext context) { + String title = ''; + bool isMyself = data['UserId'] == UserData().basicInfo.userId; + String name = Provider.of(context) + .getRefName(data['ChangeUserId'], data['UserName']); + switch (data['DetailType'] == 10 ? data['Status'] : data['DetailType']) { + case 1: + title = I18n.of(context).get_coin2; + name = data['Value'].toString(); + break; + case 2: + title = I18n.of(context).buy_vip; + name = data['Value'].toString(); + break; + case 3: + title = isMyself + ? I18n.of(context) + .paid_you4 + .replaceFirst('/s2', data['Value'].toString()) + : I18n.of(context) + .paid_you + .replaceFirst('/s2', data['Value'].toString()); + break; + case 4: + title = isMyself + ? I18n.of(context) + .paid_you5 + .replaceFirst('/s2', data['Value'].toString()) + : I18n.of(context) + .paid_you2 + .replaceFirst('/s2', data['Value'].toString()); + break; + case 5: + title = I18n.of(context).buy_program; + name = data['Value'].toString(); + break; + case 6: + if (data['Status'] == 0) { + title = I18n.of(context).del_add_money; + } else if (data['Status'] == 1) { + title = I18n.of(context).adding_money; + } else { + title = I18n.of(context).withdraw_fail; + } + name = data['Value'].toString(); + break; + case 7: + title = + isMyself ? I18n.of(context).paid_you6 : I18n.of(context).paid_you3; + break; + case 8: + title = isMyself + ? I18n.of(context) + .give_other_money + .replaceFirst('/s2', data['Value'].toString()) + : I18n.of(context) + .get_other_money + .replaceFirst('/s2', data['Value'].toString()); + break; + case 9: + title = isMyself + ? I18n.of(context) + .give_red_money + .replaceFirst('/s2', data['Value'].toString()) + : I18n.of(context) + .get_red_money + .replaceFirst('/s2', data['Value'].toString()); + break; + case 11: + title = I18n.of(context).Redeem; + name = data['Value'].toString(); + break; + } + return TitleItem(title: title, name: name); + } + + //收入金额 + static TitleItem _delInMoneyTitle(data, BuildContext context) { + String title = ''; + String name = Provider.of(context) + .getRefName(data['UserId'], data['UserName']); + switch (data['DetailType']) { + case 1: + if (data['Status'] == 0) { + title = I18n.of(context).del_add_money; + } else if (data['Status'] == 1) { + title = I18n.of(context).withdraw_fail; + } else { + title = I18n.of(context).adding_money; + } + + name = data['Value'].toString(); + break; + case 2: + title = I18n.of(context).change_h_coin; + name = data['Value'].toString(); + break; + case 3: + title = I18n.of(context) + .get_other_money + .replaceFirst('/s2', data['Value'].toString()); + break; + case 4: + title = I18n.of(context) + .get_red_money + .replaceFirst('/s2', data['Value'].toString()); + break; + case 5: + title = I18n.of(context).paid_you3; + break; + case 6: + title = I18n.of(context) + .paid_you + .replaceFirst('/s2', data['Value'].toString()); + break; + case 7: + title = I18n.of(context) + .paid_you2 + .replaceFirst('/s2', data['Value'].toString()); + break; + case 8: + title = I18n.of(context).Representation_succes; + break; + case 9: + title = I18n.of(context).system_give; + break; + case 10: + title = I18n.of(context).exchange_fail; + break; + } + return TitleItem(title: title, name: name); + } + + //我的余额 + static TitleItem _delMyMoneyTitle(data, BuildContext context) { + String title = ''; + String name = Provider.of(context) + .getRefName(data['UserId'], data['UserName']); + switch (data['DetailType']) { + case 1: + title = I18n.of(context).get_coin2; + name = data['Value'].toString(); + break; + case 2: + title = I18n.of(context).hibok_exchange; + name = data['Value'].toString(); + break; + case 3: + title = I18n.of(context).bind_code_success; + break; + case 4: + title = I18n.of(context) + .give_other_money + .replaceFirst('/s2', data['Value'].toString()); + break; + case 5: + title = I18n.of(context) + .give_red_money + .replaceFirst('/s2', data['Value'].toString()); + break; + case 6: + title = I18n.of(context) + .paid_you6 + .replaceFirst('/s2', data['Value'].toString()); + break; + case 7: + title = I18n.of(context) + .paid_you4 + .replaceFirst('/s2', data['Value'].toString()); + break; + case 8: + title = I18n.of(context) + .paid_you5 + .replaceFirst('/s2', data['Value'].toString()); + break; + case 9: + title = I18n.of(context).buy_vip; + name = data['Value'].toString(); + break; + case 10: + title = I18n.of(context).translate_money; + name = data['Value'].toString(); + break; + case 11: + title = I18n.of(context).buy_program; + name = data['Value'].toString(); + break; + case 12: + title = I18n.of(context).Representation_succes; + break; + case 13: + title = I18n.of(context).system_back; + break; + case 14: + title = I18n.of(context).system_give; + break; + } + return TitleItem(title: title, name: name); + } + + static TitleItem _getTypeTitleItem(userInfo, BuildContext context, int type) { + var tileItem = TitleItem(); + switch (type) { + case InfoType.Apply: + tileItem = _delApplyTitle(userInfo, context); + break; + case InfoType.Radio: + tileItem = _delRadioTitle(userInfo, context); + break; + case InfoType.System: + tileItem = _delSystemTitle(userInfo, context); + break; + case InfoType.Money: + tileItem = _delMoneyTitle(userInfo, context); + break; + case InfoType.IncomeMoney: + tileItem = _delInMoneyTitle(userInfo, context); + break; + case InfoType.MyMoney: + tileItem = _delMyMoneyTitle(userInfo, context); + break; + case InfoType.Evaluation: + tileItem = _delEvaluateTitle(userInfo, context); + break; + default: + } + return tileItem; + } + + static Widget getRichTitleWidget(userInfo, BuildContext context, int type, + {titleStyle, nameStyle}) { + var tileItem = _getTypeTitleItem(userInfo, context, type); + return RichText( + text: TextSpan( + children: getRichText(tileItem, + titleStyle: titleStyle, nameStyle: nameStyle))); + } + + static String normalTitle(userInfo, BuildContext context, int type) { + if (userInfo == null) { + return ''; + } + var tileItem = _getTypeTitleItem(userInfo, context, type); + var res = getNormalText(tileItem); + int maxlength = 17; + return res.length > maxlength ? res.substring(0, maxlength) + '...' : res; + } +} diff --git a/lib/home/search_newfriend.dart b/lib/home/search_newfriend.dart new file mode 100644 index 0000000..3466ffa --- /dev/null +++ b/lib/home/search_newfriend.dart @@ -0,0 +1,34 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/global_search.dart'; +import 'package:chat/home/my_qr.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:flutter/material.dart'; + +class SearchNewFriendsPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: Text( + I18n.of(context).add_friends, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + bottom: CustomUI.buildSearchButton(context, () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return GlobalSearchPage( + type: GlobalSearchPageType.SearchNewFriends, + ); + }, + ), + ); + })), + body: MyQr()); + } +} diff --git a/lib/home/send_msg_state.dart b/lib/home/send_msg_state.dart new file mode 100644 index 0000000..62b5f50 --- /dev/null +++ b/lib/home/send_msg_state.dart @@ -0,0 +1,40 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:flutter/material.dart'; + +class SendMsgState extends StatefulWidget { + final int sessionId; + final int time; + SendMsgState({this.sessionId,this.time}); + @override + _SendMsgStateState createState() => _SendMsgStateState(); +} + +class _SendMsgStateState extends State { + @override + Widget build(BuildContext context) { + var sendCache = MsgHandler.sendCache; + for (var msg in sendCache) { + if (msg.sessionId == widget.sessionId && + msg.time == widget.time) { + + if (msg.state == MsgState.SendingFailed) { + return Padding( + padding: EdgeInsets.only(right: 10), + child: Icon(Icons.error_outline, + size: 12, color: Color(0xFFc0c0c0))); + } else if (msg.state <= MsgState.Sending) { + return Padding( + padding: EdgeInsets.only(right: 10), + child: Icon( + IconData(0xe657, fontFamily: Constants.IconFontFamily), + size: 12, + color: Color(0xFFc0c0c0))); + } + } + } + + return SizedBox(width: 0); + } +} \ No newline at end of file diff --git a/lib/home/service_view.dart b/lib/home/service_view.dart new file mode 100644 index 0000000..3a36fa2 --- /dev/null +++ b/lib/home/service_view.dart @@ -0,0 +1,372 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/list_msg_model.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class QuestionModel { + final String question; + final int index; + + QuestionModel({this.question, this.index}); + + QuestionModel.fromJson(Map json) + : question = json['Question'], + index = json['Number']; +} + +class ServiceMsgModel { + final bool isMe; + final List msg; + + ServiceMsgModel({this.isMe, this.msg}); +} + +class ServiceCenterPage extends StatefulWidget { + int questionIndex = -1; + ServiceCenterPage(this.questionIndex); + + @override + _ServiceCenterPageState createState() => _ServiceCenterPageState(); +} + +class _ServiceCenterPageState extends State { + final TextEditingController _textCtrl = new TextEditingController(); + + List questions = []; + ScrollController _scrollCtrl = new ScrollController(); + + ListModel _list; + GlobalKey _listKey = GlobalKey(); + + @override + void initState() { + super.initState(); + + _list = ListModel( + listKey: _listKey, + initialItems: [], + ); + + getAllQuestions(); + } + + @override + void dispose() { + _listKey = null; + _scrollCtrl.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + leading: CustomUI.buildCustomLeading(context), + title: Text( + I18n.of(context).help, + textScaleFactor: 1.0, + style: TextStyle(color: AppColors.NewAppbarTextColor), + ), + centerTitle: true, + ), + body: SafeArea( + child: Column( + children: [ + Expanded( + child: GestureDetector( + onTap: () { + print('隐藏FocusNode'); + FocusScope.of(context).requestFocus(FocusNode()); + setState(() {}); + }, + child: _buildMessageList())), + _buildTextComposer(), + ], + )), + ); + } + + getAllQuestions() async { + Map data = { + "language": UserData().language, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('message/staff/question', data: data); + var resData = res.data; + if (resData['code'] == 0) { + questions = resData['data'] + .map((v) => QuestionModel.fromJson(v)) + .toList(); + + String userName; + if (UserData().isMan()) { + userName = I18n.of(context).man_vi; + } else { + userName = I18n.of(context).women_vi; + } + var allTexts = ['$userName,${I18n.of(context).kf_tips}']; + for (var i = 0; i < questions.length; i++) { + allTexts.add(questions[i].question); + } + + _list.add(ServiceMsgModel(isMe: false, msg: allTexts)); + + ///自动发送提问 + if (widget.questionIndex != -1) { + _textCtrl.text = widget.questionIndex.toString(); + sendMessage(); + } + } + } + + buildQuestions(msg) { + if (questions == null) { + return Container(); + } + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ClipRRect( + child: Image.asset(R.assetsImagesServiceIcon), + borderRadius: BorderRadius.circular(8), + ), + SizedBox(width: 8), + Container( + width: Screen.width - 120, + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 5), + decoration: BoxDecoration( + color: Colors.white, borderRadius: BorderRadius.circular(10)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: msg + .map((text) => Container( + child: Text(text, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 13)), + )) + .toList())) + ], + ); + } + + getAnswerWith(int index) async { + Map data = {"language": UserData().language, "number": index}; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('message/staff/answer', data: data); + var resData = res.data; + if (resData['code'] == 0) { + _list.add(ServiceMsgModel(isMe: false, msg: [resData['data']])); + } else { + print(resData['msg']); + } + } + + buildAnswer(msg) { + String answer = msg[0]; + print('anser a$answer'); + String sign = ''; + bool isHttp = answer.trim().startsWith('http'); + + if (isHttp) { + answer = I18n.of(context).service_withdraw_tips; + Map data = { + "userId": UserData().basicInfo.userId, + "language": UserData().language, + }; + sign = TokenMgr().getSign(data); + print( + '@@@@@@ sign $sign ${UserData().basicInfo.userId} ${UserData().language}'); + } + + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ClipRRect( + child: Image.asset(R.assetsImagesServiceIcon), + borderRadius: BorderRadius.circular(8), + ), + SizedBox(width: 8), + Container( + width: Screen.width - 120, + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 5), + decoration: BoxDecoration( + color: Colors.white, borderRadius: BorderRadius.circular(10)), + child: isHttp + ? Container( + child: Column( + children: [ + Text(answer, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 13)), + SizedBox( + height: 6, + ), + GestureDetector( + child: Text(I18n.of(context).withdraw_tips, + textScaleFactor: 1.0, + style: + TextStyle(fontSize: 13, color: Colors.blue)), + onTap: () async { + String url = msg[0] + + '/Bank/Getlanguage?userId=${UserData().basicInfo.userId}&language=${UserData().language}&sign=$sign'; + print('url :$url'); + await launch(url); + }, + ), + ], + ), + ) + : Container( + child: Text(msg[0], + textScaleFactor: 1.0, style: TextStyle(fontSize: 13)), + )) + ], + ); + } + + _buildMessageList() { + return AnimatedList( + key: _listKey, + initialItemCount: _list.length, + controller: _scrollCtrl, + padding: EdgeInsets.symmetric(horizontal: 8, vertical: 10), + itemBuilder: _buildItem, + ); + } + + Widget _buildItem( + BuildContext context, int index, Animation animation) { + ServiceMsgModel msg = _list[index]; + + Widget item; + if (index == 0) { + item = buildQuestions(msg.msg); + } else { + if (msg.isMe) { + item = buildSendMsg(msg.msg.first); + } else { + item = buildAnswer(msg.msg); + } + } + + return SizeTransition( + sizeFactor: + CurvedAnimation(parent: animation, curve: Curves.decelerate), + axisAlignment: -2, + child: Padding(padding: EdgeInsets.only(bottom: 10), child: item)); + } + + Future _textMessageSubmitted(String text) async { + sendMessage(); + } + + buildSendMsg(msg) { + return Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + constraints: BoxConstraints(maxWidth: Screen.width - 120), + child: Text(msg, + textScaleFactor: 1.0, style: TextStyle(color: Colors.white)), + padding: EdgeInsets.symmetric(horizontal: 15, vertical: 12), + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.blue[200], + offset: Offset(0, 2), + blurRadius: 3.0), + ], + color: Color(0xFF377dfe), + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(15), + topLeft: Radius.circular(15), + bottomRight: Radius.circular(15), + )), + ), + SizedBox(width: 5), + Container( + width: 40, + height: 40, + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: CachedNetworkImage( + imageUrl: UserData().basicInfo.headimgurl, + placeholder: (context, url) => + Image.asset(R.assetsImagesDefaultNorAvatar), + ))), + ], + ); + } + + sendMessage() { + var text = _textCtrl.text; + if (text.length > 0) { + int index = int.parse(text); + + if (index > 0 && index <= questions.length) { + _list.add(ServiceMsgModel(isMe: true, msg: [text])); + + getAnswerWith(index); + + _textCtrl.clear(); + } else { + showToast(I18n.of(context).reinput); + } + } + } + + _buildTextComposer() { + return Container( + alignment: Alignment.center, + width: Screen.width, + child: Row( + children: [ + Expanded( + child: Container( + child: TextField( + keyboardAppearance: Brightness.light, + onSubmitted: _textMessageSubmitted, + controller: _textCtrl, + keyboardType: TextInputType.number, + cursorColor: Color.fromARGB(255, 0, 189, 96), + style: TextStyle( + fontSize: fixedFontSize(15), + textBaseline: TextBaseline.alphabetic), + ), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.circular(10), + ), + ), + ), + SizedBox(width: 5), + SizedBox( + child: OutlineButton( + child: Text(I18n.of(context).send, textScaleFactor: 1.0), + onPressed: sendMessage, + )) + ], + ), + padding: EdgeInsets.symmetric(horizontal: 10, vertical: 8), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(8), topRight: Radius.circular(8)), + ), + ); + } +} diff --git a/lib/home/splash_page.dart b/lib/home/splash_page.dart new file mode 100644 index 0000000..f69d124 --- /dev/null +++ b/lib/home/splash_page.dart @@ -0,0 +1,155 @@ +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sp_utils.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../data/constants.dart'; +import 'IndexPage.dart'; + +class SplashPage extends StatefulWidget { + @override + State createState() { + return SplashPageState(); + } +} + +class SplashBean { + String icon; + String title; + String content; + Color titleColor; + + SplashBean(this.icon, this.title, this.content, this.titleColor); +} + +class SplashPageState extends State { + List list = []; + + int currentIndex = 0; + PageController pageController; + + @override + void initState() { + super.initState(); + + list.add(SplashBean('assets/images/img_splash_1.png',I18n.of( LoadingManage.context).splash_tips1 , I18n.of( LoadingManage.context).splash_tips_content1, + Color(0xffEC527D))); + list.add(SplashBean('assets/images/img_splash_2.png', I18n.of( LoadingManage.context).splash_tips2, I18n.of( LoadingManage.context).splash_tips_content2, + Color(0xffB439EB))); + list.add(SplashBean('assets/images/img_splash_3.png', I18n.of( LoadingManage.context).splash_tips3, I18n.of( LoadingManage.context).splash_tips_content3, + Color(0xff2B79F7))); + + pageController = PageController( + initialPage: 0, + ); + + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + color: Colors.white, + child: SafeArea( + child: Container( + color: Colors.white, + child: Stack( + children: [ + PageView.builder( + controller: pageController, + itemBuilder: _buildItem, + itemCount: list.length, + onPageChanged: (int index) { + setState(() { + currentIndex = index; + }); + }, + ), + Container( + child: Column( + children: [ + Expanded(child: Container()), + currentIndex != 2 ? getIndicator() : Container(), + currentIndex == 2 + ? InkWell(onTap: ()async{ + await SPUtils.saveBool(Constants.Splash_OPENED, true); + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => IndexPage(), + ), + ); + + },child: Padding( + padding: EdgeInsets.only(bottom: 40), + child: Container( + padding: EdgeInsets.only(left: 16,right: 16,top: 5,bottom: 5), + decoration: BoxDecoration( + border: Border.all( + color: Color(0xff2B79F7), width: 1),borderRadius: BorderRadius.circular(16)), + child: Text(I18n.of(context).splash_go,style: TextStyle(fontSize: 18,color: Color(0xff2B79F7)),), + ), + ),) + : Container(), + ], + ), + ) + ], + ), + )), + ), + ); + } + + Widget getIndicator() { + List pointList = []; + for (int k = 0; k < list.length; k++) { + pointList.add(Padding( + padding: EdgeInsets.only(left: 6, right: 6), + child: ClipOval( + child: Container( + color: k == currentIndex ? Color(0xff2B79F7) : Color(0xffBFBEBE), + width: 10, + height: 10, + ), + ), + )); + } + + return Padding( + padding: EdgeInsets.only(bottom: 40), + child: Container( + width: Screen.width, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: pointList, + ), + ), + ); + } + + Widget _buildItem(BuildContext context, int index) { + SplashBean data = list[index]; + return Container( + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 30, bottom: 40), + child: Image.asset( + data.icon, + height: 400, + ), + ), + Text( + data.title, + style: TextStyle(color: data.titleColor, fontSize: 30), + ), + SizedBox(height: 6,), + Text(data.content, + style: TextStyle(color: Color(0xff999999), fontSize: 15)), + ], + ), + ); + } +} diff --git a/lib/home/translate_robot.dart b/lib/home/translate_robot.dart new file mode 100644 index 0000000..1179fd1 --- /dev/null +++ b/lib/home/translate_robot.dart @@ -0,0 +1,616 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/chat/record_view.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/data/robot_chat_mgr.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/keyboard_utils.dart'; +import 'package:chat/utils/net_state_widget.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/sound_util.dart'; +import 'package:chat/utils/upload_util.dart'; +import 'package:chat/utils/video_anim.dart'; +import 'package:chat/utils/wpop/w_popup_menu.dart'; +import 'package:flutter/material.dart'; +import 'package:chat/utils/PopUpMenu.dart' as myPop; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +//import 'package:menu/menu.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../r.dart'; + +const Color SendMsgBg = Color(0xFFD4F0FF); + +class TranslateRobotPage extends StatefulWidget { + @override + _TranslateRobotPageState createState() => _TranslateRobotPageState(); +} + +class _TranslateRobotPageState extends State { + final TextEditingController _textCtrl = TextEditingController(); + FocusNode editFocus = FocusNode(); + bool _isComposingMessage = false; + int curToLang = 1; + int curSourceLang = UserData().language; + ScrollController _scrollCtrl = ScrollController(); + + int curKeyboardIndex = -1; + List langList; + double keyboardHeight; + KeyboardBloc _bloc = KeyboardBloc(); + + @override + void initState() { + super.initState(); + + getKeyboardHeight(); + _bloc.start(); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + + langList = [ + I18n.of(context).english, + I18n.of(context).Vietnamese, + I18n.of(context).traditional_Chinese, + I18n.of(context).Simplified_Chinese, + I18n.of(context).Korean, + I18n.of(context).Japanese, + ]; + } + + @override + void dispose() { + editFocus?.unfocus(); + super.dispose(); + } + + getKeyboardHeight() async { + var sp = await SharedPreferences.getInstance(); + keyboardHeight = sp.getDouble(Constants.KeyboardHeight); + + if (keyboardHeight == null || keyboardHeight < 100) { + keyboardHeight = 280; + } + } + + hideKeyBoard() { + setState(() { + curKeyboardIndex = -1; + }); + } + + _langPopMenu(bool isSource) { + var curIndex = isSource ? curSourceLang : curToLang; + + return myPop.PopupMenuButton( + child: Container( + child: Row( + children: [ + fixedText(langList[curIndex], color: Colors.black, fontSize: 16), + Icon(IconData(0xe63b, fontFamily: Constants.IconFontFamily), + color: Colors.grey) + ], + ), + ), + offset: Offset(0, 100), + onSelected: (int index) { + if (curIndex != index) { + if (isSource) { + curSourceLang = index; + } else { + curToLang = index; + } + print('更换翻译语言'); + setState(() {}); + } + }, + itemBuilder: (BuildContext context) { + return List>.generate(langList.length, + (int i) { + return myPop.PopupMenuItem( + child: Container( + alignment: Alignment.center, + color: Colors.white, + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10), + child: Text(langList[i], + textScaleFactor: 1.0, + maxLines: 1, + style: TextStyle( + color: i == curIndex + ? Colors.blueAccent + : Color(AppColors.AppBarColor), + fontSize: 14)), + ), + value: i, + ); + }); + }); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: hideKeyBoard, + child: Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + title: Row( + mainAxisSize: MainAxisSize.min, + children: [ + _langPopMenu(true), + SizedBox(width: 10), + InkWell( + onTap: () { + var temp = curSourceLang; + curSourceLang = curToLang; + curToLang = temp; + setState(() {}); + }, + child: Container( + child: Icon( + IconData(0xe669, fontFamily: Constants.IconFontFamily), + size: 12, + ), + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 5), + ), + ), + SizedBox(width: 20), + _langPopMenu(false), + ], + ), + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ), + body: SafeArea( + child: Column( + children: [ + NetStateWidget(), + Expanded(child: _buildMessageList()), + _inputBar(), + ], + )), + )); + } + + Widget _buildMessageList() { + return Container( + alignment: Alignment.topCenter, + child: ListView.builder( + reverse: true, + shrinkWrap: true, + itemCount: RobotChatMgr().robotChatList.length, + controller: _scrollCtrl, + padding: EdgeInsets.all(8.0), + itemBuilder: _buildItem, + ), + ); + } + + Widget _buildItem(BuildContext context, int index) { + var chat = RobotChatMgr().robotChatList[index]; + + + List actionsFunc = []; + List actions = [I18n.of(context).delete]; + if (chat.type == 0) { + actions.add(I18n.of(context).copy); + } + actionsFunc.add(() { + RobotChatMgr().robotChatList.remove(chat); + setState(() {}); + }); + actionsFunc.add(() { + ClipboardData clipboardData = ClipboardData(text: chat.msgContent); + Clipboard.setData(clipboardData); + }); + + return WPopupMenu( + child: chat.isMe ? _buildMyMsg(chat) : _buildRobotMsg(chat), + actions: actions, + menuWidth: 200, + onValueChanged: (int value) { + print('选择的是$value个菜单'); + if (value >= 0 && value < actionsFunc.length) { + actionsFunc[value](); + } + }, + ); + + + } + + Widget _buildMyMsg(RobotChatModel msg) { + bool hasHeadImg = true; + if (UserData().basicInfo.headimgurl == null || + UserData().basicInfo.headimgurl.length == 0) { + hasHeadImg = false; + } + + return Container( + width: Screen.width, + margin: const EdgeInsets.symmetric(vertical: 10.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + msg.type == 0 ? _textMsg(msg) : _soundMsg(msg), + SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: hasHeadImg + ? CachedNetworkImage( + imageUrl: UserData().basicInfo.headimgurl, + width: 40, + height: 40, + ) + : SizedBox( + width: 40, + height: 40, + child: + Image.asset(R.assetsImagesDefaultNorAvatar))), + ], + ) + ])); + } + + Widget _soundMsg(RobotChatModel msg) { + double time = msg.extraInfo / 1000; + if (time > 60) { + time = 60.0; + } + bool isPlaying = false; + + var soundPath = msg.msgContent; + + isPlaying = SoundUtils().isPlaying(soundPath); + + return GestureDetector( + child: Container( + width: 120, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + alignment: Alignment.center, + padding: EdgeInsets.only(bottom: 2), + margin: EdgeInsets.only(right: 10), + width: 25.5, + height: 25.5, + decoration: BoxDecoration( + border: + Border.all(color: const Color(0xFF1B92C7), width: 0.5), + color: const Color(0xFF04A4FE), + shape: BoxShape.circle), + child: Icon( + IconData(isPlaying ? 0xe652 : 0xe653, + fontFamily: Constants.IconFontFamily), + size: isPlaying ? 15 : 18, + color: Colors.white, + ), + ), + isPlaying + ? Stack( + children: [ + Container( + height: 18, + width: 19, + ), + Positioned( + bottom: 0, + child: VideoAnim( + begin: 18, + start: 0.444, + end: 4.5, + )), + Positioned( + left: 7, + bottom: 0, + child: VideoAnim( + begin: 4.5, + end: 18, + )), + Positioned( + left: 14, + bottom: 0, + child: VideoAnim( + begin: 18, + end: 4.5, + )) + ], + ) + : Stack( + children: [ + Container( + height: 18, + width: 19, + ), + Positioned( + bottom: 0, child: CustomUI.buildAudioContaniner(12)), + Positioned( + left: 7, + bottom: 0, + child: CustomUI.buildAudioContaniner(4.5)), + Positioned( + left: 14, + bottom: 0, + child: CustomUI.buildAudioContaniner(18)) + ], + ), + Expanded(child: SizedBox()), + fixedText(time.toStringAsFixed(0), + color: Constants.BlackTextColor, fontSize: 16) + ], + ), + padding: EdgeInsets.symmetric(horizontal: 15, vertical: 12), + decoration: BoxDecoration( + color: SendMsgBg, + border: Border.all(color: Color(0xFFB9CBD7), width: 0.6), + borderRadius: BorderRadius.all(Radius.circular(8))), + ), + onTap: () async { + print('播放状态 : $isPlaying'); + + if (isPlaying) { + SoundUtils().pause(); + } else { + SoundUtils().play(soundPath, onPlayed: () { + if (mounted) { + setState(() {}); + } + }, complete: () { + if (mounted) { + setState(() {}); + } + }); + } + }, + ); + } + + Widget _textMsg(RobotChatModel msg) { + return Container( + constraints: BoxConstraints(maxWidth: Screen.width - 120), + child: fixedText(msg.msgContent, fontSize: 15, color: Colors.black), + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + decoration: BoxDecoration( + color: SendMsgBg, + border: Border.all(color: Color(0xFFB9CBD7), width: 0.6), + borderRadius: BorderRadius.all(Radius.circular(8))), + ); + } + + Widget _buildRobotMsg(RobotChatModel msg) { + return Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Container( + margin: const EdgeInsets.only(right: 8.0), + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: SizedBox( + width: 40, + height: 40, + child: Image.asset(R.assetsImagesRobot))), + ), + + ///todo + Container( + constraints: BoxConstraints(maxWidth: Screen.width - 120), + padding: EdgeInsets.symmetric(horizontal: 9, vertical: 10.5), + child: fixedText(msg.msgContent), + decoration: BoxDecoration( + border: Border.all(color: Color(0xFFDCDCDC), width: 0.5), + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(8))), + ) + ]); + } + +//输入框 + _inputBar() { + if (curKeyboardIndex != 0) { + if (editFocus.hasFocus) { + editFocus.unfocus(); + } + } else { + if (!editFocus.hasFocus) { + FocusScope.of(context).requestFocus(editFocus); + } + } + return GestureDetector( + onTap: () { + print('other keyboard'); + }, + child: Container( + width: Screen.width, + color: Colors.white, + child: Column( + children: [ + Container( + padding: EdgeInsets.symmetric(horizontal: 7, vertical: 7), + alignment: Alignment.topCenter, + decoration: BoxDecoration( + color: Colors.white, + border: + Border(top: BorderSide(color: Color(0xFFDFDFDF)))), + child: Row( + children: [ + //输入框 + Flexible( + child: Container( + child: TextField( + keyboardAppearance: Brightness.light, + onChanged: (String messageText) { + setState(() { + _isComposingMessage = _textCtrl.text.length > 0; + }); + }, + autofocus: false, + style: TextStyle( + fontSize: ScreenUtil().setSp(16), + textBaseline: TextBaseline.alphabetic), + maxLines: 3, + minLines: 1, + controller: _textCtrl, + textInputAction: TextInputAction.newline, + inputFormatters: [ + LengthLimitingTextInputFormatter(600) //限制长度 + ], + onSubmitted: _textMessageSubmitted, + focusNode: editFocus, + onTap: () { + setState(() { + curKeyboardIndex = 0; + }); + }, + decoration: InputDecoration( + hintText: I18n.of(context).input_content, + hintStyle: TextStyle( + color: const Color(0xffBDBDBD), fontSize: 16), + border: null, + contentPadding: EdgeInsets.only( + left: 5, right: 5, top: 8, bottom: 8), + ), + ), + ), + ), + SizedBox(width: 10), + _isComposingMessage + ? InkWell( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Icon( + Icons.send, + color: Color(0xFF087FF3), + size: 28, + )), + onTap: _sendTextMessage) + : InkWell( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Icon( + IconData(0xe64f, + fontFamily: Constants.IconFontFamily), + color: curKeyboardIndex == 1 + ? Color(0xFF0A80F3) + : Color(0xFF797A7C), + size: 28, + )), + onTap: () { + if (curKeyboardIndex == 1) { + setState(() { + curKeyboardIndex = 0; + }); + } else { + setState(() { + curKeyboardIndex = 1; + }); + } + }) + ], + ), + ), + Divider(height: 1, color: const Color(0xffE0E0E0)), + StreamBuilder( + stream: _bloc.stream, + builder: (BuildContext context, AsyncSnapshot snapshot) { + double keyHeight = MediaQuery.of(context).viewInsets.bottom; + if (keyHeight > 10) { + keyboardHeight = keyHeight; + UserData().setKeyboardHeight(keyHeight); + } + return Container( + width: double.infinity, + color: Colors.white, + height: curKeyboardIndex == 0 || curKeyboardIndex == 1 + ? keyboardHeight + : 0, + child: RecordView( + keyboardHeight: keyboardHeight, + sendMsg: _sendSoundMsg)); + }, + ) + ], + ))); + } + + showKeyBoard() { + setState(() { + curKeyboardIndex = 0; + }); + editFocus.requestFocus(); + //SystemChannels.textInput.invokeMethod('TextInput.show'); + } + + _sendSoundMsg(String soundPath, int duration) { + print('上传文件'); + + RobotChatModel model = RobotChatModel( + msgContent: soundPath, extraInfo: duration, isMe: true, type: 1); + RobotChatMgr().addSource(model); + setState(() {}); + + UploadUtil() + .commitTranslateSource(2, curSourceLang, curToLang, soundPath) + .then((tranStr) { + if (tranStr == null) { + showToast(I18n.of(context).translate_fail); + return; + } + RobotChatModel model = RobotChatModel(msgContent: tranStr, isMe: false); + RobotChatMgr().addSource(model); + if (mounted) { + setState(() {}); + } + }); + } + + _sendTextMessage() { + if (!checkMessage()) { + return; + } + var sendStr = _textCtrl.text; + + RobotChatModel model = RobotChatModel(msgContent: sendStr, isMe: true); + RobotChatMgr().addSource(model); + setState(() {}); + + UploadUtil() + .commitTranslateSource(1, curSourceLang, curToLang, sendStr) + .then((tranStr) { + if (tranStr == null) { + showToast(I18n.of(context).translate_fail); + return; + } + RobotChatModel model = RobotChatModel(msgContent: tranStr, isMe: false); + RobotChatMgr().addSource(model); + if (mounted) { + setState(() {}); + } + }); + + _textCtrl.clear(); + setState(() { + _isComposingMessage = false; + }); + } + + bool checkMessage() { + if (_textCtrl.text.length == 0) { + showToast(I18n.of(context).msg_not); + return false; + } + return true; + } + + Future _textMessageSubmitted(String text) async { + _sendTextMessage(); + } +} diff --git a/lib/home/unread_dot_widget.dart b/lib/home/unread_dot_widget.dart new file mode 100644 index 0000000..ab210b6 --- /dev/null +++ b/lib/home/unread_dot_widget.dart @@ -0,0 +1,79 @@ +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/home/ConversActionPage.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:flutter/material.dart'; + +import 'friend_page.dart'; + +class UnreadDot extends StatefulWidget { + final Widget child; + final int type; + UnreadDot({this.child, this.type = 1}); + @override + _UnreadDotState createState() => _UnreadDotState(); +} + +class _UnreadDotState extends State { + @override + void initState() { + super.initState(); + + MessageMgr().on('Update UnreadCount', updateDotState); + } + + @override + void dispose() { + MessageMgr().off('Update UnreadCount', updateDotState); + super.dispose(); + } + + updateDotState(args) { + print('更新未读状态'); + Future.delayed(Duration(milliseconds: 100), () { + if (mounted) { + setState(() {}); + } + }); + } + + @override + Widget build(BuildContext context) { + bool isHasUnread = false; + switch (widget.type) { + case 1: + isHasUnread = ChatDataMgr().unreadCountProvider.checkUnreadMsg(); + break; + case 2: + isHasUnread = isShowMsg(); + break; + case 3: + isHasUnread = + ChatDataMgr().unreadCountProvider.checkUnreadMsg() || isShowMsg(); + break; + case 4: + isHasUnread = ChatDataMgr().groupUnreadProvider.checkUnreadMsg(); + break; + case 5: + isHasUnread = isHaveNewFriends(); + break; + } + + return Stack( + children: [ + Padding( + padding: EdgeInsets.only(right: 2), + child: widget.child, + ), + Positioned( + right: 0, + top: 0, + child: Offstage( + offstage: !isHasUnread, + child: CircleAvatar( + radius: 3.5, + backgroundColor: Colors.red, + ))) + ], + ); + } +} diff --git a/lib/home/upload_picture_view.dart b/lib/home/upload_picture_view.dart new file mode 100644 index 0000000..8c9abd7 --- /dev/null +++ b/lib/home/upload_picture_view.dart @@ -0,0 +1,103 @@ +import 'dart:io'; + +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; + +class UploadPicture extends StatefulWidget { + @required + final File img; + + UploadPicture({Key key, this.img}) : super(key: key); + + _UploadPictureState createState() => _UploadPictureState(); +} + +class _UploadPictureState extends State { + bool isAgree = false; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + actions: [ + Container( + alignment: Alignment.center, + child: new InkWell( + child: new Padding( + padding: + EdgeInsets.only(right: 15, left: 15, top: 10, bottom: 10), + child: new Text(I18n.of(context).determine, + textScaleFactor: 1.0, + style: Constants.AppBarActionTextStyle), + ), + onTap: () async { + Map data = {"type": 2, "userId": UserData().basicInfo.userId}; + data['sign'] = TokenMgr().getSign(data); + data['sex'] = UserData().basicInfo.sex; + data['isBurn'] = isAgree ? 1 : 0; + Response res = await HttpUtil().uploadFile( + widget.img, data, 'upload/file/postflie', 'image', + isShowLoading: true); + var resData = res.data; + + if (resData['code'] == 0) { + if (resData['data']['msg'] != '') { + showToast(resData['data']['msg']); + } + resData['Type'] = isAgree ? 1 : 0; + MessageMgr().emit('refresh_photo'); + Navigator.of(context).pop(); + } + }, + ), + ) + ], + centerTitle: true, + leading: CustomUI.buildCustomLeading(context), + ), + body: SafeArea( + child: Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: Column( + children: [ + Expanded( + child: Container( + color: Constants.BlackTextColor, + child: Image.file( + widget.img, + ), + ), + ), + Container( + height: 60, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Checkbox( + value: isAgree, + activeColor: Colors.blue, + onChanged: (bool val) { + this.setState(() { + isAgree = !isAgree; + }); + }, + ), + Text(I18n.of(context).destroy_after, textScaleFactor: 1.0) + ], + ), + ) + ], + ), + ), + )); + } +} diff --git a/lib/home/webview_page.dart b/lib/home/webview_page.dart new file mode 100644 index 0000000..4b48c6f --- /dev/null +++ b/lib/home/webview_page.dart @@ -0,0 +1,59 @@ +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_webview_plugin/flutter_webview_plugin.dart'; + +class WebviewPage extends StatefulWidget { + final String url; + + WebviewPage(this.url); + + @override + State createState() { + return WebviewPageState(); + } +} + +class WebviewPageState extends State { + @override + void dispose() { + super.dispose(); + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return WebviewScaffold( +// url: "https://www.sandbox.paypal.com/checkoutnow?token=3WB31189WV294590T", + url: widget.url, +// url: 'https://cypayos.yht521.com/api/payment/paypal_return?pay_type=paypal_web&success=true&token=5D224968VR002563M&PayerID=B9PMKYC3EB3B4', + withJavascript: true, + + javascriptChannels: [ + ///与后端约定好的, js调用 Methods.postMessage("post") + JavascriptChannel( + name: "Methods", + onMessageReceived: (JavascriptMessage message) { +// print("参数: ${message.message}"); + if (message.message == 'close') { + Navigator.of(context).pop(); + } + }), + ].toSet(), + appBar: AppBar( + title: Text( + I18n.of(context).sign_in, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white), + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..39da0ac --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,495 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'package:amap_location/amap_location.dart'; +import 'package:apple_sign_in/apple_sign_in.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/home/homeMain.dart'; +import 'package:chat/home/splash_page.dart'; +import 'package:chat/models/gift_select_provider.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/NetUtil.dart'; +import 'package:chat/utils/OtherLogin.dart'; +import 'package:chat/utils/file_cache_mgr.dart'; +import 'package:chat/utils/flutter_windowmanager.dart'; +import 'package:chat/utils/local_notification_util.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/receive_share_file.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/screen_shot.dart'; +import 'package:chat/utils/sound_util.dart'; +import 'package:chat/utils/sp_utils.dart'; +import 'package:chat/utils/sql_util.dart'; +import 'package:easy_contact_picker/easy_contact_picker.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bugly/flutter_bugly.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +//import 'package:flutter_bugly/flutter_bugly.dart'; +import 'package:location_permissions/location_permissions.dart' as lp; +import 'package:package_info/package_info.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'home/IndexPage.dart'; +import 'generated/i18n.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx; +import 'package:chat/data/UserData.dart' show UserData; +import 'package:auto_orientation/auto_orientation.dart'; + +import 'models/voucher_change.dart'; + +//读取本地数据 +initLocalData() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + + var localUserId = prefs.getInt(Constants.LocalUserId); + if (localUserId != null) { + print('用户不为空'); + //设置用户基本信息 + UserData().basicInfo.userId = localUserId; + String localUserData = await SPUtils.get(Constants.LocalUsrInfo); + if (localUserData != null) { + UserData().fromLocalJson(json.decode(localUserData)); + } + + //读取好友信息 + //读取聊天信息 + await ChatDataMgr().initMsg(); + //读取群信息 + await GroupInfoMgr().initLocalGroupList(); + } +} + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + LocalNotificationUtil.instance.initJPush(); + LocalNotificationUtil.instance.initLocalPush(); + + await FileCacheMgr.initPathKey(); + await SqlUtil.init(); + await initLocalData(); + + AutoOrientation.portraitUpMode(); + AMapLocationClient.setApiKey("3f4c9fca5f513ac0be361e92d8586ff3"); + AMapLocationClient.startup(new AMapLocationOption( + desiredAccuracy: CLLocationAccuracy.kCLLocationAccuracyHundredMeters)); + setStatusBar(); + + FlutterBugly.init(androidAppId: "d2a8d2c6a0", iOSAppId: "f0ad7340d0"); + + FlutterBugly.postCatchedException(() { + runApp(MyApp()); + }, debugUpload: true); + +// runApp(RestartWidget( +// child: MyApp(), +// )); +} + +void setCustomErrorPage(BuildContext context) { + ErrorWidget.builder = (FlutterErrorDetails flutterErrorDetails) { + print(flutterErrorDetails.toString()); + return Scaffold( + body: Center( + child: Column( + children: [ + Container( + margin: EdgeInsets.only( + top: ScreenUtil.instance.setHeight(180), + bottom: ScreenUtil.instance.setHeight(49)), + child: Image.asset( + 'assets/images/net_error.png', + width: ScreenUtil.instance.setWidth(150), + ), + ), + Container( + margin: EdgeInsets.only(top: ScreenUtil().setHeight(50)), + child: Text( + I18n.of(LoadingManage.context).server_error_tips, + style: TextStyle(color: Color(0xFF8F8E8E), fontSize: 18), + ), + ), + ], + )), + ); + }; +} + +Map language = { + 'en_US': LanguageType.English, + 'en_CN': LanguageType.English, + 'vi_VN': LanguageType.Vietnamese, + 'vi_CN': LanguageType.Vietnamese, + 'vi_US': LanguageType.Vietnamese, + 'zh_Hant_CN': LanguageType.TraditionalChinese, + 'zh_TW': LanguageType.TraditionalChinese, + 'zh_HK': LanguageType.TraditionalChinese, + 'zh_Hant_MO': LanguageType.TraditionalChinese, + 'zh_Hant_US': LanguageType.TraditionalChinese, + 'zh_Hans_CN': LanguageType.SimplifiedChinese, + 'zh_Hans_US': LanguageType.SimplifiedChinese, + 'zh_CN': LanguageType.SimplifiedChinese, + 'ko_KR': LanguageType.Korean, + 'ko_KP': LanguageType.Korean, + 'ko_Kore_CN': LanguageType.Korean, + 'ko_Kore_US': LanguageType.Korean, + 'ko_CN': LanguageType.Korean, + 'ja_JP': LanguageType.Japanese, + 'ja_US': LanguageType.Japanese, + 'ja_CN': LanguageType.Japanese, +}; + +//全局去掉水波纹 +class NoSplashFactory extends InteractiveInkFeatureFactory { + const NoSplashFactory(); + + InteractiveInkFeature create({ + @required MaterialInkController controller, + @required RenderBox referenceBox, + @required Offset position, + @required Color color, + TextDirection textDirection, + bool containedInkWell: false, + RectCallback rectCallback, + BorderRadius borderRadius, + ShapeBorder customBorder, + double radius, + VoidCallback onRemoved, + }) { + return new NoSplash( + controller: controller, + referenceBox: referenceBox, + color: color, + onRemoved: onRemoved, + ); + } +} + +class NoSplash extends InteractiveInkFeature { + NoSplash({ + @required MaterialInkController controller, + @required RenderBox referenceBox, + Color color, + VoidCallback onRemoved, + }) : assert(controller != null), + assert(referenceBox != null), + super( + controller: controller, + referenceBox: referenceBox, + onRemoved: onRemoved) { + controller.addInkFeature(this); + } + @override + void paintFeature(Canvas canvas, Matrix4 transform) {} +} + +class FallbackCupertinoLocalisationsDelegate + extends LocalizationsDelegate { + const FallbackCupertinoLocalisationsDelegate(); + + @override + bool isSupported(Locale locale) => true; + + @override + Future load(Locale locale) => + DefaultCupertinoLocalizations.load(locale); + + @override + bool shouldReload(FallbackCupertinoLocalisationsDelegate old) => false; +} + +class MyApp extends StatefulWidget { + MyApp({Key key}) : super(key: key); + + _MyAppState createState() => _MyAppState(); +} + +final GlobalKey navigatorKey = new GlobalKey(); + +class _MyAppState extends State with WidgetsBindingObserver { + final i18n = I18n.delegate; + RefNameProvider _refNameProvider; + bool isOpen = true; + + @override + void initState() { + super.initState(); + + setCustomErrorPage(context); + isAvailableAppleSignIn(); + Screen.initFactor(); + + initVersionName(); + + askLocationPermission(); + MsgHandler.context = context; + I18n.onLocaleChanged = onLocaleChange; + WidgetsBinding.instance.addObserver(this); + ReceiveShareFile.init(); + + + ScreenShot.getFileStream(); + + + } + + isAvailableAppleSignIn() async { + isOpen = (await SPUtils.getBool(Constants.Splash_OPENED)) ?? false; + OtherLogin.isAvailableForAppleSignIn = await AppleSignIn.isAvailable(); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + if (_refNameProvider == null) { + _refNameProvider = RefNameProvider(); + } + } + + initVersionName() async { + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + Constants.versionName = packageInfo.version; + Constants.packageName = packageInfo.packageName; + } + + @override + void dispose() { + //positionStream?.cancel(); + WidgetsBinding.instance.removeObserver(this); +// LocalNotificationUtil.instance.dispose(); + super.dispose(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) async { + print("--" + state.toString()); + switch (state) { + case AppLifecycleState.inactive: // 处于这种状态的应用程序应该假设它们可能在任何时候暂停。 + break; + case AppLifecycleState.resumed: // 应用程序可见,前台 + setStatusBar(); + print('切换到前台'); + //检测用户是否开启定位权限 + MessageMgr().emit('test_Permission'); + NetWork().checkConnect(); + MessageMgr().emit(MessageMgr.REFRESH_PUSH_PERMISSION); + LocalNotificationUtil.isBackground = false; + LocalNotificationUtil.instance.cleanAllNotifications(); + if (UserData().isBannerStatus) { + UserData().isBannerStatus = false; + MessageMgr().emit('refresh_money'); + } + + if (MsgHandler.audioChatRequestFriendId > 0) { + MessageMgr().emit( + 'Receive AudioChat Request', MsgHandler.audioChatRequestFriendId); + } + + + + break; + case AppLifecycleState.paused: // 应用程序不可见,后台 + print('切换到后台'); + LocalNotificationUtil.isBackground = true; + SoundUtils.instance.pause(); + if(Platform.isIOS)NetWork().reallyClose(); ///iOS切后台关闭socket不然会闪退 + break; +// case AppLifecycleState.suspending: // 申请将暂时暂停 +// print('程序挂起'); +// break; + case AppLifecycleState.detached: // 申请将暂时暂停 +// print('程序挂起'); + break; + } + } + + void onLocaleChange(Locale locale) { + final String lang = locale != null ? locale.toString() : ""; + print('#### onLocaleChange $lang'); + setState(() { + I18n.locale = locale; + }); + } + + setDisableScreenshots() async { + print('Platform.isAndroid ${Platform.isAndroid}'); + if (Platform.isAndroid) { + await FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE); + } + } + + @override + Widget build(BuildContext context) { + fluwx.registerWxApi( + appId: Constants.AppId, + universalLink: "https://www.xxx.com/iosuniversallink/"); + return OKToast( + child: MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => GiftSelectProvider()), + ChangeNotifierProvider(create: (_) => MoneyChangeProvider()), + ChangeNotifierProvider(create: (_) => _refNameProvider), + ChangeNotifierProvider(create: (_) => VoucherChangeProvider()), + ], + child: MaterialApp( + theme: ThemeData( + platform: TargetPlatform.iOS, + highlightColor: Colors.transparent, + splashFactory: const NoSplashFactory(), + toggleableActiveColor: Constants.BlueTextColor, + scaffoldBackgroundColor: Constants.GreyBackgroundColor, + accentColor: Constants.BlueTextColor, + indicatorColor: Constants.BlueTextColor, + tabBarTheme: TabBarTheme( + indicatorSize: TabBarIndicatorSize.label, + labelColor: Constants.BlueTextColor, + unselectedLabelColor: Constants.GreyTextColor, + labelPadding: EdgeInsets.only(bottom: 5, left: 15, right: 15), + labelStyle: + TextStyle(fontWeight: FontWeight.w600, fontSize: 15), + unselectedLabelStyle: + TextStyle(fontWeight: FontWeight.w500, fontSize: 15), + ), + appBarTheme: AppBarTheme( + elevation: 0, + brightness: Brightness.light, + color: Colors.white, + iconTheme: IconThemeData(color: Colors.black), + actionsIconTheme: IconThemeData(color: Colors.black), + textTheme: TextTheme( + title: TextStyle( + color: Constants.BlackTextColor, fontSize: 20))), + primaryColor: Constants.BlueTextColor, + inputDecorationTheme: InputDecorationTheme( + labelStyle: TextStyle( + fontSize: 13, color: Constants.BlackTextColor), + border: InputBorder.none, + contentPadding: EdgeInsets.all(10), + hintStyle: TextStyle( + fontSize: 11, + color: Color.fromARGB(255, 192, 191, 191))), + ), + localizationsDelegates: [ + i18n, + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, // <-- needed for iOS + const FallbackCupertinoLocalisationsDelegate() + ], + supportedLocales: i18n.supportedLocales, + title: 'Chat', + onGenerateTitle: (context) { + // 此处 + return 'Hibok'; + }, + navigatorKey: navigatorKey, + routes: { + '/main': (BuildContext context) => HomeMain(), + }, + home: Builder(builder: (context) { + return goIndex(); + }), + //home: IndexPage(), + localeResolutionCallback: (deviceLocale, supportedLocales) { + if (deviceLocale != null) { + final String lang = + deviceLocale != null ? deviceLocale.toString() : ""; + print('#### fl: $lang'); + //设置设备语言 + if (language.containsKey(deviceLocale.toString())) + UserData().deviceLanguage = + language[deviceLocale.toString()]; + getPosition(deviceLocale); + } + return deviceLocale; + }, + ))); + } + + goIndex() { + LoadingManage.context = navigatorKey.currentState.overlay.context; + + if (!isOpen) { + return SplashPage(); + } else { + return IndexPage(); + } + } + + askLocationPermission() async { + lp.PermissionStatus status = + await lp.LocationPermissions().checkPermissionStatus(); + print('定位权限 $status'); + + final PermissionStatus addStatus = await PermissionHandler() + .checkPermissionStatus(PermissionGroup.contacts); + + print('通讯录权限 $addStatus'); + + List permissionList = []; + if (status == lp.PermissionStatus.granted) { + UserData().hasLocationPermission = true; + } else { + permissionList.add(PermissionGroup.locationWhenInUse); + } + if (addStatus == PermissionStatus.granted) { + setContact(); + } else { + if (Platform.isAndroid) { +// ///ios隐藏 + permissionList.add(PermissionGroup.contacts); + } + } + print(permissionList); + if (permissionList.length != 0) { + Map permissionRequestResult = + await PermissionHandler().requestPermissions(permissionList); + var status = permissionRequestResult[PermissionGroup.locationWhenInUse]; + var addStatus = permissionRequestResult[PermissionGroup.contacts]; + if (status == PermissionStatus.granted) { + UserData().hasLocationPermission = true; + } + if (addStatus == PermissionStatus.granted) { + setContact(); + } + } + + MessageMgr().emit('test_Permission'); + } + + setContact() async { + final EasyContactPicker _contactPicker = new EasyContactPicker(); + List _list = await _contactPicker.selectContacts(); + UserData().contactList.clear(); + _list.forEach((contack) { + UserData() + .contactList + .add({'PhoneNumber': contack.phoneNumber, 'Name': contack.fullName}); + }); + MessageMgr().emit('PostContact'); + } + + void getPosition(deviceLocale) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + var localLanguage = prefs.getInt(Constants.Language); + print('localLanguage$localLanguage'); + if (localLanguage == null) { + if (language.containsKey(deviceLocale.toString())) + UserData().language = language[deviceLocale.toString()]; + } else { + UserData().language = localLanguage; + } + WebData().getAllData(); + UserData().getCurrentPosition(); + } +} diff --git a/lib/map/auto_comp_iete_item.dart b/lib/map/auto_comp_iete_item.dart new file mode 100644 index 0000000..e9c21c2 --- /dev/null +++ b/lib/map/auto_comp_iete_item.dart @@ -0,0 +1,22 @@ + +/// Autocomplete results item returned from Google will be deserialized +/// into this model. +class AutoCompleteItem { + /// The id of the place. This helps to fetch the lat,lng of the place. + String id; + + /// The text (name of place) displayed in the autocomplete suggestions list. + String text; + + /// Assistive index to begin highlight of matched part of the [text] with + /// the original query + int offset; + + /// Length of matched part of the [text] + int length; + + @override + String toString() { + return 'AutoCompleteItem{id: $id, text: $text, offset: $offset, length: $length}'; + } +} \ No newline at end of file diff --git a/lib/map/google_map_location_picker.dart b/lib/map/google_map_location_picker.dart new file mode 100644 index 0000000..c2740a2 --- /dev/null +++ b/lib/map/google_map_location_picker.dart @@ -0,0 +1,406 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:chat/map/auto_comp_iete_item.dart'; +import 'package:chat/map/location_provider.dart'; +import 'package:chat/map/location_result.dart'; +import 'package:chat/map/map.dart'; +import 'package:chat/map/nearby_place.dart'; +import 'package:chat/map/rich_suggestion.dart'; +import 'package:chat/map/search_input.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/uuid.dart'; +import 'package:flutter/material.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:http/http.dart' as http; +import 'package:provider/provider.dart'; + +class LocationPicker extends StatefulWidget { + LocationPicker( + this.apiKey, { + Key key, + this.initialCenter, + this.requiredGPS = true, + }); + + final String apiKey; + + final LatLng initialCenter; + + final bool requiredGPS; + + @override + LocationPickerState createState() => LocationPickerState(); + + /// Returns a [LatLng] object of the location that was picked. + /// + /// The [apiKey] argument API key generated from Google Cloud Console. + /// You can get an API key [here](https://cloud.google.com/maps-platform/) + /// + /// [initialCenter] The geographical location that the camera is pointing at. + /// + static Future pickLocation( + BuildContext context, + String apiKey, { + LatLng initialCenter = const LatLng(45.521563, -122.677433), + bool requiredGPS = true, + }) async { + var results = await Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) { + return LocationPicker( + apiKey, + initialCenter: initialCenter, + requiredGPS: requiredGPS, + ); + }, + ), + ); + + if (results != null && results.containsKey('location')) { + return results['location']; + } else { + return null; + } + } +} + +class LocationPickerState extends State { + /// Result returned after user completes selection + LocationResult locationResult; + + /// Overlay to display autocomplete suggestions + OverlayEntry overlayEntry; + + List nearbyPlaces = List(); + + /// Session token required for autocomplete API call + String sessionToken = Uuid().generateV4(); + + var mapKey = GlobalKey(); + + var appBarKey = GlobalKey(); + + var searchInputKey = GlobalKey(); + + bool hasSearchTerm = false; + + /// Hides the autocomplete overlay + void clearOverlay() { + if (overlayEntry != null) { + overlayEntry.remove(); + overlayEntry = null; + } + } + + /// Begins the search process by displaying a "wait" overlay then + /// proceeds to fetch the autocomplete list. The bottom "dialog" + /// is hidden so as to give more room and better experience for the + /// autocomplete list overlay. + void searchPlace(String place) { + if (context == null) return; + + clearOverlay(); + + setState(() => hasSearchTerm = place.length > 0); + + if (place.length < 1) return; + + final RenderBox renderBox = context.findRenderObject(); + Size size = renderBox.size; + + final RenderBox appBarBox = appBarKey.currentContext.findRenderObject(); + + overlayEntry = OverlayEntry( + builder: (context) => Positioned( + top: appBarBox.size.height, + width: size.width, + child: Material( + elevation: 1, + child: Container( + padding: EdgeInsets.symmetric( + vertical: 16, + horizontal: 24, + ), + color: Colors.white, + child: Row( + children: [ + SizedBox( + height: 24, + width: 24, + child: CircularProgressIndicator( + strokeWidth: 3, + ), + ), + SizedBox( + width: 24, + ), + Expanded( + child: Text( + "Finding place...", + style: TextStyle( + fontSize: 16, + ), + ), + ) + ], + ), + ), + ), + ), + ); + + Overlay.of(context).insert(overlayEntry); + + autoCompleteSearch(place); + } + + /// Fetches the place autocomplete list with the query [place]. + void autoCompleteSearch(String place) { + place = place.replaceAll(" ", "+"); + var endpoint = + "https://maps.googleapis.com/maps/api/place/autocomplete/json?" + + "key=${widget.apiKey}&" + + "input={$place}&sessiontoken=$sessionToken"; + + if (locationResult != null) { + endpoint += "&location=${locationResult.latLng.latitude}," + + "${locationResult.latLng.longitude}"; + } + http.get(endpoint).then((response) { + if (response.statusCode == 200) { + Map data = jsonDecode(response.body); + List predictions = data['predictions']; + + List suggestions = []; + + if (predictions.isEmpty) { + AutoCompleteItem aci = AutoCompleteItem(); + aci.text = "No result found"; + aci.offset = 0; + aci.length = 0; + + suggestions.add(RichSuggestion(aci, () {})); + } else { + for (dynamic t in predictions) { + AutoCompleteItem aci = AutoCompleteItem(); + + aci.id = t['place_id']; + aci.text = t['description']; + aci.offset = t['matched_substrings'][0]['offset']; + aci.length = t['matched_substrings'][0]['length']; + + suggestions.add(RichSuggestion(aci, () { + decodeAndSelectPlace(aci.id); + })); + } + } + + displayAutoCompleteSuggestions(suggestions); + } + }).catchError((error) { + print(error); + }); + } + + /// To navigate to the selected place from the autocomplete list to the map, + /// the lat,lng is required. This method fetches the lat,lng of the place and + /// proceeds to moving the map to that location. + void decodeAndSelectPlace(String placeId) { + clearOverlay(); + + String endpoint = + "https://maps.googleapis.com/maps/api/place/details/json?key=${widget.apiKey}" + + "&placeid=$placeId"; + + http.get(endpoint).then((response) { + if (response.statusCode == 200) { + Map location = + jsonDecode(response.body)['result']['geometry']['location']; + + LatLng latLng = LatLng(location['lat'], location['lng']); + + moveToLocation(latLng); + } + }).catchError((error) { + print(error); + }); + } + + /// Display autocomplete suggestions with the overlay. + void displayAutoCompleteSuggestions(List suggestions) { + final RenderBox renderBox = context.findRenderObject(); + Size size = renderBox.size; + + final RenderBox appBarBox = appBarKey.currentContext.findRenderObject(); + + clearOverlay(); + + overlayEntry = OverlayEntry( + builder: (context) => Positioned( + width: size.width, + top: appBarBox.size.height, + child: Material( + elevation: 1, + color: Colors.white, + child: Column( + children: suggestions, + ), + ), + ), + ); + + Overlay.of(context).insert(overlayEntry); + } + + /// Utility function to get clean readable name of a location. First checks + /// for a human-readable name from the nearby list. This helps in the cases + /// that the user selects from the nearby list (and expects to see that as a + /// result, instead of road name). If no name is found from the nearby list, + /// then the road name returned is used instead. +// String getLocationName() { +// if (locationResult == null) { +// return "Unnamed location"; +// } +// +// for (NearbyPlace np in nearbyPlaces) { +// if (np.latLng == locationResult.latLng) { +// locationResult.name = np.name; +// return np.name; +// } +// } +// +// return "${locationResult.name}, ${locationResult.locality}"; +// } + + /// Fetches and updates the nearby places to the provided lat,lng + void getNearbyPlaces(LatLng latLng) { + http + .get("https://maps.googleapis.com/maps/api/place/nearbysearch/json?" + + "key=${widget.apiKey}&" + + "location=${latLng.latitude},${latLng.longitude}&radius=150") + .then((response) { + if (response.statusCode == 200) { + nearbyPlaces.clear(); + for (Map item + in jsonDecode(response.body)['results']) { + NearbyPlace nearbyPlace = NearbyPlace(); + + nearbyPlace.name = item['name']; + nearbyPlace.icon = item['icon']; + double latitude = item['geometry']['location']['lat']; + double longitude = item['geometry']['location']['lng']; + + LatLng _latLng = LatLng(latitude, longitude); + + nearbyPlace.latLng = _latLng; + + nearbyPlaces.add(nearbyPlace); + } + } + + // to update the nearby places + setState(() { + // this is to require the result to show + hasSearchTerm = false; + }); + }).catchError((error) {}); + } + + /// This method gets the human readable name of the location. Mostly appears + /// to be the road name and the locality. + Future reverseGeocodeLatLng(LatLng latLng) async { + /* + var placeMarks = await Geolocator() + .placemarkFromCoordinates(latLng.latitude, latLng.longitude); + + if (placeMarks == null) { + return; + } + Placemark place = placeMarks.first; + + print('~~~~~~~~~~~~~~~~~~~~~~~~'); + print(place.toString()); + setState(() { + locationResult = LocationResult(); + locationResult.address = place.name; + locationResult.latLng = + LatLng(place.position.latitude, place.position.longitude); + }); + */ + + var response = await http.get( + "https://maps.googleapis.com/maps/api/geocode/json?latlng=${latLng.latitude},${latLng.longitude}" + "&key=${widget.apiKey}"); + + if (response.statusCode == 200) { + Map responseJson = jsonDecode(response.body); + + String road = + responseJson['results'][0]['address_components'][0]['short_name']; + + setState(() { + locationResult = LocationResult(); + locationResult.address = road; + locationResult.latLng = latLng; + }); + } + } + + /// Moves the camera to the provided location and updates other UI features to + /// match the location. + void moveToLocation(LatLng latLng) { + mapKey.currentState.mapController.future.then((controller) { + controller.animateCamera( + CameraUpdate.newCameraPosition( + CameraPosition( + target: latLng, + zoom: 18.0, + ), + ), + ); + }); + + reverseGeocodeLatLng(latLng); + + getNearbyPlaces(latLng); + } + + @override + void dispose() { + mapKey = null; + appBarKey = null; + + clearOverlay(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => LocationProvider()), + ], + child: Builder(builder: (context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.white, + iconTheme: IconThemeData(color: Colors.black), + key: appBarKey, + title: SearchInput( + (input) => searchPlace(input), + key: searchInputKey, + ), + leading: CustomUI.buildCustomLeading(context), + ), + body: MapPicker( + initialCenter: widget.initialCenter, + key: mapKey, + apiKey: widget.apiKey, + requiredGPS: widget.requiredGPS, + ), + ); + }), + ); + } +} diff --git a/lib/map/location_provider.dart b/lib/map/location_provider.dart new file mode 100644 index 0000000..d8fa086 --- /dev/null +++ b/lib/map/location_provider.dart @@ -0,0 +1,19 @@ +import 'package:flutter/widgets.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:provider/provider.dart'; + +class LocationProvider extends ChangeNotifier { + static LocationProvider of(BuildContext context) => + Provider.of(context); + + LatLng _lastIdleLocation; + + LatLng get lastIdleLocation => _lastIdleLocation; + + void setLastIdleLocation(LatLng lastIdleLocation) { + if (_lastIdleLocation != lastIdleLocation) { + _lastIdleLocation = lastIdleLocation; + notifyListeners(); + } + } +} \ No newline at end of file diff --git a/lib/map/location_result.dart b/lib/map/location_result.dart new file mode 100644 index 0000000..5e65fd5 --- /dev/null +++ b/lib/map/location_result.dart @@ -0,0 +1,42 @@ + +import 'dart:typed_data'; + +import 'package:google_maps_flutter/google_maps_flutter.dart'; + +/// The result returned after completing location selection. +class LocationResult { + /// The human readable name of the location. This is primarily the + /// name of the road. But in cases where the place was selected from Nearby + /// places list, we use the name provided on the list item. + String address; // or road + + /// Latitude/Longitude of the selected location. + LatLng latLng; + + List screen; + + LocationResult({this.latLng, this.address,this.screen}); + + LocationResult.fromJson(Map json) { + address = json['address']; + + var latlngJson = json['latLng']; + if (latlngJson != null) { + latLng = LatLng(latlngJson[0], latlngJson[1]); + } + screen = Uint8List.fromList(List.from(json['screen'])); + } + + Map toJson() { + final Map data = new Map(); + data['address'] = this.address??''; + data['latLng'] = [this.latLng.latitude,this.latLng.longitude]; + data['screen'] = this.screen.toList(); + return data; + } + + @override + String toString() { + return 'LocationResult{address: $address, latLng: $latLng,screen:$screen}'; + } +} \ No newline at end of file diff --git a/lib/map/map.dart b/lib/map/map.dart new file mode 100644 index 0000000..7e391ac --- /dev/null +++ b/lib/map/map.dart @@ -0,0 +1,363 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:ui'; + +import 'package:android_intent/android_intent.dart'; +import 'package:chat/utils/loading_builder.dart'; +import 'package:chat/utils/log.dart'; +import 'package:chat/utils/screen_shot.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:provider/provider.dart'; + +import 'location_provider.dart'; +import 'location_result.dart'; +import 'package:http/http.dart' as http; + +class MapPicker extends StatefulWidget { + final LatLng initialCenter; + final String apiKey; + final bool requiredGPS; + + const MapPicker({ + Key key, + this.initialCenter, + this.apiKey, + this.requiredGPS, + }) : super(key: key); + + @override + MapPickerState createState() => MapPickerState(); +} + +class MapPickerState extends State { + Completer mapController = Completer(); + GlobalKey rootWidgetKey = GlobalKey(); + + LatLng _lastMapPosition; + + Position _currentPosition; + + String _address; + + // void _onToggleMapTypePressed() { + // final MapType nextType = + // MapType.values[(_currentMapType.index + 1) % MapType.values.length]; + + // setState(() => _currentMapType = nextType); + // } + + // this also checks for location permission. + Future _initCurrentLocation() async { + Position currentPosition; + try { + currentPosition = await Geolocator() + .getCurrentPosition(desiredAccuracy: LocationAccuracy.best); + + d("position = $currentPosition"); + + setState(() => _currentPosition = currentPosition); + } on PlatformException catch (e) { + currentPosition = null; + d("_initCurrentLocation#e = $e"); + } + + if (!mounted) return; + + setState(() => _currentPosition = currentPosition); + + if (currentPosition != null) + moveToCurrentLocation( + LatLng(currentPosition.latitude, currentPosition.longitude)); + } + + @override + void initState() { + super.initState(); + _initCurrentLocation(); + } + + @override + void dispose() { + rootWidgetKey = null; + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (widget.requiredGPS) { + _checkGps(); + _checkGeolocationPermission(); + } + return Scaffold( + body: Builder(builder: (context) { + if (_currentPosition == null && widget.requiredGPS) + return const Center(child: CircularProgressIndicator()); + + return buildMap(); + }), + ); + } + + Widget buildMap() { + return Center( + child: Stack( + children: [ + GoogleMap( + onMapCreated: (GoogleMapController controller) { + mapController.complete(controller); + + _lastMapPosition = widget.initialCenter; + LocationProvider.of(context) + .setLastIdleLocation(_lastMapPosition); + }, + initialCameraPosition: CameraPosition( + target: widget.initialCenter, + zoom: 18.0, + ), + onCameraMove: (CameraPosition position) { + _lastMapPosition = position.target; + }, + onCameraIdle: () async { + LocationProvider.of(context) + .setLastIdleLocation(_lastMapPosition); + }, + myLocationEnabled: true, + myLocationButtonEnabled: true), + // _MapFabs( + // onToggleMapTypePressed: _onToggleMapTypePressed, + // ), + pin(), + locationCard(), + ], + ), + ); + } + + Widget locationCard() { + return Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 24), + child: Card( + child: Padding( + padding: const EdgeInsets.all(8), + child: Consumer( + builder: (context, locationProvider, _) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + flex: 20, + child: FutureLoadingBuilder( + future: getAddress(locationProvider.lastIdleLocation), + mutable: true, + loadingIndicator: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CircularProgressIndicator(), + ], + ), + builder: (context, address) { + _address = address; + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + address ?? 'Unnamed place', + style: TextStyle( + fontSize: 18, + ), + ), + ], + ); + }), + ), + Spacer(), + FloatingActionButton( + onPressed: () async { + var capture = await ScreenShot.takeScreenshotImage(); + + Navigator.of(context).pop({ + 'location': LocationResult( + latLng: locationProvider.lastIdleLocation, + address: _address, + screen: capture), + }); + }, + child: Icon(Icons.send, color: Colors.white), + ), + ], + ); + }), + ), + ), + ), + ); + } + + Future getAddress(LatLng latLng) async { + try { + + /* + var placeMarks = await Geolocator() + .placemarkFromCoordinates(latLng.latitude, latLng.longitude); + + if (placeMarks == null) { + return null; + } + var place = placeMarks.first; + + print('place ${place.toJson()}'); + return place.name; + */ + + + var endPoint = + 'https://maps.googleapis.com/maps/api/geocode/json?latlng=${latLng?.latitude},${latLng?.longitude}&key=${widget.apiKey}'; + var response = jsonDecode((await http.get(endPoint)).body); + + return response['results'][0]['formatted_address']; + + } catch (e) { + print(e); + } + + return null; + } + + Center pin() { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.place, size: 56, color: Colors.lightBlue), + Container( + decoration: ShapeDecoration( + shadows: [ + BoxShadow( + color: Colors.black38, + blurRadius: 4, + ), + ], + shape: CircleBorder( + side: BorderSide( + width: 4, + color: Colors.transparent, + ), + ), + ), + ), + SizedBox(height: 56), + ], + ), + ); + } + + Future moveToCurrentLocation(LatLng currentLocation) async { + var controller = await mapController.future; + controller.animateCamera(CameraUpdate.newCameraPosition( + CameraPosition(target: currentLocation, zoom: 18.0), + )); + } + + var dialogOpen; + + Future _checkGeolocationPermission() async { + var geolocationStatus = + await Geolocator().checkGeolocationPermissionStatus(); + + if (geolocationStatus == GeolocationStatus.denied && dialogOpen == null) { + d('showDialog'); + dialogOpen = showDialog( + context: context, + barrierDismissible: false, + builder: (context) { + return AlertDialog( + title: Text('Access to location denied'), + content: Text('Allow access to the location services.'), + actions: [ + FlatButton( + child: Text('Ok'), + onPressed: () { + Navigator.of(context, rootNavigator: true).pop(); + _initCurrentLocation(); + dialogOpen = null; + }, + ), + ], + ); + }, + ); + //} else if (geolocationStatus == GeolocationStatus.disabled) { + } else if (geolocationStatus == GeolocationStatus.granted) { + d('GeolocationStatus.granted'); + if (dialogOpen != null) { + Navigator.of(context, rootNavigator: true).pop(); + dialogOpen = null; + } + } + } + + Future _checkGps() async { + if (!(await Geolocator().isLocationServiceEnabled())) { + if (Theme.of(context).platform == TargetPlatform.android) { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return AlertDialog( + title: Text("Can't get current location"), + content: Text('Please make sure you enable GPS and try again'), + actions: [ + FlatButton( + child: Text('Ok'), + onPressed: () { + final AndroidIntent intent = AndroidIntent( + action: 'android.settings.LOCATION_SOURCE_SETTINGS'); + + intent.launch(); + Navigator.of(context, rootNavigator: true).pop(); + }, + ), + ], + ); + }, + ); + } + } + } +} + +/* +class _MapFabs extends StatelessWidget { + const _MapFabs({ + Key key, + @required this.onToggleMapTypePressed, + }) : assert(onToggleMapTypePressed != null), + super(key: key); + + final VoidCallback onToggleMapTypePressed; + + @override + Widget build(BuildContext context) { + return Container( + alignment: Alignment.topRight, + margin: const EdgeInsets.only(top: 64, right: 8), + child: Column( + children: [ + FloatingActionButton( + onPressed: onToggleMapTypePressed, + materialTapTargetSize: MaterialTapTargetSize.padded, + mini: true, + child: const Icon(Icons.layers, size: 28, color: Colors.white), + heroTag: "layers", + ), + ], + ), + ); + } +}*/ diff --git a/lib/map/map_view.dart b/lib/map/map_view.dart new file mode 100644 index 0000000..2b5e881 --- /dev/null +++ b/lib/map/map_view.dart @@ -0,0 +1,250 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/map/location_result.dart'; +import 'package:chat/map/map.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/screen_shot.dart'; +import 'package:flutter/material.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:http/http.dart' as http; + +class MapView extends StatefulWidget { + MapView({ + Key key, + this.locationResult, + this.requiredGPS = true, + }); + + final LocationResult locationResult; + + final bool requiredGPS; + + @override + MapViewState createState() => MapViewState(); +} + +class MapViewState extends State { + Completer mapController = Completer(); + + var mapKey = GlobalKey(); + + String address; + + BitmapDescriptor _markerIcon; + + void moveToMyLocation(LatLng latLng) { + mapKey.currentState.mapController.future.then((controller) { + controller.animateCamera( + CameraUpdate.newCameraPosition( + CameraPosition( + target: latLng, + zoom: 18.0, + ), + ), + ); + }); + } + + @override + void initState() { + super.initState(); + address = widget.locationResult.address; + + reverseGeocodeLatLng(widget.locationResult.latLng); + } + + @override + void dispose() { + mapKey = null; + super.dispose(); + } + + @override + Widget build(BuildContext context) { + _createMarkerImageFromAsset(context); + + return Scaffold( + body: SafeArea( + child: Center( + child: Stack( + children: [ + GoogleMap( + onMapCreated: (GoogleMapController controller) { + mapController.complete(controller); + }, + initialCameraPosition: CameraPosition( + target: widget.locationResult.latLng, + zoom: 18.0, + ), + markers: _createMarker(), + myLocationEnabled: true, + myLocationButtonEnabled: true), + locationCard(), + Positioned( + left: 10, + top: 10, + child: IconButton( + icon: Icon(Icons.arrow_back_ios), + onPressed: () { + Navigator.pop(context); + }, + ), + ) + ], + )))); + } + + Future reverseGeocodeLatLng(LatLng latLng) async { + + /* + var placeMarks = await Geolocator() + .placemarkFromCoordinates(latLng.latitude, latLng.longitude); + + if (placeMarks == null) { + return; + } + var place = placeMarks.first; + + + setState(() { + address = place.name; + }); + */ + + + var response = await http.get( + "https://maps.googleapis.com/maps/api/geocode/json?latlng=${latLng.latitude},${latLng.longitude}" + "&key=$googleMapApiKey"); + + if (response.statusCode == 200) { + Map responseJson = jsonDecode(response.body); + + setState(() { + address = responseJson['results'][0]['formatted_address']; + }); + } + + } + + Set _createMarker() { + return [ + Marker( + markerId: MarkerId("marker_1"), + position: widget.locationResult.latLng, + icon: _markerIcon, + ), + ].toSet(); + } + + Future _createMarkerImageFromAsset(BuildContext context) async { + if (_markerIcon == null) { + final ImageConfiguration imageConfiguration = + createLocalImageConfiguration(context); + BitmapDescriptor.fromAssetImage( + imageConfiguration, R.assetsImagesDefaultNorAvatar) + .then(_updateBitmap); + } + } + + void _updateBitmap(BitmapDescriptor bitmap) { + setState(() { + // _markerIcon = bitmap; + _markerIcon = + BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed); + }); + } + + Widget locationCard() { + return Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 24), + child: Card( + child: Padding( + padding: const EdgeInsets.all(8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + flex: 20, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + address ?? '', + style: TextStyle( + fontSize: 18, + ), + ), + ], + )), + Spacer(), + FloatingActionButton( + onPressed: () async { + _showMapApps(); + }, + child: Icon(Icons.navigation, color: Colors.white), + ), + ], + )), + ), + ), + ); + } + + getMapName(String mapType) { + var name; + switch (mapType) { + case 'minimap': + name = I18n.of(context).amap; + break; + case 'baidu': + name = I18n.of(context).baidumap; + break; + case 'google': + name = I18n.of(context).googlemap; + break; + case 'apple': + name = I18n.of(context).applemap; + + break; + default: + } + + return name; + } + + _showMapApps() async { + var mapList = await ScreenShot.getOtherMapAppList(); + + print('可用地图' + mapList.toString()); + + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return Container( + color: Colors.transparent, + child: Column( + mainAxisSize: MainAxisSize.min, + children: List.generate( + mapList.length, + (int i) => Padding( + padding: EdgeInsets.only(bottom: 2), + child: Container( + width: double.infinity, + color: Colors.white, + child: FlatButton( + child: Text(getMapName(mapList[i])), + onPressed: () { + print('跳转到其他地图'); + ScreenShot.openMapForOth( + mapList[i], widget.locationResult); + }))))), + ); + }, + ); + } +} diff --git a/lib/map/nearby_place.dart b/lib/map/nearby_place.dart new file mode 100644 index 0000000..c0c3aa8 --- /dev/null +++ b/lib/map/nearby_place.dart @@ -0,0 +1,20 @@ +import 'package:google_maps_flutter/google_maps_flutter.dart'; + +/// Nearby place data will be deserialized into this model. +class NearbyPlace { + /// The human-readable name of the location provided. This value is provided + /// for [LocationResult.address] when the user selects this nearby place. + String name; + + /// The icon identifying the kind of place provided. Eg. lodging, chapel, + /// hospital, etc. + String icon; + + // Latitude/Longitude of the provided location. + LatLng latLng; + + @override + String toString() { + return 'NearbyPlace{name: $name, icon: $icon, latLng: $latLng}'; + } +} \ No newline at end of file diff --git a/lib/map/rich_suggestion.dart b/lib/map/rich_suggestion.dart new file mode 100644 index 0000000..92fc112 --- /dev/null +++ b/lib/map/rich_suggestion.dart @@ -0,0 +1,79 @@ +import 'package:flutter/material.dart'; + +import 'auto_comp_iete_item.dart'; + + +class RichSuggestion extends StatelessWidget { + final VoidCallback onTap; + final AutoCompleteItem autoCompleteItem; + + RichSuggestion(this.autoCompleteItem, this.onTap); + + @override + Widget build(BuildContext context) { + return Material( + child: InkWell( + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 24, + vertical: 16, + ), + child: Row( + children: [ + Expanded( + child: RichText( + text: TextSpan(children: getStyledTexts(context)), + ), + ) + ], + )), + onTap: onTap, + ), + ); + } + + List getStyledTexts(BuildContext context) { + final List result = []; + + String startText = + autoCompleteItem.text.substring(0, autoCompleteItem.offset); + if (startText.isNotEmpty) { + result.add( + TextSpan( + text: startText, + style: TextStyle( + color: Colors.grey, + fontSize: 15, + ), + ), + ); + } + + String boldText = autoCompleteItem.text.substring(autoCompleteItem.offset, + autoCompleteItem.offset + autoCompleteItem.length); + + result.add(TextSpan( + text: boldText, + style: TextStyle( + color: Colors.black, + fontSize: 15, + ), + )); + + String remainingText = this + .autoCompleteItem + .text + .substring(autoCompleteItem.offset + autoCompleteItem.length); + result.add( + TextSpan( + text: remainingText, + style: TextStyle( + color: Colors.grey, + fontSize: 15, + ), + ), + ); + + return result; + } +} \ No newline at end of file diff --git a/lib/map/search_input.dart b/lib/map/search_input.dart new file mode 100644 index 0000000..91a04c0 --- /dev/null +++ b/lib/map/search_input.dart @@ -0,0 +1,119 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +/// Custom Search input field, showing the search and clear icons. +class SearchInput extends StatefulWidget { + final ValueChanged onSearchInput; + final Key searchInputKey; + + SearchInput( + this.onSearchInput, { + Key key, + this.searchInputKey, + }) : super(key: key); + + @override + State createState() { + return SearchInputState(onSearchInput); + } +} + +class SearchInputState extends State { + final ValueChanged onSearchInput; + + TextEditingController editController = TextEditingController(); + + Timer debouncer; + + bool hasSearchEntry = false; + + SearchInputState(this.onSearchInput); + + @override + void initState() { + super.initState(); + editController.addListener(onSearchInputChange); + } + + @override + void dispose() { + editController.removeListener(onSearchInputChange); + editController.dispose(); + + super.dispose(); + } + + void onSearchInputChange() { + if (editController.text.isEmpty) { + debouncer?.cancel(); + onSearchInput(editController.text); + return; + } + + if (debouncer?.isActive ?? false) { + debouncer.cancel(); + } + + debouncer = Timer(Duration(milliseconds: 500), () { + onSearchInput(editController.text); + }); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.symmetric( + horizontal: 8, + ), + child: Row( + children: [ + Icon( + Icons.search, + color: Colors.black, + ), + SizedBox( + width: 8, + ), + Expanded( + child: TextField( + keyboardAppearance: Brightness.light, + style: TextStyle(textBaseline: TextBaseline.alphabetic), + decoration: InputDecoration( + hintText: 'Search place', + border: InputBorder.none, + ), + controller: editController, + onChanged: (value) { + setState(() { + hasSearchEntry = value.isNotEmpty; + }); + }, + ), + ), + SizedBox( + width: 8, + ), + hasSearchEntry + ? GestureDetector( + child: Icon( + Icons.clear, + color: Colors.black, + ), + onTap: () { + editController.clear(); + setState(() { + hasSearchEntry = false; + }); + }, + ) + : SizedBox(), + ], + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + color: Colors.grey[100], + ), + ); + } +} diff --git a/lib/models/ChatMsg.dart b/lib/models/ChatMsg.dart new file mode 100644 index 0000000..43d6ff0 --- /dev/null +++ b/lib/models/ChatMsg.dart @@ -0,0 +1,199 @@ +import 'dart:typed_data'; +import 'dart:convert'; + +import 'package:chat/proto/chat.pbenum.dart'; +import 'package:chat/utils/file_cache_mgr.dart'; +import 'package:chat/utils/sql_util.dart'; +import 'package:chat/data/group_data_mgr.dart'; + +class MsgState { + static const int None = 0; //默认 + static const int UnUpload = 1; //未上传 + static const int Uploading = 2; //上传中 + static const int UploadFailed = 3; //上传失败 + static const int Uploaded = 4; //已上传 + static const int Sending = 5; //发送中 + static const int SendingFailed = 6; //发送失败, + static const int SendingSuccess = 7; //发送成功 + static const int Downloading = 9; //下载中 + static const int DownloadFailed = 10; //下载失败 + static const int DownloadSuccess = 11; //下载成功 +} + +class MsgModel { + int transTag; //翻译类型标记 + int channelType; //群聊还是会话 + int from; + int friendId; + int msgType; + List msgContent; + int time; //消息的时间 + int sessionId; //会话id + int readState; //0代表已显示 + String extraFile; //下载文件的识别码 + int extraInfo; //表示语音的长度信息 + List translateContent; //腾讯翻译 + List enTranslateContent; //google翻译 + String localFile; //文件的本地路径 + int state; //发送状态0默认,1代表未上传 2代表上传中,3代表已上传,4代表发送中,5发送失败,6发送成功 + int soundListened; //语音是否听过0没有,1有 + List refMsgContent; //引用的内容 + List altUsers; //@的用户 + + MsgModel(this.from, this.friendId, this.msgType, this.msgContent, this.time, + this.sessionId, + {this.extraFile, + this.extraInfo, + this.transTag = 0, + this.translateContent, + this.enTranslateContent, + this.channelType = 0, + int readState = 0, + this.localFile, + this.state = MsgState.None, + this.soundListened = 0, + this.refMsgContent, + this.altUsers}); + + copy() { + return MsgModel(this.from, this.friendId, this.msgType, this.msgContent, + this.time, this.sessionId, + extraFile: this.extraFile, + transTag: this.transTag, + translateContent: this.translateContent, + enTranslateContent: this.enTranslateContent, + extraInfo: this.extraInfo, + readState: this.readState ?? 0, + localFile: this.localFile, + state: this.state, + soundListened: this.soundListened, + refMsgContent: this.refMsgContent, + altUsers: this.altUsers); + } + + //从本地数据库数据初始化消息体 + MsgModel.fromJson(Map json, [bool isGroup = false]) { + transTag = json['transTag']; + from = json['fromId']; + friendId = json['friendId']; + msgType = json['msgType']; + msgContent = json['msgContent'] ?? Uint8List(0); + time = json['time']; + sessionId = json['sessionId']; + readState = json['readState'] ?? 0; + if (json['extraFile'] != '') { + extraFile = json['extraFile']; + } + extraInfo = json['extraInfo'] ?? 0; + + if (json['translateContent'] != null) { + translateContent = json['translateContent']; + } + if (json['enTranslateContent'] != null) { + enTranslateContent = json['enTranslateContent']; + } + + if (json['localFile'] != '') { + localFile = FileCacheMgr.replacePath(json['localFile']); + } + + soundListened = json['soundListened']; + refMsgContent = json['refMsgContent']; + altUsers = json['altUsers']; + + //群聊还是私聊 + if (isGroup) { + channelType = 1; + } else { + channelType = 0; + } + + state = json['msgState']; + } + + updateSoundListened() { + soundListened = 1; + SqlUtil().updateSoundListened(this); + } + + //人工付费翻译收费 + getNeedMoney() { + int needMoney = 0; + if (msgType == ChatType.TextChatType.value) { + int length = utf8.decode(msgContent).length; + needMoney = length ~/ 50 + 1; //每50个字耗费1H币 + + } else if (msgType == ChatType.ShortVoiceChatType.value) { + //没20秒扣除1Hb + needMoney = extraInfo != null ? extraInfo ~/ 20000 + 1 : 0; + } + + return needMoney; + } + + //获得翻译的结果数组 + getTransTextList() { + List textList = []; + if (translateContent != null && translateContent.length > 0) { + try { + var transTxt = utf8.decode(translateContent); + if (transTxt.contains('[ ')) { + transTxt = transTxt.replaceAll('[ ', '['); + } + if (transTxt.contains(' ]')) { + transTxt = transTxt.replaceAll(' ]', ']'); + } + + print('翻译结果:$transTxt'); + + if (altUsers != null && altUsers.length > 0) { + var alterStr = ''; + for (var i = 0; i < altUsers.length; i++) { + var name = GroupInfoMgr().getGroupFdName(sessionId, altUsers[i]); + alterStr = '@$name $alterStr'; + } + transTxt = '$alterStr $transTxt'; + } + + textList.add(transTxt); + } catch (e) { + var origin = utf8.decode(msgContent); + print('译文异常,原文 $origin 发送人 $from 发送时间$time'); + } + } + + //人工翻译之后就不需要这个字段了 + if (enTranslateContent != null && + enTranslateContent.length > 0 && + (transTag != 4 && transTag != 10)) { + var enTransTxt = utf8.decode(enTranslateContent); + + if (enTransTxt.contains('[ ')) { + enTransTxt = enTransTxt.replaceAll('[ ', '['); + } + if (enTransTxt.contains(' ]')) { + enTransTxt = enTransTxt.replaceAll(' ]', ']'); + } + + if (altUsers != null && altUsers.length > 0) { + var alterStr = ''; + for (var i = 0; i < altUsers.length; i++) { + var name = GroupInfoMgr().getGroupFdName(sessionId, altUsers[i]); + alterStr = '@$name $alterStr'; + } + enTransTxt = '$alterStr $enTransTxt'; + } + + textList.add(enTransTxt); + } + + if (msgType == ChatType.TextChatType.value) { + if (msgContent != null && msgContent.length > 0) { + var text = utf8.decode(msgContent); + textList.add(text); + } + } + + return textList; + } +} diff --git a/lib/models/PersonInfo.dart b/lib/models/PersonInfo.dart new file mode 100644 index 0000000..03c8e52 --- /dev/null +++ b/lib/models/PersonInfo.dart @@ -0,0 +1,32 @@ +class PersonInfo { + final String name; + final String city; + final String email; + final int age; + final String star; + final String distance; + final String professional; + final bool isOnline; + final userId; + + PersonInfo({this.name, this.email, + this.city, + this.age, + this.isOnline, + this.professional, + this.distance, + this.star, + this.userId}); + + PersonInfo.fromJson(Map json) + : name = json['name'], + email = json['email'], + city = json['city'], + age = json['age'], + star = json['star'], + professional = json['professional'], + distance = json['distance'], + isOnline = json['isOnline'], + userId = json['userId']; + +} diff --git a/lib/models/UserInfo.dart b/lib/models/UserInfo.dart new file mode 100644 index 0000000..d84b4c7 --- /dev/null +++ b/lib/models/UserInfo.dart @@ -0,0 +1,352 @@ +class UserInfo { + int userId; + String headimgurl; + String nickName; + String meetPlace; + String birthday; + String occupation; + String program; + String hopeObject; + double height; + double weight; + String ownMsg; + bool isAttestation; + bool isVipAttestation; + int invisibleStatus; + int distanceStatus; + int accountStatus; + int chatStatus; + int photoAut; + int infoAut; + String loginDate; + int onlineStatus; + int sex; + int applyStatus; + int payStatus; + String city; + String country; + int constellation; + int price; + int burnNum; + int accessNum; + int distince; + String wechat; + String facebook; + int isMember = 0; + bool isAuthority; + int freeNum; + int usedNum; + int publishNum; + int usedPublishNum; + bool isBlackList;//你是否拉黑别人 + bool isLike; + int followNum; + int fans; + int dynamicNum; + bool isCanStrangerNews; + bool isBlackened; //对方是否拉黑你 + int isAddFriends; + + UserInfo( + {this.userId, + this.headimgurl, + this.nickName = "", + this.meetPlace, + this.birthday, + this.occupation, + this.program, + this.hopeObject, + this.height, + this.weight, + this.ownMsg, + this.isAttestation = false, + this.isVipAttestation = false, + this.invisibleStatus, + this.distanceStatus, + this.accountStatus, + this.chatStatus, + this.photoAut, + this.infoAut, + this.loginDate, + this.onlineStatus, + this.payStatus, + this.applyStatus, + this.sex, + this.city, + this.constellation, + this.price, + this.burnNum, + this.accessNum, + this.distince: 0, + this.wechat: '', + this.country, + this.facebook: '', + this.isMember = 0, + this.isAuthority: false, + this.freeNum = 0, + this.usedNum = 0, + this.publishNum = 0, + this.usedPublishNum = 0, + this.isBlackList: false, + this.isLike: false, + this.fans: 0, + this.followNum: 0, + this.dynamicNum: 0, + this.isCanStrangerNews: true, + this.isAddFriends: 3, + this.isBlackened = false}); + UserInfo.fromJson(Map json) { + userId = json['UserId']; + headimgurl = json['Headimgurl']; + nickName = json['NickName']; + meetPlace = json['MeetPlace']; + birthday = json['Birthday']; + occupation = json['Occupation']; + program = json['Program']; + hopeObject = json['HopeObject']; + height = double.parse(json['Height']); + weight = double.parse(json['Weight']); + ownMsg = json['OwnMsg']; + isAttestation = json['IsAttestation'] > 0; + isVipAttestation = json['IsAttestation'] == 2; + invisibleStatus = json['InvisibleStatus']; + distanceStatus = json['DistanceStatus']; + accountStatus = json['AccountStatus']; + chatStatus = json['ChatStatus']; + photoAut = json['PhotoAut']; + infoAut = json['InfoAut']; + loginDate = json['LoginDate']; + onlineStatus = json['OnlineStatus']; + applyStatus = json['ApplyStatus']; + payStatus = json['PayStatus']; + sex = json['Sex']; + city = json['City']; + constellation = int.parse(json['Constellation']); + price = json['Price']; + burnNum = json['BurnNum']; + accessNum = json['AccessNum']; + distince = json['Distance']; + wechat = json['WxAcount']; + facebook = json['FbAcount']; + isMember = json['IsMember'] ?? 0; + isAuthority = json['IsAuthority'] == 1; + freeNum = json['FreeNum']; + usedNum = json['UsedNum']; + publishNum = json['PublishNum']; + usedPublishNum = json['UsedPublishNum']; + isBlackList = json['IsBlackList'] == 1; + country = json['Country']; + isLike = json['IsLike'] == 0; + followNum = json['FollowNum']; + fans = json['Fans']; + dynamicNum = json['DynamicNum']; + isCanStrangerNews = json['StrangerNews'] == 1; + isAddFriends = json['IsAddFriends']; + isBlackened = json['IsBlackened'] == 1; + } + + Map toJson() { + Map json = new Map(); + json['userId'] = userId; + json['headimgurl'] = headimgurl; + json['nickName'] = nickName; + json['meetPlace'] = meetPlace; + json['birthday'] = birthday; + json['occupation'] = occupation; + json['program'] = program; + json['hopeObject'] = hopeObject; + json['height'] = height; + json['weight'] = weight; + json['ownMsg'] = ownMsg; + json['isAttestation'] = isAttestation; + json['isVipAttestation'] = isVipAttestation; + json['invisibleStatus'] = invisibleStatus; + json['distanceStatus'] = distanceStatus; + json['accountStatus'] = accountStatus; + json['chatStatus'] = chatStatus; + json['photoAut'] = photoAut; + json['infoAut'] = infoAut; + json['loginDate'] = loginDate; + json['onlineStatus'] = onlineStatus; + json['applyStatus'] = applyStatus; + json['payStatus'] = payStatus; + json['sex'] = sex; + json['city'] = city; + json['constellation'] = constellation; + json['price'] = price; + json['burnNum'] = burnNum; + json['accessNum'] = accessNum; + json['distince'] = distince; + json['wechat'] = wechat; + json['facebook'] = facebook; + json['isMember'] = isMember; + json['isAuthority'] = isAuthority; + json['freeNum'] = freeNum; + json['usedNum'] = usedNum; + json['publishNum'] = publishNum; + json['usedPublishNum'] = usedPublishNum; + json['isBlackList'] = isBlackList; + json['country'] = country; + json['isLike'] = isLike; + json['followNum'] = followNum; + json['fans'] = fans; + json['dynamicNum'] = dynamicNum; + json['isCanStrangerNews'] = isCanStrangerNews; + json['isAddFriends'] = isAddFriends; + json['isBlackened'] = isBlackened; + return json; + } + + UserInfo.fromLocalJson(Map json) { + userId = json['userId']; + headimgurl = json['headimgurl']; + nickName = json['nickName']; + meetPlace = json['meetPlace']; + birthday = json['birthday']; + occupation = json['occupation']; + program = json['program']; + hopeObject = json['hopeObject']; + height = json['height']; + weight = json['weight']; + ownMsg = json['ownMsg']; + isAttestation = json['isAttestation']; + isVipAttestation = json['isVipAttestation']; + invisibleStatus = json['invisibleStatus']; + distanceStatus = json['distanceStatus']; + accountStatus = json['accountStatus']; + chatStatus = json['chatStatus']; + photoAut = json['photoAut']; + infoAut = json['infoAut']; + loginDate = json['loginDate']; + onlineStatus = json['onlineStatus']; + applyStatus = json['applyStatus']; + payStatus = json['payStatus']; + sex = json['sex']; + city = json['city']; + constellation = json['constellation']; + price = json['price']; + burnNum = json['burnNum']; + accessNum = json['accessNum']; + distince = json['distince']; + wechat = json['wechat']; + facebook = json['facebook']; + isMember = json['isMember']; + isAuthority = json['isAuthority']; + freeNum = json['freeNum']; + usedNum = json['usedNum']; + publishNum = json['publishNum']; + usedPublishNum = json['usedPublishNum']; + isBlackList = json['isBlackList']; + country = json['country']; + isLike = json['isLike']; + followNum = json['followNum']; + fans = json['fans']; + dynamicNum = json['dynamicNum']; + isCanStrangerNews = json['isCanStrangerNews']; + isAddFriends = json['isAddFriends']; + isBlackened = json['isBlackened'];// + } + + + Map toDbJson() { + Map json = new Map(); + json['userId'] = userId; + json['headimgurl'] = headimgurl; + json['nickName'] = nickName; + json['meetPlace'] = meetPlace; + json['birthday'] = birthday; + json['occupation'] = occupation; + json['program'] = program; + json['hopeObject'] = hopeObject; + json['height'] = height.toInt(); + json['weight'] = weight.toInt(); + json['ownMsg'] = ownMsg; + json['isAttestation'] = isAttestation ? 1 : 0; + json['isVipAttestation'] = isVipAttestation ? 2 : 0; + json['invisibleStatus'] = invisibleStatus; + json['distanceStatus'] = distanceStatus; + json['accountStatus'] = accountStatus; + json['chatStatus'] = chatStatus; + json['photoAut'] = photoAut; + json['infoAut'] = infoAut; + json['loginDate'] = loginDate; + json['onlineStatus'] = onlineStatus; + json['applyStatus'] = applyStatus; + json['payStatus'] = payStatus; + json['sex'] = sex; + json['city'] = city; + json['constellation'] = constellation; + json['price'] = price; + json['burnNum'] = burnNum; + json['accessNum'] = accessNum; + json['distince'] = distince; + json['wechat'] = wechat; + json['facebook'] = facebook; + json['isMember'] = isMember; + json['isAuthority'] = isAuthority ? 1: 0; + json['freeNum'] = freeNum; + json['usedNum'] = usedNum; + json['publishNum'] = publishNum; + json['usedPublishNum'] = usedPublishNum; + json['isBlackList'] = isBlackList ? 1 : 0; + json['country'] = country; + json['isLike'] = isLike ? 0 : 1; + json['followNum'] = followNum; + json['fans'] = fans; + json['dynamicNum'] = dynamicNum; + json['isCanStrangerNews'] = isCanStrangerNews ? 1 : 0; + json['isAddFriends'] = isAddFriends; + json['isBlackened'] = isBlackened ? 1 : 0; + return json; + } + + UserInfo.fromLocalDB(Map json) { + userId = json['userId']; + headimgurl = json['headimgurl']; + nickName = json['nickName']; + meetPlace = json['meetPlace']; + birthday = json['birthday']; + occupation = json['occupation']; + program = json['program']; + hopeObject = json['hopeObject']; + height = json['height'].toDouble(); + weight = json['weight'].toDouble(); + ownMsg = json['ownMsg']; + isAttestation = json['isAttestation'] > 0; + isVipAttestation = json['isVipAttestation'] == 2; + invisibleStatus = json['invisibleStatus']; + distanceStatus = json['distanceStatus']; + accountStatus = json['accountStatus']; + chatStatus = json['chatStatus']; + photoAut = json['photoAut']; + infoAut = json['infoAut']; + loginDate = json['loginDate']; + onlineStatus = json['onlineStatus']; + applyStatus = json['applyStatus']; + payStatus = json['payStatus']; + sex = json['sex']; + city = json['city']; + constellation = json['constellation']; + price = json['price']; + burnNum = json['burnNum']; + accessNum = json['accessNum']; + distince = json['distince']; + wechat = json['wechat']; + facebook = json['facebook']; + isMember = json['isMember']; + isAuthority = json['isAuthority'] == 1; + freeNum = json['freeNum']; + usedNum = json['usedNum']; + publishNum = json['publishNum']; + usedPublishNum = json['usedPublishNum']; + isBlackList = json['isBlackList'] == 1; + country = json['country']; + isLike = json['isLike'] == 0; + followNum = json['followNum']; + fans = json['fans']; + dynamicNum = json['dynamicNum']; + isCanStrangerNews = json['isCanStrangerNews'] == 1; + isAddFriends = json['isAddFriends']; + isBlackened = json['isBlackened'] == 1; + } +} diff --git a/lib/models/daily_bonus.dart b/lib/models/daily_bonus.dart new file mode 100644 index 0000000..3a7dbe2 --- /dev/null +++ b/lib/models/daily_bonus.dart @@ -0,0 +1,73 @@ + + +/// score : 0 +/// isSignIn : 1 +/// days : 31 +/// currentDay : 1 +/// startScore : 100 +/// addScore : 100 +/// goods : [{"id":1,"s":15000,"h":18,"state":1},{"id":2,"s":30000,"h":38,"state":0},{"id":7,"s":49600,"h":88,"state":0}] + +class DailyBonusBean { + int score=0; + int isSignIn=0; + int currentDay=0; + int days=31; + int startScore; + int addScore; + List goods; + + static DailyBonusBean fromMap(Map map) { + if (map == null) return null; + DailyBonusBean dataBean = DailyBonusBean(); + dataBean.score = map['score']; + dataBean.isSignIn = map['isSignIn']; + dataBean.days = map['days']; + dataBean.currentDay = map['currentDay']; + dataBean.startScore = map['startScore']; + dataBean.addScore = map['addScore']; + dataBean.goods = List()..addAll( + (map['goods'] as List ?? []).map((o) => GoodsBean.fromMap(o)) + ); + return dataBean; + } + + Map toJson() => { + "score": score, + "isSignIn": isSignIn, + "days": days, + "currentDay": currentDay, + "startScore": startScore, + "addScore": addScore, + "goods": goods, + }; +} + +/// id : 1 +/// s : 15000 +/// h : 18 +/// state : 1 + +class GoodsBean { + int id; + int s; + int h; + int state; + + static GoodsBean fromMap(Map map) { + if (map == null) return null; + GoodsBean goodsBean = GoodsBean(); + goodsBean.id = map['id']; + goodsBean.s = map['s']; + goodsBean.h = map['h']; + goodsBean.state = map['state']; + return goodsBean; + } + + Map toJson() => { + "id": id, + "s": s, + "h": h, + "state": state, + }; +} \ No newline at end of file diff --git a/lib/models/friends_info.dart b/lib/models/friends_info.dart new file mode 100644 index 0000000..bc4941b --- /dev/null +++ b/lib/models/friends_info.dart @@ -0,0 +1,199 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/ProfilePage.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/friend_list_mgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; + +class FriendsInfo extends StatelessWidget { + FriendsInfo({ + @required this.avatar, + @required this.title, + @required this.userId, + this.groupTitle, + this.onPressed, + this.gradient, + this.iconCode, + this.isShowDivder: true, + }); + final int userId; + final int iconCode; + final String avatar; + final String title; + final String groupTitle; + final VoidCallback onPressed; + final Gradient gradient; + final bool isShowDivder; + + static double height(bool hasGroupTitle) { + final _buttonHeight = MARGIN_VERTICAL * 2 + + Constants.ContactAvatarSize + + Constants.DividerWidth; + if (hasGroupTitle) { + return _buttonHeight + GROUP_TITLE_HEIGHT; + } else { + return _buttonHeight; + } + } + + @override + Widget build(BuildContext context) { + Widget _avatarIcon; + if (iconCode == null) { + _avatarIcon = ClipRRect( + borderRadius: BorderRadius.circular(6), + child: CachedNetworkImage( + imageUrl: this.avatar, + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + )); + } else { + _avatarIcon = Container( + width: Constants.ContactAvatarSize, + height: Constants.ContactAvatarSize, + decoration: BoxDecoration( + gradient: gradient, borderRadius: BorderRadius.circular(6)), + child: Icon( + IconData(this.iconCode, fontFamily: Constants.IconFontFamily), + color: Colors.white, + ), + ); + } + + Widget _button = Container( + padding: const EdgeInsets.symmetric( + vertical: MARGIN_VERTICAL, horizontal: 16.0), + decoration: BoxDecoration(color: Colors.white), + child: Row( + children: [ + _avatarIcon, + SizedBox(width: 10.0), + Text(title), + ], + ), + ); + if (userId != 0) { + _button = Dismissible( + key: Key(userId.toString()), + child: _button, + direction: DismissDirection.endToStart, + background: Container( + color: Colors.red, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + fixedText(I18n.of(context).delete, color: Colors.white), + Icon( + Icons.delete, + color: Colors.white, + ), + SizedBox(width: 20), + ], + ), + ), + confirmDismiss: (direction) async { + var _confirmContent = I18n.of(context).confirm_delete; + // CustomUI.buildOneConfirm( + // context, _confirmContent, I18n.of(context).determine, () async { + // Map data = { + // "userId": UserData().basicInfo.userId, + // "friendsUserId": userId, + // }; + // data['sign'] = TokenMgr().getSign(data); + + // Response res = await HttpUtil().post('friendship/delete/friends', + // data: data, isShowLoading: true); + + // Map resData = res.data; + // showToast(resData['msg']); + // if (resData['code'] == 0) { + // FriendListMgr().delteFriend(userId); + // MessageMgr().emit('Delete friend'); + // } + // Navigator.of(context).pop(true); + // }); + //return false; + bool isDismiss = await CustomUI.showIosDialog( + context, _confirmContent, () async { + Map data = { + "userId": UserData().basicInfo.userId, + "friendsUserId": userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('friendship/delete/friends', + data: data, isShowLoading: true); + + Map resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + FriendListMgr().delteFriend(userId); + MessageMgr().emit('Delete friend'); + } + Navigator.of(context).pop(true); + }, () { + Navigator.of(context).pop(false); + }); + + return isDismiss; + }); + } + //分组标签 + Widget _itemBody; + if (this.groupTitle != null) { + _itemBody = Column( + children: [ + Container( + height: GROUP_TITLE_HEIGHT, + padding: EdgeInsets.only(left: 16.0, right: 16.0), + color: const Color(AppColors.ContactGroupTitleBgColor), + alignment: Alignment.centerLeft, + child: + Text(this.groupTitle, style: AppStyles.GroupTitleItemTextStyle), + ), + _button, + ], + ); + } else { + _itemBody = _button; + } + + return InkWell( + onTap: onPressed == null + ? () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: userId, + ); + }, + ), + ); + } + : onPressed, + child: Container( + color: Colors.white, + child: Column( + children: [ + _itemBody, + isShowDivder + ? Container( + height: 1, + color: const Color(0xFFF3F3F3), + margin: EdgeInsets.only( + left: 26 + Constants.ContactAvatarSize), + ) + : Container() + ], + ))); + } +} diff --git a/lib/models/gift_item_model.dart b/lib/models/gift_item_model.dart new file mode 100644 index 0000000..b9facb7 --- /dev/null +++ b/lib/models/gift_item_model.dart @@ -0,0 +1,34 @@ +class GiftItemModel { + int id; + String name; + int price; + int amount;//用户当前拥有的数量 + String imgurl; + + GiftItemModel({this.id, this.name, this.price, this.imgurl, this.amount}); + + GiftItemModel.fromJson(Map json) { + id = json['id']; + name = json['name']; + price = json['price']; + imgurl = json['imgurl']; + amount = json['amount']; + } + + GiftItemModel.havedFromJson(Map json) { + id = json['Id']; + name = json['Name']; + imgurl = json['ImgUrl']; + amount = json['GetAmount']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['price'] = this.price; + data['imgurl'] = this.imgurl; + data['amount'] = this.amount; + return data; + } +} diff --git a/lib/models/gift_select_provider.dart b/lib/models/gift_select_provider.dart new file mode 100644 index 0000000..5ed799d --- /dev/null +++ b/lib/models/gift_select_provider.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; + +class GiftSelectProvider with ChangeNotifier { + int curSelectIndex = 0; + + changeSelectIndex(int newIndex) { + curSelectIndex = newIndex; + notifyListeners(); + } +} diff --git a/lib/models/group_info_model.dart b/lib/models/group_info_model.dart new file mode 100644 index 0000000..70c4999 --- /dev/null +++ b/lib/models/group_info_model.dart @@ -0,0 +1,396 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/group_info_server_model.dart'; +import 'package:chat/models/last_message_model.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/group_member_model.dart'; +import 'package:chat/utils/sql_util.dart'; + +class GroupInfoModel { + int sessionId; //群ID + List members; //群成员 + int hosterId; // 群主id + int topTag; //是否置顶 + String describe; //群公告 + int decribeTime; //群公告时间 + String name; //群名称 + LastMessageModel lastMsg; + String image; //群图片 + String myName; //我在群中的别名 + int isSave; //是否保存到通讯录 + int askSwitch; //是否开启验证 + int messageFree; //群信息提醒 + int isShowName; //在聊天消息中是否显示名称 + bool isInGroup; //自己是否还在该群中 + + GroupInfoModel(this.sessionId, + {this.hosterId, + this.topTag = 0, + this.describe = '', + this.decribeTime = 0, + this.name = '', + this.image = '', + this.myName = '', + this.askSwitch = 0, + this.messageFree = 0, + this.isShowName = 1, + this.isSave = 0, + this.isInGroup = true}) + : this.members = []; + + GroupInfoModel.fromJson(Map jsonStr) { + print('群信息 $jsonStr'); + this.sessionId = jsonStr['sessionId']; + this.hosterId = jsonStr['hosterId']; + this.topTag = jsonStr['topTag'] ?? 0; + this.describe = jsonStr['describe']; + this.decribeTime = jsonStr['decribeTime']; + this.name = jsonStr['name']; + this.image = jsonStr['image']; + this.myName = jsonStr['my_name']; + this.askSwitch = jsonStr['ask_switch'] ?? 0; + this.isSave = jsonStr['is_save'] ?? 0; + this.messageFree = jsonStr['messageFree'] ?? 0; + this.isShowName = jsonStr['show_name'] ?? 1; + this.isInGroup = true; + } + + GroupInfoModel.fromInfo(GroupInfo groupInfo) { + this.sessionId = groupInfo.id; + + var myId = UserData().basicInfo.userId; + if (members == null) { + members = []; + } + + for (var i = 0; i < groupInfo.members.length; i++) { + var member = groupInfo.members[i]; + GroupMemberModel model = GroupMemberModel.fromPb(member); + members.add(model); + + if (model.identity == GroupMemberIdentity.identityMaster.value) { + hosterId = model.memberId; + } + if (member.info.id == myId) { + myName = member.name; + messageFree = member.messageFree ? 1 : 0; + } + } + + describe = groupInfo.notice; + askSwitch = groupInfo.isOpenMemberCheck ? 1 : 0; + isShowName = members.length > 20 ? 1 : 0;//群人数大于20个自动打开 + topTag = 0; + isSave = 0; + this.isInGroup = true; + this.name = groupInfo.groupName; + } + + GroupInfoModel.fromServerGroupInfo(GroupInfoServerModel groupInfo) { + this.sessionId = groupInfo.id; + + var myId = UserData().basicInfo.userId; + if (members == null) { + members = []; + } + + for (var i = 0; i < groupInfo.members.length; i++) { + var member = groupInfo.members[i]; + GroupMemberModel model = GroupMemberModel.fromServerMember(member); + members.add(model); + + if (model.identity == GroupMemberIdentity.identityMaster.value) { + hosterId = model.memberId; + } + if (member.info.id == myId) { + myName = member.name; + messageFree = member.messageFree ? 1 : 0; + } + } + + describe = groupInfo.notice; + askSwitch = groupInfo.isOpenMemberCheck ? 1 : 0; + isShowName = members.length > 20 ? 1 : 0;//群人数大于20个自动打开 + isSave = 0; + topTag = 0; + this.isInGroup = true; + this.name = groupInfo.groupName; + } + + updateWithInfo(GroupInfoModel groupInfo) { + members = groupInfo.members; + describe = groupInfo.describe; + name = groupInfo.name; + askSwitch = groupInfo.askSwitch; + messageFree = groupInfo.messageFree; + myName = groupInfo.myName; + hosterId = groupInfo.hosterId; + image = groupInfo.image; + isShowName = groupInfo.isShowName; + isSave = groupInfo.isSave; + } + + //是否可以修改群名称 + canAlterGroupName() { + //70人以上的群只有群主或者管理员才能修改群名 + if (members.length >= 70) { + int myId = UserData().basicInfo.userId; + var myInfo = getMember(myId); + if (myInfo != null && + (myInfo.identity == GroupMemberIdentity.identityMaster.value || + myInfo.identity == GroupMemberIdentity.identityManager.value)) { + return true; + } else { + return false; + } + } else { + //普通群都可以修改群名 + return true; + } + } + + //更新最新的消息 + updateLastMsg(MsgModel msgModel) { + if (msgModel == null) { + print('消息未空,无法初始化最新消息'); + return; + } + if (lastMsg != null) { + //更新 + lastMsg.updateWithMessage(msgModel); + } else { + lastMsg = LastMessageModel.fromChatMsg(msgModel); + } + MessageMgr().emit('Update Group List'); + print('msgModel.sessionId ${msgModel.sessionId}'); + MessageMgr().emit('Update LastMsg', msgModel.sessionId); + } + + //更新最新的消息 + updateLastMsgWithUnread(UserUnreadMsgNotice unread) { + if (lastMsg == null) { + lastMsg = LastMessageModel.fromUnreadMsg(unread); + } else { + lastMsg.updateWithUnreadMsg(unread); + } + + MessageMgr().emit('Update Group List'); + MessageMgr().emit('Update LastMsg', unread.targetId); + } + + updateLastMsgWithTransMsg(PushChat chat) { + //更新 + if (chat.cType == ChatType.TextChatType) { + print('更新最新数据的翻译结果'); + + if (lastMsg != null && chat.hasTencentTranslate()) { + lastMsg.msgContent = chat.tencentTranslate; + } + MessageMgr().emit('Update Group List'); + MessageMgr().emit('Update LastMsg', chat.targetId); + } + } + + //获取还在群中的成员 + List getMembersInGroup() { + List inMembers = []; + + for (var i = 0; i < members.length; i++) { + if (members[i].inGroup == 1) { + inMembers.add(members[i]); + } + } + + return inMembers; + } + + getHoster() { + for (var i = 0; i < members.length; i++) { + if (members[i].identity == GroupMemberIdentity.identityMaster.value) { + return members[i]; + } + } + return null; + } + + getGroupName(Map refMap) { + if (name != null && name != '') { + return name; + } else { + var members = getMembersInGroup(); + String res = ''; + int nums = members.length > 4 ? 4 : members.length; + for (int i = 0; i < nums; i++) { + if (i != 0) { + res += '、'; + } + if (refMap[members[i].memberId] != null) { + String name = (refMap[members[i].memberId] as String); + res += name.length>8?name.substring(0,8)+'..':name; + } else { + String name = members[i].refName; + res += name.length>8?name.substring(0,8)+'..':name; + } + } + return res; + } + } + + //置顶 + updateTopTag(bool isTop) { + topTag = isTop ? 1 : 0; + SqlUtil.groupInfoTableModel.updateTopTag(sessionId, topTag); + } + + //修改群校验开关 + updateAskSwitch(bool isOpen) { + askSwitch = isOpen ? 1 : 0; + SqlUtil.groupInfoTableModel.updateAskSwitch(sessionId, askSwitch); + } + + //修改是否在聊天中展示用户名称 + updateShowNameSwitch(bool isShow) { + isShowName = isShow ? 1 : 0; + SqlUtil.groupInfoTableModel.updateShowNameSwitch(sessionId, isShowName); + } + + //添加群成员 + addMember(GroupMemberModel member) { + var oldMember = getMember(member.memberId); + + //如果该群中已有数据,更新状态 + if (oldMember != null) { + if (oldMember.inGroup == 0) { + oldMember.inGroup = 1; + SqlUtil.groupMemberTableModel + .updateMemberState(sessionId, member.memberId, 1); + } + } else { + members.add(member); + SqlUtil.groupMemberTableModel.addSingleMember(sessionId, member); + } + print('addMember ${member.memberId} ${UserData().basicInfo.userId}'); + if (member.memberId == UserData().basicInfo.userId) { + print('addMember ture'); + isInGroup = true; + } + + MessageMgr().emit('Update Group Info'); + } + + //删除成员,更新状态即可 + removeMember(int uId) { + var member = getMember(uId); + if (member != null) { + member.inGroup = 0; + SqlUtil.groupMemberTableModel.updateMemberState(sessionId, uId, 0); + } + } + + //修改群名称 + updateGroupName(String groupName) { + name = groupName; + + SqlUtil.groupInfoTableModel.updateGroupName(sessionId, groupName); + + MessageMgr().emit('Update Group Info'); + } + + //修改群公告 + updateGroupNotice(String notice) { + describe = notice; + SqlUtil.groupInfoTableModel.updateGroupNotice(sessionId, notice); + + MessageMgr().emit('Update Group Info'); + } + + GroupMemberModel getMember(int uId) { + for (var i = 0; i < members.length; i++) { + if (members[i].memberId == uId) { + return members[i]; + } + } + + print('找不到该成员$uId'); + + return null; + } + + //修改成员免打扰设置 + updateMemberMsgFree(int isAvoid) { + messageFree = isAvoid; + MessageMgr().emit('Update Group Info'); + SqlUtil.groupInfoTableModel.updateGroupMesssageFree(sessionId, isAvoid); + } + + //修改成员别名 + updateMemberRefName(int uId, String refName) { + print('修改成员别名 $uId $refName'); + var member = getMember(uId); + if (member != null) { + member.refName = refName; + if (uId == UserData().basicInfo.userId) { + //自己 + myName = refName; + SqlUtil.groupInfoTableModel.updateMyName(sessionId, refName); + } else { + SqlUtil.groupMemberTableModel + .updateMemberRefName(sessionId, uId, refName); + } + + MessageMgr().emit('Update Group Info'); + } + } + + //修改群主 + updateGroupHoster(int oldId, int uId) { + //系统 + if (oldId == 0) { + //去除旧的群主 + for (var i = 0; i < members.length; i++) { + if (members[i].identity == GroupMemberIdentity.identityMaster.value) { + members[i].identity = 0; + SqlUtil.groupMemberTableModel + .updateMemberIdentity(sessionId, members[i].memberId, 0); + break; + } + } + } else { + var member = getMember(oldId); + member.identity = 0; + SqlUtil.groupMemberTableModel + .updateMemberIdentity(sessionId, member.memberId, 0); + } + + //修改新的群主 + var member = getMember(uId); + if (member != null) { + hosterId = member.memberId; + member.identity = GroupMemberIdentity.identityMaster.value; + SqlUtil.groupMemberTableModel + .updateMemberIdentity(sessionId, member.memberId, member.identity); + SqlUtil.groupInfoTableModel.updateHoster(sessionId, member.memberId); + } + MessageMgr().emit('Update Group Info'); + } + + //判断是否在群中 + bool isGroupMember(int userId) { + for (var i = 0; i < members.length; i++) { + if (members[i].memberId == userId) { + return members[i].inGroup == 1; + } + } + return false; + } + + updateAvatar(String path) { + image = path; + SqlUtil.groupInfoTableModel.updateImage(sessionId, image); + } + + cleanAvatar() { + image = ''; + } +} diff --git a/lib/models/group_info_server_model.dart b/lib/models/group_info_server_model.dart new file mode 100644 index 0000000..b72735a --- /dev/null +++ b/lib/models/group_info_server_model.dart @@ -0,0 +1,93 @@ +class GroupInfoServerModel { + int id; + String groupName; + String notice; + bool isOpenMemberCheck; + + List members; + + GroupInfoServerModel({this.id, this.groupName, this.notice, this.members}); + + GroupInfoServerModel.fromJson(Map json) { + id = json['Id']; + groupName = json['GroupName']; + print('服务器群名:$groupName'); + notice = json['Notice']; + isOpenMemberCheck = json['IsOpenMemberCheck']??false; + + if (json['Members'] != null) { + members = new List(); + json['Members'].forEach((v) { + members.add(new GroupServerMembers.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['Id'] = this.id; + data['GroupName'] = this.groupName; + data['Notice'] = this.notice; + if (this.members != null) { + data['Members'] = this.members.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class GroupServerMembers { + BaseServerInfo info; + String name; + int identity; + bool messageFree; + bool effectiveUser; + + GroupServerMembers( + {this.info, + this.name, + this.identity, + this.messageFree, + this.effectiveUser}); + + GroupServerMembers.fromJson(Map json) { + info = json['Info'] != null ? new BaseServerInfo.fromJson(json['Info']) : null; + name = json['Name']; + identity = json['Identity']; + messageFree = json['MessageFree']; + effectiveUser = json['EffectiveUser']; + } + + Map toJson() { + final Map data = new Map(); + if (this.info != null) { + data['Info'] = this.info.toJson(); + } + data['Name'] = this.name; + data['Identity'] = this.identity; + data['MessageFree'] = this.messageFree; + data['EffectiveUser'] = this.effectiveUser; + return data; + } +} + +class BaseServerInfo { + int id; + String niceName; + String headUrl; + + BaseServerInfo({this.id, this.niceName, this.headUrl}); + + BaseServerInfo.fromJson(Map json) { + id = json['Id']; + niceName = json['NiceName']; + headUrl = json['HeadUrl']; + } + + Map toJson() { + final Map data = new Map(); + data['Id'] = this.id; + data['NiceName'] = this.niceName; + data['HeadUrl'] = this.headUrl; + return data; + } +} diff --git a/lib/models/group_list_provider.dart b/lib/models/group_list_provider.dart new file mode 100644 index 0000000..dad8aa6 --- /dev/null +++ b/lib/models/group_list_provider.dart @@ -0,0 +1,20 @@ +import 'package:chat/utils/conversation_table.dart'; +import 'package:flutter/material.dart'; + +class GroupSelectProvider with ChangeNotifier { + List curSelectFriendList = []; + + addFriend(FriendModel friendModel) { + curSelectFriendList.add(friendModel); + notifyListeners(); + } + + removeFriend(FriendModel friendModel) { + curSelectFriendList.remove(friendModel); + notifyListeners(); + } + + isSelect(FriendModel friendModel) { + return curSelectFriendList.contains(friendModel); + } +} diff --git a/lib/models/keyboard_provider.dart b/lib/models/keyboard_provider.dart new file mode 100644 index 0000000..310e590 --- /dev/null +++ b/lib/models/keyboard_provider.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; + +class KeyboardIndexProvider with ChangeNotifier { + int curKeyboardIndex = -1; + + bool soundPlayMode = false; + + bool readOnly = true; + + init(bool bl) { + soundPlayMode = bl; + } + + changeSoundPlayMode(bool playmode) { + soundPlayMode = playmode; + notifyListeners(); + } + + changeReadOnlyKey(bool emoji) { + readOnly = emoji; + notifyListeners(); + } + + changeSelectIndex(int newIndex) { + if (newIndex != curKeyboardIndex) { + curKeyboardIndex = newIndex; + if (newIndex != 0) { + readOnly = true; + }else{ + readOnly = false; + } + print('设置当前键盘 $newIndex'); + notifyListeners(); + } + } +} diff --git a/lib/models/last_message_model.dart b/lib/models/last_message_model.dart new file mode 100644 index 0000000..62df97b --- /dev/null +++ b/lib/models/last_message_model.dart @@ -0,0 +1,132 @@ + +import 'package:chat/data/UserData.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/proto/all.pbserver.dart'; + +class LastMessageModel { + int channelType; + int friendId; + int sessionId; + int fromId; + int updateAt; + ChatType type; + List msgContent; + + LastMessageModel( + {this.sessionId, + this.friendId, + this.fromId, + this.updateAt, + this.type, + this.msgContent, + this.channelType = 0}); + + LastMessageModel.fromChatMsg(MsgModel msgModel) { +// print('### gg msgModel from:${msgModel.from} msgModel.friendId ${ msgModel.friendId} msgModel.sessionId ${msgModel.sessionId} msgtype ${msgModel.msgType}'); + sessionId = msgModel.sessionId; + fromId = msgModel.from; + if (msgModel.from == UserData().basicInfo.userId) { + //自己 + friendId = msgModel.friendId; + } else { + friendId = msgModel.from; + } + + channelType = msgModel.channelType; + + type = ChatType.valueOf(msgModel.msgType); + msgContent = msgModel.msgContent; + if (type == ChatType.TextChatType) { + if (msgModel.translateContent != null && + msgModel.translateContent.length > 0) { + msgContent = msgModel.translateContent; + } + } + + updateAt = msgModel.time; + } + + updateWithMessage(MsgModel msgModel) { + fromId = msgModel.from; + + type = ChatType.valueOf(msgModel.msgType); + msgContent = msgModel.msgContent; + if (type == ChatType.TextChatType) { + if (msgModel.translateContent != null && + msgModel.translateContent.length > 0) { + msgContent = msgModel.translateContent; + } + } + + updateAt = msgModel.time; + } + + LastMessageModel.fromUnreadMsg(UserUnreadMsgNotice notice) { + var lastMsg = notice.lastUnreadMsg; + + sessionId = notice.targetId; + fromId = lastMsg.sendUserId; + friendId = fromId; + + channelType = notice.channelType.value; + + print('未读$sessionId from:$fromId'); + + type = lastMsg.cType; + msgContent = lastMsg.contentBuff; + if (lastMsg.hasTencentTranslate()) { + msgContent = lastMsg.tencentTranslate; + } + + ///解析红包消息 + if(lastMsg.cType== ChatType.RedWalletChatType){ + RedWallet wallet = RedWallet.fromBuffer(lastMsg.contentBuff); + var myId = UserData().basicInfo.userId; + + if (myId == wallet.suId) { + friendId = wallet.tuId; + } else { + friendId = wallet.suId; + } + }else if(lastMsg.cType == ChatType.GroupChatNoticeType){ + GroupChatNotice notice = GroupChatNotice.fromBuffer(lastMsg.contentBuff); + + var optId = notice.operatuId; + print('### gourp add optid ${optId.id}'); + List optedIds = notice.operateduId; + for(int k=0;k _LastMsgDescriptionState(); +} + +class _LastMsgDescriptionState extends State { + var desc = ''; + + @override + void initState() { + super.initState(); + getLastMsgDesc(); + + MessageMgr().on('Update LastMsg', updateList); + } + + @override + void dispose() { + MessageMgr().off('Update LastMsg', updateList); + super.dispose(); + } + + updateList(sessionId) { + if (sessionId == widget.lastMessageModel.sessionId) { + getLastMsgDesc(); + } + } + + //获取用户的名字 + getFriendName() async { + String fdName; + + if (widget.lastMessageModel.channelType == ChatChannelType.Group.value) { + //群的最新消息 + fdName = Provider.of(context).getGroupRefName( + widget.lastMessageModel.sessionId, widget.lastMessageModel.fromId); + } else { + //私聊最新消息 + var friendInfo = + await HttpUtil().getFriendInfo(widget.lastMessageModel.friendId); + if (friendInfo != null) { + fdName = Provider.of(context) + .getRefName(friendInfo.userId, friendInfo.nickName); + } + } + return fdName; + } + + getLastMsgDesc() async { + MessageMgr().emit('Update Group List'); + if (widget.lastMessageModel == null) { + return; + } + switch (widget.lastMessageModel.type) { + case ChatType.TextChatType: + desc = utf8.decode(widget.lastMessageModel.msgContent); + print('desc: $desc'); + if (desc.contains('[ ')) { + desc = desc.replaceAll('[ ', '['); + } + if (desc.contains(' ]')) { + desc = desc.replaceAll(' ]', ']'); + } + break; + case ChatType.EmoticonType: + desc = '[${I18n.of(LoadingManage.context).emoji}]'; + break; + case ChatType.ImageChatType: + desc = '[${I18n.of(LoadingManage.context).picture}]'; + break; + case ChatType.ShortVideoChatType: + desc = '[${I18n.of(LoadingManage.context).video}]'; + break; + case ChatType.PlaceChatType: + desc = '[${I18n.of(LoadingManage.context).locate}]'; + break; + case ChatType.ShortVoiceChatType: + desc = '[${I18n.of(LoadingManage.context).voice}]'; + break; + + case ChatType.GiftChatType: + GiftChat giftChat = + GiftChat.fromBuffer(widget.lastMessageModel.msgContent); + + if (giftChat.tuId == UserData().basicInfo.userId) { + desc = I18n.of(LoadingManage.context).you_get; + } else { + desc = I18n.of(LoadingManage.context).you_give; + } + + break; + + case ChatType.RedWalletChatType: + if (widget.lastMessageModel.fromId == 0) { + var fdName = await getFriendName(); + //服务器通知消息 + RedWallet wallet = + RedWallet.fromBuffer(widget.lastMessageModel.msgContent); + if (wallet.state == RedWalletState.Received) { + var myId = UserData().basicInfo.userId; + if (wallet.suId == myId) { + desc = I18n.of(LoadingManage.context) + .get_money + .replaceFirst('/s1', fdName); + } else { + desc = I18n.of(LoadingManage.context) + .you_get_money + .replaceFirst('/s1', fdName); + } + } else if (wallet.state == RedWalletState.Expire) { + desc = I18n.of(LoadingManage.context).money_over; + } else { + print('WWWWW${wallet.state}'); + } + } else { + desc = '[${I18n.of(LoadingManage.context).red_money}]'; + } + break; + + case ChatType.GroupChatNoticeType: + var notice = + GroupChatNotice.fromBuffer(widget.lastMessageModel.msgContent); + print('widget.lastMessageModel.type ${widget.lastMessageModel.type}'); + var groupInfo = await GroupInfoMgr() + .getGroupInfo(widget.lastMessageModel.sessionId); + + desc = MsgHandler.getGroupNoticeMsg(notice, groupInfo); + print('ggdesc $desc}'); + if (desc.contains('\$')) { + desc = desc.substring(0, desc.indexOf('\$')); + } else {} + + break; + + case ChatType.FileChatType: + desc = '[文件]'; + break; + default: + } + if (mounted) { + setState(() {}); + } + } + + @override + Widget build(BuildContext context) { + if (widget.lastMessageModel == null) { + return Container(); + } + + if (widget.lastMessageModel.type == ChatType.TextChatType) { + //处理表情 + return extendedText(desc, + fontSize: 12, + color: Constants.GreyTextColor, + emojisize: 12.0, + maxLines: 1); + } else { + return Text(desc, + textScaleFactor: 1.0, + textAlign: TextAlign.center, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: AppStyles.DescStyle); + } + } +} diff --git a/lib/models/last_msg_provider.dart b/lib/models/last_msg_provider.dart new file mode 100644 index 0000000..d76502f --- /dev/null +++ b/lib/models/last_msg_provider.dart @@ -0,0 +1,112 @@ +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/last_message_model.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:flutter/material.dart'; + +class LastMsgProvider with ChangeNotifier { + List lastMsgList = []; + + addMsg(MsgModel msgModel) { + var lastMsg = getLastRecordBy(msgModel.sessionId); + + //服务器消息优先级高 + if (lastMsg == null) { + lastMsg = LastMessageModel.fromChatMsg(msgModel); + lastMsgList.insert(0, lastMsg); + + if (msgModel.channelType == ChatChannelType.Group.value) { + MessageMgr().emit('Update Group List'); + } else { + MessageMgr().emit('Update LastMsg',lastMsg.sessionId); + } + } + } + + + sortLastMsg() { + lastMsgList.sort((b, a) => a.updateAt.compareTo(b.updateAt)); + } + + updateLastMsg(MsgModel msgModel) { + var lastMsg = getLastRecordBy(msgModel.sessionId); + + if (lastMsg != null) { + //更新 + lastMsg.updateWithMessage(msgModel); + lastMsgList.sort((b, a) => a.updateAt.compareTo(b.updateAt)); + } else { + lastMsg = LastMessageModel.fromChatMsg(msgModel); + lastMsgList.insert(0, lastMsg); + } + + if (msgModel.channelType == ChatChannelType.Group.value) { + MessageMgr().emit('Update Group List'); + } else { + MessageMgr().emit('Update LastMsg',lastMsg.sessionId); + } + } + + updateWithTranslateMsg(PushChat chat) { + //更新 + if (chat.cType == ChatType.TextChatType) { + print('更新最新数据的翻译结果'); + var lastMsg = getLastRecordBy(chat.targetId); + + if (lastMsg != null && chat.hasTencentTranslate()) { + lastMsg.msgContent = chat.tencentTranslate; + } + + if (chat.channelType == ChatChannelType.Group) { + MessageMgr().emit('Update Group List'); + } else { + MessageMgr().emit('Update LastMsg',lastMsg.sessionId); + } + } + } + + addUnreadMsg(UserUnreadMsgNotice unread) { + var lastMsg = getLastRecordBy(unread.targetId); + if (lastMsg == null) { + lastMsg = LastMessageModel.fromUnreadMsg(unread); + lastMsgList.insert(0, lastMsg); + + //可能是新增的用户 + + } else { + lastMsg.updateWithUnreadMsg(unread); + lastMsgList.sort((b, a) => a.updateAt.compareTo(b.updateAt)); + } + + if (unread.channelType == ChatChannelType.Group) { + MessageMgr().emit('Update Group List'); + } else { + MessageMgr().emit('Update LastMsg',lastMsg.sessionId); + } + } + + + deleteMsg(LastMessageModel msgModel) { + lastMsgList.remove(msgModel); + if (msgModel.channelType == ChatChannelType.Group.value) { + MessageMgr().emit('Update Group List'); + } else { + MessageMgr().emit('Update LastMsg',msgModel.sessionId); + } + } + + LastMessageModel getLastRecordBy(int sessionId) { + for (var i = 0; i < lastMsgList.length; i++) { + var lastMsg = lastMsgList[i]; + if (lastMsg.sessionId == sessionId) { + return lastMsg; + } + } + + return null; + } + + clear() { + lastMsgList.clear(); + } +} diff --git a/lib/models/list_msg_model.dart b/lib/models/list_msg_model.dart new file mode 100644 index 0000000..b593ddf --- /dev/null +++ b/lib/models/list_msg_model.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; + +class ListModel { + final GlobalKey listKey; + final List _items; + + ListModel({ + @required this.listKey, + List initialItems, + }) : assert(listKey != null), + _items = initialItems ?? []; + + AnimatedListState get _animateList => listKey.currentState; + + int get length => _items.length; + T operator [](int index) => _items[index]; + int indexOf(T item) => _items.indexOf(item); + + void insert(int index, T item) { + _items.insert(index, item); + _animateList.insertItem(index); + } + + void remove(T item) { + int index = _items.indexOf(item); + _items.remove(item); + _animateList.removeItem(index, + (BuildContext context, Animation animation) { + return Container(); + }); + } + + void add(T item) { + int curLen = _items.length; + + _items.insert(curLen, item); + _animateList.insertItem(curLen, duration: Duration(milliseconds: 100)); + + var scrollCtrl = _animateList.widget.controller; + Future.delayed(Duration(milliseconds: 300), () { + scrollCtrl.animateTo(scrollCtrl.position.maxScrollExtent, + curve: Curves.ease, duration: Duration(milliseconds: 300)); + }); + } +} diff --git a/lib/models/money_change.dart b/lib/models/money_change.dart new file mode 100644 index 0000000..2c9a9ab --- /dev/null +++ b/lib/models/money_change.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; + +class MoneyChangeProvider with ChangeNotifier { + int money = 0; + + initMoney(int fromMoney) { + money = fromMoney; + notifyListeners(); + } + + addMoney(int fromMoney) { + money += fromMoney; + notifyListeners(); + } + + subMoney(int fromMoney) { + money -= fromMoney; + notifyListeners(); + } +} diff --git a/lib/models/received_notification.dart b/lib/models/received_notification.dart new file mode 100644 index 0000000..fd535c8 --- /dev/null +++ b/lib/models/received_notification.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; + +class ReceivedNotification { + final int id; + final String title; + final String body; + final String payload; + + ReceivedNotification( + {@required this.id, + @required this.title, + @required this.body, + @required this.payload}); +} \ No newline at end of file diff --git a/lib/models/ref_name_provider.dart b/lib/models/ref_name_provider.dart new file mode 100644 index 0000000..6fe7e76 --- /dev/null +++ b/lib/models/ref_name_provider.dart @@ -0,0 +1,121 @@ +import 'dart:convert'; + +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/friend_list_mgr.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class RefNameProvider with ChangeNotifier { + int curSelectIndex = 0; + Map refMap = {}; + + init() async { + print('初始化别名'); + var sp = await SharedPreferences.getInstance(); + List refList = + sp.getStringList('Ref_Name' + UserData().basicInfo.userId.toString()); + refMap.clear(); + if (refList != null) { + for (var i = 0; i < refList.length; i++) { + Map ref = json.decode(refList[i]); + refMap[ref['userId']] = ref['refName']; + } + notifyListeners(); + } else { + sysnRefListFromServer(); + } + } + + sysnRefListFromServer() async { + Map data = {"userId": UserData().basicInfo.userId}; + data['sign'] = TokenMgr().getSign(data); + try { + Response res = await HttpUtil().post('alias/user/list', data: data); + if (res == null) { + return; + } + var resData = res.data; + if (resData['code'] == 0) { + List jsonList = resData['data']; + if (jsonList == null || jsonList.length == 0) { + return; + } + + for (var i = 0; i < jsonList.length; i++) { + var ref = jsonList[i]; + refMap[ref['userId']] = Uri.decodeComponent(ref['aliasName']); + } + } + } catch (e) {} + } + + getRefName(int userId, String name) { + return refMap[userId] == null ? name : refMap[userId]; + } + + String getGroupRefName(int sessionId, int userId) { + if (refMap[userId] != null) { + return refMap[userId]; + } + + var groupRefName = GroupInfoMgr().getGroupFdName(sessionId, userId); + if (groupRefName != null) { + return groupRefName; + } + + return ''; + } + + changeRefName(int userId, String refName, callback) { + if (refName == null || refName == '') { + refMap.remove(userId); + } else { + refMap[userId] = refName; + } + + notifyListeners(); + + saveRefName(); + FriendListMgr().updateRefNmae(userId); + commitChangeToServer(userId, refName, callback); + } + + commitChangeToServer(int userId, String refName, callback) async { + Map data = {"userId": UserData().basicInfo.userId, "aliasUserId": userId}; + data['sign'] = TokenMgr().getSign(data); + data["aliasName"] = Uri.encodeComponent(refName); + + try { + Response res = await HttpUtil() + .post('alias/set/up', data: data, isShowLoading: true); + if (res == null) { + return; + } + var resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + print('设置别名成功'); + if (callback != null) callback(); + } else { + print(resData.msg); + } + } catch (e) {} + } + + saveRefName() async { + List refList = []; + refMap.keys.forEach((userId) { + var refStr = json.encode({"userId": userId, "refName": refMap[userId]}); + refList.add(refStr); + }); + + var sp = await SharedPreferences.getInstance(); + sp.setStringList( + 'Ref_Name' + UserData().basicInfo.userId.toString(), refList); + } +} diff --git a/lib/models/unread_count_provider.dart b/lib/models/unread_count_provider.dart new file mode 100644 index 0000000..62cbf43 --- /dev/null +++ b/lib/models/unread_count_provider.dart @@ -0,0 +1,43 @@ +import 'package:chat/utils/MessageMgr.dart'; + +class UnreadCountProvider { +//未读消息条数管理 + Map unreadCountMap = {}; + + updateUnreadCount(int sessionId, int count) { + if (unreadCountMap[sessionId] == null) { + unreadCountMap[sessionId] = 0; + } + unreadCountMap[sessionId] += count; + + MessageMgr().emit('Update UnreadCount', sessionId); + } + + clear() { + unreadCountMap.clear(); + } + + int getUnreadCount(int sessionId) { + return unreadCountMap[sessionId] ?? 0; + } + + bool checkUnreadMsg() { + for (var v in unreadCountMap.values) { + if (v > 0) { + return true; + } + } + return false; + } + + signRead(int sessionId) { + print('消除未读标记:$sessionId'); + + int count = getUnreadCount(sessionId); + if (count > 0) { + unreadCountMap[sessionId] = 0; + + MessageMgr().emit('Update UnreadCount', sessionId); + } + } +} diff --git a/lib/models/voucher_change.dart b/lib/models/voucher_change.dart new file mode 100644 index 0000000..08707a5 --- /dev/null +++ b/lib/models/voucher_change.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; + +class VoucherChangeProvider with ChangeNotifier { + int voucher = 0; + + initVoucher(int newValue) { + voucher = newValue; + notifyListeners(); + } + + addVoucher(int newValue) { + voucher += newValue; + notifyListeners(); + } + + subVoucher(int newValue) { + voucher -= newValue; + notifyListeners(); + } +} diff --git a/lib/photo/delegate/loading_delegate.dart b/lib/photo/delegate/loading_delegate.dart new file mode 100644 index 0000000..23703ac --- /dev/null +++ b/lib/photo/delegate/loading_delegate.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:photo_manager/photo_manager.dart'; + +abstract class LoadingDelegate { + Widget buildBigImageLoading( + BuildContext context, AssetEntity entity, Color themeColor); + + Widget buildPreviewLoading( + BuildContext context, AssetEntity entity, Color themeColor); +} + +class DefaultLoadingDelegate extends LoadingDelegate { + @override + Widget buildBigImageLoading( + BuildContext context, AssetEntity entity, Color themeColor) { + return Center( + child: Container( + width: 30.0, + height: 30.0, + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(themeColor), + ), + ), + ); + } + + @override + Widget buildPreviewLoading( + BuildContext context, AssetEntity entity, Color themeColor) { + return Center( + child: Container( + width: 30.0, + height: 30.0, + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(themeColor), + ), + ), + ); + } +} diff --git a/lib/photo/delegate/sort_asset_delegate.dart b/lib/photo/delegate/sort_asset_delegate.dart new file mode 100644 index 0000000..ffabe64 --- /dev/null +++ b/lib/photo/delegate/sort_asset_delegate.dart @@ -0,0 +1,18 @@ +part of './sort_delegate.dart'; + +abstract class SortAssetDelegate { + const SortAssetDelegate(); + + void sort(List list); +} + +class DefaultAssetDelegate extends SortAssetDelegate { + const DefaultAssetDelegate(); + + @override + void sort(List list) { + list.sort((entity1, entity2) { + return entity2.createDateTime.compareTo(entity1.createDateTime); + }); + } +} diff --git a/lib/photo/delegate/sort_delegate.dart b/lib/photo/delegate/sort_delegate.dart new file mode 100644 index 0000000..e47eae7 --- /dev/null +++ b/lib/photo/delegate/sort_delegate.dart @@ -0,0 +1,77 @@ +import 'package:photo_manager/photo_manager.dart'; + +part './sort_asset_delegate.dart'; + +/// SortPathDelegate +abstract class SortDelegate { + final SortAssetDelegate assetDelegate; + + const SortDelegate({ + this.assetDelegate = const DefaultAssetDelegate(), + }); + + void sort(List list); + + static const none = DefaultSortDelegate(); + + static const common = CommonSortDelegate(); +} + +class DefaultSortDelegate extends SortDelegate { + const DefaultSortDelegate({ + SortAssetDelegate assetDelegate = const DefaultAssetDelegate(), + }) : super(assetDelegate: assetDelegate); + + @override + void sort(List list) {} +} + +class CommonSortDelegate extends SortDelegate { + const CommonSortDelegate({ + SortAssetDelegate assetDelegate = const DefaultAssetDelegate(), + }) : super(assetDelegate: assetDelegate); + + @override + void sort(List list) { + list.sort((path1, path2) { + if (path1.isAll) { + return -1; + } + + if (path2.isAll) { + return 1; + } + + if (_isCamera(path1)) { + return -1; + } + + if (_isCamera(path2)) { + return 1; + } + + if (_isScreenShot(path1)) { + return -1; + } + + if (_isScreenShot(path2)) { + return 1; + } + + return otherSort(path1, path2); + }); + } + + int otherSort(AssetPathEntity path1, AssetPathEntity path2) { + return path1.name.compareTo(path2.name); + } + + bool _isCamera(AssetPathEntity entity) { + return entity.name.toUpperCase() == "camera".toUpperCase(); + } + + bool _isScreenShot(AssetPathEntity entity) { + return entity.name.toUpperCase() == "screenshots".toUpperCase() || + entity.name.toUpperCase() == "screenshot".toUpperCase(); + } +} diff --git a/lib/photo/engine/lru_cache.dart b/lib/photo/engine/lru_cache.dart new file mode 100644 index 0000000..5e9eaec --- /dev/null +++ b/lib/photo/engine/lru_cache.dart @@ -0,0 +1,72 @@ +import 'dart:collection'; +import 'dart:typed_data'; + +import 'package:photo_manager/photo_manager.dart'; + +class ImageLruCache { + static LRUMap<_ImageCacheEntity, Uint8List> _map = LRUMap(500); + + static Uint8List getData(AssetEntity entity, [int size = 64]) { + return _map.get(_ImageCacheEntity(entity, size)); + } + + static void setData(AssetEntity entity, int size, Uint8List list) { + _map.put(_ImageCacheEntity(entity, size), list); + } +} + +class _ImageCacheEntity { + AssetEntity entity; + int size; + + _ImageCacheEntity(this.entity, this.size); + + @override + bool operator ==(Object other) => + identical(this, other) || + other is _ImageCacheEntity && + runtimeType == other.runtimeType && + entity == other.entity && + size == other.size; + + @override + int get hashCode => entity.hashCode ^ size.hashCode; +} + +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +typedef EvictionHandler(K key, V value); + +class LRUMap { + final LinkedHashMap _map = new LinkedHashMap(); + final int _maxSize; + final EvictionHandler _handler; + + LRUMap(this._maxSize, [this._handler]); + + V get(K key) { + V value = _map.remove(key); + if (value != null) { + _map[key] = value; + } + return value; + } + + void put(K key, V value) { + _map.remove(key); + _map[key] = value; + if (_map.length > _maxSize) { + K evictedKey = _map.keys.first; + V evictedValue = _map.remove(evictedKey); + if (_handler != null) { + _handler(evictedKey, evictedValue); + } + } + } + + void remove(K key) { + _map.remove(key); + } +} diff --git a/lib/photo/engine/throttle.dart b/lib/photo/engine/throttle.dart new file mode 100644 index 0000000..6e5a07e --- /dev/null +++ b/lib/photo/engine/throttle.dart @@ -0,0 +1,52 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; + +typedef VoidCallback(); + +/// When multiple calls are repeated, only the first time is valid. +/// +/// Like rxdart `throttle` method +class Throttle { + Duration duration; + + VoidCallback onCall; + + bool _isRunning = false; + + Timer _timer; + + Throttle({ + @required this.onCall, + this.duration = const Duration(seconds: 2), + }); + + void call(call) { + if (!_isRunning) { + _startTimer(); + onCall?.call(); + } + } + + void _startTimer() { + if (_timer != null) { + _stopTimer(); + } + _isRunning = true; + _timer = Timer(duration, () { + _isRunning = false; + _timer = null; + }); + } + + void _stopTimer() { + _timer?.cancel(); + _isRunning = false; + _timer = null; + } + + void dispose() { + this.onCall = null; + _stopTimer(); + } +} diff --git a/lib/photo/entity/options.dart b/lib/photo/entity/options.dart new file mode 100644 index 0000000..bb35c14 --- /dev/null +++ b/lib/photo/entity/options.dart @@ -0,0 +1,51 @@ + +import 'package:chat/photo/delegate/loading_delegate.dart'; +import 'package:chat/photo/delegate/sort_delegate.dart'; +import 'package:flutter/material.dart'; + +class Options { + final int rowCount; + + final int maxSelected; + + final double padding; + + final double itemRadio; + + final Color themeColor; + + final Color dividerColor; + + final Color textColor; + + final Color disableColor; + + final int thumbSize; + + final SortDelegate sortDelegate; + + final LoadingDelegate loadingDelegate; + + final PickType pickType; + + const Options({ + this.rowCount, + this.maxSelected, + this.padding, + this.itemRadio, + this.themeColor, + this.dividerColor, + this.textColor, + this.disableColor, + this.thumbSize, + this.sortDelegate, + this.loadingDelegate, + this.pickType, + }); +} + +enum PickType { + all, + onlyImage, + onlyVideo, +} diff --git a/lib/photo/photo.dart b/lib/photo/photo.dart new file mode 100644 index 0000000..8ccf10c --- /dev/null +++ b/lib/photo/photo.dart @@ -0,0 +1,146 @@ +library photo; + +import 'dart:async'; + +import 'package:chat/utils/CustomUI.dart'; +import 'package:flutter/material.dart'; + +import 'package:photo_manager/photo_manager.dart'; +import 'delegate/loading_delegate.dart'; +import 'delegate/sort_delegate.dart'; +import 'entity/options.dart'; +import 'ui/photo_app.dart'; + +class PhotoPicker { + static PhotoPicker _instance; + + PhotoPicker._(); + + factory PhotoPicker() { + _instance ??= PhotoPicker._(); + return _instance; + } + + static const String rootRouteName = "photo_picker_image"; + + /// 没有授予权限的时候,会开启一个dialog去帮助用户去应用设置页面开启权限 + /// 确定开启设置页面,取消关闭弹窗,无论选择什么,返回值都是null + /// + /// + /// 当用户给予权限后 + /// + /// 当用户确定时,返回一个图片[AssetEntity]列表 + /// + /// 当用户取消时返回一个空数组 + /// + /// [photoPathList] 一旦设置 则 [pickType]参数无效 + /// + /// 关于参数可以查看readme文档介绍 + /// + /// if user not grand permission, then return null and show a dialog to help user open setting. + /// sure is open setting cancel ,cancel to dismiss dialog, return null + /// + /// when user give permission. + /// + /// when user sure , return a [AssetEntity] of [List] + /// + /// when user cancel selected,result is empty list + /// + /// when [photoPathList] is not null , [pickType] invalid + /// + /// params see readme.md + static Future> pickAsset({ + @required BuildContext context, + int rowCount = 4, + int maxSelected = 9, + double padding = 0.5, + double itemRadio = 1.0, + Color themeColor, + Color dividerColor, + Color textColor, + Color disableColor, + int thumbSize = 64, + + SortDelegate sortDelegate, + LoadingDelegate loadingDelegate, + PickType pickType = PickType.onlyImage, + List photoPathList, + }) { + + assert(context != null, "context must be not null"); + assert(pickType != null, "pickType must be not null"); + + themeColor ??= Theme.of(context)?.primaryColor ?? Colors.white; + dividerColor ??= Theme.of(context)?.dividerColor ?? Colors.grey; + disableColor ??= Theme.of(context)?.disabledColor ?? Colors.grey; + textColor ??= Colors.white; + + sortDelegate ??= SortDelegate.common; + + loadingDelegate ??= DefaultLoadingDelegate(); + + var options = Options( + rowCount: rowCount, + dividerColor: dividerColor, + maxSelected: maxSelected, + itemRadio: itemRadio, + padding: padding, + disableColor: disableColor, + textColor: textColor, + themeColor: themeColor, + thumbSize: thumbSize, + sortDelegate: sortDelegate, + loadingDelegate: loadingDelegate, + pickType: pickType, + ); + + return PhotoPicker()._pickAsset( + context, + options, + + photoPathList, + ); + } + + Future> _pickAsset( + BuildContext context, + Options options, + + List photoList, + ) async { +// var requestPermission = await PhotoManager.requestPermission(); +// if (requestPermission != true) { +// var result = await showDialog( +// context: context, +// builder: (ctx) => NotPermissionDialog(), +// ); +// if (result == true) { +// ; +// } +// return null; +// } + + if(await CustomUI.showPhotoPermissionSetting(context)){ + return _openGalleryContentPage(context, options, photoList); + }else{ + return null; + } + +// return _openGalleryContentPage(context, options, photoList); + } + + Future> _openGalleryContentPage( + BuildContext context, + Options options, + List photoList, + ) async { + return Navigator.of(context, rootNavigator: true).push( + MaterialPageRoute( + builder: (ctx) => PhotoApp( + options: options, + photoList: photoList, + ), + ), + ); + } +} diff --git a/lib/photo/provider/asset_provider.dart b/lib/photo/provider/asset_provider.dart new file mode 100644 index 0000000..7321b24 --- /dev/null +++ b/lib/photo/provider/asset_provider.dart @@ -0,0 +1,62 @@ +import 'dart:async'; + +import 'package:photo_manager/photo_manager.dart'; + +class AssetProvider { + Map _dataMap = {}; + + AssetPathEntity _current; + + AssetPathEntity get current => _current; + + set current(AssetPathEntity current) { + _current = current; + if (_dataMap[current] == null) { + final paging = AssetPaging(current); + _dataMap[current] = paging; + } + } + + List get data => _dataMap[current]?.data ?? []; + + Future loadMore() async { + final paging = getPaging(); + if (paging != null) { + await paging.loadMore(); + } + } + + AssetPaging getPaging() => _dataMap[current]; + + bool get noMore => getPaging()?.noMore ?? false; + + int get count => data?.length ?? 0; +} + +class AssetPaging { + int page = 0; + + List data = []; + + final AssetPathEntity path; + + final int pageCount; + + bool noMore = false; + + AssetPaging(this.path, {this.pageCount = 50}); + + Future loadMore() async { + if (noMore == true) { + print('noMore'); + return; + } + var data = await path.getAssetListPaged(page, pageCount); + if (data.length == 0) { + print('数据长度为0'); + noMore = true; + } + page++; + this.data.addAll(data); + } +} diff --git a/lib/photo/provider/config_provider.dart b/lib/photo/provider/config_provider.dart new file mode 100644 index 0000000..19168c7 --- /dev/null +++ b/lib/photo/provider/config_provider.dart @@ -0,0 +1,25 @@ +import 'package:chat/photo/entity/options.dart'; +import 'package:chat/photo/provider/asset_provider.dart'; +import 'package:flutter/material.dart'; + +class PhotoPickerProvider extends InheritedWidget { + final Options options; + final AssetProvider assetProvider = AssetProvider(); + + PhotoPickerProvider({ + @required this.options, + @required Widget child, + Key key, + }) : super(key: key, child: child); + + @override + bool updateShouldNotify(InheritedWidget oldWidget) { + return true; + } + + static PhotoPickerProvider of(BuildContext context) => + context.dependOnInheritedWidgetOfExactType(); + + static AssetProvider assetProviderOf(BuildContext context) => + of(context).assetProvider; +} diff --git a/lib/photo/provider/selected_provider.dart b/lib/photo/provider/selected_provider.dart new file mode 100644 index 0000000..3f62635 --- /dev/null +++ b/lib/photo/provider/selected_provider.dart @@ -0,0 +1,60 @@ +import 'dart:async'; + +import 'package:photo_manager/photo_manager.dart'; + +abstract class SelectedProvider { + List selectedList = []; + + int get selectedCount => selectedList.length; + + bool containsEntity(AssetEntity entity) { + return selectedList.contains(entity); + } + + int indexOfSelected(AssetEntity entity) { + return selectedList.indexOf(entity); + } + + bool isUpperLimit(); + + bool addSelectEntity(AssetEntity entity) { + if (containsEntity(entity)) { + return false; + } + if (isUpperLimit() == true) { + return false; + } + selectedList.add(entity); + return true; + } + + bool removeSelectEntity(AssetEntity entity) { + return selectedList.remove(entity); + } + + void compareAndRemoveEntities(List previewSelectedList) { + var srcList = List.of(selectedList); + selectedList.clear(); + srcList.forEach((entity) { + if (previewSelectedList.contains(entity)) { + selectedList.add(entity); + } + }); + } + + void sure(); + + Future checkPickImageEntity() async { + List notExistsList = []; + for (var entity in selectedList) { + var exists = await entity.exists; + if (!exists) { + notExistsList.add(entity); + } + } + + selectedList.removeWhere((e) { + return notExistsList.contains(e); + }); + } +} diff --git a/lib/photo/ui/dialog/not_permission_dialog.dart b/lib/photo/ui/dialog/not_permission_dialog.dart new file mode 100644 index 0000000..3ef9ecd --- /dev/null +++ b/lib/photo/ui/dialog/not_permission_dialog.dart @@ -0,0 +1,39 @@ + +import 'package:chat/generated/i18n.dart'; +import 'package:flutter/material.dart'; +class NotPermissionDialog extends StatefulWidget { + + final String title; + NotPermissionDialog(this.title); + + @override + _NotPermissionDialogState createState() => _NotPermissionDialogState(); +} + +class _NotPermissionDialogState extends State { + @override + Widget build(BuildContext context) { + + return AlertDialog( + title: Text(widget.title), + actions: [ + FlatButton( + onPressed: _onCancel, + child: Text(I18n.of(context).cancel), + ), + FlatButton( + onPressed: _onSure, + child: Text(I18n.of(context).go_open), + ), + ], + ); + } + + void _onCancel() { + Navigator.pop(context); + } + + void _onSure() { + Navigator.pop(context, true); + } +} diff --git a/lib/photo/ui/page/bottom_widget.dart b/lib/photo/ui/page/bottom_widget.dart new file mode 100644 index 0000000..2700e19 --- /dev/null +++ b/lib/photo/ui/page/bottom_widget.dart @@ -0,0 +1,84 @@ +part of 'photo_main_page.dart'; + +class _BottomWidget extends StatefulWidget { + + final Options options; + + final SelectedProvider selectedProvider; + + final String galleryName; + + final VoidCallback onTapPreview; + final VoidCallback onSend; + + const _BottomWidget( + {Key key, + this.options, + this.selectedProvider, + this.galleryName = "", + this.onTapPreview, + this.onSend}) + : super(key: key); + + @override + __BottomWidgetState createState() => __BottomWidgetState(); +} + +class __BottomWidgetState extends State<_BottomWidget> { + Options get options => widget.options; + + @override + Widget build(BuildContext context) { + var textStyle = TextStyle(fontSize: 14.0); + const textPadding = const EdgeInsets.symmetric(horizontal: 16.0); + + var curCount = widget.selectedProvider.selectedCount; + return Container( + color: Colors.white, + child: SafeArea( + bottom: true, + top: false, + child: Container( + height: 52.0, + child: Row( + children: [ + FlatButton( + onPressed: widget.onTapPreview, + textColor: options.textColor, + splashColor: Colors.transparent, + disabledTextColor: options.disableColor, + child: Container( + height: 44.0, + alignment: Alignment.center, + child: Text( + I18n.of(context).Preview, + style: textStyle, + ), + padding: textPadding, + ), + ), + Expanded( + child: Container(), + ), + InkWell( + onTap: curCount > 0 ? widget.onSend : null, + child: Container( + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15), + margin: EdgeInsets.symmetric(vertical: 5, horizontal: 5), + decoration: BoxDecoration( + color: + curCount > 0 ? Color(0xFF2D81FF) : Color(0xFFC7C7C7), + borderRadius: BorderRadius.circular(8)), + child: Text( + "${I18n.of(context).determine}(${widget.selectedProvider.selectedCount})", + style: textStyle.copyWith(color: Colors.white), + ), + ), + ) + ], + ), + ), + ), + ); + } +} diff --git a/lib/photo/ui/page/first_photo_item.dart b/lib/photo/ui/page/first_photo_item.dart new file mode 100644 index 0000000..7581a0e --- /dev/null +++ b/lib/photo/ui/page/first_photo_item.dart @@ -0,0 +1,92 @@ +import 'dart:typed_data'; + +import 'package:chat/photo/engine/lru_cache.dart'; +import 'package:flutter/material.dart'; +import 'package:photo_manager/photo_manager.dart'; + +class FirstPhotoItem extends StatefulWidget { + final AssetPathEntity pathEntity; + final double size; + final Function onSelectFolder; + + const FirstPhotoItem( + {Key key, this.pathEntity, this.size = 50, this.onSelectFolder}) + : super(key: key); + + @override + _FirstPhotoItemState createState() => _FirstPhotoItemState(); +} + +class _FirstPhotoItemState extends State { + AssetEntity entity; + + @override + void initState() { + super.initState(); + getAssetEntity(); + } + + Widget _buildImg(Uint8List data) { + return ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image.memory( + data, + width: widget.size, + height: widget.size, + fit: BoxFit.contain, + )); + } + + Future getAssetEntity() async { + var entityList = await widget.pathEntity.getAssetListPaged(0, 1); + setState(() { + entity = entityList.first; + }); + } + + @override + Widget build(BuildContext context) { + Widget leading; + + if (entity == null) { + leading = Container( + width: widget.size, + height: widget.size, + child: CircularProgressIndicator(), + padding: EdgeInsets.all(8)); + } else { + var thumb = ImageLruCache.getData(entity); + if (thumb != null) { + leading = _buildImg(thumb); + } else { + leading = FutureBuilder( + future: entity.thumbDataWithSize( + widget.size.toInt(), widget.size.toInt()), + builder: (BuildContext context, AsyncSnapshot snapshot) { + var futureData = snapshot.data; + if (snapshot.connectionState == ConnectionState.done && + futureData != null) { + ImageLruCache.setData(entity, widget.size.toInt(), futureData); + return _buildImg(futureData); + } else { + return Center( + child: Container( + width: 30.0, + height: 30.0, + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.blueAccent), + ), + ), + ); + } + }); + } + } + + return ListTile( + leading: leading, + title: Text(widget.pathEntity.name), + subtitle: Text('${widget.pathEntity.assetCount}'), + onTap:widget.onSelectFolder); + } +} diff --git a/lib/photo/ui/page/image_item.dart b/lib/photo/ui/page/image_item.dart new file mode 100644 index 0000000..b32263e --- /dev/null +++ b/lib/photo/ui/page/image_item.dart @@ -0,0 +1,57 @@ + +part of 'photo_main_page.dart'; + +class ImageItem extends StatelessWidget { + final AssetEntity entity; + + final Color themeColor; + + final int size; + + final LoadingDelegate loadingDelegate; + + + const ImageItem({ + Key key, + this.entity, + this.themeColor, + this.size = 64, + this.loadingDelegate, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + var thumb = ImageLruCache.getData(entity, size); + if (thumb != null) { + return _buildImageItem(context, thumb); + } + + return FutureBuilder( + future: entity.thumbDataWithSize(size, size), + builder: (BuildContext context, AsyncSnapshot snapshot) { + var futureData = snapshot.data; + if (snapshot.connectionState == ConnectionState.done && + futureData != null) { + ImageLruCache.setData(entity, size, futureData); + return _buildImageItem(context, futureData); + } + return Center( + child: loadingDelegate.buildPreviewLoading( + context, + entity, + themeColor, + ), + ); + }, + ); + } + + Widget _buildImageItem(BuildContext context, Uint8List data) { + return Image.memory( + data, + width: double.infinity, + height: double.infinity, + fit: BoxFit.cover, + ); + } +} diff --git a/lib/photo/ui/page/photo_folder_select_menu.dart b/lib/photo/ui/page/photo_folder_select_menu.dart new file mode 100644 index 0000000..2050aab --- /dev/null +++ b/lib/photo/ui/page/photo_folder_select_menu.dart @@ -0,0 +1,114 @@ +import 'package:chat/generated/i18n.dart'; +import 'package:chat/photo/provider/asset_provider.dart'; +import 'package:chat/photo/provider/config_provider.dart'; +import 'package:chat/photo/ui/page/first_photo_item.dart'; +import 'package:chat/utils/loading_builder.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:photo_manager/photo_manager.dart'; + +class PhotoSelectMenu extends StatefulWidget { + final GlobalKey parentKey; + final Function onSelectFolder; + PhotoSelectMenu({this.parentKey, this.onSelectFolder}); + @override + _PhotoSelectMenuState createState() => _PhotoSelectMenuState(); +} + +class _PhotoSelectMenuState extends State { + AssetProvider get assetProvider => + PhotoPickerProvider.of(context).assetProvider; + + OverlayEntry overlayEntry; + bool isQuit = false; + @override + void dispose() { + isQuit = true; + clearOverlay(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return InkWell( + child: Container( + child: Row(mainAxisSize: MainAxisSize.min, children: [ + Text(assetProvider.current == null + ? I18n.of(context).Photo_album + : assetProvider.current.name), + Icon( + overlayEntry == null + ? Icons.keyboard_arrow_down + : Icons.keyboard_arrow_up, + color: Color(0xFFB5B4B4), + size: 20, + ), + ]), + ), + onTap: overlayEntry == null ? showAllFolders : clearOverlay); + } + + void showAllFolders() { + final RenderBox appBarBox = + widget.parentKey.currentContext.findRenderObject(); + + overlayEntry = OverlayEntry( + builder: (context) => Positioned( + width: Screen.width, + top: appBarBox.size.height, + child: Material( + elevation: 1, + color: Colors.black26, + child: Container( + height: Screen.height, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(10.0), + bottomRight: Radius.circular(10.0))), + child: FutureLoadingBuilder>( + future: PhotoManager.getAssetPathList( + type: RequestType.image), + builder: (BuildContext context, + List pathList) { + return ListView( + children: List.generate( + pathList.length, + (i) => FirstPhotoItem( + pathEntity: pathList[i], + onSelectFolder: () { + widget.onSelectFolder(pathList[i]); + clearOverlay(); + }, + ))); + })), + ))); + + Overlay.of(context).insert(overlayEntry); + setState(() {}); + } + + Widget _mask() { + return GestureDetector( + onTap: () { + print('到mask了'); + clearOverlay(); + }, + child: Expanded( + child: Container( + width: MediaQuery.of(context).size.width, + color: Color.fromRGBO(0, 0, 0, 0.1), + ))); + } + + void clearOverlay() { + if (overlayEntry != null) { + overlayEntry.remove(); + overlayEntry = null; + + if (!isQuit) { + setState(() {}); + } + } + } +} diff --git a/lib/photo/ui/page/photo_main_page.dart b/lib/photo/ui/page/photo_main_page.dart new file mode 100644 index 0000000..4358582 --- /dev/null +++ b/lib/photo/ui/page/photo_main_page.dart @@ -0,0 +1,495 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:chat/generated/i18n.dart'; +import 'package:chat/photo/delegate/loading_delegate.dart'; +import 'package:chat/photo/engine/lru_cache.dart'; +import 'package:chat/photo/engine/throttle.dart'; +import 'package:chat/photo/entity/options.dart'; +import 'package:chat/photo/provider/asset_provider.dart'; +import 'package:chat/photo/provider/config_provider.dart'; +import 'package:chat/photo/provider/selected_provider.dart'; +import 'package:chat/photo/ui/page/photo_folder_select_menu.dart'; +import 'package:chat/photo/ui/page/photo_preview_page.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:photo_manager/photo_manager.dart'; + +part './bottom_widget.dart'; +part './image_item.dart'; + +class PhotoMainPage extends StatefulWidget { + final ValueChanged> onClose; + final Options options; + final List photoList; + + const PhotoMainPage({ + Key key, + this.onClose, + this.options, + this.photoList, + }) : super(key: key); + + @override + _PhotoMainPageState createState() => _PhotoMainPageState(); +} + +class _PhotoMainPageState extends State with SelectedProvider { + Options get options => widget.options; + + AssetProvider get assetProvider => + PhotoPickerProvider.of(context).assetProvider; + + List get list => assetProvider.data; + + Color get themeColor => options.themeColor; + + AssetPathEntity _currentPath; + + bool _isInit = false; + + AssetPathEntity get currentPath { + if (_currentPath == null) { + return null; + } + return _currentPath; + } + + set currentPath(AssetPathEntity value) { + _currentPath = value; + } + + String get currentGalleryName { + if (currentPath?.isAll == true) { + return I18n.of(context).all_photo; + } + return currentPath?.name ?? "Select Folder"; + } + + GlobalKey scaffoldKey; + ScrollController scrollController; + + bool isPushed = false; + + bool get useAlbum => widget.photoList == null || widget.photoList.isEmpty; + + Throttle _changeThrottle; + + var appBarKey = GlobalKey(); + OverlayEntry overlayEntry; + + bool isQuit = false; + + @override + void initState() { + super.initState(); + + scaffoldKey = GlobalKey(); + scrollController = ScrollController(); + _changeThrottle = Throttle(onCall: _onAssetChange); + PhotoManager.addChangeCallback(_changeThrottle.call); + PhotoManager.startChangeNotify(); + _refreshListFromGallery(); + } + + @override + void dispose() { + PhotoManager.removeChangeCallback(_changeThrottle.call); + PhotoManager.stopChangeNotify(); + _changeThrottle.dispose(); + scaffoldKey = null; + appBarKey = null; + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var textStyle = TextStyle( + color: options.textColor, + fontSize: 14.0, + ); + return Theme( + data: Theme.of(context).copyWith(primaryColor: options.themeColor), + child: DefaultTextStyle( + style: textStyle, + child: Scaffold( + backgroundColor: Color(0xFFF0F0F0), + appBar: AppBar( + elevation: 1.0, + key: appBarKey, + backgroundColor: Colors.white, + leading: IconButton( + icon: fixedText( + I18n.of(context).cancel, + color: options.textColor, + ), + onPressed: _cancel, + ), + title: PhotoSelectMenu( + parentKey: appBarKey, onSelectFolder: _onGalleryChange), + centerTitle: true, + actions: [ + Center( + child:Padding(padding: EdgeInsets.only(right:16),child: fixedText('$selectedCount/${options.maxSelected}',color: Colors.blue,fontSize: 16)) + ) + ], + ), + body: _buildBody(), + bottomNavigationBar: _BottomWidget( + key: scaffoldKey, + options: options, + galleryName: currentGalleryName, + onSend: selectedList.isEmpty ? null : sure, + onTapPreview: selectedList.isEmpty ? null : _onTapPreview, + selectedProvider: this, + ), + ), + ), + ); + } + + void _cancel() { + selectedList.clear(); + widget.onClose(selectedList); + } + + @override + bool isUpperLimit() { + var result = selectedCount == options.maxSelected; + if (result) + _showTip(I18n.of(context) + .have_select + .replaceFirst('/s1', options.maxSelected.toString())); + return result; + } + + void sure() { + widget.onClose?.call(selectedList); + } + + void _showTip(String msg) { + if (isPushed) { + return; + } + Scaffold.of(scaffoldKey.currentContext).showSnackBar( + SnackBar( + content: Text( + msg, + style: TextStyle( + color: options.textColor, + fontSize: 15.0, + ), + ), + duration: Duration(milliseconds: 1500), + backgroundColor: themeColor.withOpacity(0.8), + ), + ); + } + + Future _refreshListFromGallery() async { + List pathList; + switch (options.pickType) { + case PickType.onlyImage: + pathList = await PhotoManager.getAssetPathList(type: RequestType.image); + break; + case PickType.onlyVideo: + pathList = await PhotoManager.getAssetPathList(type: RequestType.video); + break; + default: + pathList = await PhotoManager.getAssetPathList(); + } + + if (pathList == null) { + return; + } + + options.sortDelegate.sort(pathList); + + if (pathList.isNotEmpty) { + assetProvider.current = pathList[0]; + await assetProvider.loadMore(); + } + + for (var path in pathList) { + if (path.isAll) { + path.name = I18n.of(context).all_photo; + } + } + setState(() { + _isInit = true; + }); + } + + Widget _buildBody() { + if (!_isInit) { + return Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(themeColor), + )); + } + + final noMore = assetProvider.noMore; + + final count = assetProvider.count + (noMore ? 0 : 1); + if (list.length == 0) { + print('图片数目为空'); + _refreshListFromGallery(); + return Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(themeColor), + )); + } + print('图片数目${list.length}'); + return Container( + color: options.dividerColor, + child: GridView.builder( + controller: scrollController, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: options.rowCount, + childAspectRatio: options.itemRadio, + crossAxisSpacing: options.padding, + mainAxisSpacing: options.padding, + ), + itemBuilder: _buildItem, + itemCount: count, + ), + ); + } + + Widget _buildItem(BuildContext context, int index) { + final noMore = assetProvider.noMore; + if (!noMore && index == assetProvider.count) { + _loadMore(); + return _buildLoading(); + } + + var data = list[index]; + return RepaintBoundary( + child: GestureDetector( + onTap: () => _onItemClick(data, index), + child: Stack( + children: [ + ImageItem( + entity: data, + themeColor: themeColor, + size: options.thumbSize, + loadingDelegate: options.loadingDelegate, + ), + _buildMask(containsEntity(data)), + _buildSelected(data), + ], + ), + ), + ); + } + + _loadMore() async { + await assetProvider.loadMore(); + setState(() {}); + } + + _buildMask(bool showMask) { + return IgnorePointer( + child: AnimatedContainer( + color: showMask ? Colors.black.withOpacity(0.5) : Colors.transparent, + duration: Duration(milliseconds: 300), + ), + ); + } + + Widget _buildSelected(AssetEntity entity) { + var currentSelected = containsEntity(entity); + return Positioned( + right: 0.0, + width: 40.0, + height: 40.0, + child: GestureDetector( + onTap: () { + changeCheck(!currentSelected, entity); + }, + behavior: HitTestBehavior.translucent, + child: _buildText(entity), + ), + ); + } + + Widget _buildText(AssetEntity entity) { + var isSelected = containsEntity(entity); + Widget child; + BoxDecoration decoration; + if (isSelected) { + child = Text( + (indexOfSelected(entity) + 1).toString(), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12.0, + color: Colors.white, + ), + ); + decoration = BoxDecoration( + color: Color(0xFF2D81FF), + shape: BoxShape.circle, + border: Border.all( + color: Colors.white30, + ), + ); + } else { + decoration = BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: themeColor, + ), + boxShadow: [BoxShadow(color: Colors.black38)], + color: Colors.white24); + } + return Padding( + padding: const EdgeInsets.all(8.0), + child: AnimatedContainer( + duration: Duration(milliseconds: 300), + decoration: decoration, + alignment: Alignment.center, + child: child, + ), + ); + } + + void changeCheck(bool value, AssetEntity entity) { + if (value) { + addSelectEntity(entity); + } else { + removeSelectEntity(entity); + } + setState(() {}); + } + + void _onGalleryChange(AssetPathEntity assetPathEntity) async { + if (assetPathEntity != assetProvider.current) { + assetProvider.current = assetPathEntity; + await assetProvider.loadMore(); + setState(() {}); + } + } + + void _onItemClick(AssetEntity data, int index) { + var result = new PhotoPreviewResult(); + isPushed = true; + Navigator.of(context).push( + MaterialPageRoute( + builder: (ctx) { + return PhotoPickerProvider( + options: options, + child: PhotoPreviewPage( + selectedProvider: this, + list: List.of(list), + initIndex: index, + changeProviderOnCheckChange: true, + result: result, + isPreview: false, + assetProvider: assetProvider, + ), + ); + }, + ), + ).then((v) { + if (handlePreviewResult(v)) { + Navigator.pop(context, v); + return; + } + isPushed = false; + setState(() {}); + }); + } + + void _onTapPreview() async { + var result = new PhotoPreviewResult(); + isPushed = true; + var v = await Navigator.of(context).push( + MaterialPageRoute( + builder: (ctx) => PhotoPickerProvider( + options: options, + child: PhotoPreviewPage( + selectedProvider: this, + list: List.of(selectedList), + changeProviderOnCheckChange: false, + result: result, + isPreview: true, + assetProvider: assetProvider, + ), + ), + ), + ); + if (handlePreviewResult(v)) { + // print(v); + Navigator.pop(context, v); + return; + } + isPushed = false; + compareAndRemoveEntities(result.previewSelectedList); + } + + bool handlePreviewResult(List v) { + if (v == null) { + return false; + } + if (v is List) { + return true; + } + return false; + } + + Widget _buildLoading() { + return Center( + child: Column( + children: [ + Container( + width: 40.0, + height: 40.0, + padding: const EdgeInsets.all(5.0), + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(themeColor), + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + I18n.of(context).loading, + style: const TextStyle( + fontSize: 12.0, + ), + ), + ), + ], + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + ), + ); + } + + void _onAssetChange() { + if (useAlbum) { + _onPhotoRefresh(); + } + } + + void _onPhotoRefresh() async { + List pathList; + switch (options.pickType) { + case PickType.onlyImage: + pathList = await PhotoManager.getAssetPathList(type: RequestType.image); + break; + case PickType.onlyVideo: + pathList = await PhotoManager.getAssetPathList(type: RequestType.video); + break; + default: + pathList = await PhotoManager.getAssetPathList(); + } + + if (pathList == null) { + return; + } + + // Not deleted + _onGalleryChange(this.currentPath); + } +} diff --git a/lib/photo/ui/page/photo_preview_page.dart b/lib/photo/ui/page/photo_preview_page.dart new file mode 100644 index 0000000..5d73a31 --- /dev/null +++ b/lib/photo/ui/page/photo_preview_page.dart @@ -0,0 +1,423 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:chat/generated/i18n.dart'; +import 'package:chat/photo/entity/options.dart'; +import 'package:chat/photo/provider/asset_provider.dart'; +import 'package:chat/photo/provider/config_provider.dart'; +import 'package:chat/photo/provider/selected_provider.dart'; +import 'package:chat/photo/ui/page/photo_main_page.dart'; +import 'package:flutter/material.dart'; +import 'package:photo_manager/photo_manager.dart'; + +class PhotoPreviewPage extends StatefulWidget { + final SelectedProvider selectedProvider; + + final List list; + + final int initIndex; + + /// 这个参数是控制在内部点击check后是否实时修改provider状态 + final bool changeProviderOnCheckChange; + + /// 是否通过预览进来的 + final bool isPreview; + + /// 这里封装了结果 + final PhotoPreviewResult result; + + final AssetProvider assetProvider; + + const PhotoPreviewPage({ + Key key, + @required this.selectedProvider, + @required this.list, + @required this.changeProviderOnCheckChange, + @required this.result, + @required this.assetProvider, + this.initIndex = 0, + this.isPreview = false, + }) : super(key: key); + + @override + _PhotoPreviewPageState createState() => _PhotoPreviewPageState(); +} + +class _PhotoPreviewPageState extends State { + PhotoPickerProvider get config => PhotoPickerProvider.of(context); + AssetProvider get assetProvider => widget.assetProvider; + + Options get options => config.options; + + Color get themeColor => options.themeColor; + + Color get textColor => options.textColor; + + SelectedProvider get selectedProvider => widget.selectedProvider; + + List get list { + if (!widget.isPreview) { + return assetProvider.data; + } + return widget.list; + } + + StreamController pageChangeController = StreamController.broadcast(); + + Stream get pageStream => pageChangeController.stream; + + bool get changeProviderOnCheckChange => widget.changeProviderOnCheckChange; + + PhotoPreviewResult get result => widget.result; + + /// 缩略图用的数据 + /// + /// 用于与provider数据联动 + List get previewList { + return selectedProvider.selectedList; + } + + /// 选中的数据 + List _selectedList = []; + + List get selectedList { + if (changeProviderOnCheckChange) { + return previewList; + } + return _selectedList; + } + + PageController pageController; + + @override + void initState() { + super.initState(); + pageChangeController.add(0); + pageController = PageController( + initialPage: widget.initIndex, + ); + + _selectedList.clear(); + _selectedList.addAll(selectedProvider.selectedList); + + result.previewSelectedList = _selectedList; + } + + @override + void dispose() { + pageChangeController.close(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + int totalCount = 0; + + totalCount = assetProvider.current?.assetCount ?? 0; + if (!widget.isPreview) { + totalCount = assetProvider.current.assetCount; + } else { + totalCount = list.length; + } + + var data = Theme.of(context); + + return Theme( + data: data.copyWith( + primaryColor: options.themeColor, + ), + child: Scaffold( + appBar: AppBar( + backgroundColor: config.options.themeColor, + leading: BackButton( + color: options.textColor, + ), + centerTitle: true, + title: StreamBuilder( + stream: pageStream, + initialData: widget.initIndex, + builder: (ctx, snap) { + return Text( + "${snap.data + 1}/$totalCount", + style: TextStyle( + color: options.textColor, + ), + ); + }, + ), + actions: [ + Container( + width: 60, + height: 60, + padding: EdgeInsets.only(right: 20), + alignment: Alignment.center, + child: StreamBuilder( + builder: (ctx, snapshot) { + var index = snapshot.data; + var data = list[index]; + var checked = selectedList.contains(data); + return Stack( + alignment: Alignment.center, + children: [ + IgnorePointer( + child: _buildCheckboxContent(checked, index), + ), + GestureDetector( + onTap: () => _changeSelected(!checked, index), + behavior: HitTestBehavior.translucent, + child: Container(), + ), + ], + ); + }, + initialData: widget.initIndex, + stream: pageStream, + )) + ], + ), + body: PageView.builder( + controller: pageController, + itemBuilder: _buildItem, + itemCount: totalCount, + onPageChanged: _onPageChanged, + ), + bottomSheet: _buildThumb(), + bottomNavigationBar: _buildBottom(), + ), + ); + } + + Widget _buildBottom() { + var textStyle = TextStyle( + color: options.textColor, + fontSize: 14.0, + ); + + return StreamBuilder( + stream: pageStream, + builder: (ctx, s) => Row( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded(child: SizedBox()), + InkWell( + onTap: selectedList.length == 0 ? null : sure, + child: Container( + padding: + EdgeInsets.symmetric(vertical: 5, horizontal: 15), + margin: EdgeInsets.symmetric(vertical: 5, horizontal: 5), + decoration: BoxDecoration( + color: selectedList.length > 0 + ? Color(0xFF2D81FF) + : Color(0xFFC7C7C7), + borderRadius: BorderRadius.circular(8)), + child: Text( + "${I18n.of(context).determine}(${selectedList.length})", + style: textStyle.copyWith(color: Colors.white), + ), + )), Expanded(child: SizedBox()), + ], + )); + } + + Widget _buildCheckboxContent(bool checked, int index) { + Widget child; + BoxDecoration decoration; + if (checked) { + child = Text( + (index + 1).toString(), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12.0, + color: Colors.white, + ), + ); + decoration = + BoxDecoration(color: Color(0xFF2D81FF), shape: BoxShape.circle); + } else { + child = Icon(Icons.check); + decoration = BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: Colors.black, + ), + color: Colors.white); + } + return Padding( + padding: const EdgeInsets.all(8.0), + child: AnimatedContainer( + duration: Duration(milliseconds: 300), + decoration: decoration, + alignment: Alignment.center, + child: child, + ), + ); + } + + void _changeSelected(bool isChecked, int index) { + if (changeProviderOnCheckChange) { + _onChangeProvider(isChecked, index); + } else { + _onCheckInOnlyPreview(isChecked, index); + } + } + + /// 仅仅修改预览时的状态,在退出时,再更新provider的顺序,这里无论添加与否不修改顺序 + void _onCheckInOnlyPreview(bool check, int index) { + var item = list[index]; + if (check) { + selectedList.add(item); + } else { + selectedList.remove(item); + } + pageChangeController.add(index); + } + + /// 直接修改预览状态,会直接移除item + void _onChangeProvider(bool check, int index) { + var item = list[index]; + if (check) { + selectedProvider.addSelectEntity(item); + } else { + selectedProvider.removeSelectEntity(item); + } + pageChangeController.add(index); + } + + Widget _buildItem(BuildContext context, int index) { + if (!widget.isPreview && index >= list.length - 5) { + _loadMore(); + } + + var data = list[index]; + return BigPhotoImage( + assetEntity: data, + loadingWidget: _buildLoadingWidget(data), + ); + } + + Future _loadMore() async { + assetProvider.loadMore(); + } + + Widget _buildLoadingWidget(AssetEntity entity) { + return options.loadingDelegate + .buildBigImageLoading(context, entity, themeColor); + } + + void _onPageChanged(int value) { + pageChangeController.add(value); + } + + Widget _buildThumb() { + return Container( + height: 80.0, + color: Color(0xFFF0F0F0), + child: ListView.builder( + padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), + itemBuilder: _buildThumbItem, + itemCount: previewList.length, + scrollDirection: Axis.horizontal, + ), + ); + } + + Widget _buildThumbItem(BuildContext context, int index) { + var item = previewList[index]; + + return StreamBuilder( + initialData: widget.initIndex, + builder: (ctx, snapshot) => RepaintBoundary( + child: GestureDetector( + onTap: () => changeSelected(item, index), + child: Container( + width: 80.0, + child: Container( + margin: EdgeInsets.all(10), + decoration: BoxDecoration( + border: snapshot.data == index + ? Border.all(color: Colors.blue, width: 2) + : null), + child: Stack( + children: [ + ImageItem( + themeColor: themeColor, + entity: item, + size: options.thumbSize, + loadingDelegate: options.loadingDelegate, + ), + IgnorePointer( + child: selectedList.contains(item) + ? Container() + : Container( + color: Colors.white.withOpacity(0.5), + )), + ], + ), + ), + )), + ), + stream: pageStream, + ); + } + + void changeSelected(AssetEntity entity, int index) { + var itemIndex = list.indexOf(entity); + if (itemIndex != -1) pageController.jumpToPage(itemIndex); + } + + void sure() { + Navigator.pop(context, selectedList); + } +} + +class BigPhotoImage extends StatefulWidget { + final AssetEntity assetEntity; + final Widget loadingWidget; + + const BigPhotoImage({ + Key key, + this.assetEntity, + this.loadingWidget, + }) : super(key: key); + + @override + _BigPhotoImageState createState() => _BigPhotoImageState(); +} + +class _BigPhotoImageState extends State + with AutomaticKeepAliveClientMixin { + Widget get loadingWidget { + return widget.loadingWidget ?? Container(); + } + + @override + Widget build(BuildContext context) { + super.build(context); + var width = MediaQuery.of(context).size.width; + var height = MediaQuery.of(context).size.height; + return FutureBuilder( + future: + widget.assetEntity.thumbDataWithSize(width.floor(), height.floor()), + builder: (BuildContext context, AsyncSnapshot snapshot) { + var file = snapshot.data; + if (snapshot.connectionState == ConnectionState.done && file != null) { + print(file.length); + return Image.memory( + file, + fit: BoxFit.contain, + width: double.infinity, + height: double.infinity, + ); + } + return loadingWidget; + }, + ); + } + + @override + bool get wantKeepAlive => true; +} + +class PhotoPreviewResult { + List previewSelectedList = []; +} diff --git a/lib/photo/ui/photo_app.dart b/lib/photo/ui/photo_app.dart new file mode 100644 index 0000000..652ad32 --- /dev/null +++ b/lib/photo/ui/photo_app.dart @@ -0,0 +1,34 @@ +import 'package:chat/photo/entity/options.dart'; +import 'package:chat/photo/provider/config_provider.dart'; +import 'package:chat/photo/ui/page/photo_main_page.dart'; +import 'package:flutter/material.dart'; + +import 'package:photo_manager/photo_manager.dart'; + + +class PhotoApp extends StatelessWidget { + final Options options; + + final List photoList; + const PhotoApp({ + Key key, + this.options, + + this.photoList, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return PhotoPickerProvider( + + options: options, + child: PhotoMainPage( + onClose: (List value) { + Navigator.pop(context, value); + }, + options: options, + photoList: photoList, + ), + ); + } +} diff --git a/lib/proto/all.pbserver.dart b/lib/proto/all.pbserver.dart new file mode 100644 index 0000000..81d7247 --- /dev/null +++ b/lib/proto/all.pbserver.dart @@ -0,0 +1,13 @@ +/// +// Generated code. Do not modify. +// source: login.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +export 'login.pb.dart'; +export 'system.pb.dart'; +export 'chat.pb.dart'; +export 'net.pb.dart'; +export 'msgContent.pb.dart'; + diff --git a/lib/proto/chat.pb.dart b/lib/proto/chat.pb.dart new file mode 100644 index 0000000..96628ee --- /dev/null +++ b/lib/proto/chat.pb.dart @@ -0,0 +1,2205 @@ +/// +// Generated code. Do not modify. +// source: chat.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String; + +import 'package:fixnum/fixnum.dart'; +import 'package:protobuf/protobuf.dart' as $pb; + +import 'chat.pbenum.dart'; + +export 'chat.pbenum.dart'; + +class RedWallet extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('RedWallet', package: const $pb.PackageName('yl_pb')) + ..aOS(1, 'orderId') + ..a<$core.int>(2, 'suId', $pb.PbFieldType.OU3) + ..a<$core.int>(3, 'tuId', $pb.PbFieldType.OU3) + ..aOS(4, 'title') + ..a<$core.int>(5, 'amount', $pb.PbFieldType.OU3) + ..e(6, 'state', $pb.PbFieldType.OE, RedWalletState.Uncollected, RedWalletState.valueOf, RedWalletState.values) + ..aInt64(7, 'recTime') + ..hasRequiredFields = false + ; + + RedWallet._() : super(); + factory RedWallet() => create(); + factory RedWallet.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RedWallet.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + RedWallet clone() => RedWallet()..mergeFromMessage(this); + RedWallet copyWith(void Function(RedWallet) updates) => super.copyWith((message) => updates(message as RedWallet)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RedWallet create() => RedWallet._(); + RedWallet createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static RedWallet getDefault() => _defaultInstance ??= create()..freeze(); + static RedWallet _defaultInstance; + + $core.String get orderId => $_getS(0, ''); + set orderId($core.String v) { $_setString(0, v); } + $core.bool hasOrderId() => $_has(0); + void clearOrderId() => clearField(1); + + $core.int get suId => $_get(1, 0); + set suId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasSuId() => $_has(1); + void clearSuId() => clearField(2); + + $core.int get tuId => $_get(2, 0); + set tuId($core.int v) { $_setUnsignedInt32(2, v); } + $core.bool hasTuId() => $_has(2); + void clearTuId() => clearField(3); + + $core.String get title => $_getS(3, ''); + set title($core.String v) { $_setString(3, v); } + $core.bool hasTitle() => $_has(3); + void clearTitle() => clearField(4); + + $core.int get amount => $_get(4, 0); + set amount($core.int v) { $_setUnsignedInt32(4, v); } + $core.bool hasAmount() => $_has(4); + void clearAmount() => clearField(5); + + RedWalletState get state => $_getN(5); + set state(RedWalletState v) { setField(6, v); } + $core.bool hasState() => $_has(5); + void clearState() => clearField(6); + + Int64 get recTime => $_getI64(6); + set recTime(Int64 v) { $_setInt64(6, v); } + $core.bool hasRecTime() => $_has(6); + void clearRecTime() => clearField(7); +} + +class BaseUserInfo extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('BaseUserInfo', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'id', $pb.PbFieldType.OU3) + ..aOS(2, 'niceName') + ..aOS(3, 'headUrl') + ..hasRequiredFields = false + ; + + BaseUserInfo._() : super(); + factory BaseUserInfo() => create(); + factory BaseUserInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory BaseUserInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + BaseUserInfo clone() => BaseUserInfo()..mergeFromMessage(this); + BaseUserInfo copyWith(void Function(BaseUserInfo) updates) => super.copyWith((message) => updates(message as BaseUserInfo)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static BaseUserInfo create() => BaseUserInfo._(); + BaseUserInfo createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static BaseUserInfo getDefault() => _defaultInstance ??= create()..freeze(); + static BaseUserInfo _defaultInstance; + + $core.int get id => $_get(0, 0); + set id($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasId() => $_has(0); + void clearId() => clearField(1); + + $core.String get niceName => $_getS(1, ''); + set niceName($core.String v) { $_setString(1, v); } + $core.bool hasNiceName() => $_has(1); + void clearNiceName() => clearField(2); + + $core.String get headUrl => $_getS(2, ''); + set headUrl($core.String v) { $_setString(2, v); } + $core.bool hasHeadUrl() => $_has(2); + void clearHeadUrl() => clearField(3); +} + +class ChatNiceo extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ChatNiceo', package: const $pb.PackageName('yl_pb')) + ..e(1, 'nictoType', $pb.PbFieldType.OE, ChatNiceoType.GroupAddMember, ChatNiceoType.valueOf, ChatNiceoType.values) + ..aOS(2, 'nictoMsg') + ..hasRequiredFields = false + ; + + ChatNiceo._() : super(); + factory ChatNiceo() => create(); + factory ChatNiceo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ChatNiceo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + ChatNiceo clone() => ChatNiceo()..mergeFromMessage(this); + ChatNiceo copyWith(void Function(ChatNiceo) updates) => super.copyWith((message) => updates(message as ChatNiceo)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static ChatNiceo create() => ChatNiceo._(); + ChatNiceo createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static ChatNiceo getDefault() => _defaultInstance ??= create()..freeze(); + static ChatNiceo _defaultInstance; + + ChatNiceoType get nictoType => $_getN(0); + set nictoType(ChatNiceoType v) { setField(1, v); } + $core.bool hasNictoType() => $_has(0); + void clearNictoType() => clearField(1); + + $core.String get nictoMsg => $_getS(1, ''); + set nictoMsg($core.String v) { $_setString(1, v); } + $core.bool hasNictoMsg() => $_has(1); + void clearNictoMsg() => clearField(2); +} + +class GiftChat extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GiftChat', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'suId', $pb.PbFieldType.OU3) + ..a<$core.int>(2, 'tuId', $pb.PbFieldType.OU3) + ..a<$core.int>(3, 'giftId', $pb.PbFieldType.OU3) + ..aOS(4, 'giftName') + ..a<$core.int>(5, 'giftAmount', $pb.PbFieldType.OU3) + ..a<$core.int>(6, 'money', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + GiftChat._() : super(); + factory GiftChat() => create(); + factory GiftChat.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GiftChat.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GiftChat clone() => GiftChat()..mergeFromMessage(this); + GiftChat copyWith(void Function(GiftChat) updates) => super.copyWith((message) => updates(message as GiftChat)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GiftChat create() => GiftChat._(); + GiftChat createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GiftChat getDefault() => _defaultInstance ??= create()..freeze(); + static GiftChat _defaultInstance; + + $core.int get suId => $_get(0, 0); + set suId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasSuId() => $_has(0); + void clearSuId() => clearField(1); + + $core.int get tuId => $_get(1, 0); + set tuId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasTuId() => $_has(1); + void clearTuId() => clearField(2); + + $core.int get giftId => $_get(2, 0); + set giftId($core.int v) { $_setUnsignedInt32(2, v); } + $core.bool hasGiftId() => $_has(2); + void clearGiftId() => clearField(3); + + $core.String get giftName => $_getS(3, ''); + set giftName($core.String v) { $_setString(3, v); } + $core.bool hasGiftName() => $_has(3); + void clearGiftName() => clearField(4); + + $core.int get giftAmount => $_get(4, 0); + set giftAmount($core.int v) { $_setUnsignedInt32(4, v); } + $core.bool hasGiftAmount() => $_has(4); + void clearGiftAmount() => clearField(5); + + $core.int get money => $_get(5, 0); + set money($core.int v) { $_setUnsignedInt32(5, v); } + $core.bool hasMoney() => $_has(5); + void clearMoney() => clearField(6); +} + +class FileChat extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('FileChat', package: const $pb.PackageName('yl_pb')) + ..aOS(1, 'type') + ..a<$core.int>(2, 'size', $pb.PbFieldType.OU3) + ..aOS(3, 'name') + ..hasRequiredFields = false + ; + + FileChat._() : super(); + factory FileChat() => create(); + factory FileChat.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory FileChat.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + FileChat clone() => FileChat()..mergeFromMessage(this); + FileChat copyWith(void Function(FileChat) updates) => super.copyWith((message) => updates(message as FileChat)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static FileChat create() => FileChat._(); + FileChat createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static FileChat getDefault() => _defaultInstance ??= create()..freeze(); + static FileChat _defaultInstance; + + $core.String get type => $_getS(0, ''); + set type($core.String v) { $_setString(0, v); } + $core.bool hasType() => $_has(0); + void clearType() => clearField(1); + + $core.int get size => $_get(1, 0); + set size($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasSize() => $_has(1); + void clearSize() => clearField(2); + + $core.String get name => $_getS(2, ''); + set name($core.String v) { $_setString(2, v); } + $core.bool hasName() => $_has(2); + void clearName() => clearField(3); +} + +class QuoteMsg extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('QuoteMsg', package: const $pb.PackageName('yl_pb')) + ..e(1, 'channelType', $pb.PbFieldType.OE, ChatChannelType.Session, ChatChannelType.valueOf, ChatChannelType.values) + ..a<$core.int>(2, 'targetId', $pb.PbFieldType.OU3) + ..a<$core.int>(3, 'sendUserId', $pb.PbFieldType.OU3) + ..aInt64(4, 'sendTime') + ..aOS(5, 'content') + ..hasRequiredFields = false + ; + + QuoteMsg._() : super(); + factory QuoteMsg() => create(); + factory QuoteMsg.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory QuoteMsg.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + QuoteMsg clone() => QuoteMsg()..mergeFromMessage(this); + QuoteMsg copyWith(void Function(QuoteMsg) updates) => super.copyWith((message) => updates(message as QuoteMsg)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static QuoteMsg create() => QuoteMsg._(); + QuoteMsg createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static QuoteMsg getDefault() => _defaultInstance ??= create()..freeze(); + static QuoteMsg _defaultInstance; + + ChatChannelType get channelType => $_getN(0); + set channelType(ChatChannelType v) { setField(1, v); } + $core.bool hasChannelType() => $_has(0); + void clearChannelType() => clearField(1); + + $core.int get targetId => $_get(1, 0); + set targetId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasTargetId() => $_has(1); + void clearTargetId() => clearField(2); + + $core.int get sendUserId => $_get(2, 0); + set sendUserId($core.int v) { $_setUnsignedInt32(2, v); } + $core.bool hasSendUserId() => $_has(2); + void clearSendUserId() => clearField(3); + + Int64 get sendTime => $_getI64(3); + set sendTime(Int64 v) { $_setInt64(3, v); } + $core.bool hasSendTime() => $_has(3); + void clearSendTime() => clearField(4); + + $core.String get content => $_getS(4, ''); + set content($core.String v) { $_setString(4, v); } + $core.bool hasContent() => $_has(4); + void clearContent() => clearField(5); +} + +class ChatSendReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ChatSendReq', package: const $pb.PackageName('yl_pb')) + ..e(1, 'channelType', $pb.PbFieldType.OE, ChatChannelType.Session, ChatChannelType.valueOf, ChatChannelType.values) + ..a<$core.int>(2, 'targetId', $pb.PbFieldType.OU3) + ..aInt64(3, 'sendTime') + ..e(4, 'cType', $pb.PbFieldType.OE, ChatType.TextChatType, ChatType.valueOf, ChatType.values) + ..a<$core.List<$core.int>>(5, 'contentBuff', $pb.PbFieldType.OY) + ..a<$core.int>(6, 'contentSzie', $pb.PbFieldType.OU3) + ..aOS(7, 'enclosureUrl') + ..p<$core.int>(8, 'altUserIds', $pb.PbFieldType.PU3) + ..a<$core.List<$core.int>>(9, 'quoteMsg', $pb.PbFieldType.OY) + ..hasRequiredFields = false + ; + + ChatSendReq._() : super(); + factory ChatSendReq() => create(); + factory ChatSendReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ChatSendReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + ChatSendReq clone() => ChatSendReq()..mergeFromMessage(this); + ChatSendReq copyWith(void Function(ChatSendReq) updates) => super.copyWith((message) => updates(message as ChatSendReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static ChatSendReq create() => ChatSendReq._(); + ChatSendReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static ChatSendReq getDefault() => _defaultInstance ??= create()..freeze(); + static ChatSendReq _defaultInstance; + + ChatChannelType get channelType => $_getN(0); + set channelType(ChatChannelType v) { setField(1, v); } + $core.bool hasChannelType() => $_has(0); + void clearChannelType() => clearField(1); + + $core.int get targetId => $_get(1, 0); + set targetId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasTargetId() => $_has(1); + void clearTargetId() => clearField(2); + + Int64 get sendTime => $_getI64(2); + set sendTime(Int64 v) { $_setInt64(2, v); } + $core.bool hasSendTime() => $_has(2); + void clearSendTime() => clearField(3); + + ChatType get cType => $_getN(3); + set cType(ChatType v) { setField(4, v); } + $core.bool hasCType() => $_has(3); + void clearCType() => clearField(4); + + $core.List<$core.int> get contentBuff => $_getN(4); + set contentBuff($core.List<$core.int> v) { $_setBytes(4, v); } + $core.bool hasContentBuff() => $_has(4); + void clearContentBuff() => clearField(5); + + $core.int get contentSzie => $_get(5, 0); + set contentSzie($core.int v) { $_setUnsignedInt32(5, v); } + $core.bool hasContentSzie() => $_has(5); + void clearContentSzie() => clearField(6); + + $core.String get enclosureUrl => $_getS(6, ''); + set enclosureUrl($core.String v) { $_setString(6, v); } + $core.bool hasEnclosureUrl() => $_has(6); + void clearEnclosureUrl() => clearField(7); + + $core.List<$core.int> get altUserIds => $_getList(7); + + $core.List<$core.int> get quoteMsg => $_getN(8); + set quoteMsg($core.List<$core.int> v) { $_setBytes(8, v); } + $core.bool hasQuoteMsg() => $_has(8); + void clearQuoteMsg() => clearField(9); +} + +class ChatSendRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ChatSendRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..e(2, 'channelType', $pb.PbFieldType.OE, ChatChannelType.Session, ChatChannelType.valueOf, ChatChannelType.values) + ..a<$core.int>(3, 'targetId', $pb.PbFieldType.OU3) + ..aInt64(4, 'sendTime') + ..hasRequiredFields = false + ; + + ChatSendRes._() : super(); + factory ChatSendRes() => create(); + factory ChatSendRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ChatSendRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + ChatSendRes clone() => ChatSendRes()..mergeFromMessage(this); + ChatSendRes copyWith(void Function(ChatSendRes) updates) => super.copyWith((message) => updates(message as ChatSendRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static ChatSendRes create() => ChatSendRes._(); + ChatSendRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static ChatSendRes getDefault() => _defaultInstance ??= create()..freeze(); + static ChatSendRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + ChatChannelType get channelType => $_getN(1); + set channelType(ChatChannelType v) { setField(2, v); } + $core.bool hasChannelType() => $_has(1); + void clearChannelType() => clearField(2); + + $core.int get targetId => $_get(2, 0); + set targetId($core.int v) { $_setUnsignedInt32(2, v); } + $core.bool hasTargetId() => $_has(2); + void clearTargetId() => clearField(3); + + Int64 get sendTime => $_getI64(3); + set sendTime(Int64 v) { $_setInt64(3, v); } + $core.bool hasSendTime() => $_has(3); + void clearSendTime() => clearField(4); +} + +class PushChat extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('PushChat', package: const $pb.PackageName('yl_pb')) + ..e(1, 'channelType', $pb.PbFieldType.OE, ChatChannelType.Session, ChatChannelType.valueOf, ChatChannelType.values) + ..a<$core.int>(2, 'targetId', $pb.PbFieldType.OU3) + ..a<$core.int>(3, 'sendUserId', $pb.PbFieldType.OU3) + ..aInt64(4, 'sendTime') + ..e(5, 'cType', $pb.PbFieldType.OE, ChatType.TextChatType, ChatType.valueOf, ChatType.values) + ..a<$core.List<$core.int>>(6, 'contentBuff', $pb.PbFieldType.OY) + ..a<$core.int>(7, 'contentSzie', $pb.PbFieldType.OU3) + ..a<$core.int>(8, 'translateState', $pb.PbFieldType.OU3) + ..a<$core.List<$core.int>>(9, 'tencentTranslate', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>(10, 'googleTranslate', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>(11, 'humanTranslate', $pb.PbFieldType.OY) + ..aOS(12, 'enclosureUrl') + ..p<$core.int>(13, 'altUserIds', $pb.PbFieldType.PU3) + ..a<$core.List<$core.int>>(14, 'quoteMsg', $pb.PbFieldType.OY) + ..hasRequiredFields = false + ; + + PushChat._() : super(); + factory PushChat() => create(); + factory PushChat.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory PushChat.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + PushChat clone() => PushChat()..mergeFromMessage(this); + PushChat copyWith(void Function(PushChat) updates) => super.copyWith((message) => updates(message as PushChat)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static PushChat create() => PushChat._(); + PushChat createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static PushChat getDefault() => _defaultInstance ??= create()..freeze(); + static PushChat _defaultInstance; + + ChatChannelType get channelType => $_getN(0); + set channelType(ChatChannelType v) { setField(1, v); } + $core.bool hasChannelType() => $_has(0); + void clearChannelType() => clearField(1); + + $core.int get targetId => $_get(1, 0); + set targetId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasTargetId() => $_has(1); + void clearTargetId() => clearField(2); + + $core.int get sendUserId => $_get(2, 0); + set sendUserId($core.int v) { $_setUnsignedInt32(2, v); } + $core.bool hasSendUserId() => $_has(2); + void clearSendUserId() => clearField(3); + + Int64 get sendTime => $_getI64(3); + set sendTime(Int64 v) { $_setInt64(3, v); } + $core.bool hasSendTime() => $_has(3); + void clearSendTime() => clearField(4); + + ChatType get cType => $_getN(4); + set cType(ChatType v) { setField(5, v); } + $core.bool hasCType() => $_has(4); + void clearCType() => clearField(5); + + $core.List<$core.int> get contentBuff => $_getN(5); + set contentBuff($core.List<$core.int> v) { $_setBytes(5, v); } + $core.bool hasContentBuff() => $_has(5); + void clearContentBuff() => clearField(6); + + $core.int get contentSzie => $_get(6, 0); + set contentSzie($core.int v) { $_setUnsignedInt32(6, v); } + $core.bool hasContentSzie() => $_has(6); + void clearContentSzie() => clearField(7); + + $core.int get translateState => $_get(7, 0); + set translateState($core.int v) { $_setUnsignedInt32(7, v); } + $core.bool hasTranslateState() => $_has(7); + void clearTranslateState() => clearField(8); + + $core.List<$core.int> get tencentTranslate => $_getN(8); + set tencentTranslate($core.List<$core.int> v) { $_setBytes(8, v); } + $core.bool hasTencentTranslate() => $_has(8); + void clearTencentTranslate() => clearField(9); + + $core.List<$core.int> get googleTranslate => $_getN(9); + set googleTranslate($core.List<$core.int> v) { $_setBytes(9, v); } + $core.bool hasGoogleTranslate() => $_has(9); + void clearGoogleTranslate() => clearField(10); + + $core.List<$core.int> get humanTranslate => $_getN(10); + set humanTranslate($core.List<$core.int> v) { $_setBytes(10, v); } + $core.bool hasHumanTranslate() => $_has(10); + void clearHumanTranslate() => clearField(11); + + $core.String get enclosureUrl => $_getS(11, ''); + set enclosureUrl($core.String v) { $_setString(11, v); } + $core.bool hasEnclosureUrl() => $_has(11); + void clearEnclosureUrl() => clearField(12); + + $core.List<$core.int> get altUserIds => $_getList(12); + + $core.List<$core.int> get quoteMsg => $_getN(13); + set quoteMsg($core.List<$core.int> v) { $_setBytes(13, v); } + $core.bool hasQuoteMsg() => $_has(13); + void clearQuoteMsg() => clearField(14); +} + +class AnswerPushChat extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('AnswerPushChat', package: const $pb.PackageName('yl_pb')) + ..aInt64(1, 'msgId') + ..hasRequiredFields = false + ; + + AnswerPushChat._() : super(); + factory AnswerPushChat() => create(); + factory AnswerPushChat.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory AnswerPushChat.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + AnswerPushChat clone() => AnswerPushChat()..mergeFromMessage(this); + AnswerPushChat copyWith(void Function(AnswerPushChat) updates) => super.copyWith((message) => updates(message as AnswerPushChat)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static AnswerPushChat create() => AnswerPushChat._(); + AnswerPushChat createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static AnswerPushChat getDefault() => _defaultInstance ??= create()..freeze(); + static AnswerPushChat _defaultInstance; + + Int64 get msgId => $_getI64(0); + set msgId(Int64 v) { $_setInt64(0, v); } + $core.bool hasMsgId() => $_has(0); + void clearMsgId() => clearField(1); +} + +class PushUserUnreadMsgNotice extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('PushUserUnreadMsgNotice', package: const $pb.PackageName('yl_pb')) + ..pc(2, 'notices', $pb.PbFieldType.PM,UserUnreadMsgNotice.create) + ..hasRequiredFields = false + ; + + PushUserUnreadMsgNotice._() : super(); + factory PushUserUnreadMsgNotice() => create(); + factory PushUserUnreadMsgNotice.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory PushUserUnreadMsgNotice.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + PushUserUnreadMsgNotice clone() => PushUserUnreadMsgNotice()..mergeFromMessage(this); + PushUserUnreadMsgNotice copyWith(void Function(PushUserUnreadMsgNotice) updates) => super.copyWith((message) => updates(message as PushUserUnreadMsgNotice)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static PushUserUnreadMsgNotice create() => PushUserUnreadMsgNotice._(); + PushUserUnreadMsgNotice createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static PushUserUnreadMsgNotice getDefault() => _defaultInstance ??= create()..freeze(); + static PushUserUnreadMsgNotice _defaultInstance; + + $core.List get notices => $_getList(0); +} + +class UnreadMsgDes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('UnreadMsgDes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'sendUserId', $pb.PbFieldType.OU3) + ..aInt64(2, 'sendTime') + ..e(3, 'cType', $pb.PbFieldType.OE, ChatType.TextChatType, ChatType.valueOf, ChatType.values) + ..a<$core.List<$core.int>>(4, 'contentBuff', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>(5, 'tencentTranslate', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>(6, 'googleTranslate', $pb.PbFieldType.OY) + ..hasRequiredFields = false + ; + + UnreadMsgDes._() : super(); + factory UnreadMsgDes() => create(); + factory UnreadMsgDes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory UnreadMsgDes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + UnreadMsgDes clone() => UnreadMsgDes()..mergeFromMessage(this); + UnreadMsgDes copyWith(void Function(UnreadMsgDes) updates) => super.copyWith((message) => updates(message as UnreadMsgDes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static UnreadMsgDes create() => UnreadMsgDes._(); + UnreadMsgDes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static UnreadMsgDes getDefault() => _defaultInstance ??= create()..freeze(); + static UnreadMsgDes _defaultInstance; + + $core.int get sendUserId => $_get(0, 0); + set sendUserId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasSendUserId() => $_has(0); + void clearSendUserId() => clearField(1); + + Int64 get sendTime => $_getI64(1); + set sendTime(Int64 v) { $_setInt64(1, v); } + $core.bool hasSendTime() => $_has(1); + void clearSendTime() => clearField(2); + + ChatType get cType => $_getN(2); + set cType(ChatType v) { setField(3, v); } + $core.bool hasCType() => $_has(2); + void clearCType() => clearField(3); + + $core.List<$core.int> get contentBuff => $_getN(3); + set contentBuff($core.List<$core.int> v) { $_setBytes(3, v); } + $core.bool hasContentBuff() => $_has(3); + void clearContentBuff() => clearField(4); + + $core.List<$core.int> get tencentTranslate => $_getN(4); + set tencentTranslate($core.List<$core.int> v) { $_setBytes(4, v); } + $core.bool hasTencentTranslate() => $_has(4); + void clearTencentTranslate() => clearField(5); + + $core.List<$core.int> get googleTranslate => $_getN(5); + set googleTranslate($core.List<$core.int> v) { $_setBytes(5, v); } + $core.bool hasGoogleTranslate() => $_has(5); + void clearGoogleTranslate() => clearField(6); +} + +class UserUnreadMsgNotice extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('UserUnreadMsgNotice', package: const $pb.PackageName('yl_pb')) + ..e(1, 'channelType', $pb.PbFieldType.OE, ChatChannelType.Session, ChatChannelType.valueOf, ChatChannelType.values) + ..a<$core.int>(2, 'targetId', $pb.PbFieldType.OU3) + ..a<$core.int>(3, 'unreadMsgNum', $pb.PbFieldType.OU3) + ..a(4, 'lastUnreadMsg', $pb.PbFieldType.OM, UnreadMsgDes.getDefault, UnreadMsgDes.create) + ..hasRequiredFields = false + ; + + UserUnreadMsgNotice._() : super(); + factory UserUnreadMsgNotice() => create(); + factory UserUnreadMsgNotice.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory UserUnreadMsgNotice.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + UserUnreadMsgNotice clone() => UserUnreadMsgNotice()..mergeFromMessage(this); + UserUnreadMsgNotice copyWith(void Function(UserUnreadMsgNotice) updates) => super.copyWith((message) => updates(message as UserUnreadMsgNotice)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static UserUnreadMsgNotice create() => UserUnreadMsgNotice._(); + UserUnreadMsgNotice createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static UserUnreadMsgNotice getDefault() => _defaultInstance ??= create()..freeze(); + static UserUnreadMsgNotice _defaultInstance; + + ChatChannelType get channelType => $_getN(0); + set channelType(ChatChannelType v) { setField(1, v); } + $core.bool hasChannelType() => $_has(0); + void clearChannelType() => clearField(1); + + $core.int get targetId => $_get(1, 0); + set targetId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasTargetId() => $_has(1); + void clearTargetId() => clearField(2); + + $core.int get unreadMsgNum => $_get(2, 0); + set unreadMsgNum($core.int v) { $_setUnsignedInt32(2, v); } + $core.bool hasUnreadMsgNum() => $_has(2); + void clearUnreadMsgNum() => clearField(3); + + UnreadMsgDes get lastUnreadMsg => $_getN(3); + set lastUnreadMsg(UnreadMsgDes v) { setField(4, v); } + $core.bool hasLastUnreadMsg() => $_has(3); + void clearLastUnreadMsg() => clearField(4); +} + +class RequestTargetUnreadReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('RequestTargetUnreadReq', package: const $pb.PackageName('yl_pb')) + ..e(1, 'channelType', $pb.PbFieldType.OE, ChatChannelType.Session, ChatChannelType.valueOf, ChatChannelType.values) + ..a<$core.int>(2, 'targetId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + RequestTargetUnreadReq._() : super(); + factory RequestTargetUnreadReq() => create(); + factory RequestTargetUnreadReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RequestTargetUnreadReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + RequestTargetUnreadReq clone() => RequestTargetUnreadReq()..mergeFromMessage(this); + RequestTargetUnreadReq copyWith(void Function(RequestTargetUnreadReq) updates) => super.copyWith((message) => updates(message as RequestTargetUnreadReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RequestTargetUnreadReq create() => RequestTargetUnreadReq._(); + RequestTargetUnreadReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static RequestTargetUnreadReq getDefault() => _defaultInstance ??= create()..freeze(); + static RequestTargetUnreadReq _defaultInstance; + + ChatChannelType get channelType => $_getN(0); + set channelType(ChatChannelType v) { setField(1, v); } + $core.bool hasChannelType() => $_has(0); + void clearChannelType() => clearField(1); + + $core.int get targetId => $_get(1, 0); + set targetId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasTargetId() => $_has(1); + void clearTargetId() => clearField(2); +} + +class RequestTargetUnreadRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('RequestTargetUnreadRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..hasRequiredFields = false + ; + + RequestTargetUnreadRes._() : super(); + factory RequestTargetUnreadRes() => create(); + factory RequestTargetUnreadRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RequestTargetUnreadRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + RequestTargetUnreadRes clone() => RequestTargetUnreadRes()..mergeFromMessage(this); + RequestTargetUnreadRes copyWith(void Function(RequestTargetUnreadRes) updates) => super.copyWith((message) => updates(message as RequestTargetUnreadRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RequestTargetUnreadRes create() => RequestTargetUnreadRes._(); + RequestTargetUnreadRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static RequestTargetUnreadRes getDefault() => _defaultInstance ??= create()..freeze(); + static RequestTargetUnreadRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); +} + +class RequestSetHTranslReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('RequestSetHTranslReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'sessionId', $pb.PbFieldType.OU3) + ..e(2, 'hTransl', $pb.PbFieldType.OE, TranslateState.NoPerson, TranslateState.valueOf, TranslateState.values) + ..hasRequiredFields = false + ; + + RequestSetHTranslReq._() : super(); + factory RequestSetHTranslReq() => create(); + factory RequestSetHTranslReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RequestSetHTranslReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + RequestSetHTranslReq clone() => RequestSetHTranslReq()..mergeFromMessage(this); + RequestSetHTranslReq copyWith(void Function(RequestSetHTranslReq) updates) => super.copyWith((message) => updates(message as RequestSetHTranslReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RequestSetHTranslReq create() => RequestSetHTranslReq._(); + RequestSetHTranslReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static RequestSetHTranslReq getDefault() => _defaultInstance ??= create()..freeze(); + static RequestSetHTranslReq _defaultInstance; + + $core.int get sessionId => $_get(0, 0); + set sessionId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasSessionId() => $_has(0); + void clearSessionId() => clearField(1); + + TranslateState get hTransl => $_getN(1); + set hTransl(TranslateState v) { setField(2, v); } + $core.bool hasHTransl() => $_has(1); + void clearHTransl() => clearField(2); +} + +class RequestSetHTranslRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('RequestSetHTranslRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..hasRequiredFields = false + ; + + RequestSetHTranslRes._() : super(); + factory RequestSetHTranslRes() => create(); + factory RequestSetHTranslRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RequestSetHTranslRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + RequestSetHTranslRes clone() => RequestSetHTranslRes()..mergeFromMessage(this); + RequestSetHTranslRes copyWith(void Function(RequestSetHTranslRes) updates) => super.copyWith((message) => updates(message as RequestSetHTranslRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RequestSetHTranslRes create() => RequestSetHTranslRes._(); + RequestSetHTranslRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static RequestSetHTranslRes getDefault() => _defaultInstance ??= create()..freeze(); + static RequestSetHTranslRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); +} + +class PushHTranslState extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('PushHTranslState', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'sessionId', $pb.PbFieldType.OU3) + ..a<$core.int>(2, 'userId', $pb.PbFieldType.OU3) + ..e(3, 'hTransl', $pb.PbFieldType.OE, TranslateState.NoPerson, TranslateState.valueOf, TranslateState.values) + ..hasRequiredFields = false + ; + + PushHTranslState._() : super(); + factory PushHTranslState() => create(); + factory PushHTranslState.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory PushHTranslState.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + PushHTranslState clone() => PushHTranslState()..mergeFromMessage(this); + PushHTranslState copyWith(void Function(PushHTranslState) updates) => super.copyWith((message) => updates(message as PushHTranslState)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static PushHTranslState create() => PushHTranslState._(); + PushHTranslState createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static PushHTranslState getDefault() => _defaultInstance ??= create()..freeze(); + static PushHTranslState _defaultInstance; + + $core.int get sessionId => $_get(0, 0); + set sessionId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasSessionId() => $_has(0); + void clearSessionId() => clearField(1); + + $core.int get userId => $_get(1, 0); + set userId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasUserId() => $_has(1); + void clearUserId() => clearField(2); + + TranslateState get hTransl => $_getN(2); + set hTransl(TranslateState v) { setField(3, v); } + $core.bool hasHTransl() => $_has(2); + void clearHTransl() => clearField(3); +} + +class RequestRealtimeCallReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('RequestRealtimeCallReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'tUserId', $pb.PbFieldType.OU3) + ..e(2, 'cType', $pb.PbFieldType.OE, ChatType.TextChatType, ChatType.valueOf, ChatType.values) + ..hasRequiredFields = false + ; + + RequestRealtimeCallReq._() : super(); + factory RequestRealtimeCallReq() => create(); + factory RequestRealtimeCallReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RequestRealtimeCallReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + RequestRealtimeCallReq clone() => RequestRealtimeCallReq()..mergeFromMessage(this); + RequestRealtimeCallReq copyWith(void Function(RequestRealtimeCallReq) updates) => super.copyWith((message) => updates(message as RequestRealtimeCallReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RequestRealtimeCallReq create() => RequestRealtimeCallReq._(); + RequestRealtimeCallReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static RequestRealtimeCallReq getDefault() => _defaultInstance ??= create()..freeze(); + static RequestRealtimeCallReq _defaultInstance; + + $core.int get tUserId => $_get(0, 0); + set tUserId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasTUserId() => $_has(0); + void clearTUserId() => clearField(1); + + ChatType get cType => $_getN(1); + set cType(ChatType v) { setField(2, v); } + $core.bool hasCType() => $_has(1); + void clearCType() => clearField(2); +} + +class RequestRealtimeCallRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('RequestRealtimeCallRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..hasRequiredFields = false + ; + + RequestRealtimeCallRes._() : super(); + factory RequestRealtimeCallRes() => create(); + factory RequestRealtimeCallRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RequestRealtimeCallRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + RequestRealtimeCallRes clone() => RequestRealtimeCallRes()..mergeFromMessage(this); + RequestRealtimeCallRes copyWith(void Function(RequestRealtimeCallRes) updates) => super.copyWith((message) => updates(message as RequestRealtimeCallRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RequestRealtimeCallRes create() => RequestRealtimeCallRes._(); + RequestRealtimeCallRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static RequestRealtimeCallRes getDefault() => _defaultInstance ??= create()..freeze(); + static RequestRealtimeCallRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); +} + +class PushRealtimeCall extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('PushRealtimeCall', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'sUserId', $pb.PbFieldType.OU3) + ..e(2, 'cType', $pb.PbFieldType.OE, ChatType.TextChatType, ChatType.valueOf, ChatType.values) + ..hasRequiredFields = false + ; + + PushRealtimeCall._() : super(); + factory PushRealtimeCall() => create(); + factory PushRealtimeCall.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory PushRealtimeCall.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + PushRealtimeCall clone() => PushRealtimeCall()..mergeFromMessage(this); + PushRealtimeCall copyWith(void Function(PushRealtimeCall) updates) => super.copyWith((message) => updates(message as PushRealtimeCall)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static PushRealtimeCall create() => PushRealtimeCall._(); + PushRealtimeCall createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static PushRealtimeCall getDefault() => _defaultInstance ??= create()..freeze(); + static PushRealtimeCall _defaultInstance; + + $core.int get sUserId => $_get(0, 0); + set sUserId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasSUserId() => $_has(0); + void clearSUserId() => clearField(1); + + ChatType get cType => $_getN(1); + set cType(ChatType v) { setField(2, v); } + $core.bool hasCType() => $_has(1); + void clearCType() => clearField(2); +} + +class RespondRealtimeCallReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('RespondRealtimeCallReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'sUserId', $pb.PbFieldType.OU3) + ..aOB(2, 'isAnswer') + ..hasRequiredFields = false + ; + + RespondRealtimeCallReq._() : super(); + factory RespondRealtimeCallReq() => create(); + factory RespondRealtimeCallReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RespondRealtimeCallReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + RespondRealtimeCallReq clone() => RespondRealtimeCallReq()..mergeFromMessage(this); + RespondRealtimeCallReq copyWith(void Function(RespondRealtimeCallReq) updates) => super.copyWith((message) => updates(message as RespondRealtimeCallReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RespondRealtimeCallReq create() => RespondRealtimeCallReq._(); + RespondRealtimeCallReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static RespondRealtimeCallReq getDefault() => _defaultInstance ??= create()..freeze(); + static RespondRealtimeCallReq _defaultInstance; + + $core.int get sUserId => $_get(0, 0); + set sUserId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasSUserId() => $_has(0); + void clearSUserId() => clearField(1); + + $core.bool get isAnswer => $_get(1, false); + set isAnswer($core.bool v) { $_setBool(1, v); } + $core.bool hasIsAnswer() => $_has(1); + void clearIsAnswer() => clearField(2); +} + +class PushRealtimeCallRespond extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('PushRealtimeCallRespond', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'tUserId', $pb.PbFieldType.OU3) + ..aOB(2, 'isAnswer') + ..hasRequiredFields = false + ; + + PushRealtimeCallRespond._() : super(); + factory PushRealtimeCallRespond() => create(); + factory PushRealtimeCallRespond.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory PushRealtimeCallRespond.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + PushRealtimeCallRespond clone() => PushRealtimeCallRespond()..mergeFromMessage(this); + PushRealtimeCallRespond copyWith(void Function(PushRealtimeCallRespond) updates) => super.copyWith((message) => updates(message as PushRealtimeCallRespond)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static PushRealtimeCallRespond create() => PushRealtimeCallRespond._(); + PushRealtimeCallRespond createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static PushRealtimeCallRespond getDefault() => _defaultInstance ??= create()..freeze(); + static PushRealtimeCallRespond _defaultInstance; + + $core.int get tUserId => $_get(0, 0); + set tUserId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasTUserId() => $_has(0); + void clearTUserId() => clearField(1); + + $core.bool get isAnswer => $_get(1, false); + set isAnswer($core.bool v) { $_setBool(1, v); } + $core.bool hasIsAnswer() => $_has(1); + void clearIsAnswer() => clearField(2); +} + +class RequestGiftGivingReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('RequestGiftGivingReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'targetUserId', $pb.PbFieldType.OU3) + ..a<$core.int>(2, 'giftId', $pb.PbFieldType.OU3) + ..a<$core.int>(3, 'giftAmount', $pb.PbFieldType.OU3) + ..a<$core.int>(4, 'money', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + RequestGiftGivingReq._() : super(); + factory RequestGiftGivingReq() => create(); + factory RequestGiftGivingReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RequestGiftGivingReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + RequestGiftGivingReq clone() => RequestGiftGivingReq()..mergeFromMessage(this); + RequestGiftGivingReq copyWith(void Function(RequestGiftGivingReq) updates) => super.copyWith((message) => updates(message as RequestGiftGivingReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RequestGiftGivingReq create() => RequestGiftGivingReq._(); + RequestGiftGivingReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static RequestGiftGivingReq getDefault() => _defaultInstance ??= create()..freeze(); + static RequestGiftGivingReq _defaultInstance; + + $core.int get targetUserId => $_get(0, 0); + set targetUserId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasTargetUserId() => $_has(0); + void clearTargetUserId() => clearField(1); + + $core.int get giftId => $_get(1, 0); + set giftId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasGiftId() => $_has(1); + void clearGiftId() => clearField(2); + + $core.int get giftAmount => $_get(2, 0); + set giftAmount($core.int v) { $_setUnsignedInt32(2, v); } + $core.bool hasGiftAmount() => $_has(2); + void clearGiftAmount() => clearField(3); + + $core.int get money => $_get(3, 0); + set money($core.int v) { $_setUnsignedInt32(3, v); } + $core.bool hasMoney() => $_has(3); + void clearMoney() => clearField(4); +} + +class PushGiftGiving extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('PushGiftGiving', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'sendUserId', $pb.PbFieldType.OU3) + ..a<$core.int>(2, 'giftId', $pb.PbFieldType.OU3) + ..a<$core.int>(3, 'giftAmount', $pb.PbFieldType.OU3) + ..a<$core.int>(4, 'money', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + PushGiftGiving._() : super(); + factory PushGiftGiving() => create(); + factory PushGiftGiving.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory PushGiftGiving.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + PushGiftGiving clone() => PushGiftGiving()..mergeFromMessage(this); + PushGiftGiving copyWith(void Function(PushGiftGiving) updates) => super.copyWith((message) => updates(message as PushGiftGiving)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static PushGiftGiving create() => PushGiftGiving._(); + PushGiftGiving createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static PushGiftGiving getDefault() => _defaultInstance ??= create()..freeze(); + static PushGiftGiving _defaultInstance; + + $core.int get sendUserId => $_get(0, 0); + set sendUserId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasSendUserId() => $_has(0); + void clearSendUserId() => clearField(1); + + $core.int get giftId => $_get(1, 0); + set giftId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasGiftId() => $_has(1); + void clearGiftId() => clearField(2); + + $core.int get giftAmount => $_get(2, 0); + set giftAmount($core.int v) { $_setUnsignedInt32(2, v); } + $core.bool hasGiftAmount() => $_has(2); + void clearGiftAmount() => clearField(3); + + $core.int get money => $_get(3, 0); + set money($core.int v) { $_setUnsignedInt32(3, v); } + $core.bool hasMoney() => $_has(3); + void clearMoney() => clearField(4); +} + +class QueryUsersInfoReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('QueryUsersInfoReq', package: const $pb.PackageName('yl_pb')) + ..p<$core.int>(1, 'userIds', $pb.PbFieldType.PU3) + ..hasRequiredFields = false + ; + + QueryUsersInfoReq._() : super(); + factory QueryUsersInfoReq() => create(); + factory QueryUsersInfoReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory QueryUsersInfoReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + QueryUsersInfoReq clone() => QueryUsersInfoReq()..mergeFromMessage(this); + QueryUsersInfoReq copyWith(void Function(QueryUsersInfoReq) updates) => super.copyWith((message) => updates(message as QueryUsersInfoReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static QueryUsersInfoReq create() => QueryUsersInfoReq._(); + QueryUsersInfoReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static QueryUsersInfoReq getDefault() => _defaultInstance ??= create()..freeze(); + static QueryUsersInfoReq _defaultInstance; + + $core.List<$core.int> get userIds => $_getList(0); +} + +class QueryUsersInfoRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('QueryUsersInfoRes', package: const $pb.PackageName('yl_pb')) + ..pc(1, 'infos', $pb.PbFieldType.PM,BaseUserInfo.create) + ..hasRequiredFields = false + ; + + QueryUsersInfoRes._() : super(); + factory QueryUsersInfoRes() => create(); + factory QueryUsersInfoRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory QueryUsersInfoRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + QueryUsersInfoRes clone() => QueryUsersInfoRes()..mergeFromMessage(this); + QueryUsersInfoRes copyWith(void Function(QueryUsersInfoRes) updates) => super.copyWith((message) => updates(message as QueryUsersInfoRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static QueryUsersInfoRes create() => QueryUsersInfoRes._(); + QueryUsersInfoRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static QueryUsersInfoRes getDefault() => _defaultInstance ??= create()..freeze(); + static QueryUsersInfoRes _defaultInstance; + + $core.List get infos => $_getList(0); +} + +class CreateSessionReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('CreateSessionReq', package: const $pb.PackageName('yl_pb')) + ..p<$core.int>(1, 'memberIds', $pb.PbFieldType.PU3) + ..hasRequiredFields = false + ; + + CreateSessionReq._() : super(); + factory CreateSessionReq() => create(); + factory CreateSessionReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CreateSessionReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + CreateSessionReq clone() => CreateSessionReq()..mergeFromMessage(this); + CreateSessionReq copyWith(void Function(CreateSessionReq) updates) => super.copyWith((message) => updates(message as CreateSessionReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CreateSessionReq create() => CreateSessionReq._(); + CreateSessionReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static CreateSessionReq getDefault() => _defaultInstance ??= create()..freeze(); + static CreateSessionReq _defaultInstance; + + $core.List<$core.int> get memberIds => $_getList(0); +} + +class QuerySessionReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('QuerySessionReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'sessionId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + QuerySessionReq._() : super(); + factory QuerySessionReq() => create(); + factory QuerySessionReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory QuerySessionReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + QuerySessionReq clone() => QuerySessionReq()..mergeFromMessage(this); + QuerySessionReq copyWith(void Function(QuerySessionReq) updates) => super.copyWith((message) => updates(message as QuerySessionReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static QuerySessionReq create() => QuerySessionReq._(); + QuerySessionReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static QuerySessionReq getDefault() => _defaultInstance ??= create()..freeze(); + static QuerySessionReq _defaultInstance; + + $core.int get sessionId => $_get(0, 0); + set sessionId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasSessionId() => $_has(0); + void clearSessionId() => clearField(1); +} + +class SessionInfoRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('SessionInfoRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a<$core.int>(2, 'sessionId', $pb.PbFieldType.OU3) + ..pc(3, 'members', $pb.PbFieldType.PM,BaseUserInfo.create) + ..e(4, 'isNeedHTransl', $pb.PbFieldType.OE, TranslateState.NoPerson, TranslateState.valueOf, TranslateState.values) + ..hasRequiredFields = false + ; + + SessionInfoRes._() : super(); + factory SessionInfoRes() => create(); + factory SessionInfoRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SessionInfoRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + SessionInfoRes clone() => SessionInfoRes()..mergeFromMessage(this); + SessionInfoRes copyWith(void Function(SessionInfoRes) updates) => super.copyWith((message) => updates(message as SessionInfoRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SessionInfoRes create() => SessionInfoRes._(); + SessionInfoRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static SessionInfoRes getDefault() => _defaultInstance ??= create()..freeze(); + static SessionInfoRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.int get sessionId => $_get(1, 0); + set sessionId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasSessionId() => $_has(1); + void clearSessionId() => clearField(2); + + $core.List get members => $_getList(2); + + TranslateState get isNeedHTransl => $_getN(3); + set isNeedHTransl(TranslateState v) { setField(4, v); } + $core.bool hasIsNeedHTransl() => $_has(3); + void clearIsNeedHTransl() => clearField(4); +} + +class GroupMember extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GroupMember', package: const $pb.PackageName('yl_pb')) + ..a(1, 'info', $pb.PbFieldType.OM, BaseUserInfo.getDefault, BaseUserInfo.create) + ..aOS(2, 'name') + ..e(3, 'identity', $pb.PbFieldType.OE, GroupMemberIdentity.identityNormal, GroupMemberIdentity.valueOf, GroupMemberIdentity.values) + ..aOB(4, 'messageFree') + ..aOB(5, 'effectiveUser') + ..hasRequiredFields = false + ; + + GroupMember._() : super(); + factory GroupMember() => create(); + factory GroupMember.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GroupMember.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GroupMember clone() => GroupMember()..mergeFromMessage(this); + GroupMember copyWith(void Function(GroupMember) updates) => super.copyWith((message) => updates(message as GroupMember)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GroupMember create() => GroupMember._(); + GroupMember createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GroupMember getDefault() => _defaultInstance ??= create()..freeze(); + static GroupMember _defaultInstance; + + BaseUserInfo get info => $_getN(0); + set info(BaseUserInfo v) { setField(1, v); } + $core.bool hasInfo() => $_has(0); + void clearInfo() => clearField(1); + + $core.String get name => $_getS(1, ''); + set name($core.String v) { $_setString(1, v); } + $core.bool hasName() => $_has(1); + void clearName() => clearField(2); + + GroupMemberIdentity get identity => $_getN(2); + set identity(GroupMemberIdentity v) { setField(3, v); } + $core.bool hasIdentity() => $_has(2); + void clearIdentity() => clearField(3); + + $core.bool get messageFree => $_get(3, false); + set messageFree($core.bool v) { $_setBool(3, v); } + $core.bool hasMessageFree() => $_has(3); + void clearMessageFree() => clearField(4); + + $core.bool get effectiveUser => $_get(4, false); + set effectiveUser($core.bool v) { $_setBool(4, v); } + $core.bool hasEffectiveUser() => $_has(4); + void clearEffectiveUser() => clearField(5); +} + +class GroupInfo extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GroupInfo', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'id', $pb.PbFieldType.OU3) + ..a<$core.int>(2, 'code', $pb.PbFieldType.OU3) + ..aOS(3, 'groupName') + ..aOS(4, 'notice') + ..pc(5, 'members', $pb.PbFieldType.PM,GroupMember.create) + ..aOB(6, 'isOpenMemberCheck') + ..hasRequiredFields = false + ; + + GroupInfo._() : super(); + factory GroupInfo() => create(); + factory GroupInfo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GroupInfo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GroupInfo clone() => GroupInfo()..mergeFromMessage(this); + GroupInfo copyWith(void Function(GroupInfo) updates) => super.copyWith((message) => updates(message as GroupInfo)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GroupInfo create() => GroupInfo._(); + GroupInfo createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GroupInfo getDefault() => _defaultInstance ??= create()..freeze(); + static GroupInfo _defaultInstance; + + $core.int get id => $_get(0, 0); + set id($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasId() => $_has(0); + void clearId() => clearField(1); + + $core.int get code => $_get(1, 0); + set code($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasCode() => $_has(1); + void clearCode() => clearField(2); + + $core.String get groupName => $_getS(2, ''); + set groupName($core.String v) { $_setString(2, v); } + $core.bool hasGroupName() => $_has(2); + void clearGroupName() => clearField(3); + + $core.String get notice => $_getS(3, ''); + set notice($core.String v) { $_setString(3, v); } + $core.bool hasNotice() => $_has(3); + void clearNotice() => clearField(4); + + $core.List get members => $_getList(4); + + $core.bool get isOpenMemberCheck => $_get(5, false); + set isOpenMemberCheck($core.bool v) { $_setBool(5, v); } + $core.bool hasIsOpenMemberCheck() => $_has(5); + void clearIsOpenMemberCheck() => clearField(6); +} + +class GroupChatNotice extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GroupChatNotice', package: const $pb.PackageName('yl_pb')) + ..e(1, 'changeType', $pb.PbFieldType.OE, GroupChangeType.AddMember, GroupChangeType.valueOf, GroupChangeType.values) + ..a(2, 'operatuId', $pb.PbFieldType.OM, BaseUserInfo.getDefault, BaseUserInfo.create) + ..pc(3, 'operateduId', $pb.PbFieldType.PM,BaseUserInfo.create) + ..aOS(4, 'changeStr') + ..aOB(5, 'changeBool') + ..hasRequiredFields = false + ; + + GroupChatNotice._() : super(); + factory GroupChatNotice() => create(); + factory GroupChatNotice.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GroupChatNotice.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GroupChatNotice clone() => GroupChatNotice()..mergeFromMessage(this); + GroupChatNotice copyWith(void Function(GroupChatNotice) updates) => super.copyWith((message) => updates(message as GroupChatNotice)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GroupChatNotice create() => GroupChatNotice._(); + GroupChatNotice createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GroupChatNotice getDefault() => _defaultInstance ??= create()..freeze(); + static GroupChatNotice _defaultInstance; + + GroupChangeType get changeType => $_getN(0); + set changeType(GroupChangeType v) { setField(1, v); } + $core.bool hasChangeType() => $_has(0); + void clearChangeType() => clearField(1); + + BaseUserInfo get operatuId => $_getN(1); + set operatuId(BaseUserInfo v) { setField(2, v); } + $core.bool hasOperatuId() => $_has(1); + void clearOperatuId() => clearField(2); + + $core.List get operateduId => $_getList(2); + + $core.String get changeStr => $_getS(3, ''); + set changeStr($core.String v) { $_setString(3, v); } + $core.bool hasChangeStr() => $_has(3); + void clearChangeStr() => clearField(4); + + $core.bool get changeBool => $_get(4, false); + set changeBool($core.bool v) { $_setBool(4, v); } + $core.bool hasChangeBool() => $_has(4); + void clearChangeBool() => clearField(5); +} + +class CreateChatGroupReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('CreateChatGroupReq', package: const $pb.PackageName('yl_pb')) + ..p<$core.int>(3, 'members', $pb.PbFieldType.PU3) + ..hasRequiredFields = false + ; + + CreateChatGroupReq._() : super(); + factory CreateChatGroupReq() => create(); + factory CreateChatGroupReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CreateChatGroupReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + CreateChatGroupReq clone() => CreateChatGroupReq()..mergeFromMessage(this); + CreateChatGroupReq copyWith(void Function(CreateChatGroupReq) updates) => super.copyWith((message) => updates(message as CreateChatGroupReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CreateChatGroupReq create() => CreateChatGroupReq._(); + CreateChatGroupReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static CreateChatGroupReq getDefault() => _defaultInstance ??= create()..freeze(); + static CreateChatGroupReq _defaultInstance; + + $core.List<$core.int> get members => $_getList(0); +} + +class CreateChatGroupRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('CreateChatGroupRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a(2, 'group', $pb.PbFieldType.OM, GroupInfo.getDefault, GroupInfo.create) + ..hasRequiredFields = false + ; + + CreateChatGroupRes._() : super(); + factory CreateChatGroupRes() => create(); + factory CreateChatGroupRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CreateChatGroupRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + CreateChatGroupRes clone() => CreateChatGroupRes()..mergeFromMessage(this); + CreateChatGroupRes copyWith(void Function(CreateChatGroupRes) updates) => super.copyWith((message) => updates(message as CreateChatGroupRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CreateChatGroupRes create() => CreateChatGroupRes._(); + CreateChatGroupRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static CreateChatGroupRes getDefault() => _defaultInstance ??= create()..freeze(); + static CreateChatGroupRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + GroupInfo get group => $_getN(1); + set group(GroupInfo v) { setField(2, v); } + $core.bool hasGroup() => $_has(1); + void clearGroup() => clearField(2); +} + +class QuitChatGroupReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('QuitChatGroupReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'groupId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + QuitChatGroupReq._() : super(); + factory QuitChatGroupReq() => create(); + factory QuitChatGroupReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory QuitChatGroupReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + QuitChatGroupReq clone() => QuitChatGroupReq()..mergeFromMessage(this); + QuitChatGroupReq copyWith(void Function(QuitChatGroupReq) updates) => super.copyWith((message) => updates(message as QuitChatGroupReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static QuitChatGroupReq create() => QuitChatGroupReq._(); + QuitChatGroupReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static QuitChatGroupReq getDefault() => _defaultInstance ??= create()..freeze(); + static QuitChatGroupReq _defaultInstance; + + $core.int get groupId => $_get(0, 0); + set groupId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasGroupId() => $_has(0); + void clearGroupId() => clearField(1); +} + +class QuitChatGroupRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('QuitChatGroupRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a<$core.int>(2, 'groupId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + QuitChatGroupRes._() : super(); + factory QuitChatGroupRes() => create(); + factory QuitChatGroupRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory QuitChatGroupRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + QuitChatGroupRes clone() => QuitChatGroupRes()..mergeFromMessage(this); + QuitChatGroupRes copyWith(void Function(QuitChatGroupRes) updates) => super.copyWith((message) => updates(message as QuitChatGroupRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static QuitChatGroupRes create() => QuitChatGroupRes._(); + QuitChatGroupRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static QuitChatGroupRes getDefault() => _defaultInstance ??= create()..freeze(); + static QuitChatGroupRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.int get groupId => $_get(1, 0); + set groupId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasGroupId() => $_has(1); + void clearGroupId() => clearField(2); +} + +class QueryChatGroupReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('QueryChatGroupReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'groupId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + QueryChatGroupReq._() : super(); + factory QueryChatGroupReq() => create(); + factory QueryChatGroupReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory QueryChatGroupReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + QueryChatGroupReq clone() => QueryChatGroupReq()..mergeFromMessage(this); + QueryChatGroupReq copyWith(void Function(QueryChatGroupReq) updates) => super.copyWith((message) => updates(message as QueryChatGroupReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static QueryChatGroupReq create() => QueryChatGroupReq._(); + QueryChatGroupReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static QueryChatGroupReq getDefault() => _defaultInstance ??= create()..freeze(); + static QueryChatGroupReq _defaultInstance; + + $core.int get groupId => $_get(0, 0); + set groupId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasGroupId() => $_has(0); + void clearGroupId() => clearField(1); +} + +class QueryChatGroupRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('QueryChatGroupRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a(2, 'group', $pb.PbFieldType.OM, GroupInfo.getDefault, GroupInfo.create) + ..hasRequiredFields = false + ; + + QueryChatGroupRes._() : super(); + factory QueryChatGroupRes() => create(); + factory QueryChatGroupRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory QueryChatGroupRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + QueryChatGroupRes clone() => QueryChatGroupRes()..mergeFromMessage(this); + QueryChatGroupRes copyWith(void Function(QueryChatGroupRes) updates) => super.copyWith((message) => updates(message as QueryChatGroupRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static QueryChatGroupRes create() => QueryChatGroupRes._(); + QueryChatGroupRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static QueryChatGroupRes getDefault() => _defaultInstance ??= create()..freeze(); + static QueryChatGroupRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + GroupInfo get group => $_getN(1); + set group(GroupInfo v) { setField(2, v); } + $core.bool hasGroup() => $_has(1); + void clearGroup() => clearField(2); +} + +class AddGroupMemberReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('AddGroupMemberReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'groupId', $pb.PbFieldType.OU3) + ..p<$core.int>(2, 'userIds', $pb.PbFieldType.PU3) + ..hasRequiredFields = false + ; + + AddGroupMemberReq._() : super(); + factory AddGroupMemberReq() => create(); + factory AddGroupMemberReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory AddGroupMemberReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + AddGroupMemberReq clone() => AddGroupMemberReq()..mergeFromMessage(this); + AddGroupMemberReq copyWith(void Function(AddGroupMemberReq) updates) => super.copyWith((message) => updates(message as AddGroupMemberReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static AddGroupMemberReq create() => AddGroupMemberReq._(); + AddGroupMemberReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static AddGroupMemberReq getDefault() => _defaultInstance ??= create()..freeze(); + static AddGroupMemberReq _defaultInstance; + + $core.int get groupId => $_get(0, 0); + set groupId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasGroupId() => $_has(0); + void clearGroupId() => clearField(1); + + $core.List<$core.int> get userIds => $_getList(1); +} + +class AddGroupMemberRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('AddGroupMemberRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a<$core.int>(2, 'groupId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + AddGroupMemberRes._() : super(); + factory AddGroupMemberRes() => create(); + factory AddGroupMemberRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory AddGroupMemberRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + AddGroupMemberRes clone() => AddGroupMemberRes()..mergeFromMessage(this); + AddGroupMemberRes copyWith(void Function(AddGroupMemberRes) updates) => super.copyWith((message) => updates(message as AddGroupMemberRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static AddGroupMemberRes create() => AddGroupMemberRes._(); + AddGroupMemberRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static AddGroupMemberRes getDefault() => _defaultInstance ??= create()..freeze(); + static AddGroupMemberRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.int get groupId => $_get(1, 0); + set groupId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasGroupId() => $_has(1); + void clearGroupId() => clearField(2); +} + +class RemoveGroupMemberReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('RemoveGroupMemberReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'groupId', $pb.PbFieldType.OU3) + ..p<$core.int>(2, 'userIds', $pb.PbFieldType.PU3) + ..hasRequiredFields = false + ; + + RemoveGroupMemberReq._() : super(); + factory RemoveGroupMemberReq() => create(); + factory RemoveGroupMemberReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RemoveGroupMemberReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + RemoveGroupMemberReq clone() => RemoveGroupMemberReq()..mergeFromMessage(this); + RemoveGroupMemberReq copyWith(void Function(RemoveGroupMemberReq) updates) => super.copyWith((message) => updates(message as RemoveGroupMemberReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RemoveGroupMemberReq create() => RemoveGroupMemberReq._(); + RemoveGroupMemberReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static RemoveGroupMemberReq getDefault() => _defaultInstance ??= create()..freeze(); + static RemoveGroupMemberReq _defaultInstance; + + $core.int get groupId => $_get(0, 0); + set groupId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasGroupId() => $_has(0); + void clearGroupId() => clearField(1); + + $core.List<$core.int> get userIds => $_getList(1); +} + +class RemoveGroupMemberRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('RemoveGroupMemberRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a<$core.int>(2, 'groupId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + RemoveGroupMemberRes._() : super(); + factory RemoveGroupMemberRes() => create(); + factory RemoveGroupMemberRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RemoveGroupMemberRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + RemoveGroupMemberRes clone() => RemoveGroupMemberRes()..mergeFromMessage(this); + RemoveGroupMemberRes copyWith(void Function(RemoveGroupMemberRes) updates) => super.copyWith((message) => updates(message as RemoveGroupMemberRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RemoveGroupMemberRes create() => RemoveGroupMemberRes._(); + RemoveGroupMemberRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static RemoveGroupMemberRes getDefault() => _defaultInstance ??= create()..freeze(); + static RemoveGroupMemberRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.int get groupId => $_get(1, 0); + set groupId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasGroupId() => $_has(1); + void clearGroupId() => clearField(2); +} + +class ModifyGroupNoticeReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ModifyGroupNoticeReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'groupId', $pb.PbFieldType.OU3) + ..aOS(2, 'notice') + ..hasRequiredFields = false + ; + + ModifyGroupNoticeReq._() : super(); + factory ModifyGroupNoticeReq() => create(); + factory ModifyGroupNoticeReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ModifyGroupNoticeReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + ModifyGroupNoticeReq clone() => ModifyGroupNoticeReq()..mergeFromMessage(this); + ModifyGroupNoticeReq copyWith(void Function(ModifyGroupNoticeReq) updates) => super.copyWith((message) => updates(message as ModifyGroupNoticeReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static ModifyGroupNoticeReq create() => ModifyGroupNoticeReq._(); + ModifyGroupNoticeReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static ModifyGroupNoticeReq getDefault() => _defaultInstance ??= create()..freeze(); + static ModifyGroupNoticeReq _defaultInstance; + + $core.int get groupId => $_get(0, 0); + set groupId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasGroupId() => $_has(0); + void clearGroupId() => clearField(1); + + $core.String get notice => $_getS(1, ''); + set notice($core.String v) { $_setString(1, v); } + $core.bool hasNotice() => $_has(1); + void clearNotice() => clearField(2); +} + +class ModifyGroupNoticeRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ModifyGroupNoticeRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a<$core.int>(2, 'groupId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + ModifyGroupNoticeRes._() : super(); + factory ModifyGroupNoticeRes() => create(); + factory ModifyGroupNoticeRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ModifyGroupNoticeRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + ModifyGroupNoticeRes clone() => ModifyGroupNoticeRes()..mergeFromMessage(this); + ModifyGroupNoticeRes copyWith(void Function(ModifyGroupNoticeRes) updates) => super.copyWith((message) => updates(message as ModifyGroupNoticeRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static ModifyGroupNoticeRes create() => ModifyGroupNoticeRes._(); + ModifyGroupNoticeRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static ModifyGroupNoticeRes getDefault() => _defaultInstance ??= create()..freeze(); + static ModifyGroupNoticeRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.int get groupId => $_get(1, 0); + set groupId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasGroupId() => $_has(1); + void clearGroupId() => clearField(2); +} + +class ModifyGroupNameReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ModifyGroupNameReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'groupId', $pb.PbFieldType.OU3) + ..aOS(2, 'name') + ..hasRequiredFields = false + ; + + ModifyGroupNameReq._() : super(); + factory ModifyGroupNameReq() => create(); + factory ModifyGroupNameReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ModifyGroupNameReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + ModifyGroupNameReq clone() => ModifyGroupNameReq()..mergeFromMessage(this); + ModifyGroupNameReq copyWith(void Function(ModifyGroupNameReq) updates) => super.copyWith((message) => updates(message as ModifyGroupNameReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static ModifyGroupNameReq create() => ModifyGroupNameReq._(); + ModifyGroupNameReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static ModifyGroupNameReq getDefault() => _defaultInstance ??= create()..freeze(); + static ModifyGroupNameReq _defaultInstance; + + $core.int get groupId => $_get(0, 0); + set groupId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasGroupId() => $_has(0); + void clearGroupId() => clearField(1); + + $core.String get name => $_getS(1, ''); + set name($core.String v) { $_setString(1, v); } + $core.bool hasName() => $_has(1); + void clearName() => clearField(2); +} + +class ModifyGroupNameRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('ModifyGroupNameRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a<$core.int>(2, 'groupId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + ModifyGroupNameRes._() : super(); + factory ModifyGroupNameRes() => create(); + factory ModifyGroupNameRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ModifyGroupNameRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + ModifyGroupNameRes clone() => ModifyGroupNameRes()..mergeFromMessage(this); + ModifyGroupNameRes copyWith(void Function(ModifyGroupNameRes) updates) => super.copyWith((message) => updates(message as ModifyGroupNameRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static ModifyGroupNameRes create() => ModifyGroupNameRes._(); + ModifyGroupNameRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static ModifyGroupNameRes getDefault() => _defaultInstance ??= create()..freeze(); + static ModifyGroupNameRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.int get groupId => $_get(1, 0); + set groupId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasGroupId() => $_has(1); + void clearGroupId() => clearField(2); +} + +class GroupMemberModifyAliasReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GroupMemberModifyAliasReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'groupId', $pb.PbFieldType.OU3) + ..aOS(2, 'name') + ..hasRequiredFields = false + ; + + GroupMemberModifyAliasReq._() : super(); + factory GroupMemberModifyAliasReq() => create(); + factory GroupMemberModifyAliasReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GroupMemberModifyAliasReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GroupMemberModifyAliasReq clone() => GroupMemberModifyAliasReq()..mergeFromMessage(this); + GroupMemberModifyAliasReq copyWith(void Function(GroupMemberModifyAliasReq) updates) => super.copyWith((message) => updates(message as GroupMemberModifyAliasReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GroupMemberModifyAliasReq create() => GroupMemberModifyAliasReq._(); + GroupMemberModifyAliasReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GroupMemberModifyAliasReq getDefault() => _defaultInstance ??= create()..freeze(); + static GroupMemberModifyAliasReq _defaultInstance; + + $core.int get groupId => $_get(0, 0); + set groupId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasGroupId() => $_has(0); + void clearGroupId() => clearField(1); + + $core.String get name => $_getS(1, ''); + set name($core.String v) { $_setString(1, v); } + $core.bool hasName() => $_has(1); + void clearName() => clearField(2); +} + +class GroupMemberModifyAliasRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GroupMemberModifyAliasRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a<$core.int>(2, 'groupId', $pb.PbFieldType.OU3) + ..aOS(3, 'name') + ..hasRequiredFields = false + ; + + GroupMemberModifyAliasRes._() : super(); + factory GroupMemberModifyAliasRes() => create(); + factory GroupMemberModifyAliasRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GroupMemberModifyAliasRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GroupMemberModifyAliasRes clone() => GroupMemberModifyAliasRes()..mergeFromMessage(this); + GroupMemberModifyAliasRes copyWith(void Function(GroupMemberModifyAliasRes) updates) => super.copyWith((message) => updates(message as GroupMemberModifyAliasRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GroupMemberModifyAliasRes create() => GroupMemberModifyAliasRes._(); + GroupMemberModifyAliasRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GroupMemberModifyAliasRes getDefault() => _defaultInstance ??= create()..freeze(); + static GroupMemberModifyAliasRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.int get groupId => $_get(1, 0); + set groupId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasGroupId() => $_has(1); + void clearGroupId() => clearField(2); + + $core.String get name => $_getS(2, ''); + set name($core.String v) { $_setString(2, v); } + $core.bool hasName() => $_has(2); + void clearName() => clearField(3); +} + +class QueryUserRelationGroupReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('QueryUserRelationGroupReq', package: const $pb.PackageName('yl_pb')) + ..hasRequiredFields = false + ; + + QueryUserRelationGroupReq._() : super(); + factory QueryUserRelationGroupReq() => create(); + factory QueryUserRelationGroupReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory QueryUserRelationGroupReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + QueryUserRelationGroupReq clone() => QueryUserRelationGroupReq()..mergeFromMessage(this); + QueryUserRelationGroupReq copyWith(void Function(QueryUserRelationGroupReq) updates) => super.copyWith((message) => updates(message as QueryUserRelationGroupReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static QueryUserRelationGroupReq create() => QueryUserRelationGroupReq._(); + QueryUserRelationGroupReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static QueryUserRelationGroupReq getDefault() => _defaultInstance ??= create()..freeze(); + static QueryUserRelationGroupReq _defaultInstance; +} + +class QueryUserRelationGroupRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('QueryUserRelationGroupRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..pc(2, 'relationGroup', $pb.PbFieldType.PM,GroupInfo.create) + ..hasRequiredFields = false + ; + + QueryUserRelationGroupRes._() : super(); + factory QueryUserRelationGroupRes() => create(); + factory QueryUserRelationGroupRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory QueryUserRelationGroupRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + QueryUserRelationGroupRes clone() => QueryUserRelationGroupRes()..mergeFromMessage(this); + QueryUserRelationGroupRes copyWith(void Function(QueryUserRelationGroupRes) updates) => super.copyWith((message) => updates(message as QueryUserRelationGroupRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static QueryUserRelationGroupRes create() => QueryUserRelationGroupRes._(); + QueryUserRelationGroupRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static QueryUserRelationGroupRes getDefault() => _defaultInstance ??= create()..freeze(); + static QueryUserRelationGroupRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.List get relationGroup => $_getList(1); +} + +class SettingGroupReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('SettingGroupReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'groupId', $pb.PbFieldType.OU3) + ..aOB(2, 'isOpenMemberCheck') + ..hasRequiredFields = false + ; + + SettingGroupReq._() : super(); + factory SettingGroupReq() => create(); + factory SettingGroupReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SettingGroupReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + SettingGroupReq clone() => SettingGroupReq()..mergeFromMessage(this); + SettingGroupReq copyWith(void Function(SettingGroupReq) updates) => super.copyWith((message) => updates(message as SettingGroupReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SettingGroupReq create() => SettingGroupReq._(); + SettingGroupReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static SettingGroupReq getDefault() => _defaultInstance ??= create()..freeze(); + static SettingGroupReq _defaultInstance; + + $core.int get groupId => $_get(0, 0); + set groupId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasGroupId() => $_has(0); + void clearGroupId() => clearField(1); + + $core.bool get isOpenMemberCheck => $_get(1, false); + set isOpenMemberCheck($core.bool v) { $_setBool(1, v); } + $core.bool hasIsOpenMemberCheck() => $_has(1); + void clearIsOpenMemberCheck() => clearField(2); +} + +class SettingGroupRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('SettingGroupRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a<$core.int>(2, 'groupId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + SettingGroupRes._() : super(); + factory SettingGroupRes() => create(); + factory SettingGroupRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SettingGroupRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + SettingGroupRes clone() => SettingGroupRes()..mergeFromMessage(this); + SettingGroupRes copyWith(void Function(SettingGroupRes) updates) => super.copyWith((message) => updates(message as SettingGroupRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SettingGroupRes create() => SettingGroupRes._(); + SettingGroupRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static SettingGroupRes getDefault() => _defaultInstance ??= create()..freeze(); + static SettingGroupRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.int get groupId => $_get(1, 0); + set groupId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasGroupId() => $_has(1); + void clearGroupId() => clearField(2); +} + +class GroupQRcodeAddMemberReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GroupQRcodeAddMemberReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'groupId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + GroupQRcodeAddMemberReq._() : super(); + factory GroupQRcodeAddMemberReq() => create(); + factory GroupQRcodeAddMemberReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GroupQRcodeAddMemberReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GroupQRcodeAddMemberReq clone() => GroupQRcodeAddMemberReq()..mergeFromMessage(this); + GroupQRcodeAddMemberReq copyWith(void Function(GroupQRcodeAddMemberReq) updates) => super.copyWith((message) => updates(message as GroupQRcodeAddMemberReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GroupQRcodeAddMemberReq create() => GroupQRcodeAddMemberReq._(); + GroupQRcodeAddMemberReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GroupQRcodeAddMemberReq getDefault() => _defaultInstance ??= create()..freeze(); + static GroupQRcodeAddMemberReq _defaultInstance; + + $core.int get groupId => $_get(0, 0); + set groupId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasGroupId() => $_has(0); + void clearGroupId() => clearField(1); +} + +class GroupQRcodeAddMemberRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GroupQRcodeAddMemberRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a(2, 'group', $pb.PbFieldType.OM, GroupInfo.getDefault, GroupInfo.create) + ..hasRequiredFields = false + ; + + GroupQRcodeAddMemberRes._() : super(); + factory GroupQRcodeAddMemberRes() => create(); + factory GroupQRcodeAddMemberRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GroupQRcodeAddMemberRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GroupQRcodeAddMemberRes clone() => GroupQRcodeAddMemberRes()..mergeFromMessage(this); + GroupQRcodeAddMemberRes copyWith(void Function(GroupQRcodeAddMemberRes) updates) => super.copyWith((message) => updates(message as GroupQRcodeAddMemberRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GroupQRcodeAddMemberRes create() => GroupQRcodeAddMemberRes._(); + GroupQRcodeAddMemberRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GroupQRcodeAddMemberRes getDefault() => _defaultInstance ??= create()..freeze(); + static GroupQRcodeAddMemberRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + GroupInfo get group => $_getN(1); + set group(GroupInfo v) { setField(2, v); } + $core.bool hasGroup() => $_has(1); + void clearGroup() => clearField(2); +} + +class GroupMasterTransReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GroupMasterTransReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'groupId', $pb.PbFieldType.OU3) + ..a<$core.int>(2, 'userId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + GroupMasterTransReq._() : super(); + factory GroupMasterTransReq() => create(); + factory GroupMasterTransReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GroupMasterTransReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GroupMasterTransReq clone() => GroupMasterTransReq()..mergeFromMessage(this); + GroupMasterTransReq copyWith(void Function(GroupMasterTransReq) updates) => super.copyWith((message) => updates(message as GroupMasterTransReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GroupMasterTransReq create() => GroupMasterTransReq._(); + GroupMasterTransReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GroupMasterTransReq getDefault() => _defaultInstance ??= create()..freeze(); + static GroupMasterTransReq _defaultInstance; + + $core.int get groupId => $_get(0, 0); + set groupId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasGroupId() => $_has(0); + void clearGroupId() => clearField(1); + + $core.int get userId => $_get(1, 0); + set userId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasUserId() => $_has(1); + void clearUserId() => clearField(2); +} + +class GroupMasterTransRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GroupMasterTransRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a<$core.int>(2, 'groupId', $pb.PbFieldType.OU3) + ..a<$core.int>(3, 'userId', $pb.PbFieldType.OU3) + ..hasRequiredFields = false + ; + + GroupMasterTransRes._() : super(); + factory GroupMasterTransRes() => create(); + factory GroupMasterTransRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GroupMasterTransRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GroupMasterTransRes clone() => GroupMasterTransRes()..mergeFromMessage(this); + GroupMasterTransRes copyWith(void Function(GroupMasterTransRes) updates) => super.copyWith((message) => updates(message as GroupMasterTransRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GroupMasterTransRes create() => GroupMasterTransRes._(); + GroupMasterTransRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GroupMasterTransRes getDefault() => _defaultInstance ??= create()..freeze(); + static GroupMasterTransRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.int get groupId => $_get(1, 0); + set groupId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasGroupId() => $_has(1); + void clearGroupId() => clearField(2); + + $core.int get userId => $_get(2, 0); + set userId($core.int v) { $_setUnsignedInt32(2, v); } + $core.bool hasUserId() => $_has(2); + void clearUserId() => clearField(3); +} + +class GroupMasterCheckAddMemberReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GroupMasterCheckAddMemberReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'groupId', $pb.PbFieldType.OU3) + ..p<$core.int>(2, 'userIds', $pb.PbFieldType.PU3) + ..hasRequiredFields = false + ; + + GroupMasterCheckAddMemberReq._() : super(); + factory GroupMasterCheckAddMemberReq() => create(); + factory GroupMasterCheckAddMemberReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GroupMasterCheckAddMemberReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GroupMasterCheckAddMemberReq clone() => GroupMasterCheckAddMemberReq()..mergeFromMessage(this); + GroupMasterCheckAddMemberReq copyWith(void Function(GroupMasterCheckAddMemberReq) updates) => super.copyWith((message) => updates(message as GroupMasterCheckAddMemberReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GroupMasterCheckAddMemberReq create() => GroupMasterCheckAddMemberReq._(); + GroupMasterCheckAddMemberReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GroupMasterCheckAddMemberReq getDefault() => _defaultInstance ??= create()..freeze(); + static GroupMasterCheckAddMemberReq _defaultInstance; + + $core.int get groupId => $_get(0, 0); + set groupId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasGroupId() => $_has(0); + void clearGroupId() => clearField(1); + + $core.List<$core.int> get userIds => $_getList(1); +} + +class GroupMasterCheckAddMemberRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GroupMasterCheckAddMemberRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a<$core.int>(2, 'groupId', $pb.PbFieldType.OU3) + ..p<$core.int>(3, 'userIds', $pb.PbFieldType.PU3) + ..hasRequiredFields = false + ; + + GroupMasterCheckAddMemberRes._() : super(); + factory GroupMasterCheckAddMemberRes() => create(); + factory GroupMasterCheckAddMemberRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GroupMasterCheckAddMemberRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GroupMasterCheckAddMemberRes clone() => GroupMasterCheckAddMemberRes()..mergeFromMessage(this); + GroupMasterCheckAddMemberRes copyWith(void Function(GroupMasterCheckAddMemberRes) updates) => super.copyWith((message) => updates(message as GroupMasterCheckAddMemberRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GroupMasterCheckAddMemberRes create() => GroupMasterCheckAddMemberRes._(); + GroupMasterCheckAddMemberRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GroupMasterCheckAddMemberRes getDefault() => _defaultInstance ??= create()..freeze(); + static GroupMasterCheckAddMemberRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.int get groupId => $_get(1, 0); + set groupId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasGroupId() => $_has(1); + void clearGroupId() => clearField(2); + + $core.List<$core.int> get userIds => $_getList(2); +} + +class SetGroupMasterMessageFreeReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('SetGroupMasterMessageFreeReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'groupId', $pb.PbFieldType.OU3) + ..aOB(2, 'messageFree') + ..hasRequiredFields = false + ; + + SetGroupMasterMessageFreeReq._() : super(); + factory SetGroupMasterMessageFreeReq() => create(); + factory SetGroupMasterMessageFreeReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SetGroupMasterMessageFreeReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + SetGroupMasterMessageFreeReq clone() => SetGroupMasterMessageFreeReq()..mergeFromMessage(this); + SetGroupMasterMessageFreeReq copyWith(void Function(SetGroupMasterMessageFreeReq) updates) => super.copyWith((message) => updates(message as SetGroupMasterMessageFreeReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SetGroupMasterMessageFreeReq create() => SetGroupMasterMessageFreeReq._(); + SetGroupMasterMessageFreeReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static SetGroupMasterMessageFreeReq getDefault() => _defaultInstance ??= create()..freeze(); + static SetGroupMasterMessageFreeReq _defaultInstance; + + $core.int get groupId => $_get(0, 0); + set groupId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasGroupId() => $_has(0); + void clearGroupId() => clearField(1); + + $core.bool get messageFree => $_get(1, false); + set messageFree($core.bool v) { $_setBool(1, v); } + $core.bool hasMessageFree() => $_has(1); + void clearMessageFree() => clearField(2); +} + +class SetGroupMasterMessageFreeRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('SetGroupMasterMessageFreeRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..a<$core.int>(2, 'groupId', $pb.PbFieldType.OU3) + ..aOB(3, 'messageFree') + ..hasRequiredFields = false + ; + + SetGroupMasterMessageFreeRes._() : super(); + factory SetGroupMasterMessageFreeRes() => create(); + factory SetGroupMasterMessageFreeRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SetGroupMasterMessageFreeRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + SetGroupMasterMessageFreeRes clone() => SetGroupMasterMessageFreeRes()..mergeFromMessage(this); + SetGroupMasterMessageFreeRes copyWith(void Function(SetGroupMasterMessageFreeRes) updates) => super.copyWith((message) => updates(message as SetGroupMasterMessageFreeRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SetGroupMasterMessageFreeRes create() => SetGroupMasterMessageFreeRes._(); + SetGroupMasterMessageFreeRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static SetGroupMasterMessageFreeRes getDefault() => _defaultInstance ??= create()..freeze(); + static SetGroupMasterMessageFreeRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.int get groupId => $_get(1, 0); + set groupId($core.int v) { $_setUnsignedInt32(1, v); } + $core.bool hasGroupId() => $_has(1); + void clearGroupId() => clearField(2); + + $core.bool get messageFree => $_get(2, false); + set messageFree($core.bool v) { $_setBool(2, v); } + $core.bool hasMessageFree() => $_has(2); + void clearMessageFree() => clearField(3); +} + diff --git a/lib/proto/chat.pbenum.dart b/lib/proto/chat.pbenum.dart new file mode 100644 index 0000000..35f2aa7 --- /dev/null +++ b/lib/proto/chat.pbenum.dart @@ -0,0 +1,164 @@ +/// +// Generated code. Do not modify. +// source: chat.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +// ignore_for_file: UNDEFINED_SHOWN_NAME,UNUSED_SHOWN_NAME +import 'dart:core' as $core show int, dynamic, String, List, Map; +import 'package:protobuf/protobuf.dart' as $pb; + +class ChatChannelType extends $pb.ProtobufEnum { + static const ChatChannelType Session = ChatChannelType._(0, 'Session'); + static const ChatChannelType Group = ChatChannelType._(1, 'Group'); + static const ChatChannelType CSD = ChatChannelType._(2, 'CSD'); + + static const $core.List values = [ + Session, + Group, + CSD, + ]; + + static final $core.Map<$core.int, ChatChannelType> _byValue = $pb.ProtobufEnum.initByValue(values); + static ChatChannelType valueOf($core.int value) => _byValue[value]; + + const ChatChannelType._($core.int v, $core.String n) : super(v, n); +} + +class ChatType extends $pb.ProtobufEnum { + static const ChatType TextChatType = ChatType._(0, 'TextChatType'); + static const ChatType ImageChatType = ChatType._(1, 'ImageChatType'); + static const ChatType ShortVoiceChatType = ChatType._(2, 'ShortVoiceChatType'); + static const ChatType ShortVideoChatType = ChatType._(3, 'ShortVideoChatType'); + static const ChatType RealtimeCallVoiceType = ChatType._(4, 'RealtimeCallVoiceType'); + static const ChatType RealtimeCallVideoType = ChatType._(5, 'RealtimeCallVideoType'); + static const ChatType RedWalletChatType = ChatType._(6, 'RedWalletChatType'); + static const ChatType PlaceChatType = ChatType._(7, 'PlaceChatType'); + static const ChatType EmoticonType = ChatType._(8, 'EmoticonType'); + static const ChatType GroupChatNoticeType = ChatType._(9, 'GroupChatNoticeType'); + static const ChatType GiftChatType = ChatType._(10, 'GiftChatType'); + static const ChatType FileChatType = ChatType._(11, 'FileChatType'); + + static const $core.List values = [ + TextChatType, + ImageChatType, + ShortVoiceChatType, + ShortVideoChatType, + RealtimeCallVoiceType, + RealtimeCallVideoType, + RedWalletChatType, + PlaceChatType, + EmoticonType, + GroupChatNoticeType, + GiftChatType, + FileChatType, + ]; + + static final $core.Map<$core.int, ChatType> _byValue = $pb.ProtobufEnum.initByValue(values); + static ChatType valueOf($core.int value) => _byValue[value]; + + const ChatType._($core.int v, $core.String n) : super(v, n); +} + +class RedWalletState extends $pb.ProtobufEnum { + static const RedWalletState Uncollected = RedWalletState._(0, 'Uncollected'); + static const RedWalletState Received = RedWalletState._(1, 'Received'); + static const RedWalletState Expire = RedWalletState._(2, 'Expire'); + + static const $core.List values = [ + Uncollected, + Received, + Expire, + ]; + + static final $core.Map<$core.int, RedWalletState> _byValue = $pb.ProtobufEnum.initByValue(values); + static RedWalletState valueOf($core.int value) => _byValue[value]; + + const RedWalletState._($core.int v, $core.String n) : super(v, n); +} + +class TranslateState extends $pb.ProtobufEnum { + static const TranslateState NoPerson = TranslateState._(0, 'NoPerson'); + static const TranslateState SameLan = TranslateState._(1, 'SameLan'); + static const TranslateState Unopen = TranslateState._(2, 'Unopen'); + static const TranslateState Opend = TranslateState._(3, 'Opend'); + + static const $core.List values = [ + NoPerson, + SameLan, + Unopen, + Opend, + ]; + + static final $core.Map<$core.int, TranslateState> _byValue = $pb.ProtobufEnum.initByValue(values); + static TranslateState valueOf($core.int value) => _byValue[value]; + + const TranslateState._($core.int v, $core.String n) : super(v, n); +} + +class ChatNiceoType extends $pb.ProtobufEnum { + static const ChatNiceoType GroupAddMember = ChatNiceoType._(1, 'GroupAddMember'); + static const ChatNiceoType GroupRemoveMember = ChatNiceoType._(2, 'GroupRemoveMember'); + + static const $core.List values = [ + GroupAddMember, + GroupRemoveMember, + ]; + + static final $core.Map<$core.int, ChatNiceoType> _byValue = $pb.ProtobufEnum.initByValue(values); + static ChatNiceoType valueOf($core.int value) => _byValue[value]; + + const ChatNiceoType._($core.int v, $core.String n) : super(v, n); +} + +class GroupMemberIdentity extends $pb.ProtobufEnum { + static const GroupMemberIdentity identityNormal = GroupMemberIdentity._(0, 'identityNormal'); + static const GroupMemberIdentity identityManager = GroupMemberIdentity._(1, 'identityManager'); + static const GroupMemberIdentity identityMaster = GroupMemberIdentity._(2, 'identityMaster'); + + static const $core.List values = [ + identityNormal, + identityManager, + identityMaster, + ]; + + static final $core.Map<$core.int, GroupMemberIdentity> _byValue = $pb.ProtobufEnum.initByValue(values); + static GroupMemberIdentity valueOf($core.int value) => _byValue[value]; + + const GroupMemberIdentity._($core.int v, $core.String n) : super(v, n); +} + +class GroupChangeType extends $pb.ProtobufEnum { + static const GroupChangeType AddMember = GroupChangeType._(1, 'AddMember'); + static const GroupChangeType RemoveMember = GroupChangeType._(2, 'RemoveMember'); + static const GroupChangeType MasterTrans = GroupChangeType._(3, 'MasterTrans'); + static const GroupChangeType GroupNoticeChange = GroupChangeType._(4, 'GroupNoticeChange'); + static const GroupChangeType GroupNameChange = GroupChangeType._(5, 'GroupNameChange'); + static const GroupChangeType GroupMemberAliasChange = GroupChangeType._(6, 'GroupMemberAliasChange'); + static const GroupChangeType GroupIsOpenMemberCheckChange = GroupChangeType._(7, 'GroupIsOpenMemberCheckChange'); + static const GroupChangeType GroupMemberCheckNotice = GroupChangeType._(8, 'GroupMemberCheckNotice'); + static const GroupChangeType QRCodeAddMemberNotice = GroupChangeType._(9, 'QRCodeAddMemberNotice'); + static const GroupChangeType GroupMemberCheckAddMemberNotice = GroupChangeType._(10, 'GroupMemberCheckAddMemberNotice'); + static const GroupChangeType GroupMemberLeave = GroupChangeType._(11, 'GroupMemberLeave'); + + static const $core.List values = [ + AddMember, + RemoveMember, + MasterTrans, + GroupNoticeChange, + GroupNameChange, + GroupMemberAliasChange, + GroupIsOpenMemberCheckChange, + GroupMemberCheckNotice, + QRCodeAddMemberNotice, + GroupMemberCheckAddMemberNotice, + GroupMemberLeave, + ]; + + static final $core.Map<$core.int, GroupChangeType> _byValue = $pb.ProtobufEnum.initByValue(values); + static GroupChangeType valueOf($core.int value) => _byValue[value]; + + const GroupChangeType._($core.int v, $core.String n) : super(v, n); +} + diff --git a/lib/proto/chat.pbjson.dart b/lib/proto/chat.pbjson.dart new file mode 100644 index 0000000..245d7ba --- /dev/null +++ b/lib/proto/chat.pbjson.dart @@ -0,0 +1,620 @@ +/// +// Generated code. Do not modify. +// source: chat.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +const ChatChannelType$json = const { + '1': 'ChatChannelType', + '2': const [ + const {'1': 'Session', '2': 0}, + const {'1': 'Group', '2': 1}, + const {'1': 'CSD', '2': 2}, + ], +}; + +const ChatType$json = const { + '1': 'ChatType', + '2': const [ + const {'1': 'TextChatType', '2': 0}, + const {'1': 'ImageChatType', '2': 1}, + const {'1': 'ShortVoiceChatType', '2': 2}, + const {'1': 'ShortVideoChatType', '2': 3}, + const {'1': 'RealtimeCallVoiceType', '2': 4}, + const {'1': 'RealtimeCallVideoType', '2': 5}, + const {'1': 'RedWalletChatType', '2': 6}, + const {'1': 'PlaceChatType', '2': 7}, + const {'1': 'EmoticonType', '2': 8}, + const {'1': 'GroupChatNoticeType', '2': 9}, + const {'1': 'GiftChatType', '2': 10}, + const {'1': 'FileChatType', '2': 11}, + ], +}; + +const RedWalletState$json = const { + '1': 'RedWalletState', + '2': const [ + const {'1': 'Uncollected', '2': 0}, + const {'1': 'Received', '2': 1}, + const {'1': 'Expire', '2': 2}, + ], +}; + +const TranslateState$json = const { + '1': 'TranslateState', + '2': const [ + const {'1': 'NoPerson', '2': 0}, + const {'1': 'SameLan', '2': 1}, + const {'1': 'Unopen', '2': 2}, + const {'1': 'Opend', '2': 3}, + ], +}; + +const ChatNiceoType$json = const { + '1': 'ChatNiceoType', + '2': const [ + const {'1': 'GroupAddMember', '2': 1}, + const {'1': 'GroupRemoveMember', '2': 2}, + ], +}; + +const GroupMemberIdentity$json = const { + '1': 'GroupMemberIdentity', + '2': const [ + const {'1': 'identityNormal', '2': 0}, + const {'1': 'identityManager', '2': 1}, + const {'1': 'identityMaster', '2': 2}, + ], +}; + +const GroupChangeType$json = const { + '1': 'GroupChangeType', + '2': const [ + const {'1': 'AddMember', '2': 1}, + const {'1': 'RemoveMember', '2': 2}, + const {'1': 'MasterTrans', '2': 3}, + const {'1': 'GroupNoticeChange', '2': 4}, + const {'1': 'GroupNameChange', '2': 5}, + const {'1': 'GroupMemberAliasChange', '2': 6}, + const {'1': 'GroupIsOpenMemberCheckChange', '2': 7}, + const {'1': 'GroupMemberCheckNotice', '2': 8}, + const {'1': 'QRCodeAddMemberNotice', '2': 9}, + const {'1': 'GroupMemberCheckAddMemberNotice', '2': 10}, + const {'1': 'GroupMemberLeave', '2': 11}, + ], +}; + +const RedWallet$json = const { + '1': 'RedWallet', + '2': const [ + const {'1': 'OrderId', '3': 1, '4': 1, '5': 9, '10': 'OrderId'}, + const {'1': 'SuId', '3': 2, '4': 1, '5': 13, '10': 'SuId'}, + const {'1': 'TuId', '3': 3, '4': 1, '5': 13, '10': 'TuId'}, + const {'1': 'Title', '3': 4, '4': 1, '5': 9, '10': 'Title'}, + const {'1': 'Amount', '3': 5, '4': 1, '5': 13, '10': 'Amount'}, + const {'1': 'State', '3': 6, '4': 1, '5': 14, '6': '.yl_pb.RedWalletState', '10': 'State'}, + const {'1': 'RecTime', '3': 7, '4': 1, '5': 3, '10': 'RecTime'}, + ], +}; + +const BaseUserInfo$json = const { + '1': 'BaseUserInfo', + '2': const [ + const {'1': 'Id', '3': 1, '4': 1, '5': 13, '10': 'Id'}, + const {'1': 'NiceName', '3': 2, '4': 1, '5': 9, '10': 'NiceName'}, + const {'1': 'HeadUrl', '3': 3, '4': 1, '5': 9, '10': 'HeadUrl'}, + ], +}; + +const ChatNiceo$json = const { + '1': 'ChatNiceo', + '2': const [ + const {'1': 'NictoType', '3': 1, '4': 1, '5': 14, '6': '.yl_pb.ChatNiceoType', '10': 'NictoType'}, + const {'1': 'NictoMsg', '3': 2, '4': 1, '5': 9, '10': 'NictoMsg'}, + ], +}; + +const GiftChat$json = const { + '1': 'GiftChat', + '2': const [ + const {'1': 'SuId', '3': 1, '4': 1, '5': 13, '10': 'SuId'}, + const {'1': 'TuId', '3': 2, '4': 1, '5': 13, '10': 'TuId'}, + const {'1': 'GiftId', '3': 3, '4': 1, '5': 13, '10': 'GiftId'}, + const {'1': 'GiftName', '3': 4, '4': 1, '5': 9, '10': 'GiftName'}, + const {'1': 'GiftAmount', '3': 5, '4': 1, '5': 13, '10': 'GiftAmount'}, + const {'1': 'Money', '3': 6, '4': 1, '5': 13, '10': 'Money'}, + ], +}; + +const FileChat$json = const { + '1': 'FileChat', + '2': const [ + const {'1': 'Type', '3': 1, '4': 1, '5': 9, '10': 'Type'}, + const {'1': 'Size', '3': 2, '4': 1, '5': 13, '10': 'Size'}, + const {'1': 'Name', '3': 3, '4': 1, '5': 9, '10': 'Name'}, + ], +}; + +const QuoteMsg$json = const { + '1': 'QuoteMsg', + '2': const [ + const {'1': 'ChannelType', '3': 1, '4': 1, '5': 14, '6': '.yl_pb.ChatChannelType', '10': 'ChannelType'}, + const {'1': 'TargetId', '3': 2, '4': 1, '5': 13, '10': 'TargetId'}, + const {'1': 'SendUserId', '3': 3, '4': 1, '5': 13, '10': 'SendUserId'}, + const {'1': 'SendTime', '3': 4, '4': 1, '5': 3, '10': 'SendTime'}, + const {'1': 'Content', '3': 5, '4': 1, '5': 9, '10': 'Content'}, + ], +}; + +const ChatSendReq$json = const { + '1': 'ChatSendReq', + '2': const [ + const {'1': 'ChannelType', '3': 1, '4': 1, '5': 14, '6': '.yl_pb.ChatChannelType', '10': 'ChannelType'}, + const {'1': 'TargetId', '3': 2, '4': 1, '5': 13, '10': 'TargetId'}, + const {'1': 'SendTime', '3': 3, '4': 1, '5': 3, '10': 'SendTime'}, + const {'1': 'CType', '3': 4, '4': 1, '5': 14, '6': '.yl_pb.ChatType', '10': 'CType'}, + const {'1': 'ContentBuff', '3': 5, '4': 1, '5': 12, '10': 'ContentBuff'}, + const {'1': 'ContentSzie', '3': 6, '4': 1, '5': 13, '10': 'ContentSzie'}, + const {'1': 'EnclosureUrl', '3': 7, '4': 1, '5': 9, '10': 'EnclosureUrl'}, + const {'1': 'AltUserIds', '3': 8, '4': 3, '5': 13, '10': 'AltUserIds'}, + const {'1': 'QuoteMsg', '3': 9, '4': 1, '5': 12, '10': 'QuoteMsg'}, + ], +}; + +const ChatSendRes$json = const { + '1': 'ChatSendRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'ChannelType', '3': 2, '4': 1, '5': 14, '6': '.yl_pb.ChatChannelType', '10': 'ChannelType'}, + const {'1': 'TargetId', '3': 3, '4': 1, '5': 13, '10': 'TargetId'}, + const {'1': 'SendTime', '3': 4, '4': 1, '5': 3, '10': 'SendTime'}, + ], +}; + +const PushChat$json = const { + '1': 'PushChat', + '2': const [ + const {'1': 'ChannelType', '3': 1, '4': 1, '5': 14, '6': '.yl_pb.ChatChannelType', '10': 'ChannelType'}, + const {'1': 'TargetId', '3': 2, '4': 1, '5': 13, '10': 'TargetId'}, + const {'1': 'SendUserId', '3': 3, '4': 1, '5': 13, '10': 'SendUserId'}, + const {'1': 'SendTime', '3': 4, '4': 1, '5': 3, '10': 'SendTime'}, + const {'1': 'CType', '3': 5, '4': 1, '5': 14, '6': '.yl_pb.ChatType', '10': 'CType'}, + const {'1': 'ContentBuff', '3': 6, '4': 1, '5': 12, '10': 'ContentBuff'}, + const {'1': 'ContentSzie', '3': 7, '4': 1, '5': 13, '10': 'ContentSzie'}, + const {'1': 'TranslateState', '3': 8, '4': 1, '5': 13, '10': 'TranslateState'}, + const {'1': 'TencentTranslate', '3': 9, '4': 1, '5': 12, '10': 'TencentTranslate'}, + const {'1': 'GoogleTranslate', '3': 10, '4': 1, '5': 12, '10': 'GoogleTranslate'}, + const {'1': 'HumanTranslate', '3': 11, '4': 1, '5': 12, '10': 'HumanTranslate'}, + const {'1': 'EnclosureUrl', '3': 12, '4': 1, '5': 9, '10': 'EnclosureUrl'}, + const {'1': 'AltUserIds', '3': 13, '4': 3, '5': 13, '10': 'AltUserIds'}, + const {'1': 'QuoteMsg', '3': 14, '4': 1, '5': 12, '10': 'QuoteMsg'}, + ], +}; + +const AnswerPushChat$json = const { + '1': 'AnswerPushChat', + '2': const [ + const {'1': 'MsgId', '3': 1, '4': 1, '5': 3, '10': 'MsgId'}, + ], +}; + +const PushUserUnreadMsgNotice$json = const { + '1': 'PushUserUnreadMsgNotice', + '2': const [ + const {'1': 'Notices', '3': 2, '4': 3, '5': 11, '6': '.yl_pb.UserUnreadMsgNotice', '10': 'Notices'}, + ], +}; + +const UnreadMsgDes$json = const { + '1': 'UnreadMsgDes', + '2': const [ + const {'1': 'SendUserId', '3': 1, '4': 1, '5': 13, '10': 'SendUserId'}, + const {'1': 'SendTime', '3': 2, '4': 1, '5': 3, '10': 'SendTime'}, + const {'1': 'CType', '3': 3, '4': 1, '5': 14, '6': '.yl_pb.ChatType', '10': 'CType'}, + const {'1': 'ContentBuff', '3': 4, '4': 1, '5': 12, '10': 'ContentBuff'}, + const {'1': 'TencentTranslate', '3': 5, '4': 1, '5': 12, '10': 'TencentTranslate'}, + const {'1': 'GoogleTranslate', '3': 6, '4': 1, '5': 12, '10': 'GoogleTranslate'}, + ], +}; + +const UserUnreadMsgNotice$json = const { + '1': 'UserUnreadMsgNotice', + '2': const [ + const {'1': 'ChannelType', '3': 1, '4': 1, '5': 14, '6': '.yl_pb.ChatChannelType', '10': 'ChannelType'}, + const {'1': 'TargetId', '3': 2, '4': 1, '5': 13, '10': 'TargetId'}, + const {'1': 'UnreadMsgNum', '3': 3, '4': 1, '5': 13, '10': 'UnreadMsgNum'}, + const {'1': 'LastUnreadMsg', '3': 4, '4': 1, '5': 11, '6': '.yl_pb.UnreadMsgDes', '10': 'LastUnreadMsg'}, + ], +}; + +const RequestTargetUnreadReq$json = const { + '1': 'RequestTargetUnreadReq', + '2': const [ + const {'1': 'ChannelType', '3': 1, '4': 1, '5': 14, '6': '.yl_pb.ChatChannelType', '10': 'ChannelType'}, + const {'1': 'TargetId', '3': 2, '4': 1, '5': 13, '10': 'TargetId'}, + ], +}; + +const RequestTargetUnreadRes$json = const { + '1': 'RequestTargetUnreadRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + ], +}; + +const RequestSetHTranslReq$json = const { + '1': 'RequestSetHTranslReq', + '2': const [ + const {'1': 'SessionId', '3': 1, '4': 1, '5': 13, '10': 'SessionId'}, + const {'1': 'HTransl', '3': 2, '4': 1, '5': 14, '6': '.yl_pb.TranslateState', '10': 'HTransl'}, + ], +}; + +const RequestSetHTranslRes$json = const { + '1': 'RequestSetHTranslRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + ], +}; + +const PushHTranslState$json = const { + '1': 'PushHTranslState', + '2': const [ + const {'1': 'SessionId', '3': 1, '4': 1, '5': 13, '10': 'SessionId'}, + const {'1': 'UserId', '3': 2, '4': 1, '5': 13, '10': 'UserId'}, + const {'1': 'HTransl', '3': 3, '4': 1, '5': 14, '6': '.yl_pb.TranslateState', '10': 'HTransl'}, + ], +}; + +const RequestRealtimeCallReq$json = const { + '1': 'RequestRealtimeCallReq', + '2': const [ + const {'1': 'TUserId', '3': 1, '4': 1, '5': 13, '10': 'TUserId'}, + const {'1': 'CType', '3': 2, '4': 1, '5': 14, '6': '.yl_pb.ChatType', '10': 'CType'}, + ], +}; + +const RequestRealtimeCallRes$json = const { + '1': 'RequestRealtimeCallRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + ], +}; + +const PushRealtimeCall$json = const { + '1': 'PushRealtimeCall', + '2': const [ + const {'1': 'SUserId', '3': 1, '4': 1, '5': 13, '10': 'SUserId'}, + const {'1': 'CType', '3': 2, '4': 1, '5': 14, '6': '.yl_pb.ChatType', '10': 'CType'}, + ], +}; + +const RespondRealtimeCallReq$json = const { + '1': 'RespondRealtimeCallReq', + '2': const [ + const {'1': 'SUserId', '3': 1, '4': 1, '5': 13, '10': 'SUserId'}, + const {'1': 'IsAnswer', '3': 2, '4': 1, '5': 8, '10': 'IsAnswer'}, + ], +}; + +const PushRealtimeCallRespond$json = const { + '1': 'PushRealtimeCallRespond', + '2': const [ + const {'1': 'TUserId', '3': 1, '4': 1, '5': 13, '10': 'TUserId'}, + const {'1': 'IsAnswer', '3': 2, '4': 1, '5': 8, '10': 'IsAnswer'}, + ], +}; + +const RequestGiftGivingReq$json = const { + '1': 'RequestGiftGivingReq', + '2': const [ + const {'1': 'TargetUserId', '3': 1, '4': 1, '5': 13, '10': 'TargetUserId'}, + const {'1': 'GiftId', '3': 2, '4': 1, '5': 13, '10': 'GiftId'}, + const {'1': 'GiftAmount', '3': 3, '4': 1, '5': 13, '10': 'GiftAmount'}, + const {'1': 'Money', '3': 4, '4': 1, '5': 13, '10': 'Money'}, + ], +}; + +const PushGiftGiving$json = const { + '1': 'PushGiftGiving', + '2': const [ + const {'1': 'SendUserId', '3': 1, '4': 1, '5': 13, '10': 'SendUserId'}, + const {'1': 'GiftId', '3': 2, '4': 1, '5': 13, '10': 'GiftId'}, + const {'1': 'GiftAmount', '3': 3, '4': 1, '5': 13, '10': 'GiftAmount'}, + const {'1': 'Money', '3': 4, '4': 1, '5': 13, '10': 'Money'}, + ], +}; + +const QueryUsersInfoReq$json = const { + '1': 'QueryUsersInfoReq', + '2': const [ + const {'1': 'UserIds', '3': 1, '4': 3, '5': 13, '10': 'UserIds'}, + ], +}; + +const QueryUsersInfoRes$json = const { + '1': 'QueryUsersInfoRes', + '2': const [ + const {'1': 'Infos', '3': 1, '4': 3, '5': 11, '6': '.yl_pb.BaseUserInfo', '10': 'Infos'}, + ], +}; + +const CreateSessionReq$json = const { + '1': 'CreateSessionReq', + '2': const [ + const {'1': 'MemberIds', '3': 1, '4': 3, '5': 13, '10': 'MemberIds'}, + ], +}; + +const QuerySessionReq$json = const { + '1': 'QuerySessionReq', + '2': const [ + const {'1': 'SessionId', '3': 1, '4': 1, '5': 13, '10': 'SessionId'}, + ], +}; + +const SessionInfoRes$json = const { + '1': 'SessionInfoRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'SessionId', '3': 2, '4': 1, '5': 13, '10': 'SessionId'}, + const {'1': 'Members', '3': 3, '4': 3, '5': 11, '6': '.yl_pb.BaseUserInfo', '10': 'Members'}, + const {'1': 'IsNeedHTransl', '3': 4, '4': 1, '5': 14, '6': '.yl_pb.TranslateState', '10': 'IsNeedHTransl'}, + ], +}; + +const GroupMember$json = const { + '1': 'GroupMember', + '2': const [ + const {'1': 'Info', '3': 1, '4': 1, '5': 11, '6': '.yl_pb.BaseUserInfo', '10': 'Info'}, + const {'1': 'Name', '3': 2, '4': 1, '5': 9, '10': 'Name'}, + const {'1': 'Identity', '3': 3, '4': 1, '5': 14, '6': '.yl_pb.GroupMemberIdentity', '10': 'Identity'}, + const {'1': 'MessageFree', '3': 4, '4': 1, '5': 8, '10': 'MessageFree'}, + const {'1': 'EffectiveUser', '3': 5, '4': 1, '5': 8, '10': 'EffectiveUser'}, + ], +}; + +const GroupInfo$json = const { + '1': 'GroupInfo', + '2': const [ + const {'1': 'Id', '3': 1, '4': 1, '5': 13, '10': 'Id'}, + const {'1': 'Code', '3': 2, '4': 1, '5': 13, '10': 'Code'}, + const {'1': 'GroupName', '3': 3, '4': 1, '5': 9, '10': 'GroupName'}, + const {'1': 'Notice', '3': 4, '4': 1, '5': 9, '10': 'Notice'}, + const {'1': 'Members', '3': 5, '4': 3, '5': 11, '6': '.yl_pb.GroupMember', '10': 'Members'}, + const {'1': 'IsOpenMemberCheck', '3': 6, '4': 1, '5': 8, '10': 'IsOpenMemberCheck'}, + ], +}; + +const GroupChatNotice$json = const { + '1': 'GroupChatNotice', + '2': const [ + const {'1': 'ChangeType', '3': 1, '4': 1, '5': 14, '6': '.yl_pb.GroupChangeType', '10': 'ChangeType'}, + const {'1': 'OperatuId', '3': 2, '4': 1, '5': 11, '6': '.yl_pb.BaseUserInfo', '10': 'OperatuId'}, + const {'1': 'OperateduId', '3': 3, '4': 3, '5': 11, '6': '.yl_pb.BaseUserInfo', '10': 'OperateduId'}, + const {'1': 'ChangeStr', '3': 4, '4': 1, '5': 9, '10': 'ChangeStr'}, + const {'1': 'ChangeBool', '3': 5, '4': 1, '5': 8, '10': 'ChangeBool'}, + ], +}; + +const CreateChatGroupReq$json = const { + '1': 'CreateChatGroupReq', + '2': const [ + const {'1': 'Members', '3': 3, '4': 3, '5': 13, '10': 'Members'}, + ], +}; + +const CreateChatGroupRes$json = const { + '1': 'CreateChatGroupRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'Group', '3': 2, '4': 1, '5': 11, '6': '.yl_pb.GroupInfo', '10': 'Group'}, + ], +}; + +const QuitChatGroupReq$json = const { + '1': 'QuitChatGroupReq', + '2': const [ + const {'1': 'GroupId', '3': 1, '4': 1, '5': 13, '10': 'GroupId'}, + ], +}; + +const QuitChatGroupRes$json = const { + '1': 'QuitChatGroupRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'GroupId', '3': 2, '4': 1, '5': 13, '10': 'GroupId'}, + ], +}; + +const QueryChatGroupReq$json = const { + '1': 'QueryChatGroupReq', + '2': const [ + const {'1': 'GroupId', '3': 1, '4': 1, '5': 13, '10': 'GroupId'}, + ], +}; + +const QueryChatGroupRes$json = const { + '1': 'QueryChatGroupRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'Group', '3': 2, '4': 1, '5': 11, '6': '.yl_pb.GroupInfo', '10': 'Group'}, + ], +}; + +const AddGroupMemberReq$json = const { + '1': 'AddGroupMemberReq', + '2': const [ + const {'1': 'GroupId', '3': 1, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'UserIds', '3': 2, '4': 3, '5': 13, '10': 'UserIds'}, + ], +}; + +const AddGroupMemberRes$json = const { + '1': 'AddGroupMemberRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'GroupId', '3': 2, '4': 1, '5': 13, '10': 'GroupId'}, + ], +}; + +const RemoveGroupMemberReq$json = const { + '1': 'RemoveGroupMemberReq', + '2': const [ + const {'1': 'GroupId', '3': 1, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'UserIds', '3': 2, '4': 3, '5': 13, '10': 'UserIds'}, + ], +}; + +const RemoveGroupMemberRes$json = const { + '1': 'RemoveGroupMemberRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'GroupId', '3': 2, '4': 1, '5': 13, '10': 'GroupId'}, + ], +}; + +const ModifyGroupNoticeReq$json = const { + '1': 'ModifyGroupNoticeReq', + '2': const [ + const {'1': 'GroupId', '3': 1, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'Notice', '3': 2, '4': 1, '5': 9, '10': 'Notice'}, + ], +}; + +const ModifyGroupNoticeRes$json = const { + '1': 'ModifyGroupNoticeRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'GroupId', '3': 2, '4': 1, '5': 13, '10': 'GroupId'}, + ], +}; + +const ModifyGroupNameReq$json = const { + '1': 'ModifyGroupNameReq', + '2': const [ + const {'1': 'GroupId', '3': 1, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'Name', '3': 2, '4': 1, '5': 9, '10': 'Name'}, + ], +}; + +const ModifyGroupNameRes$json = const { + '1': 'ModifyGroupNameRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'GroupId', '3': 2, '4': 1, '5': 13, '10': 'GroupId'}, + ], +}; + +const GroupMemberModifyAliasReq$json = const { + '1': 'GroupMemberModifyAliasReq', + '2': const [ + const {'1': 'GroupId', '3': 1, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'Name', '3': 2, '4': 1, '5': 9, '10': 'Name'}, + ], +}; + +const GroupMemberModifyAliasRes$json = const { + '1': 'GroupMemberModifyAliasRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'GroupId', '3': 2, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'Name', '3': 3, '4': 1, '5': 9, '10': 'Name'}, + ], +}; + +const QueryUserRelationGroupReq$json = const { + '1': 'QueryUserRelationGroupReq', +}; + +const QueryUserRelationGroupRes$json = const { + '1': 'QueryUserRelationGroupRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'RelationGroup', '3': 2, '4': 3, '5': 11, '6': '.yl_pb.GroupInfo', '10': 'RelationGroup'}, + ], +}; + +const SettingGroupReq$json = const { + '1': 'SettingGroupReq', + '2': const [ + const {'1': 'GroupId', '3': 1, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'IsOpenMemberCheck', '3': 2, '4': 1, '5': 8, '10': 'IsOpenMemberCheck'}, + ], +}; + +const SettingGroupRes$json = const { + '1': 'SettingGroupRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'GroupId', '3': 2, '4': 1, '5': 13, '10': 'GroupId'}, + ], +}; + +const GroupQRcodeAddMemberReq$json = const { + '1': 'GroupQRcodeAddMemberReq', + '2': const [ + const {'1': 'GroupId', '3': 1, '4': 1, '5': 13, '10': 'GroupId'}, + ], +}; + +const GroupQRcodeAddMemberRes$json = const { + '1': 'GroupQRcodeAddMemberRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'Group', '3': 2, '4': 1, '5': 11, '6': '.yl_pb.GroupInfo', '10': 'Group'}, + ], +}; + +const GroupMasterTransReq$json = const { + '1': 'GroupMasterTransReq', + '2': const [ + const {'1': 'GroupId', '3': 1, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'UserId', '3': 2, '4': 1, '5': 13, '10': 'UserId'}, + ], +}; + +const GroupMasterTransRes$json = const { + '1': 'GroupMasterTransRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'GroupId', '3': 2, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'UserId', '3': 3, '4': 1, '5': 13, '10': 'UserId'}, + ], +}; + +const GroupMasterCheckAddMemberReq$json = const { + '1': 'GroupMasterCheckAddMemberReq', + '2': const [ + const {'1': 'GroupId', '3': 1, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'UserIds', '3': 2, '4': 3, '5': 13, '10': 'UserIds'}, + ], +}; + +const GroupMasterCheckAddMemberRes$json = const { + '1': 'GroupMasterCheckAddMemberRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'GroupId', '3': 2, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'UserIds', '3': 3, '4': 3, '5': 13, '10': 'UserIds'}, + ], +}; + +const SetGroupMasterMessageFreeReq$json = const { + '1': 'SetGroupMasterMessageFreeReq', + '2': const [ + const {'1': 'GroupId', '3': 1, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'MessageFree', '3': 2, '4': 1, '5': 8, '10': 'MessageFree'}, + ], +}; + +const SetGroupMasterMessageFreeRes$json = const { + '1': 'SetGroupMasterMessageFreeRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'GroupId', '3': 2, '4': 1, '5': 13, '10': 'GroupId'}, + const {'1': 'MessageFree', '3': 3, '4': 1, '5': 8, '10': 'MessageFree'}, + ], +}; + diff --git a/lib/proto/chat.pbserver.dart b/lib/proto/chat.pbserver.dart new file mode 100644 index 0000000..eefa8e5 --- /dev/null +++ b/lib/proto/chat.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: chat.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +export 'chat.pb.dart'; + diff --git a/lib/proto/chat.proto b/lib/proto/chat.proto new file mode 100644 index 0000000..daade1a --- /dev/null +++ b/lib/proto/chat.proto @@ -0,0 +1,466 @@ +syntax = "proto2"; +package yl_pb; + +enum ChatChannelType { + Session = 0; //会话 + Group = 1; //群组 + CSD =2; //客服频道 +} + +enum ChatType { + TextChatType = 0; //文字聊天 + ImageChatType = 1; //图片 + ShortVoiceChatType = 2; //短语音 + ShortVideoChatType = 3; //短视频 + RealtimeCallVoiceType = 4; //实时通话-语音 + RealtimeCallVideoType = 5; //实时通话-视频 + RedWalletChatType = 6; //红包 + PlaceChatType = 7; //地址类型 + EmoticonType = 8; //表情 + GroupChatNoticeType = 9; //群公告类型 + GiftChatType = 10; //礼物聊天类型 + FileChatType = 11; //文件聊天类型 +} + +enum RedWalletState { + Uncollected = 0; //未领取 + Received = 1; //已领取 + Expire = 2; //过期 +} + +//用户间翻译状态 +enum TranslateState{ + NoPerson = 0;//没有翻译人员在线 + SameLan = 1;//同一语言 + Unopen = 2;//没有开启人工翻译 + Opend = 3; //已经开启人工翻译 +} + +//红包数据 +message RedWallet { + optional string OrderId = 1; + optional uint32 SuId = 2; //发送者Id + optional uint32 TuId = 3; //接收者Id + optional string Title = 4; + optional uint32 Amount = 5; + optional RedWalletState State = 6; + optional int64 RecTime = 7; //领取时间 +} + +message BaseUserInfo { + optional uint32 Id = 1; //用户Id + optional string NiceName =2; //昵称 + optional string HeadUrl =3; //头像Id +} + +enum ChatNiceoType { + GroupAddMember = 1; //聊天群-加入用户 + GroupRemoveMember = 2; //聊天群-移除用户 +} + +message ChatNiceo { + optional ChatNiceoType NictoType = 1; //公告类型 + optional string NictoMsg = 2; //公告消息 +} + +message GiftChat { + optional uint32 SuId = 1; //发送者Id + optional uint32 TuId = 2; //接收者Id + optional uint32 GiftId = 3; //礼物Id + optional string GiftName = 4; //礼物名称 + optional uint32 GiftAmount = 5; //礼物数量 + optional uint32 Money = 6; //钱 +} + +message FileChat { + optional string Type = 1; //文件类型 + optional uint32 Size = 2; //文件大小 + optional string Name = 3; //文件名称 +} + +//引用消息数据结构 +message QuoteMsg{ + optional ChatChannelType ChannelType = 1; //发送频道类型 + optional uint32 TargetId = 2; //发送目标Id SessionId or GroudId + optional uint32 SendUserId = 3; //消息发送者 + optional int64 SendTime = 4; //发送时间 + optional string Content = 5; //消息附件地址 +} + +//-------------------------------------------------------------------------消息-------------------------------------------------------------------------------------------------- +// MsgId=1 聊天消息发送请求 +message ChatSendReq { + optional ChatChannelType ChannelType = 1; //发送频道类型 + optional uint32 TargetId = 2; //发送目标Id SessionId or GroudId + optional int64 SendTime = 3; //发送时间 + optional ChatType CType = 4; //聊天类型 //文字 图片 短语音 短视频 + optional bytes ContentBuff = 5; //内容数据 10k 最大 + optional uint32 ContentSzie = 6; //内容大小 + optional string EnclosureUrl = 7; //消息附件地址 + repeated uint32 AltUserIds = 8; //alt用户id + optional bytes QuoteMsg =9; //引用消息 +} + +// MsgId=2 聊天消息发送请求回应 +message ChatSendRes { + optional int32 ErrorCode = 1; //0发送成功 1参数异常 + optional ChatChannelType ChannelType = 2; //发送频道类型 + optional uint32 TargetId = 3; //发送目标Id SessionId or GroudId + optional int64 SendTime = 4; //聊天消息Id +} + +// MsgId=3 推送用户聊天消息 +message PushChat { + optional ChatChannelType ChannelType = 1; //发送频道类型 + optional uint32 TargetId = 2; //发送目标Id SessionId or GroudId + optional uint32 SendUserId = 3; //发送者Id 0 通知消息 1 更新消息 非这两种未用户发送消息 + optional int64 SendTime = 4; //发送时间 + optional ChatType CType = 5; //聊天类型 //文字 图片 短语音 短视频 + optional bytes ContentBuff = 6; //内容数据 10k 最大 + optional uint32 ContentSzie = 7; //内容大小 + optional uint32 TranslateState = 8; //翻译状态 0不翻译 1机翻 2人工翻译 + optional bytes TencentTranslate = 9; //Tencent翻译 + optional bytes GoogleTranslate = 10; //Google翻译 + optional bytes HumanTranslate = 11; //人工翻译翻译 + optional string EnclosureUrl = 12; //消息附件地址 + repeated uint32 AltUserIds = 13; //alt用户id + optional bytes QuoteMsg =14; //引用消息 +} + +//MsgId=100 应答消息接收 +message AnswerPushChat { + optional int64 MsgId = 1; //消息Id +} + +// MsgId=4 用户登陆成功后推送未读消息列表 +message PushUserUnreadMsgNotice { + repeated UserUnreadMsgNotice Notices = 2; +} + +//未读消息描述 +message UnreadMsgDes { + optional uint32 SendUserId = 1; //发送者Id 0 通知消息 1 更新消息 非这两种未用户发送消息 + optional int64 SendTime = 2; //发送时间 + optional ChatType CType = 3; //聊天类型 //文字 图片 短语音 短视频 + optional bytes ContentBuff = 4; //内容数据 只有文字才有 其余的填空 + optional bytes TencentTranslate = 5; //腾讯翻译 + optional bytes GoogleTranslate = 6; //google翻译 +} + +message UserUnreadMsgNotice { + optional ChatChannelType ChannelType = 1; //发送频道类型 + optional uint32 TargetId = 2; //发送目标Id SessionId or GroudId + optional uint32 UnreadMsgNum = 3; //未读消息数量 + optional UnreadMsgDes LastUnreadMsg = 4; //最后一条未读消息 +} + +// MsgId=5 请求目标未读消息 +message RequestTargetUnreadReq { + optional ChatChannelType ChannelType = 1; //发送频道类型 + optional uint32 TargetId = 2; //发送目标Id SessionId or GroudId +} +// MsgId=6 请求目标未读消息回应 +message RequestTargetUnreadRes { + optional int32 ErrorCode = 1; //0发送成功 1参数异常 +} + +// MsgId=7 请求设置人工翻译 +message RequestSetHTranslReq { + optional uint32 SessionId = 1; //发送目标Id + optional TranslateState HTransl = 2; //是否需要人工翻译 +} + +// MsgId=8 请求设置人工翻译回应 +message RequestSetHTranslRes { + optional int32 ErrorCode = 1; // 0发送成功 1参数异常 +} + +// MsgId=9 请求设置人工翻译回应 +message PushHTranslState { + optional uint32 SessionId = 1; //会话id + optional uint32 UserId = 2; //发送目标Id + optional TranslateState HTransl = 3; //是否需要人工翻译 +} + +// MsgId=10 请求实时通话 +message RequestRealtimeCallReq{ + optional uint32 TUserId = 1; //目标用户 + optional ChatType CType = 2; //通话类型 +} +// MsgId=11 请求实时通话回应 +message RequestRealtimeCallRes{ + optional int32 ErrorCode = 1; // 0发送成功 +} +// MsgId=12 推送实时通话请求 +message PushRealtimeCall{ + optional uint32 SUserId = 1; //发起通话请求用户 + optional ChatType CType = 2; //通话类型 +} + +// MsgId=13 请求挂断实时通话请求 +message RespondRealtimeCallReq{ + optional uint32 SUserId = 1; //发起通话请求用户 + optional bool IsAnswer = 2; //是否应答 true 应答 false 挂断 +} +// MsgId=14 推送挂断实时通话请求 +message PushRealtimeCallRespond{ + optional uint32 TUserId = 1; //目标用户 + optional bool IsAnswer = 2; //是否应答 true 应答 false 挂断 +} + +// MsgId=17 请求送礼物 +message RequestGiftGivingReq{ + optional uint32 TargetUserId = 1; //目标用户Id + optional uint32 GiftId = 2; //礼物Id + optional uint32 GiftAmount = 3; //礼物数量 + optional uint32 Money = 4; //钱 +} + +// MsgId=18 推送送礼 +message PushGiftGiving{ + optional uint32 SendUserId = 1; //目标用户Id + optional uint32 GiftId = 2; //礼物Id + optional uint32 GiftAmount = 3; //礼物数量 + optional uint32 Money = 4; //钱 +} + +//MsgId=80 查询用户基本信息 +message QueryUsersInfoReq{ + repeated uint32 UserIds = 1; +} +//MsgId=81 查询用户基本信息回应 +message QueryUsersInfoRes{ + repeated BaseUserInfo Infos = 1; +} + +//-------------------------------------------------------------------------------Session相关--------------------------------------------------------------------------------------- +//MsgId=101 请求创建会话 +message CreateSessionReq { + repeated uint32 MemberIds = 1; +} +//MsgId=102 请求创建会话 +message QuerySessionReq { + optional uint32 SessionId = 1; +} +//MsgId=103 请求创建会话回应 +message SessionInfoRes { + optional int32 ErrorCode = 1; // 0发送成功 1参数异常 + optional uint32 SessionId = 2; + repeated BaseUserInfo Members = 3; + optional TranslateState IsNeedHTransl = 4; +} +//-------------------------------------------------------------------------------Group相关--------------------------------------------------------------------------------------- +//群身份 +enum GroupMemberIdentity { + identityNormal = 0; //普通成员 + identityManager = 1; //管理员 + identityMaster = 2; //群主 +} + +//聊天群信息变化类型 +enum GroupChangeType { + AddMember = 1; //加入用户 + RemoveMember = 2; //移除用户 + MasterTrans = 3; //群主转让 + GroupNoticeChange = 4; //群公告改变 + GroupNameChange = 5; //群昵称改变 + GroupMemberAliasChange = 6; //群成员别名改变 + GroupIsOpenMemberCheckChange = 7; //群设置校验成员改变 + GroupMemberCheckNotice = 8; //群成员校验公告 + QRCodeAddMemberNotice = 9; //通过二维码加入到群 + GroupMemberCheckAddMemberNotice = 10; //群主校验添加成员通告 + GroupMemberLeave = 11; //群成员离开 +} + +//群成员结构 +message GroupMember { + optional BaseUserInfo Info = 1; //用户Id + optional string Name = 2; //用户Id + optional GroupMemberIdentity Identity = 3; //成员身份 + optional bool MessageFree = 4; //消息打扰标记 + optional bool EffectiveUser = 5; //有效用户 移除群成员不直接删除数据而是修改有效标签 +} +//群结构 +message GroupInfo { + optional uint32 Id = 1; //群Id + optional uint32 Code= 2; + optional string GroupName = 3; //群名称 + optional string Notice = 4; //群公告 + repeated GroupMember Members= 5; //群成员 + optional bool IsOpenMemberCheck = 6; //是否开启成员校验 +} + +//推送聊天群变化信息 +message GroupChatNotice{ + optional GroupChangeType ChangeType = 1; //信息改变类型 + optional BaseUserInfo OperatuId = 2; //操作用户Id + repeated BaseUserInfo OperateduId = 3; //被操作用户Ids 有可能是多人 + optional string ChangeStr = 4; //改变消息 + optional bool ChangeBool = 5; //变化bool值 +} + +//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +//MsgId=201 创建聊天群 + +message CreateChatGroupReq { + repeated uint32 Members = 3; //群成员 +} + +//MsgId=202 创建聊天群回应 +message CreateChatGroupRes { + optional int32 ErrorCode = 1; //详见错误码文档 + optional GroupInfo Group = 2; //群信息 +} + +//MsgId=203 退出聊天群 +message QuitChatGroupReq { + optional uint32 GroupId = 1; //群id +} +//MsgId=204 退出聊天群回应 +message QuitChatGroupRes { + optional int32 ErrorCode = 1; //详见错误码文档 + optional uint32 GroupId = 2; //群id +} + +//MsgId=205 查询聊天群组信息 +message QueryChatGroupReq { + optional uint32 GroupId = 1; //群信息 +} +//MsgId=206 查询聊天群组信息 +message QueryChatGroupRes { + optional int32 ErrorCode = 1; //详见错误码文档 + optional GroupInfo Group = 2; //群信息 +} + +//MsgId=207 添加群成员 +message AddGroupMemberReq { + optional uint32 GroupId = 1; //群信息 + repeated uint32 UserIds = 2; //用户Id +} +//MsgId=208 添加群成员回应 +message AddGroupMemberRes { + optional int32 ErrorCode = 1; //详见错误码文档 + optional uint32 GroupId = 2; //群信息 +} + +//MsgId=209 移除群成员回应 +message RemoveGroupMemberReq { + optional uint32 GroupId = 1; //群信息 + repeated uint32 UserIds = 2; +} + +//MsgId=210 移除群成员回应 +message RemoveGroupMemberRes { + optional int32 ErrorCode = 1; //详见错误码文档 + optional uint32 GroupId = 2; //群信息 +} + +//MsgId=211 修改群公告请求 +message ModifyGroupNoticeReq{ + optional uint32 GroupId = 1; //群信息 + optional string Notice = 2; //群信息 +} + +//MsgId=212 修改群公告请求回应 +message ModifyGroupNoticeRes { + optional int32 ErrorCode = 1; //详见错误码文档 + optional uint32 GroupId = 2; //群信息 +} + +//MsgId=213 修改群昵称请求 +message ModifyGroupNameReq{ + optional uint32 GroupId = 1; //群信息 + optional string Name = 2; //群信息 +} + +//MsgId=214 修改群昵称请求回应 +message ModifyGroupNameRes { + optional int32 ErrorCode = 1; //详见错误码文档 + optional uint32 GroupId = 2; //群信息 +} + +//MsgId=215 群成员修改别名请求 +message GroupMemberModifyAliasReq{ + optional uint32 GroupId = 1; //群信息 + optional string Name = 2; //群信息 +} + +//MsgId=216 群成员修改别名请求回应 +message GroupMemberModifyAliasRes { + optional int32 ErrorCode = 1; //详见错误码文档 + optional uint32 GroupId = 2; //群信息 + optional string Name = 3; //群信息 +} + +//MsgId=217 请求用户关联群列表 +message QueryUserRelationGroupReq{ +} + +//MsgId=218 请求用户关联群列表回应 +message QueryUserRelationGroupRes { + optional int32 ErrorCode = 1; //详见错误码文档 + repeated GroupInfo RelationGroup = 2; +} + +//MsgId=219 设置成员校验 +message SettingGroupReq{ + optional uint32 GroupId = 1; //群信息 + optional bool IsOpenMemberCheck = 2; //是否开启群验证 +} + +//MsgId=220 请求用户关联群列表回应 +message SettingGroupRes { + optional int32 ErrorCode = 1; //详见错误码文档 + optional uint32 GroupId = 2; //群信息 +} + + +//MsgId=221 用户二维码加入群请求 +message GroupQRcodeAddMemberReq{ + optional uint32 GroupId = 1; //群信息 +} + +//MsgId=222 用户二维码加入群请求回应 +message GroupQRcodeAddMemberRes { + optional int32 ErrorCode = 1; //详见错误码文档 + optional GroupInfo Group = 2; //群信息 +} + +//MsgId=223 群主转让请求 +message GroupMasterTransReq{ + optional uint32 GroupId = 1; //群信息 + optional uint32 UserId = 2; //群信息 +} + +//MsgId=224 群主转让请求回应 +message GroupMasterTransRes{ + optional int32 ErrorCode = 1; //详见错误码文档 + optional uint32 GroupId = 2; //群信息 + optional uint32 UserId = 3; //群信息 +} + +//MsgId=225 群主校验用户接口 +message GroupMasterCheckAddMemberReq{ + optional uint32 GroupId = 1; //群信息 + repeated uint32 UserIds = 2; //群信息 +} + +//MsgId=226 群主校验用户接口 +message GroupMasterCheckAddMemberRes{ + optional int32 ErrorCode = 1; //详见错误码文档 + optional uint32 GroupId = 2; //群信息 + repeated uint32 UserIds = 3; //群信息 +} + +//MsgId=227 消息免打扰 +message SetGroupMasterMessageFreeReq{ + optional uint32 GroupId = 1; //群信息 + optional bool MessageFree = 2; //消息免打扰 +} + +//MsgId=228 消息免打扰 +message SetGroupMasterMessageFreeRes{ + optional int32 ErrorCode = 1; //详见错误码文档 + optional uint32 GroupId = 2; //群信息 + optional bool MessageFree = 3; //消息免打扰 +} \ No newline at end of file diff --git a/lib/proto/login.pb.dart b/lib/proto/login.pb.dart new file mode 100644 index 0000000..0afbcd8 --- /dev/null +++ b/lib/proto/login.pb.dart @@ -0,0 +1,101 @@ +/// +// Generated code. Do not modify. +// source: login.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String; + +import 'package:protobuf/protobuf.dart' as $pb; + +class LoginAccountReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('LoginAccountReq', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'userId', $pb.PbFieldType.OU3) + ..aOS(2, 'sigin') + ..hasRequiredFields = false + ; + + LoginAccountReq._() : super(); + factory LoginAccountReq() => create(); + factory LoginAccountReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory LoginAccountReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + LoginAccountReq clone() => LoginAccountReq()..mergeFromMessage(this); + LoginAccountReq copyWith(void Function(LoginAccountReq) updates) => super.copyWith((message) => updates(message as LoginAccountReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static LoginAccountReq create() => LoginAccountReq._(); + LoginAccountReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static LoginAccountReq getDefault() => _defaultInstance ??= create()..freeze(); + static LoginAccountReq _defaultInstance; + + $core.int get userId => $_get(0, 0); + set userId($core.int v) { $_setUnsignedInt32(0, v); } + $core.bool hasUserId() => $_has(0); + void clearUserId() => clearField(1); + + $core.String get sigin => $_getS(1, ''); + set sigin($core.String v) { $_setString(1, v); } + $core.bool hasSigin() => $_has(1); + void clearSigin() => clearField(2); +} + +class LoginAccountRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('LoginAccountRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..aOS(2, 'httpAddr') + ..hasRequiredFields = false + ; + + LoginAccountRes._() : super(); + factory LoginAccountRes() => create(); + factory LoginAccountRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory LoginAccountRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + LoginAccountRes clone() => LoginAccountRes()..mergeFromMessage(this); + LoginAccountRes copyWith(void Function(LoginAccountRes) updates) => super.copyWith((message) => updates(message as LoginAccountRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static LoginAccountRes create() => LoginAccountRes._(); + LoginAccountRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static LoginAccountRes getDefault() => _defaultInstance ??= create()..freeze(); + static LoginAccountRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); + + $core.String get httpAddr => $_getS(1, ''); + set httpAddr($core.String v) { $_setString(1, v); } + $core.bool hasHttpAddr() => $_has(1); + void clearHttpAddr() => clearField(2); +} + +class PushUserOutLogin extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('PushUserOutLogin', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..hasRequiredFields = false + ; + + PushUserOutLogin._() : super(); + factory PushUserOutLogin() => create(); + factory PushUserOutLogin.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory PushUserOutLogin.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + PushUserOutLogin clone() => PushUserOutLogin()..mergeFromMessage(this); + PushUserOutLogin copyWith(void Function(PushUserOutLogin) updates) => super.copyWith((message) => updates(message as PushUserOutLogin)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static PushUserOutLogin create() => PushUserOutLogin._(); + PushUserOutLogin createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static PushUserOutLogin getDefault() => _defaultInstance ??= create()..freeze(); + static PushUserOutLogin _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); +} + diff --git a/lib/proto/login.pbenum.dart b/lib/proto/login.pbenum.dart new file mode 100644 index 0000000..6f7c3dd --- /dev/null +++ b/lib/proto/login.pbenum.dart @@ -0,0 +1,7 @@ +/// +// Generated code. Do not modify. +// source: login.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + diff --git a/lib/proto/login.pbjson.dart b/lib/proto/login.pbjson.dart new file mode 100644 index 0000000..711ef8e --- /dev/null +++ b/lib/proto/login.pbjson.dart @@ -0,0 +1,30 @@ +/// +// Generated code. Do not modify. +// source: login.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +const LoginAccountReq$json = const { + '1': 'LoginAccountReq', + '2': const [ + const {'1': 'UserId', '3': 1, '4': 1, '5': 13, '10': 'UserId'}, + const {'1': 'Sigin', '3': 2, '4': 1, '5': 9, '10': 'Sigin'}, + ], +}; + +const LoginAccountRes$json = const { + '1': 'LoginAccountRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + const {'1': 'HttpAddr', '3': 2, '4': 1, '5': 9, '10': 'HttpAddr'}, + ], +}; + +const PushUserOutLogin$json = const { + '1': 'PushUserOutLogin', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + ], +}; + diff --git a/lib/proto/login.pbserver.dart b/lib/proto/login.pbserver.dart new file mode 100644 index 0000000..4e4b357 --- /dev/null +++ b/lib/proto/login.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: login.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +export 'login.pb.dart'; + diff --git a/lib/proto/login.proto b/lib/proto/login.proto new file mode 100644 index 0000000..7170cd6 --- /dev/null +++ b/lib/proto/login.proto @@ -0,0 +1,18 @@ +syntax = "proto2"; +package yl_pb; + +//Msg = 1 登陆账号 +message LoginAccountReq { + optional uint32 UserId = 1; + optional string Sigin = 2; +} +//Msg = 2 登陆返回 +message LoginAccountRes { + optional int32 ErrorCode = 1; //0 成功 1参数错误 2签名错误 3用户不存在 4用户已登陆 + optional string HttpAddr = 2; //服务器对应http服务地址 +} + +//Msg = 3 推送用户推出登陆状态 +message PushUserOutLogin { + optional int32 ErrorCode = 1; //登出原因 +} diff --git a/lib/proto/msg.pb.dart b/lib/proto/msg.pb.dart new file mode 100644 index 0000000..d3d11a2 --- /dev/null +++ b/lib/proto/msg.pb.dart @@ -0,0 +1,37 @@ +/// +// Generated code. Do not modify. +// source: msg.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String; + +import 'package:protobuf/protobuf.dart' as $pb; + +class test extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('test', package: const $pb.PackageName('Im')) + ..a<$core.int>(1, 'code', $pb.PbFieldType.O3) + ..hasRequiredFields = false + ; + + test._() : super(); + factory test() => create(); + factory test.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory test.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + test clone() => test()..mergeFromMessage(this); + test copyWith(void Function(test) updates) => super.copyWith((message) => updates(message as test)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static test create() => test._(); + test createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static test getDefault() => _defaultInstance ??= create()..freeze(); + static test _defaultInstance; + + $core.int get code => $_get(0, 0); + set code($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasCode() => $_has(0); + void clearCode() => clearField(1); +} + diff --git a/lib/proto/msg.pbenum.dart b/lib/proto/msg.pbenum.dart new file mode 100644 index 0000000..5ebddb7 --- /dev/null +++ b/lib/proto/msg.pbenum.dart @@ -0,0 +1,7 @@ +/// +// Generated code. Do not modify. +// source: msg.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + diff --git a/lib/proto/msg.pbjson.dart b/lib/proto/msg.pbjson.dart new file mode 100644 index 0000000..f774a34 --- /dev/null +++ b/lib/proto/msg.pbjson.dart @@ -0,0 +1,14 @@ +/// +// Generated code. Do not modify. +// source: msg.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +const test$json = const { + '1': 'test', + '2': const [ + const {'1': 'code', '3': 1, '4': 1, '5': 5, '10': 'code'}, + ], +}; + diff --git a/lib/proto/msg.pbserver.dart b/lib/proto/msg.pbserver.dart new file mode 100644 index 0000000..8e0f8ea --- /dev/null +++ b/lib/proto/msg.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: msg.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +export 'msg.pb.dart'; + diff --git a/lib/proto/msgContent.pb.dart b/lib/proto/msgContent.pb.dart new file mode 100644 index 0000000..2e2deeb --- /dev/null +++ b/lib/proto/msgContent.pb.dart @@ -0,0 +1,37 @@ +/// +// Generated code. Do not modify. +// source: msgContent.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String; + +import 'package:protobuf/protobuf.dart' as $pb; + +class MsgContent extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('MsgContent') + ..aOS(1, 'msgContent') + ..hasRequiredFields = false + ; + + MsgContent._() : super(); + factory MsgContent() => create(); + factory MsgContent.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory MsgContent.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + MsgContent clone() => MsgContent()..mergeFromMessage(this); + MsgContent copyWith(void Function(MsgContent) updates) => super.copyWith((message) => updates(message as MsgContent)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static MsgContent create() => MsgContent._(); + MsgContent createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static MsgContent getDefault() => _defaultInstance ??= create()..freeze(); + static MsgContent _defaultInstance; + + $core.String get msgContent => $_getS(0, ''); + set msgContent($core.String v) { $_setString(0, v); } + $core.bool hasMsgContent() => $_has(0); + void clearMsgContent() => clearField(1); +} + diff --git a/lib/proto/msgContent.pbenum.dart b/lib/proto/msgContent.pbenum.dart new file mode 100644 index 0000000..0761066 --- /dev/null +++ b/lib/proto/msgContent.pbenum.dart @@ -0,0 +1,7 @@ +/// +// Generated code. Do not modify. +// source: msgContent.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + diff --git a/lib/proto/msgContent.pbjson.dart b/lib/proto/msgContent.pbjson.dart new file mode 100644 index 0000000..b431d0a --- /dev/null +++ b/lib/proto/msgContent.pbjson.dart @@ -0,0 +1,14 @@ +/// +// Generated code. Do not modify. +// source: msgContent.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +const MsgContent$json = const { + '1': 'MsgContent', + '2': const [ + const {'1': 'msgContent', '3': 1, '4': 1, '5': 9, '10': 'msgContent'}, + ], +}; + diff --git a/lib/proto/msgContent.pbserver.dart b/lib/proto/msgContent.pbserver.dart new file mode 100644 index 0000000..2073804 --- /dev/null +++ b/lib/proto/msgContent.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: msgContent.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +export 'msgContent.pb.dart'; + diff --git a/lib/proto/msgContent.proto b/lib/proto/msgContent.proto new file mode 100644 index 0000000..9d86659 --- /dev/null +++ b/lib/proto/msgContent.proto @@ -0,0 +1,6 @@ +syntax = "proto2"; + +//聊天消息 +message MsgContent { + optional string msgContent = 1; //消息附件地址 +} diff --git a/lib/proto/net.pb.dart b/lib/proto/net.pb.dart new file mode 100644 index 0000000..8c9da12 --- /dev/null +++ b/lib/proto/net.pb.dart @@ -0,0 +1,37 @@ +/// +// Generated code. Do not modify. +// source: net.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String; + +import 'package:protobuf/protobuf.dart' as $pb; + +class PushNetRelay extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('PushNetRelay', package: const $pb.PackageName('yl_pb')) + ..aOS(1, 'msg') + ..hasRequiredFields = false + ; + + PushNetRelay._() : super(); + factory PushNetRelay() => create(); + factory PushNetRelay.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory PushNetRelay.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + PushNetRelay clone() => PushNetRelay()..mergeFromMessage(this); + PushNetRelay copyWith(void Function(PushNetRelay) updates) => super.copyWith((message) => updates(message as PushNetRelay)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static PushNetRelay create() => PushNetRelay._(); + PushNetRelay createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static PushNetRelay getDefault() => _defaultInstance ??= create()..freeze(); + static PushNetRelay _defaultInstance; + + $core.String get msg => $_getS(0, ''); + set msg($core.String v) { $_setString(0, v); } + $core.bool hasMsg() => $_has(0); + void clearMsg() => clearField(1); +} + diff --git a/lib/proto/net.pbenum.dart b/lib/proto/net.pbenum.dart new file mode 100644 index 0000000..6eb6232 --- /dev/null +++ b/lib/proto/net.pbenum.dart @@ -0,0 +1,7 @@ +/// +// Generated code. Do not modify. +// source: net.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + diff --git a/lib/proto/net.pbjson.dart b/lib/proto/net.pbjson.dart new file mode 100644 index 0000000..96f7b85 --- /dev/null +++ b/lib/proto/net.pbjson.dart @@ -0,0 +1,14 @@ +/// +// Generated code. Do not modify. +// source: net.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +const PushNetRelay$json = const { + '1': 'PushNetRelay', + '2': const [ + const {'1': 'Msg', '3': 1, '4': 1, '5': 9, '10': 'Msg'}, + ], +}; + diff --git a/lib/proto/net.pbserver.dart b/lib/proto/net.pbserver.dart new file mode 100644 index 0000000..22ffa6d --- /dev/null +++ b/lib/proto/net.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: net.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +export 'net.pb.dart'; + diff --git a/lib/proto/net.proto b/lib/proto/net.proto new file mode 100644 index 0000000..f137589 --- /dev/null +++ b/lib/proto/net.proto @@ -0,0 +1,8 @@ +syntax = "proto2"; +package yl_pb; +//ComId = 100 + +//MsgId=1 推送 Net 用户消息 +message PushNetRelay { + optional string Msg = 1; +} \ No newline at end of file diff --git a/lib/proto/system.pb.dart b/lib/proto/system.pb.dart new file mode 100644 index 0000000..2168422 --- /dev/null +++ b/lib/proto/system.pb.dart @@ -0,0 +1,103 @@ +/// +// Generated code. Do not modify. +// source: system.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String; + +import 'package:protobuf/protobuf.dart' as $pb; + +class SystemHeartbeatReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('SystemHeartbeatReq', package: const $pb.PackageName('yl_pb')) + ..hasRequiredFields = false + ; + + SystemHeartbeatReq._() : super(); + factory SystemHeartbeatReq() => create(); + factory SystemHeartbeatReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SystemHeartbeatReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + SystemHeartbeatReq clone() => SystemHeartbeatReq()..mergeFromMessage(this); + SystemHeartbeatReq copyWith(void Function(SystemHeartbeatReq) updates) => super.copyWith((message) => updates(message as SystemHeartbeatReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SystemHeartbeatReq create() => SystemHeartbeatReq._(); + SystemHeartbeatReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static SystemHeartbeatReq getDefault() => _defaultInstance ??= create()..freeze(); + static SystemHeartbeatReq _defaultInstance; +} + +class SystemHeartbeatRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('SystemHeartbeatRes', package: const $pb.PackageName('yl_pb')) + ..hasRequiredFields = false + ; + + SystemHeartbeatRes._() : super(); + factory SystemHeartbeatRes() => create(); + factory SystemHeartbeatRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SystemHeartbeatRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + SystemHeartbeatRes clone() => SystemHeartbeatRes()..mergeFromMessage(this); + SystemHeartbeatRes copyWith(void Function(SystemHeartbeatRes) updates) => super.copyWith((message) => updates(message as SystemHeartbeatRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SystemHeartbeatRes create() => SystemHeartbeatRes._(); + SystemHeartbeatRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static SystemHeartbeatRes getDefault() => _defaultInstance ??= create()..freeze(); + static SystemHeartbeatRes _defaultInstance; +} + +class SystemHandshakeReq extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('SystemHandshakeReq', package: const $pb.PackageName('yl_pb')) + ..aOS(1, 'token') + ..hasRequiredFields = false + ; + + SystemHandshakeReq._() : super(); + factory SystemHandshakeReq() => create(); + factory SystemHandshakeReq.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SystemHandshakeReq.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + SystemHandshakeReq clone() => SystemHandshakeReq()..mergeFromMessage(this); + SystemHandshakeReq copyWith(void Function(SystemHandshakeReq) updates) => super.copyWith((message) => updates(message as SystemHandshakeReq)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SystemHandshakeReq create() => SystemHandshakeReq._(); + SystemHandshakeReq createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static SystemHandshakeReq getDefault() => _defaultInstance ??= create()..freeze(); + static SystemHandshakeReq _defaultInstance; + + $core.String get token => $_getS(0, ''); + set token($core.String v) { $_setString(0, v); } + $core.bool hasToken() => $_has(0); + void clearToken() => clearField(1); +} + +class SystemHandshakeRes extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('SystemHandshakeRes', package: const $pb.PackageName('yl_pb')) + ..a<$core.int>(1, 'errorCode', $pb.PbFieldType.O3) + ..hasRequiredFields = false + ; + + SystemHandshakeRes._() : super(); + factory SystemHandshakeRes() => create(); + factory SystemHandshakeRes.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory SystemHandshakeRes.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + SystemHandshakeRes clone() => SystemHandshakeRes()..mergeFromMessage(this); + SystemHandshakeRes copyWith(void Function(SystemHandshakeRes) updates) => super.copyWith((message) => updates(message as SystemHandshakeRes)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static SystemHandshakeRes create() => SystemHandshakeRes._(); + SystemHandshakeRes createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static SystemHandshakeRes getDefault() => _defaultInstance ??= create()..freeze(); + static SystemHandshakeRes _defaultInstance; + + $core.int get errorCode => $_get(0, 0); + set errorCode($core.int v) { $_setSignedInt32(0, v); } + $core.bool hasErrorCode() => $_has(0); + void clearErrorCode() => clearField(1); +} + diff --git a/lib/proto/system.pbenum.dart b/lib/proto/system.pbenum.dart new file mode 100644 index 0000000..f90e7bc --- /dev/null +++ b/lib/proto/system.pbenum.dart @@ -0,0 +1,7 @@ +/// +// Generated code. Do not modify. +// source: system.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + diff --git a/lib/proto/system.pbjson.dart b/lib/proto/system.pbjson.dart new file mode 100644 index 0000000..6546359 --- /dev/null +++ b/lib/proto/system.pbjson.dart @@ -0,0 +1,29 @@ +/// +// Generated code. Do not modify. +// source: system.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +const SystemHeartbeatReq$json = const { + '1': 'SystemHeartbeatReq', +}; + +const SystemHeartbeatRes$json = const { + '1': 'SystemHeartbeatRes', +}; + +const SystemHandshakeReq$json = const { + '1': 'SystemHandshakeReq', + '2': const [ + const {'1': 'Token', '3': 1, '4': 1, '5': 9, '10': 'Token'}, + ], +}; + +const SystemHandshakeRes$json = const { + '1': 'SystemHandshakeRes', + '2': const [ + const {'1': 'ErrorCode', '3': 1, '4': 1, '5': 5, '10': 'ErrorCode'}, + ], +}; + diff --git a/lib/proto/system.pbserver.dart b/lib/proto/system.pbserver.dart new file mode 100644 index 0000000..55dc33f --- /dev/null +++ b/lib/proto/system.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: system.proto +// +// @dart = 2.3 +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type + +export 'system.pb.dart'; + diff --git a/lib/proto/system.proto b/lib/proto/system.proto new file mode 100644 index 0000000..d618fcc --- /dev/null +++ b/lib/proto/system.proto @@ -0,0 +1,19 @@ +syntax = "proto2"; +package yl_pb; + +//Msg = 1 心跳请求 +message SystemHeartbeatReq { +} +//Msg = 2 心跳回应 +message SystemHeartbeatRes { +} + +//Msg = 3 握手请求 +message SystemHandshakeReq { + optional string Token = 1; //握手加密信息 主要用户客户端切换服务器以及重连 +} + +//Msg = 4 握手回应 +message SystemHandshakeRes { + optional int32 ErrorCode = 1; //0 成功 +} diff --git a/lib/r.dart b/lib/r.dart new file mode 100644 index 0000000..9060a88 --- /dev/null +++ b/lib/r.dart @@ -0,0 +1,508 @@ +class R { + /// ![](http://127.0.0.1:9527/assets/images/back.png) + static final String assetsImagesBack = 'assets/images/back.png'; + /// ![](http://127.0.0.1:9527/assets/images/bg.png) + static final String assetsImagesBg = 'assets/images/bg.png'; + /// ![](http://127.0.0.1:9527/assets/images/bofang.png) + static final String assetsImagesBofang = 'assets/images/bofang.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat_item_1.png) + static final String assetsImagesChatItem1 = 'assets/images/chat_item_1.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat_item_2.png) + static final String assetsImagesChatItem2 = 'assets/images/chat_item_2.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat_item_3.png) + static final String assetsImagesChatItem3 = 'assets/images/chat_item_3.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat_item_4.png) + static final String assetsImagesChatItem4 = 'assets/images/chat_item_4.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat_item_5.png) + static final String assetsImagesChatItem5 = 'assets/images/chat_item_5.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat_item_6.png) + static final String assetsImagesChatItem6 = 'assets/images/chat_item_6.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat_item_7.png) + static final String assetsImagesChatItem7 = 'assets/images/chat_item_7.png'; + /// ![](http://127.0.0.1:9527/assets/images/coin.png) + static final String assetsImagesCoin = 'assets/images/coin.png'; + /// ![](http://127.0.0.1:9527/assets/images/daily_bg_1.png) + static final String assetsImagesDailyBg1 = 'assets/images/daily_bg_1.png'; + /// ![](http://127.0.0.1:9527/assets/images/daily_bg_2.png) + static final String assetsImagesDailyBg2 = 'assets/images/daily_bg_2.png'; + /// ![](http://127.0.0.1:9527/assets/images/daily_btn_1.png) + static final String assetsImagesDailyBtn1 = 'assets/images/daily_btn_1.png'; + /// ![](http://127.0.0.1:9527/assets/images/daily_btn_2.png) + static final String assetsImagesDailyBtn2 = 'assets/images/daily_btn_2.png'; + /// ![](http://127.0.0.1:9527/assets/images/daily_coin.png) + static final String assetsImagesDailyCoin = 'assets/images/daily_coin.png'; + /// ![](http://127.0.0.1:9527/assets/images/daily_icon.png) + static final String assetsImagesDailyIcon = 'assets/images/daily_icon.png'; + /// ![](http://127.0.0.1:9527/assets/images/default_nor_avatar.png) + static final String assetsImagesDefaultNorAvatar = 'assets/images/default_nor_avatar.png'; + /// ![](http://127.0.0.1:9527/assets/images/ext_apk.png) + static final String assetsImagesExtApk = 'assets/images/ext_apk.png'; + /// ![](http://127.0.0.1:9527/assets/images/ext_excel.png) + static final String assetsImagesExtExcel = 'assets/images/ext_excel.png'; + /// ![](http://127.0.0.1:9527/assets/images/ext_pdf.png) + static final String assetsImagesExtPdf = 'assets/images/ext_pdf.png'; + /// ![](http://127.0.0.1:9527/assets/images/ext_ppt.png) + static final String assetsImagesExtPpt = 'assets/images/ext_ppt.png'; + /// ![](http://127.0.0.1:9527/assets/images/ext_sound.png) + static final String assetsImagesExtSound = 'assets/images/ext_sound.png'; + /// ![](http://127.0.0.1:9527/assets/images/ext_txt.png) + static final String assetsImagesExtTxt = 'assets/images/ext_txt.png'; + /// ![](http://127.0.0.1:9527/assets/images/ext_unknown.png) + static final String assetsImagesExtUnknown = 'assets/images/ext_unknown.png'; + /// ![](http://127.0.0.1:9527/assets/images/ext_video.png) + static final String assetsImagesExtVideo = 'assets/images/ext_video.png'; + /// ![](http://127.0.0.1:9527/assets/images/ext_word.png) + static final String assetsImagesExtWord = 'assets/images/ext_word.png'; + /// ![](http://127.0.0.1:9527/assets/images/ext_zip.png) + static final String assetsImagesExtZip = 'assets/images/ext_zip.png'; + /// ![](http://127.0.0.1:9527/assets/images/gift_1.png) + static final String assetsImagesGift1 = 'assets/images/gift_1.png'; + /// ![](http://127.0.0.1:9527/assets/images/gift_2.png) + static final String assetsImagesGift2 = 'assets/images/gift_2.png'; + /// ![](http://127.0.0.1:9527/assets/images/gift_3.png) + static final String assetsImagesGift3 = 'assets/images/gift_3.png'; + /// ![](http://127.0.0.1:9527/assets/images/gift_anim_1.gif) + static final String assetsImagesGiftAnim1 = 'assets/images/gift_anim_1.gif'; + /// ![](http://127.0.0.1:9527/assets/images/gift_anim_2.gif) + static final String assetsImagesGiftAnim2 = 'assets/images/gift_anim_2.gif'; + /// ![](http://127.0.0.1:9527/assets/images/gift_anim_3.gif) + static final String assetsImagesGiftAnim3 = 'assets/images/gift_anim_3.gif'; + /// ![](http://127.0.0.1:9527/assets/images/gift_show_2_1.png) + static final String assetsImagesGiftShow21 = 'assets/images/gift_show_2_1.png'; + /// ![](http://127.0.0.1:9527/assets/images/gift_show_2_2.png) + static final String assetsImagesGiftShow22 = 'assets/images/gift_show_2_2.png'; + /// ![](http://127.0.0.1:9527/assets/images/gift_show_2_3.png) + static final String assetsImagesGiftShow23 = 'assets/images/gift_show_2_3.png'; + /// ![](http://127.0.0.1:9527/assets/images/gift_show_2_4.png) + static final String assetsImagesGiftShow24 = 'assets/images/gift_show_2_4.png'; + /// ![](http://127.0.0.1:9527/assets/images/hand.png) + static final String assetsImagesHand = 'assets/images/hand.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_album.png) + static final String assetsImagesIcAlbum = 'assets/images/ic_album.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_bottle_msg.png) + static final String assetsImagesIcBottleMsg = 'assets/images/ic_bottle_msg.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_cards_wallet.png) + static final String assetsImagesIcCardsWallet = 'assets/images/ic_cards_wallet.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_collections.png) + static final String assetsImagesIcCollections = 'assets/images/ic_collections.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_emotions.png) + static final String assetsImagesIcEmotions = 'assets/images/ic_emotions.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_feeds.png) + static final String assetsImagesIcFeeds = 'assets/images/ic_feeds.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_fengchao.png) + static final String assetsImagesIcFengchao = 'assets/images/ic_fengchao.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_file_transfer.png) + static final String assetsImagesIcFileTransfer = 'assets/images/ic_file_transfer.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_game_entry.png) + static final String assetsImagesIcGameEntry = 'assets/images/ic_game_entry.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_group_chat.png) + static final String assetsImagesIcGroupChat = 'assets/images/ic_group_chat.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_mini_program.png) + static final String assetsImagesIcMiniProgram = 'assets/images/ic_mini_program.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_new_friend.png) + static final String assetsImagesIcNewFriend = 'assets/images/ic_new_friend.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_people_nearby.png) + static final String assetsImagesIcPeopleNearby = 'assets/images/ic_people_nearby.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_public_account.png) + static final String assetsImagesIcPublicAccount = 'assets/images/ic_public_account.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_qrcode_preview_tiny.png) + static final String assetsImagesIcQrcodePreviewTiny = 'assets/images/ic_qrcode_preview_tiny.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_quick_scan.png) + static final String assetsImagesIcQuickScan = 'assets/images/ic_quick_scan.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_quick_search.png) + static final String assetsImagesIcQuickSearch = 'assets/images/ic_quick_search.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_settings.png) + static final String assetsImagesIcSettings = 'assets/images/ic_settings.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_shake_phone.png) + static final String assetsImagesIcShakePhone = 'assets/images/ic_shake_phone.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_shopping.png) + static final String assetsImagesIcShopping = 'assets/images/ic_shopping.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_social_circle.png) + static final String assetsImagesIcSocialCircle = 'assets/images/ic_social_circle.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_tag.png) + static final String assetsImagesIcTag = 'assets/images/ic_tag.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_tx_news.png) + static final String assetsImagesIcTxNews = 'assets/images/ic_tx_news.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_wallet.png) + static final String assetsImagesIcWallet = 'assets/images/ic_wallet.png'; + /// ![](http://127.0.0.1:9527/assets/images/ic_wx_games.png) + static final String assetsImagesIcWxGames = 'assets/images/ic_wx_games.png'; + /// ![](http://127.0.0.1:9527/assets/images/img_fyj.png) + static final String assetsImagesImgFyj = 'assets/images/img_fyj.png'; + /// ![](http://127.0.0.1:9527/assets/images/img_long_index.png) + static final String assetsImagesImgLongIndex = 'assets/images/img_long_index.png'; + /// ![](http://127.0.0.1:9527/assets/images/img_splash_1.png) + static final String assetsImagesImgSplash1 = 'assets/images/img_splash_1.png'; + /// ![](http://127.0.0.1:9527/assets/images/img_splash_2.png) + static final String assetsImagesImgSplash2 = 'assets/images/img_splash_2.png'; + /// ![](http://127.0.0.1:9527/assets/images/img_splash_3.png) + static final String assetsImagesImgSplash3 = 'assets/images/img_splash_3.png'; + /// ![](http://127.0.0.1:9527/assets/images/img_temp_hy.png) + static final String assetsImagesImgTempHy = 'assets/images/img_temp_hy.png'; + /// ![](http://127.0.0.1:9527/assets/images/img_temp_qb.png) + static final String assetsImagesImgTempQb = 'assets/images/img_temp_qb.png'; + /// ![](http://127.0.0.1:9527/assets/images/img_temp_qd.png) + static final String assetsImagesImgTempQd = 'assets/images/img_temp_qd.png'; + /// ![](http://127.0.0.1:9527/assets/images/img_temp_see.png) + static final String assetsImagesImgTempSee = 'assets/images/img_temp_see.png'; + /// ![](http://127.0.0.1:9527/assets/images/img_temp_share.png) + static final String assetsImagesImgTempShare = 'assets/images/img_temp_share.png'; + /// ![](http://127.0.0.1:9527/assets/images/img_update_bg.png) + static final String assetsImagesImgUpdateBg = 'assets/images/img_update_bg.png'; + /// ![](http://127.0.0.1:9527/assets/images/left_gray.png) + static final String assetsImagesLeftGray = 'assets/images/left_gray.png'; + /// ![](http://127.0.0.1:9527/assets/images/left_white.png) + static final String assetsImagesLeftWhite = 'assets/images/left_white.png'; + /// ![](http://127.0.0.1:9527/assets/images/net_error.png) + static final String assetsImagesNetError = 'assets/images/net_error.png'; + /// ![](http://127.0.0.1:9527/assets/images/qianbao_bg.png) + static final String assetsImagesQianbaoBg = 'assets/images/qianbao_bg.png'; + /// ![](http://127.0.0.1:9527/assets/images/red_packet_bg.png) + static final String assetsImagesRedPacketBg = 'assets/images/red_packet_bg.png'; + /// ![](http://127.0.0.1:9527/assets/images/right_gray.png) + static final String assetsImagesRightGray = 'assets/images/right_gray.png'; + /// ![](http://127.0.0.1:9527/assets/images/right_white.png) + static final String assetsImagesRightWhite = 'assets/images/right_white.png'; + /// ![](http://127.0.0.1:9527/assets/images/robot.jpg) + static final String assetsImagesRobot = 'assets/images/robot.jpg'; + /// ![](http://127.0.0.1:9527/assets/images/server_icon.png) + static final String assetsImagesServerIcon = 'assets/images/server_icon.png'; + /// ![](http://127.0.0.1:9527/assets/images/service_icon.png) + static final String assetsImagesServiceIcon = 'assets/images/service_icon.png'; + /// ![](http://127.0.0.1:9527/assets/images/suo.png) + static final String assetsImagesSuo = 'assets/images/suo.png'; + /// ![](http://127.0.0.1:9527/assets/images/svip.png) + static final String assetsImagesSvip = 'assets/images/svip.png'; + /// ![](http://127.0.0.1:9527/assets/images/VIP.png) + static final String assetsImagesVIP = 'assets/images/VIP.png'; + /// ![](http://127.0.0.1:9527/assets/images/voucher.png) + static final String assetsImagesVoucher = 'assets/images/voucher.png'; + /// ![](http://127.0.0.1:9527/assets/images/yqm_bg.png) + static final String assetsImagesYqmBg = 'assets/images/yqm_bg.png'; + /// ![](http://127.0.0.1:9527/assets/images/zhiwen.png) + static final String assetsImagesZhiwen = 'assets/images/zhiwen.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat/emoji.png) + static final String assetsImagesChatEmoji = 'assets/images/chat/emoji.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat/icon1.png) + static final String assetsImagesChatIcon1 = 'assets/images/chat/icon1.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat/icon2.png) + static final String assetsImagesChatIcon2 = 'assets/images/chat/icon2.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat/icon3.png) + static final String assetsImagesChatIcon3 = 'assets/images/chat/icon3.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat/icon4.png) + static final String assetsImagesChatIcon4 = 'assets/images/chat/icon4.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat/icon5.png) + static final String assetsImagesChatIcon5 = 'assets/images/chat/icon5.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat/icon6.png) + static final String assetsImagesChatIcon6 = 'assets/images/chat/icon6.png'; + /// ![](http://127.0.0.1:9527/assets/images/chat/onion.png) + static final String assetsImagesChatOnion = 'assets/images/chat/onion.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/delete.png) + static final String assetsImagesLoginDelete = 'assets/images/login/delete.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/dly_icon1.png) + static final String assetsImagesLoginDlyIcon1 = 'assets/images/login/dly_icon1.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/dly_icon2.png) + static final String assetsImagesLoginDlyIcon2 = 'assets/images/login/dly_icon2.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/dly_icon3.png) + static final String assetsImagesLoginDlyIcon3 = 'assets/images/login/dly_icon3.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/dly_icon4.png) + static final String assetsImagesLoginDlyIcon4 = 'assets/images/login/dly_icon4.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/dly_logo.png) + static final String assetsImagesLoginDlyLogo = 'assets/images/login/dly_logo.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/lock.png) + static final String assetsImagesLoginLock = 'assets/images/login/lock.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/money.png) + static final String assetsImagesLoginMoney = 'assets/images/login/money.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/rzzx.png) + static final String assetsImagesLoginRzzx = 'assets/images/login/rzzx.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/SY_bg.png) + static final String assetsImagesLoginSYBg = 'assets/images/login/SY_bg.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/SY_logo.png) + static final String assetsImagesLoginSYLogo = 'assets/images/login/SY_logo.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/vip_logio.png) + static final String assetsImagesLoginVipLogio = 'assets/images/login/vip_logio.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/vip_other.png) + static final String assetsImagesLoginVipOther = 'assets/images/login/vip_other.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/vip_rect1.png) + static final String assetsImagesLoginVipRect1 = 'assets/images/login/vip_rect1.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/vip_rect2.png) + static final String assetsImagesLoginVipRect2 = 'assets/images/login/vip_rect2.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/vip_rect3.png) + static final String assetsImagesLoginVipRect3 = 'assets/images/login/vip_rect3.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/vip_wx.png) + static final String assetsImagesLoginVipWx = 'assets/images/login/vip_wx.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/vip_zfb.png) + static final String assetsImagesLoginVipZfb = 'assets/images/login/vip_zfb.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/xzxb_female.png) + static final String assetsImagesLoginXzxbFemale = 'assets/images/login/xzxb_female.png'; + /// ![](http://127.0.0.1:9527/assets/images/login/xzxb_male.png) + static final String assetsImagesLoginXzxbMale = 'assets/images/login/xzxb_male.png'; + /// ![](http://127.0.0.1:9527/assets/images/park/qz_icon1.png) + static final String assetsImagesParkQzIcon1 = 'assets/images/park/qz_icon1.png'; + /// ![](http://127.0.0.1:9527/assets/images/park/qz_icon2.png) + static final String assetsImagesParkQzIcon2 = 'assets/images/park/qz_icon2.png'; + /// ![](http://127.0.0.1:9527/assets/images/park/qz_icon3.png) + static final String assetsImagesParkQzIcon3 = 'assets/images/park/qz_icon3.png'; + /// ![](http://127.0.0.1:9527/assets/images/park/qz_icon4.png) + static final String assetsImagesParkQzIcon4 = 'assets/images/park/qz_icon4.png'; + /// ![](http://127.0.0.1:9527/assets/images/park/qz_icon5.png) + static final String assetsImagesParkQzIcon5 = 'assets/images/park/qz_icon5.png'; + /// ![](http://127.0.0.1:9527/assets/images/park/qz_icon6.png) + static final String assetsImagesParkQzIcon6 = 'assets/images/park/qz_icon6.png'; + /// ![](http://127.0.0.1:9527/assets/images/park/qz_icon7.png) + static final String assetsImagesParkQzIcon7 = 'assets/images/park/qz_icon7.png'; + /// ![](http://127.0.0.1:9527/assets/images/park/qz_icon8.png) + static final String assetsImagesParkQzIcon8 = 'assets/images/park/qz_icon8.png'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_1.gif) + static final String assetsImagesStickerSticker1 = 'assets/images/sticker/sticker_1.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_10.gif) + static final String assetsImagesStickerSticker10 = 'assets/images/sticker/sticker_10.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_11.gif) + static final String assetsImagesStickerSticker11 = 'assets/images/sticker/sticker_11.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_12.gif) + static final String assetsImagesStickerSticker12 = 'assets/images/sticker/sticker_12.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_13.gif) + static final String assetsImagesStickerSticker13 = 'assets/images/sticker/sticker_13.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_14.gif) + static final String assetsImagesStickerSticker14 = 'assets/images/sticker/sticker_14.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_15.gif) + static final String assetsImagesStickerSticker15 = 'assets/images/sticker/sticker_15.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_16.gif) + static final String assetsImagesStickerSticker16 = 'assets/images/sticker/sticker_16.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_17.gif) + static final String assetsImagesStickerSticker17 = 'assets/images/sticker/sticker_17.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_18.gif) + static final String assetsImagesStickerSticker18 = 'assets/images/sticker/sticker_18.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_19.gif) + static final String assetsImagesStickerSticker19 = 'assets/images/sticker/sticker_19.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_2.gif) + static final String assetsImagesStickerSticker2 = 'assets/images/sticker/sticker_2.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_20.gif) + static final String assetsImagesStickerSticker20 = 'assets/images/sticker/sticker_20.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_21.gif) + static final String assetsImagesStickerSticker21 = 'assets/images/sticker/sticker_21.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_22.gif) + static final String assetsImagesStickerSticker22 = 'assets/images/sticker/sticker_22.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_23.gif) + static final String assetsImagesStickerSticker23 = 'assets/images/sticker/sticker_23.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_24.gif) + static final String assetsImagesStickerSticker24 = 'assets/images/sticker/sticker_24.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_25.gif) + static final String assetsImagesStickerSticker25 = 'assets/images/sticker/sticker_25.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_26.gif) + static final String assetsImagesStickerSticker26 = 'assets/images/sticker/sticker_26.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_27.gif) + static final String assetsImagesStickerSticker27 = 'assets/images/sticker/sticker_27.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_28.gif) + static final String assetsImagesStickerSticker28 = 'assets/images/sticker/sticker_28.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_29.gif) + static final String assetsImagesStickerSticker29 = 'assets/images/sticker/sticker_29.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_3.gif) + static final String assetsImagesStickerSticker3 = 'assets/images/sticker/sticker_3.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_30.gif) + static final String assetsImagesStickerSticker30 = 'assets/images/sticker/sticker_30.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_4.gif) + static final String assetsImagesStickerSticker4 = 'assets/images/sticker/sticker_4.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_5.gif) + static final String assetsImagesStickerSticker5 = 'assets/images/sticker/sticker_5.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_6.gif) + static final String assetsImagesStickerSticker6 = 'assets/images/sticker/sticker_6.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_7.gif) + static final String assetsImagesStickerSticker7 = 'assets/images/sticker/sticker_7.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_8.gif) + static final String assetsImagesStickerSticker8 = 'assets/images/sticker/sticker_8.gif'; + /// ![](http://127.0.0.1:9527/assets/images/sticker/sticker_9.gif) + static final String assetsImagesStickerSticker9 = 'assets/images/sticker/sticker_9.gif'; + /// ![](http://127.0.0.1:9527/assets/images/vip/hy_bg.png) + static final String assetsImagesVipHyBg = 'assets/images/vip/hy_bg.png'; + /// ![](http://127.0.0.1:9527/assets/images/vip/hy_cjhy.png) + static final String assetsImagesVipHyCjhy = 'assets/images/vip/hy_cjhy.png'; + /// ![](http://127.0.0.1:9527/assets/images/vip/hy_hy.png) + static final String assetsImagesVipHyHy = 'assets/images/vip/hy_hy.png'; + /// ![](http://127.0.0.1:9527/assets/images/vip/hy_tj.png) + static final String assetsImagesVipHyTj = 'assets/images/vip/hy_tj.png'; + /// ![](http://127.0.0.1:9527/assets/images/vip/hy_tq.png) + static final String assetsImagesVipHyTq = 'assets/images/vip/hy_tq.png'; + /// ![](http://127.0.0.1:9527/assets/images/vip/hy_xz.png) + static final String assetsImagesVipHyXz = 'assets/images/vip/hy_xz.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/1.png) + static final String assetsImagesEmojiface1 = 'assets/images/emojiface/1.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/10.png) + static final String assetsImagesEmojiface10 = 'assets/images/emojiface/10.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/11.png) + static final String assetsImagesEmojiface11 = 'assets/images/emojiface/11.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/12.png) + static final String assetsImagesEmojiface12 = 'assets/images/emojiface/12.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/13.png) + static final String assetsImagesEmojiface13 = 'assets/images/emojiface/13.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/14.png) + static final String assetsImagesEmojiface14 = 'assets/images/emojiface/14.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/15.png) + static final String assetsImagesEmojiface15 = 'assets/images/emojiface/15.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/16.png) + static final String assetsImagesEmojiface16 = 'assets/images/emojiface/16.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/17.png) + static final String assetsImagesEmojiface17 = 'assets/images/emojiface/17.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/18.png) + static final String assetsImagesEmojiface18 = 'assets/images/emojiface/18.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/19.png) + static final String assetsImagesEmojiface19 = 'assets/images/emojiface/19.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/2.png) + static final String assetsImagesEmojiface2 = 'assets/images/emojiface/2.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/20.png) + static final String assetsImagesEmojiface20 = 'assets/images/emojiface/20.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/21.png) + static final String assetsImagesEmojiface21 = 'assets/images/emojiface/21.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/22.png) + static final String assetsImagesEmojiface22 = 'assets/images/emojiface/22.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/23.png) + static final String assetsImagesEmojiface23 = 'assets/images/emojiface/23.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/24.png) + static final String assetsImagesEmojiface24 = 'assets/images/emojiface/24.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/25.png) + static final String assetsImagesEmojiface25 = 'assets/images/emojiface/25.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/26.png) + static final String assetsImagesEmojiface26 = 'assets/images/emojiface/26.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/27.png) + static final String assetsImagesEmojiface27 = 'assets/images/emojiface/27.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/28.png) + static final String assetsImagesEmojiface28 = 'assets/images/emojiface/28.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/29.png) + static final String assetsImagesEmojiface29 = 'assets/images/emojiface/29.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/3.png) + static final String assetsImagesEmojiface3 = 'assets/images/emojiface/3.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/30.png) + static final String assetsImagesEmojiface30 = 'assets/images/emojiface/30.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/31.png) + static final String assetsImagesEmojiface31 = 'assets/images/emojiface/31.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/32.png) + static final String assetsImagesEmojiface32 = 'assets/images/emojiface/32.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/33.png) + static final String assetsImagesEmojiface33 = 'assets/images/emojiface/33.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/34.png) + static final String assetsImagesEmojiface34 = 'assets/images/emojiface/34.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/35.png) + static final String assetsImagesEmojiface35 = 'assets/images/emojiface/35.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/36.png) + static final String assetsImagesEmojiface36 = 'assets/images/emojiface/36.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/37.png) + static final String assetsImagesEmojiface37 = 'assets/images/emojiface/37.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/38.png) + static final String assetsImagesEmojiface38 = 'assets/images/emojiface/38.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/39.png) + static final String assetsImagesEmojiface39 = 'assets/images/emojiface/39.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/4.png) + static final String assetsImagesEmojiface4 = 'assets/images/emojiface/4.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/40.png) + static final String assetsImagesEmojiface40 = 'assets/images/emojiface/40.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/41.png) + static final String assetsImagesEmojiface41 = 'assets/images/emojiface/41.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/42.png) + static final String assetsImagesEmojiface42 = 'assets/images/emojiface/42.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/43.png) + static final String assetsImagesEmojiface43 = 'assets/images/emojiface/43.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/44.png) + static final String assetsImagesEmojiface44 = 'assets/images/emojiface/44.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/45.png) + static final String assetsImagesEmojiface45 = 'assets/images/emojiface/45.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/46.png) + static final String assetsImagesEmojiface46 = 'assets/images/emojiface/46.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/47.png) + static final String assetsImagesEmojiface47 = 'assets/images/emojiface/47.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/48.png) + static final String assetsImagesEmojiface48 = 'assets/images/emojiface/48.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/49.png) + static final String assetsImagesEmojiface49 = 'assets/images/emojiface/49.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/5.png) + static final String assetsImagesEmojiface5 = 'assets/images/emojiface/5.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/50.png) + static final String assetsImagesEmojiface50 = 'assets/images/emojiface/50.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/51.png) + static final String assetsImagesEmojiface51 = 'assets/images/emojiface/51.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/52.png) + static final String assetsImagesEmojiface52 = 'assets/images/emojiface/52.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/53.png) + static final String assetsImagesEmojiface53 = 'assets/images/emojiface/53.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/54.png) + static final String assetsImagesEmojiface54 = 'assets/images/emojiface/54.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/55.png) + static final String assetsImagesEmojiface55 = 'assets/images/emojiface/55.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/56.png) + static final String assetsImagesEmojiface56 = 'assets/images/emojiface/56.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/57.png) + static final String assetsImagesEmojiface57 = 'assets/images/emojiface/57.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/58.png) + static final String assetsImagesEmojiface58 = 'assets/images/emojiface/58.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/59.png) + static final String assetsImagesEmojiface59 = 'assets/images/emojiface/59.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/6.png) + static final String assetsImagesEmojiface6 = 'assets/images/emojiface/6.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/60.png) + static final String assetsImagesEmojiface60 = 'assets/images/emojiface/60.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/61.png) + static final String assetsImagesEmojiface61 = 'assets/images/emojiface/61.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/62.png) + static final String assetsImagesEmojiface62 = 'assets/images/emojiface/62.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/63.png) + static final String assetsImagesEmojiface63 = 'assets/images/emojiface/63.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/64.png) + static final String assetsImagesEmojiface64 = 'assets/images/emojiface/64.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/65.png) + static final String assetsImagesEmojiface65 = 'assets/images/emojiface/65.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/66.png) + static final String assetsImagesEmojiface66 = 'assets/images/emojiface/66.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/67.png) + static final String assetsImagesEmojiface67 = 'assets/images/emojiface/67.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/68.png) + static final String assetsImagesEmojiface68 = 'assets/images/emojiface/68.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/69.png) + static final String assetsImagesEmojiface69 = 'assets/images/emojiface/69.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/7.png) + static final String assetsImagesEmojiface7 = 'assets/images/emojiface/7.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/70.png) + static final String assetsImagesEmojiface70 = 'assets/images/emojiface/70.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/71.png) + static final String assetsImagesEmojiface71 = 'assets/images/emojiface/71.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/72.png) + static final String assetsImagesEmojiface72 = 'assets/images/emojiface/72.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/73.png) + static final String assetsImagesEmojiface73 = 'assets/images/emojiface/73.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/74.png) + static final String assetsImagesEmojiface74 = 'assets/images/emojiface/74.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/75.png) + static final String assetsImagesEmojiface75 = 'assets/images/emojiface/75.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/76.png) + static final String assetsImagesEmojiface76 = 'assets/images/emojiface/76.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/77.png) + static final String assetsImagesEmojiface77 = 'assets/images/emojiface/77.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/78.png) + static final String assetsImagesEmojiface78 = 'assets/images/emojiface/78.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/79.png) + static final String assetsImagesEmojiface79 = 'assets/images/emojiface/79.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/8.png) + static final String assetsImagesEmojiface8 = 'assets/images/emojiface/8.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/80.png) + static final String assetsImagesEmojiface80 = 'assets/images/emojiface/80.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/81.png) + static final String assetsImagesEmojiface81 = 'assets/images/emojiface/81.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/82.png) + static final String assetsImagesEmojiface82 = 'assets/images/emojiface/82.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/83.png) + static final String assetsImagesEmojiface83 = 'assets/images/emojiface/83.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/84.png) + static final String assetsImagesEmojiface84 = 'assets/images/emojiface/84.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/85.png) + static final String assetsImagesEmojiface85 = 'assets/images/emojiface/85.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/86.png) + static final String assetsImagesEmojiface86 = 'assets/images/emojiface/86.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/87.png) + static final String assetsImagesEmojiface87 = 'assets/images/emojiface/87.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/88.png) + static final String assetsImagesEmojiface88 = 'assets/images/emojiface/88.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/89.png) + static final String assetsImagesEmojiface89 = 'assets/images/emojiface/89.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/9.png) + static final String assetsImagesEmojiface9 = 'assets/images/emojiface/9.png'; + /// ![](http://127.0.0.1:9527/assets/images/emojiface/90.png) + static final String assetsImagesEmojiface90 = 'assets/images/emojiface/90.png'; +} diff --git a/lib/rtc/agora.dart b/lib/rtc/agora.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/utils/ChargeMoney.dart b/lib/utils/ChargeMoney.dart new file mode 100644 index 0000000..9551063 --- /dev/null +++ b/lib/utils/ChargeMoney.dart @@ -0,0 +1,544 @@ +import 'dart:io'; + +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/MoneyPage.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/utils/app_navigator.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart'; +import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import 'HttpUtil.dart'; +import 'LoadingDialog.dart'; +import 'ShadowButton.dart'; +import 'TokenMgr.dart'; +import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx; + +class PayWayContent extends StatefulWidget { + @required + final goodsId; + @required + final money; + PayWayContent({Key key, this.goodsId, this.money}) : super(key: key); + + PayWayContentState createState() => PayWayContentState(); +} + +class PayWay { + static const int WxApp = 0; //微信app支付 + static const int ApplePay = 1; //苹果支付 + static const int GooglePay = 2; //谷歌支付 + static const int WxH5 = 3; //微信h5支付 + static const int Paypal = 4; //paypal支付 + static const int ShareToOther = 5; //微信他人代付 +} + +// enum PayWay { wx, apple, google, h5, paypal, shareToOther } + +class PayWayContentState extends State { + int payWay = PayWay.WxH5; + Widget _buildTip() { + return Container( + margin: EdgeInsets.only(bottom: 5), + padding: EdgeInsets.only(top: 10, left: 10, right: 10), + decoration: + BoxDecoration(border: Border(bottom: Constants.GreyBorderSide)), + child: Column( + children: [ + InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Align( + alignment: Alignment.centerRight, + child: Icon( + IconData( + 0xe679, + fontFamily: 'iconfont', + ), + size: 16, + color: const Color(0xFF969696), + )), + ), + Container( + alignment: Alignment.center, + margin: EdgeInsets.only(bottom: 16), + child: Text( + I18n.of(context).confirm_pay, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 15), + ), + ), + Container( + margin: EdgeInsets.only(bottom: 19), + alignment: Alignment.center, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + UserData().language == LanguageType.SimplifiedChinese + ? '¥' + : '₫', + textScaleFactor: 1.0, + style: TextStyle(fontSize: 20, fontWeight: FontWeight.w700), + ), + Text( + ' ${widget.money}', + textScaleFactor: 1.0, + style: TextStyle(fontSize: 28, fontWeight: FontWeight.w700), + ) + ], + ), + ) + ], + ), + ); + } + + Widget _buildPayWayItem(img, name, radio, callback) { + return InkWell( + onTap: callback, + child: Container( + child: Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(5)), + child: Image.asset( + img, + height: 26, + )), + Padding( + padding: EdgeInsets.only(left: 15), + child: Text( + name, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14), + ), + ), + Expanded( + child: + Container(alignment: Alignment.centerRight, child: radio), + ) + ], + ), + )); + } + + void addGoods() async { + var data = { + "userid": UserData().basicInfo.userId, + "moneytype": 1, + 'gid': widget.goodsId, + "payway": payWay, + }; + data['sign'] = TokenMgr().getSign(data); + data['isenable'] = Constants.isSandbox ? 0 : 1; + Response res = await HttpUtil().post('order/add/goods', data: data); + Map resData = res.data; + print('resData: $resData'); + if (resData['code'] == 0) { + Navigator.of(context).pop(); + var url = resData['data']['Weburl']; + UserData().isBannerStatus = true; + if (payWay == PayWay.Paypal) { + AppNavigator.pushWebview(context, url); + } else if (payWay == PayWay.WxH5) { + if (await canLaunch(url)) { + await launch(url); + } else { + throw 'Could not launch $url'; + } + } else if (payWay == PayWay.ShareToOther) { + shareToOther(url); + } + + setState(() {}); + } + // var data = { + // "userid": UserData().basicInfo.userId, + // "moneytype": 1, + // 'gid': widget.goodsId, + // "payway": payWay, + // }; + // data['sign'] = TokenMgr().getSign(data); + + // Response res = await HttpUtil().post('order/add/goods', data: data); + // Map resData = res.data; + // if (resData['code'] == 0) { + // fluwx.pay( + // appId: resData['data']['WxPayData']['appid'], + // partnerId: resData['data']['WxPayData']['mch_id'], + // prepayId: resData['data']['WxPayData']['prepay_id'], + // packageValue: 'Sign=WXPay', + // nonceStr: resData['data']['WxPayData']['nonce_str'], + // timeStamp: int.parse(resData['data']['WxPayData']['timestamp']), + // sign: resData['data']['WxPayData']['sign'], + // ); + // setState(() {}); + // } + } + + //确定按钮 + Widget _buildConfirmButton() { + Text text = new Text(I18n.of(context).determine, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 18, + color: Colors.white, + textBaseline: TextBaseline.ideographic)); + + LinearGradient gradientColor = new LinearGradient(colors: [ + Colors.blueAccent, + Colors.blueAccent, + ]); + // callback() { + // if (payWay == PayWay.WxH5 || payWay == PayWay.Paypal) { + // addGoods(); + // } + // if (payWay == PayWay.ShareToOther) { + // shareToOther(); + // } + // } + + return new Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + alignment: Alignment.center, + height: 44, + width: 250, + child: ShadowButton().builder(gradientColor, text, addGoods), + ); + } + + shareToOther(url) { + fluwx.WeChatShareWebPageModel model = fluwx.WeChatShareWebPageModel( + scene: fluwx.WeChatScene.SESSION, + webPage: url, + title: '点我代付[${widget.money}元]', + thumbnail: + "http://datasm.chengyouhd.com/Upload/default/icon120.png", + description: '[${UserData().basicInfo.nickName}]正在购买H币,点击帮我支付吧'); + fluwx.share(model); + } + + Widget _buildPayWay() { + Widget wxButton = Radio( + value: PayWay.WxH5, + groupValue: payWay, //当value和groupValue一致的时候则选中 + onChanged: (T) { + setState(() { + payWay = PayWay.WxH5; + }); + }); + + Widget shareToOther = Radio( + value: PayWay.ShareToOther, + groupValue: payWay, //当value和groupValue一致的时候则选中 + onChanged: (T) { + setState(() { + payWay = PayWay.ShareToOther; + }); + }); + // Widget paypalButton = Radio( + // value: PayWay.Paypal, + // groupValue: payWay, //当value和groupValue一致的时候则选中 + // onChanged: (T) { + // setState(() { + // payWay = PayWay.Paypal; + // }); + // }); + return Container( + margin: EdgeInsets.only(left: 30, right: 20), + child: Column( + children: [ + _buildPayWayItem('assets/images/login/vip_wx.png', + I18n.of(context).wechat_pay, wxButton, () { + setState(() { + payWay = PayWay.WxApp; + }); + }), + UserData().deviceLanguage == LanguageType.SimplifiedChinese || + UserData().deviceLanguage == LanguageType.TraditionalChinese + ? _buildPayWayItem('assets/images/login/vip_other.png', + I18n.of(context).other_pay, shareToOther, () { + setState(() { + payWay = PayWay.ShareToOther; + }); + }) + : Container(), +//todo paypal +// _buildPayWayItem('assets/images/login/vip_wx.png', +// 'Paypal', paypalButton, () { +// setState(() { +// payWay = PayWay.paypal.index; +// }); +// }), + + _buildConfirmButton(), + ], + ), + ); + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return new Material( + type: MaterialType.transparency, + child: new Center( + child: new SizedBox( + width: 288.25, + height: 286.6, + child: new Container( + decoration: ShapeDecoration( + color: Color(0xffffffff), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8.0), + ), + ), + ), + child: new Column( + children: [ + _buildTip(), + _buildPayWay(), + ], + ), + ), + ), + ), + ); + } +} + +class ChargeMoney { + static List goodsList = []; + + ///钱包-充值 item + static Widget _buildItem( + leftStr, rightStr, goodsId, appleProductId, BuildContext context) { + return Container( + height: 55, + margin: EdgeInsets.only(left: 15, right: 15), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(width: 1, color: Constants.DividerLineColor))), + child: Row( + children: [ + Container( + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20))), + height: 30, + width: 30, + child: Image.asset('assets/images/coin.png'), + ), + Padding( + padding: EdgeInsets.only(left: 15), + child: Text( + '$leftStr', + textScaleFactor: 1.0, + style: TextStyle(fontSize: 14.41), + ), + ), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: InkWell( + highlightColor: Colors.transparent, + radius: 0, + onTap: () { + if (Platform.isIOS && UserData().bannerZF == 1) { + /// 是ios并且苹果内购开关打开 + MoneyPageState.currentGoodsId = goodsId.toString(); +// showToast('goodsId:$goodsId money:$rightStr appleProductId: $appleProductId'); + ChargeMoney.requestPurchase( + appleProductId.toString(), context); + } else { + showDialog( + context: context, + builder: (BuildContext context) { + return PayWayContent( + goodsId: goodsId, + money: rightStr, + ); + }); + } + }, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + color: Constants.BlueTextColor, + boxShadow: [ + BoxShadow( + color: Constants.BlueTextColor.withOpacity(0.3), + offset: Offset(0, 1.5), + blurRadius: 4.5), + ], + borderRadius: BorderRadius.all( + Radius.circular(Constants.LittleButtonRadius))), + width: 75.85, + height: 28.1, + child: Text( + UserData().language == LanguageType.SimplifiedChinese + ? '¥$rightStr' + : '₫ ${(rightStr / 1000).toInt()}K', + textScaleFactor: 1.0, + textAlign: TextAlign.center, + style: TextStyle(color: Colors.white, fontSize: 13.45), + ), + ), + ))), + ], + ), + ); + } + + ///苹果必须先拉取商品列表FlutterInappPurchase.instance.getProducts ,才可以进行购买 + static void initIAP(List iosProductIdList) async { + print('initIAP ---初始化ios 内购商品列表-start'); + List iapItem = + await FlutterInappPurchase.instance.getProducts(iosProductIdList); + print('initIAP ---初始化ios 内购商品列表-end'); + print('iosProductIdList length ${iapItem.length}'); + } + + static void showChargeSheet(BuildContext context, callback) { + HttpUtil().getMoneyInfo(context, (data) { + goodsList = data; + List list = []; + + List iosProductIdList = []; + + list.addAll(goodsList.map((data) { + print('iosProductIdList data #### : data'); + iosProductIdList.add(data['Id'].toString()); + return _buildItem( + data['Amount'], data['Price'], data['Gid'], data['Id'], context); + }).toList()); + + if (Platform.isIOS) { + initIAP(iosProductIdList); + + ///初始化ios内购 + } + + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return StatefulBuilder( + builder: (BuildContext context, setBottomSheetState) { + return SafeArea( + child: Container( + height: 390, + child: Stack( + children: [ + Container( + margin: EdgeInsets.only(top: 55), + child: ListView( + children: list, + ), + ), + Container( + height: 55, + child: Row( + children: [ + Padding( + padding: EdgeInsets.only(left: 20), + child: Text( + I18n.of(context).recharge, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 18), + ), + ), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + I18n.of(context).mask_coin + + I18n.of(context) + .available_balance + .replaceFirst('/s1', ': '), + textScaleFactor: 1.0, + style: TextStyle( + color: const Color(0xFF595959), + fontSize: 13), + ), + ), + ), + Container( + alignment: Alignment.centerRight, + child: Consumer( + builder: (context, + MoneyChangeProvider counter, child) => + Text( + counter.money.toString(), + textScaleFactor: 1.0, + style: TextStyle( + color: Colors.red, fontSize: 15), + ), + ), + ), + Container( + height: 15, + margin: EdgeInsets.only(left: 12, right: 10), + decoration: BoxDecoration( + border: Border( + left: BorderSide( + color: const Color(0xFF595959)))), + ), + InkWell( + onTap: () { + HttpUtil().getWealth(context, (data) { + callback(); + Provider.of(context) + .initMoney(data['CoinValue']); + setBottomSheetState(() {}); + }); + }, + child: Container( + padding: EdgeInsets.only(right: 6), + child: Icon( + Icons.refresh, + size: 20, + ), + )), + ], + ), + ), + ], + )), + ); + }, + ); + }, + ).then((val) {}); + }); + } + + /// ios内购 请求支付 + static void requestPurchase(String productId, BuildContext context) async { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return LoadingDialog(); + }); + print('_requestPurchase >>>>>>>>>> -- $productId'); +// productId = '1488435000'; + await FlutterInappPurchase.instance + .requestPurchase(productId) + .then((value) { + print('支付结果: $value'); + }).catchError((e) { + print('支付出错结果::: $e'); + }); + } +} diff --git a/lib/utils/CustomUI.dart b/lib/utils/CustomUI.dart new file mode 100644 index 0000000..08f1919 --- /dev/null +++ b/lib/utils/CustomUI.dart @@ -0,0 +1,1251 @@ +import 'dart:io'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/VerificationCenter.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/photo/ui/dialog/not_permission_dialog.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'dart:ui' as ui; +import '../r.dart'; +import 'HttpUtil.dart'; +import 'PicSwiper.dart'; +import 'TutorialOverlay.dart'; +import 'app_navigator.dart'; +import 'conversation_table.dart'; + +class NoKeyboardEditableTextFocusNode extends FocusNode { +// @override +// bool consumeKeyboardToken() { +// return false; +// } +} + +class CustomUI { + static Widget buildPageLoading( + BuildContext context, Widget content, bool isShow) { + return Stack( + children: [ + content, + isShow + ? Scaffold( + backgroundColor: Colors.transparent, + body: LoadingDialog(), + ) + : Container(), + ], + ); + } + + static void showContentDialog( + BuildContext context, int programId, int replyId, int type, callback, + {int replyUserId = 0, + String replyUserName = '', + bool isAd = false, + bool isMyself = false}) { + if (UserData().isMan() && !UserData().isVip && !isMyself) { + showToast(I18n.of(context).cant_comment); + return; + } + if (!UserData().isMan() && !UserData().basicInfo.isAttestation) { + buildNotTrue(context); + return; + } + + Navigator.of(context).push(TutorialOverlay( + child: Scaffold( + backgroundColor: Constants.BlackTextColor.withOpacity(0.0), + body: buildInput(context, programId, replyId, type, callback, + replyUserId: replyUserId, + replyUserName: replyUserName, + isAd: isAd, + isMyself: isMyself)))); + } + + static Widget buildInput( + BuildContext context, int programId, int replyId, int type, callback, + {int replyUserId = 0, + String replyUserName = '', + bool isAd: false, + bool isMyself: false}) { + print('replyUserName $replyUserName'); + var content = ''; + var hitStr = isMyself + ? I18n.of(context).everyone_comment + : I18n.of(context).your_comment; + Widget input = Container( + alignment: Alignment.topCenter, + padding: EdgeInsets.only(left: 10, right: 10, bottom: 2), + color: Colors.white, + child: Row( + children: [ + Flexible( + child: Container( + margin: EdgeInsets.only(bottom: 10, right: 10), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(color: const Color(0xFF0368FF)))), + child: TextField( + keyboardAppearance: Brightness.light, + maxLines: 3, + minLines: 1, + style: TextStyle(textBaseline: TextBaseline.alphabetic), + autofocus: true, + inputFormatters: [ + LengthLimitingTextInputFormatter(30) //限制长度 + ], + decoration: new InputDecoration( + hintText: hitStr, + hintMaxLines: 1, + hintStyle: TextStyle(fontSize: 15), + border: InputBorder.none, + ), + onChanged: (str) { + content = str; + }, + )), + ), + RaisedButton( + color: const Color(0xFF0368FF), + child: Text( + I18n.of(context).send, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white), + ), + onPressed: () async { + content = content.trim(); + if (content == '' || content == null) { + return; + } + if (isAd) { + Map rdata = { + "userId": UserData().basicInfo.userId, + "adId": programId, + }; + rdata['sign'] = TokenMgr().getSign(rdata); + rdata['content'] = content; + + Response res = await HttpUtil().post( + 'adActivity/reply/evaluate', + data: rdata, + isShowLoading: true); + var resData = res.data; + var data = { + 'Pid': resData['data'], + 'UserId': UserData().basicInfo.userId, + 'NickName': UserData().basicInfo.nickName, + 'Type': type, + 'ReplyUserId': replyUserId, + 'ReplyNickName': replyUserName, + 'Content': content + }; + showToast(resData['msg']); + if (resData['code'] == 0) { + Navigator.of(context).pop(); + callback(data); + } + } else { + Map rdata = { + "userId": UserData().basicInfo.userId, + "id": programId, + "type": type, + }; + rdata['sign'] = TokenMgr().getSign(rdata); + rdata['content'] = content; + rdata['replyId'] = replyId; + Response res = await HttpUtil().post('station/reply/comment', + data: rdata, isShowLoading: true); + var resData = res.data; + print('station/reply/comment $resData'); + var data = { + 'Pid': resData['data'], + 'UserId': UserData().basicInfo.userId, + 'NickName': UserData().basicInfo.nickName, + 'Type': type, + 'ReplyUserId': replyUserId, + 'ReplyNickName': replyUserName, + 'Content': content + }; + showToast(resData['msg']); + if (resData['code'] == 0) { + Navigator.of(context).pop(); + callback(data); + } + } + }, + ) + ], + ), + ); + Widget button = Expanded( + child: InkWell( + highlightColor: Colors.transparent, + radius: 0, + onTap: () { + Navigator.pop(context); + }, + ), + ); + return Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + button, + input, + ], + ); + } + + static void buildNotTrue(BuildContext context) { + buildOneConfirm(context, I18n.of(context).after_authenticate, + I18n.of(context).authenticate_now, () { + Navigator.pop(context); + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return VerificationCenterPage(); + }, + ), + ); + }); + } + + static Widget buildCancleBotton(title, callback) { + return InkWell( + onTap: callback, + child: Container( + decoration: BoxDecoration( + color: const Color(0XFFC7E5FF), + borderRadius: BorderRadius.all( + Radius.circular(Constants.LittleButtonRadius))), + margin: EdgeInsets.only(top: 0, bottom: 18.5), + height: 37.5, + width: 200, + alignment: Alignment.center, + child: fixedText( + title, + fontSize: 15, + color: const Color(0xFF5781A6), + )), + ); + } + + static Widget _buildContentTip(tipTitle) { + return tipTitle == '' + ? Container() + : Container( + padding: EdgeInsets.only(top: 38.5, bottom: 31.5), + child: Text( + tipTitle, + textScaleFactor: 1.0, + + style: TextStyle( + fontSize: 14, color: Constants.BlackTextColor, height: 1.30), + //textAlign: TextAlign.center, + )); + } + + static Widget buildConfirmContent(tip, content) { + return Container( + padding: EdgeInsets.only(left: 40, right: 40), + child: Column( + children: [tip, content], + ), + ); + } + + static Widget buildImgLoding(context, url) { + return Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Constants.BlueTextColor))); + } + + static Widget buildConfirmBotton(title, callback) { + return InkWell( + onTap: callback, + child: Container( + decoration: Constants.ConfirmBUttonBoxDecoration, + height: 37.5, + width: 200, + alignment: Alignment.center, + child: fixedText( + title, + fontSize: 15, + color: Colors.white, + )), + ); + } + + static void buildOneConfirm( + BuildContext context, String tipTitle, String buttonTitle, callback, + {title = '', failcallbak}) { + var confirm = buildConfirmBotton(buttonTitle, callback); + buildTip(context, title, + buildConfirmContent(_buildContentTip(tipTitle), confirm), + failcallbak: failcallbak); + } + + static void buildContacts( + BuildContext context, String tipTitle, String buttonTitle, callback, + {title = '', failcallbak}) { + var confirm = buildConfirmBotton(buttonTitle, callback); + buildTip( + context, + title, + buildConfirmContent( + Container( + padding: EdgeInsets.only(top: 38.5, bottom: 31.5), + child: Column( + children: [ + Text( + tipTitle, + textScaleFactor: 1.0, + + style: TextStyle( + fontSize: 14, + color: Constants.BlackTextColor, + height: 1.30), + //textAlign: TextAlign.center, + ), + SizedBox( + height: 5, + ), + GestureDetector( + child: Text( + I18n.of(context).privacy, + style: TextStyle(color: Colors.blue, fontSize: 14), + ), + onTap: () { + launch( + 'http://datechatagent.chengyouhd.com/zh-CN/Home/Privacy?language=${UserData().language}'); + }, + ) + ], + )), + confirm), + failcallbak: failcallbak); + } + + static Widget buildNoData(BuildContext context, {String str, double height}) { + if (height == null) { + height = MediaQuery.of(context).size.height * 0.8; + } + return Container( + width: MediaQuery.of(context).size.width, + height: height, + alignment: Alignment.center, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + child: Icon( + IconData( + 0xe869, + fontFamily: 'iconfont', + ), + size: 60, + color: Constants.BlueTextColor, + )), + Container( + alignment: Alignment.center, + child: fixedText(str != null ? str : I18n.of(context).no_data, + color: Constants.BlueTextColor)), + ], + )); + } + + static Widget buildImgCover( + int imgId, + List pics, + String imgUrl, + double width, + double raduis, + bool isWatch, + BuildContext context, + int type, + {bool isMyself = false, + int payStatus = 0, + int state = 1}) { + Color color = isWatch + ? const Color(0xFF999999) + : const Color(0xFFFB5656); //const Color(0xfffb5656); + + String bottomStr = ''; + if (type == PhotoType.money.index) { + bottomStr = I18n.of(context).red_photo; + } else if (type == PhotoType.destroyMoney.index) { + bottomStr = I18n.of(context).red_photo; //I18n.of(context).red_photo1; + } else if (type == PhotoType.destroy.index) { + bottomStr = + isWatch ? I18n.of(context).destroyed : I18n.of(context).destroy_after; + } + + double opacity = 0.5; + + Widget normalCover = isMyself && state == 0 + ? Positioned( + right: 5, + top: 5, + child: Container( + alignment: Alignment.center, + width: width, + height: width, + decoration: BoxDecoration( + color: Colors.black.withOpacity(opacity), + borderRadius: BorderRadius.all(Radius.circular(raduis - 2))), + child: Text(I18n.of(context).reviewing, + textAlign: TextAlign.center, + textScaleFactor: 1.0, + style: TextStyle(fontSize: 12, color: Colors.white)), + ), + ) + : Container( + width: width, + height: width, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey[300], width: 1), + borderRadius: BorderRadius.circular(raduis)), + ); + + return InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return PicSwiper( + id: imgId, + pics: pics, + ); + }, + ), + ); + }, + child: Stack( + alignment: Alignment.center, + children: [ + Container( + decoration: + BoxDecoration(borderRadius: BorderRadius.circular(2.0)), + width: width, + height: width, + margin: EdgeInsets.all(5), + child: ClipRRect( + borderRadius: BorderRadius.circular(raduis), + child: CachedNetworkImage( + imageUrl: imgUrl == null ? "" : imgUrl, + placeholder: CustomUI.buildImgLoding, + fit: BoxFit.cover, + ), + )), + (type == PhotoType.free.index || + (!isMyself && + type == PhotoType.money.index && + payStatus == 1)) + ? normalCover + : Stack( + alignment: Alignment.center, + children: [ + Container( + width: width, + height: width, + decoration: BoxDecoration( + border: Border.all(color: color, width: 1), + borderRadius: BorderRadius.circular(raduis), + ), + margin: EdgeInsets.all(5), + child: ClipRRect( + borderRadius: BorderRadius.circular(raduis), + child: BackdropFilter( + //背景滤镜器 + filter: ui.ImageFilter.blur( + sigmaX: 10.0, + sigmaY: 10.0), //图片模糊过滤,横向竖向都设置5.0 + child: Opacity( + //透明控件 + opacity: isMyself ? 0 : 0.5, + child: Container( + decoration: BoxDecoration( + border: Border.all(color: color, width: 0), + borderRadius: BorderRadius.circular(0), + ), + alignment: Alignment.center, + ), + ), + )), + ), + isMyself && state == 0 + ? Positioned( + right: 6, + top: 6, + child: Container( + alignment: Alignment.center, + width: width - 2, + height: width - 2, + decoration: BoxDecoration( + color: Colors.black.withOpacity(opacity), + borderRadius: BorderRadius.all( + Radius.circular(raduis - 1))), + child: Text(I18n.of(context).reviewing, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 12, color: Colors.white)), + ), + ) + : Text(''), + Positioned( + left: 0, + top: 0, + child: Container( + width: 18, + height: 18, + margin: EdgeInsets.all(5), + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(raduis), + bottomRight: Radius.circular(raduis))), + child: Icon( + IconData( + type == PhotoType.money.index ? 0xe632 : 0xe634, + fontFamily: 'iconfont', + ), + color: Colors.white, + size: 15, + ), + ), + ), + Positioned( + bottom: 6, + child: Container( + width: width - 2, + padding: EdgeInsets.only( + bottom: 1, top: 2, left: 5, right: 5), + decoration: isMyself + ? BoxDecoration( + color: Colors.red.withOpacity(0.7), + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(raduis - 1), + bottomRight: + Radius.circular(raduis - 1))) + : BoxDecoration(), + child: Text(bottomStr, + textScaleFactor: 1.0, + textAlign: TextAlign.center, + style: TextStyle( + color: isMyself ? Colors.white : color, + fontSize: 10)), + )), + ], + ), + ], + )); + } + + static void buildTowConfirm( + BuildContext context, + String tipTitle, + String confirmButtonTitle, + confirmCallback, + cancleButtonTitle, + cancleCallback, + {title = ''}) { + var confirm = buildConfirmBotton(confirmButtonTitle, confirmCallback); + var cancle = buildCancleBotton(cancleButtonTitle, cancleCallback); + buildTip( + context, + title, + buildConfirmContent( + _buildContentTip(tipTitle), + Column( + children: [cancle, confirm], + ))); + } + + static Widget buildTipContent( + BuildContext context, String tips, Widget content, + {failcallbak}) { + return Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Stack( + children: [ + Container( + padding: EdgeInsets.only(bottom: 25), + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10.0)), + width: MediaQuery.of(context).size.width * 0.91, + child: Column( + children: [ + tips == '' + ? Container() + : Container( + margin: + EdgeInsets.only(top: 15.5, left: 40, right: 40), + padding: EdgeInsets.only(bottom: 10.5), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Constants.DividerLineColor))), + alignment: Alignment.center, + child: Text( + tips, + textScaleFactor: 1.0, + style: TextStyle( + color: Constants.BlackTextColor, + fontSize: 16.5, + fontWeight: FontWeight.w400), + textAlign: TextAlign.center, + ), + ), + content + ], + ), + ), + Positioned( + top: -40, + right: 0, + child: InkWell( + highlightColor: Colors.transparent, + radius: 0, + onTap: () { + Navigator.of(context).pop(); + if (failcallbak != null) failcallbak(); + }, + child: Container( + width: 40, + height: 40, + alignment: Alignment.center, + margin: EdgeInsets.only(top: 36.5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(50.0)), + child: Icon( + // IconData( + // 0xe679, + // fontFamily: 'iconfont', + // ), + Icons.close, + color: Colors.grey[700], + size: 24, + ), + ))) + ], + ) + ])); + // return Container( + // child: Column( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Container( + // padding: EdgeInsets.only(bottom: 25), + // alignment: Alignment.center, + // decoration: BoxDecoration( + // color: Colors.white, borderRadius: BorderRadius.circular(10.0)), + // width: MediaQuery.of(context).size.width * 0.91, + // child: Column( + // children: [ + // tips == '' + // ? Container() + // : Container( + // margin: EdgeInsets.only(top: 15.5, left: 40, right: 40), + // padding: EdgeInsets.only(bottom: 10.5), + // decoration: BoxDecoration( + // border: Border( + // bottom: BorderSide( + // color: Constants.DividerLineColor))), + // alignment: Alignment.center, + // child: Text( + // tips, + // textScaleFactor: 1.0, + // style: TextStyle( + // color: Constants.BlackTextColor, + // fontSize: 16.5, + // fontWeight: FontWeight.w400), + // textAlign: TextAlign.center, + // ), + // ), + // content + // ], + // ), + // ), + // InkWell( + // highlightColor: Colors.transparent, + // radius: 0, + // onTap: () { + // Navigator.of(context).pop(); + // if (failcallbak != null) failcallbak(); + // }, + // child: Container( + // width: 40, + // height: 40, + // alignment: Alignment.center, + // margin: EdgeInsets.only(top: 36.5), + // decoration: BoxDecoration( + // color: Colors.white, + // borderRadius: BorderRadius.circular(50.0)), + // child: Icon( + // IconData( + // 0xe679, + // fontFamily: 'iconfont', + // ), + // size: 20, + // ), + // )) + // ])); + } + + static void buildTip(BuildContext context, String tips, Widget content, + {failcallbak}) { + Navigator.of(context).push(TutorialOverlay( + child: + buildTipContent(context, tips, content, failcallbak: failcallbak))); + } + + static Future showIosDialog(BuildContext context, String title, + Function sureFunction, Function cancelFunction) async { + bool isDismiss = await showDialog( + context: context, + builder: (context) { + return CupertinoAlertDialog( + title: fixedText(title), + actions: [ + CupertinoDialogAction( + child: fixedText(I18n.of(context).determine), + onPressed: sureFunction), + CupertinoDialogAction( + child: fixedText(I18n.of(context).cancel), + onPressed: cancelFunction), + ], + ); + }); + return isDismiss; + } + + static Widget buildTopTip(double leftPadding, str, + {double fontSize = 15, bool showStar = false}) { + return Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border(bottom: Constants.GreyBorderSide)), + margin: EdgeInsets.only(top: 20), + padding: EdgeInsets.only(left: leftPadding, top: 8, bottom: 8), + alignment: Alignment.centerLeft, + child: Row( + children: [ + showStar + ? Padding( + padding: EdgeInsets.only(top: 2, right: 2), + child: Text( + '*', + style: TextStyle(color: Colors.red), + )) + : Text(''), + Container( + width: Screen.width - leftPadding * 2, + child: Text(str, + textScaleFactor: 1.0, + style: TextStyle( + color: Constants.BlackTextColor, + fontSize: fontSize, + fontWeight: FontWeight.w500)), + ) + ], + ), + ); + } + + static Widget buildAudioContaniner(double height) { + return ClipRRect( + borderRadius: BorderRadius.circular(2.5), + child: Container( + height: height, + color: const Color(0xFF04A4FE), + width: 5, + ), + ); + } + + static Widget buildBox(nums, str) { + return Container( + width: (Screen.width - 80) / 3, + child: Column( + children: [ + Container( + alignment: Alignment.center, + margin: EdgeInsets.only(top: 10), + width: 58.1, + height: 24.85, + decoration: BoxDecoration( + color: nums > 0 ? Constants.BlueTextColor : Colors.grey[200], + borderRadius: + BorderRadius.circular(Constants.LittleButtonRadius)), + child: Text( + nums > 99 ? '99+' : nums.toString(), + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 17.76, + color: nums > 0 ? Colors.white : Colors.grey), + ), + ), + Container( + margin: EdgeInsets.only(top: 5), + alignment: Alignment.center, + child: Text( + str, + textScaleFactor: 1.0, + style: TextStyle(color: Constants.BlackTextColor, fontSize: 12), + ), + ), + ], + ), + ); + } + + static Future _willPop(BuildContext context, bool isForceUpdate) async { + print('_willPop $isForceUpdate'); + if (isForceUpdate) { + await SystemChannels.platform.invokeMethod('SystemNavigator.pop'); + } else { + Navigator.pop(context); + } + + return null; + } + + static void buildVersionUpdate( + BuildContext context, + String versionName, + + ///版本号 + bool isForceUpdate, + + ///强制升级 + String describe, + + ///版本描述 + ValueNotifier updateProgress, + + ///进度更新 + Function go + + ///点击开始体验回调 + ) { + Navigator.of(context).push(TutorialOverlay( + child: WillPopScope( + child: Container( + alignment: Alignment.center, + width: 296, + child: Container( + width: 296, + height: 387, + child: Stack( + children: [ + Positioned( + top: 10, + child: Container( + height: 307, + width: 296, + child: Column( + children: [ + SizedBox( + height: 75, + ), + Container( + padding: EdgeInsets.fromLTRB(20, 10, 20, 10), + height: 161, + width: 296, + child: SingleChildScrollView( + child: Text( + describe ?? '', + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w300), + ), + ), + ), + ValueListenableBuilder( + builder: (BuildContext context, String value, + Widget child) { + return value == '-1' + ? GestureDetector( + onTap: go, + child: Container( + alignment: Alignment.center, + width: 164, + height: 40, + child: Text( + I18n.of(context).test_it, + style: TextStyle( + fontWeight: FontWeight.w500, + color: Colors.white, + fontSize: 17), + ), + decoration: BoxDecoration( + color: Color(0xff3875E9), + borderRadius: + BorderRadius.all( + Radius.circular( + 3.0))), + ), + ) + : Container( + alignment: Alignment.center, + width: 164, + height: 40, + child: Stack( + children: [ + SizedBox( + //限制进度条的高度 + height: 40, + //限制进度条的宽度 + width: 164, + child: ClipRRect( + borderRadius: + BorderRadius.all( + Radius.circular( + 3.0)), + child: + LinearProgressIndicator( + + //0~1的浮点数,用来表示进度多少;如果 value 为 null 或空,则显示一个动画,否则显示一个定值 + value: double.parse( + value) / + 100, + //背景颜色 + backgroundColor: + Color( + 0xff4E5D7A), + //进度颜色 + valueColor: + new AlwaysStoppedAnimation< + Color>( + Color( + 0xff65A5FC))), + ), + ), + Container( + alignment: Alignment.center, + child: Text( + '$value %', + style: TextStyle( + fontWeight: + FontWeight.w500, + color: Colors.white, + fontSize: 19), + ), + ) + ], + ), + decoration: BoxDecoration( + color: Color(0xff3875E9), + borderRadius: BorderRadius.all( + Radius.circular(3.0))), + ); + }, + valueListenable: updateProgress, + ) + ], + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12)))), + Container( + height: 81, + child: Stack( + children: [ + Image.asset( + R.assetsImagesImgUpdateBg, + height: 81, + ), + Positioned.fill( + child: Align( + alignment: Alignment.center, + child: Text( + '${I18n.of(context).found_new} ($versionName)', + style: + TextStyle(color: Colors.white, fontSize: 18), + ), + )), + Positioned.fill( + child: Offstage( + offstage: isForceUpdate, + child: Align( + alignment: Alignment.topRight, + child: Container( + width: 50, + height: 50, + child: GestureDetector( + onTap: () { + Navigator.of(context).pop(); + }, + child: Icon( + IconData( + 0xe679, + fontFamily: 'iconfont', + ), + size: 16, + color: Color(0xffa4c1fe), + ), + ), + ), + ), + )) + ], + ), + ) + ], + ), + ), + ), + onWillPop: () => _willPop(context, isForceUpdate)))); + } + + ///访问相册权限 + static Future showPhotoPermissionSetting(BuildContext context) async { + return showPermissionSetting( + context, + Platform.isAndroid ? PermissionGroup.storage : PermissionGroup.photos, + Platform.isAndroid + ? I18n.of(context).location_permission + : I18n.of(context).photo_permission); + } + + ///权限申请被拒后 弹窗提示到设置界面打开 + static Future showPermissionSetting(BuildContext context, + PermissionGroup permissionGroup, String tips) async { + final PermissionStatus addStatus = + await PermissionHandler().checkPermissionStatus(permissionGroup); + print('check :$permissionGroup addStatus: $addStatus'); + if (addStatus == PermissionStatus.granted) { + return true; + } else { + /// ios第一次-发起询问权限 || android 第一次发起请求或者被拒过 + if (addStatus == PermissionStatus.unknown || + (addStatus == PermissionStatus.denied && Platform.isAndroid)) { + Map permissionRequestResult = + await PermissionHandler().requestPermissions([permissionGroup]); + + PermissionStatus status = permissionRequestResult[permissionGroup]; + print('status: $status'); + if (status == PermissionStatus.granted) { + return true; + } else { + var result = await showDialog( + context: context, + builder: (ctx) => NotPermissionDialog(tips), + ); + if (result == true) { + PermissionHandler().openAppSettings(); + } + + return false; + } + } else { + ///被用户禁用,所以弹窗去设置打开权限 + var result = await showDialog( + context: context, + builder: (ctx) => NotPermissionDialog(tips), + ); + if (result == true) { + PermissionHandler().openAppSettings(); + } + + return false; + } + } + } + + goScanPage(BuildContext context) async { + if (await CustomUI.showPermissionSetting( + context, PermissionGroup.camera, I18n.of(context).camera_permission)) { + AppNavigator.pushScannerPage(context); + } + } + + getSearchResult(String searchKey, List sourceList) { + List res = []; + for (var i = 0; i < sourceList.length; i++) { + var friendModel = sourceList[i]; + if ((friendModel.refName != null && + friendModel.refName.contains(searchKey)) || + friendModel.name.contains(searchKey)) { + res.add(friendModel); + } + } + return res; + } + + getGroupSearchResult( + String searchKey, List sourceList, Map refMap) { + List res = []; + for (var i = 0; i < sourceList.length; i++) { + var groupModel = sourceList[i]; + if ((groupModel.name.contains(searchKey)) || + groupModel.getGroupName(refMap).contains(searchKey)) { + res.add(groupModel); + } + } + return res; + } + + static Widget buildLoaingAnim(BuildContext context, + {String str, double height}) { + if (height == null) { + height = MediaQuery.of(context).size.height * 0.8; + } + return InkWell( + onTap: null, + child: Container( + width: MediaQuery.of(context).size.width, + height: height, + alignment: Alignment.topCenter, + child: Container( + width: 40, + height: 40, + margin: EdgeInsets.only(top: 20), + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + boxShadow: [ + BoxShadow(blurRadius: 3.0, color: Colors.black26) + ]), + child: new CircularProgressIndicator( + strokeWidth: 2, + ), + ))); + } + + static Widget buildLoadingFooter() { + return CustomFooter( + builder: (BuildContext context, LoadStatus mode) { + Widget body = Container(); + if (mode == LoadStatus.idle) { + //body = Text("pull up load"); + } else if (mode == LoadStatus.loading) { + body = CupertinoActivityIndicator(); + } else if (mode == LoadStatus.failed) { + //body = Text("Load Failed!Click retry!"); + } else if (mode == LoadStatus.canLoading) { + //body = Text("release to load more"); + } else { + //body = Text("No more Data"); + } + return Container( + //height: 50.0, + child: Center(child: body), + ); + }, + ); + } + + static PreferredSizeWidget buildSearchButton(BuildContext context, callback) { + return PreferredSize( + preferredSize: Size.fromHeight(49), + child: InkWell( + onTap: callback, + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.only(bottom: 14, left: 12.5, right: 12.5), + height: 35, + decoration: BoxDecoration( + color: const Color(0xFFEEEEEE), + borderRadius: BorderRadius.all(Radius.circular(8))), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + margin: EdgeInsets.only(left: 15, right: 15), + child: Icon( + IconData( + 0xe664, + fontFamily: Constants.IconFontFamily, + ), + color: const Color(0xFFA0A0A0), + size: 18, + ), + ), + Text(I18n.of(context).search, + style: TextStyle(fontSize: 14.5, color: Colors.grey)), + ], + ))), + ); + } + + static Widget buildCustomLeading(BuildContext context, + {onTap, double iconPadding = 10}) { + return InkWell( + onTap: onTap == null + ? () { + Navigator.of(context).pop(); + } + : onTap, + child: Container( + margin: + EdgeInsets.only(top: 2, left: iconPadding, right: iconPadding), + child: Image.asset( + 'assets/images/back.png', + scale: 2, + )), + ); + } + + static Widget buildImageLabel(String url, int nums, + {bool isLeft = true, double imgOpc = 0.6, double imgHeight = 14}) { + double radius = 2.75; + return Container( + margin: EdgeInsets.only(top: 16, bottom: 14), + height: 18.5, + constraints: BoxConstraints(minWidth: 30), + decoration: BoxDecoration( + color: const Color(0xFFF0F0F0), + borderRadius: isLeft + ? BorderRadius.only( + topLeft: Radius.circular(radius), + bottomLeft: Radius.circular(radius)) + : BorderRadius.only( + topRight: Radius.circular(radius), + bottomRight: Radius.circular(radius))), + child: Row( + children: [ + Container( + margin: EdgeInsets.only(top: 2.5, bottom: 2.5), + width: !isLeft ? 0.5 : 0, + color: const Color(0xFFDEDEDE), + ), + Opacity( + opacity: imgOpc, + child: Container( + height: imgHeight, + margin: EdgeInsets.only(left: 5.5), + child: Image.asset(url))), + Opacity( + opacity: 0.8, + child: Container( + margin: EdgeInsets.only(left: 7, right: 7), + child: Text( + nums.toString(), + style: + TextStyle(color: const Color(0xFF4C4C4C), fontSize: 12), + ))), + ], + ), + ); + } +} diff --git a/lib/utils/DropDownMemu.dart b/lib/utils/DropDownMemu.dart new file mode 100644 index 0000000..7720196 --- /dev/null +++ b/lib/utils/DropDownMemu.dart @@ -0,0 +1,338 @@ +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; + +class GZXDropdownMenuController extends ChangeNotifier { + double dropDownHearderHeight; + + int menuIndex = 0; + + bool isShow = false; + + void show(int index) { + isShow = true; + menuIndex = index; + notifyListeners(); + } + + void hide() { + isShow = false; + notifyListeners(); + } +} + +typedef OnItemTap = void Function(T value); + +class GZXDropDownHeader extends StatefulWidget { + final Color color; + final double borderWidth; + final Color borderColor; + final TextStyle style; + final TextStyle dropDownStyle; + final double iconSize; + final Color iconColor; + final Color iconDropDownColor; + +// final List menuStrings; + final double height; + final double dividerHeight; + final Color dividerColor; + final GZXDropdownMenuController controller; + final OnItemTap onItemTap; + final List items; + final GlobalKey stackKey; + + GZXDropDownHeader({ + Key key, + @required this.items, + @required this.controller, + @required this.stackKey, + this.style = const TextStyle(color: Color(0xFF666666), fontSize: 13), + this.dropDownStyle, + this.height = 40, + this.iconColor = const Color(0xFFafada7), + this.iconDropDownColor, + this.iconSize = 20, + this.borderWidth = 0, + this.borderColor = const Color(0xFFeeede6), + this.dividerHeight = 20, + this.dividerColor = const Color(0xFFeeede6), + this.onItemTap, + this.color = Colors.white, + }) : super(key: key); + + @override + _GZXDropDownHeaderState createState() => _GZXDropDownHeaderState(); +} + +class _GZXDropDownHeaderState extends State + with SingleTickerProviderStateMixin { + bool _isShowDropDownItemWidget = false; + + int _menuCount; + GlobalKey _keyDropDownHearder = GlobalKey(); + + @override + void initState() { + + super.initState(); + + widget.controller.addListener(_onController); + } + + _onController() { +// print(widget.controller.menuIndex); + } + + @override + Widget build(BuildContext context) { +// print('_GZXDropDownHeaderState.build'); + + _menuCount = widget.items.length; + + var gridView = GridView.count( + physics: new NeverScrollableScrollPhysics(), + crossAxisCount: _menuCount, + childAspectRatio: (Screen.width / _menuCount) / widget.height, + children: widget.items.map((item) { + return _menu(item); + }).toList(), + ); + + return Container( + key: _keyDropDownHearder, + height: widget.height, + margin: EdgeInsets.zero, + padding: EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + border: + Border.all(color: widget.borderColor, width: widget.borderWidth), + ), + child: gridView, + ); + } + + dispose() { + super.dispose(); + } + + _menu(GZXDropDownHeaderItem item) { + int index = widget.items.indexOf(item); + int menuIndex = widget.controller.menuIndex; + _isShowDropDownItemWidget = index == menuIndex && widget.controller.isShow; + + return GestureDetector( + onTap: () { + final RenderBox overlay = + widget.stackKey.currentContext.findRenderObject(); + + final RenderBox dropDownItemRenderBox = + _keyDropDownHearder.currentContext.findRenderObject(); + + var position = + dropDownItemRenderBox.localToGlobal(Offset.zero, ancestor: overlay); +// print("POSITION : $position "); + var size = dropDownItemRenderBox.size; +// print("SIZE : $size"); + + widget.controller.dropDownHearderHeight = size.height + position.dy; + + if (widget.controller.isShow) { + widget.controller.hide(); + } else { + widget.controller.show(index); + } + if (widget.onItemTap != null) { + widget.onItemTap(index); + } + setState(() {}); + }, + child: Container( + color: widget.color, + width: Screen.width/3-20, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Text( + item.title, textScaleFactor: 1.0, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: _isShowDropDownItemWidget + ? widget.dropDownStyle + ??TextStyle(color: Theme.of(context).primaryColor, fontSize: 13) + : widget.style, + )), + Icon( + !_isShowDropDownItemWidget + ? item.iconData ?? Icons.arrow_drop_down + : item.iconData ?? Icons.arrow_drop_up, + color: _isShowDropDownItemWidget + ? widget.iconDropDownColor ?? Theme.of(context).primaryColor + : widget.iconColor, + size: item.iconSize ?? widget.iconSize, + ), + ], + ), + ) + ], + )), + ); + } +} + +class GZXDropDownHeaderItem { + final String title; + final IconData iconData; + final double iconSize; + + GZXDropDownHeaderItem( + this.title, { + this.iconData, + this.iconSize, + }); +} + +class GZXDropdownMenuBuilder { + final Widget dropDownWidget; + final double dropDownHeight; + final callback; + + GZXDropdownMenuBuilder( + {@required this.dropDownWidget, + @required this.dropDownHeight, + @required this.callback}); +} + +class GZXDropDownMenu extends StatefulWidget { + final GZXDropdownMenuController controller; + final List menus; + final int animationMilliseconds; + + const GZXDropDownMenu( + {Key key, + @required this.controller, + @required this.menus, + this.animationMilliseconds = 100}) + : super(key: key); + + @override + _GZXDropDownMenuState createState() => _GZXDropDownMenuState(); +} + +class _GZXDropDownMenuState extends State + with SingleTickerProviderStateMixin { + bool _isShowDropDownItemWidget = false; + bool _isShowMask = false; + bool _isControllerDisposed = false; + Animation _animation; + AnimationController _controller; + + @override + void initState() { + + super.initState(); + + widget.controller.addListener(_onController); + _controller = new AnimationController( + duration: Duration(milliseconds: widget.animationMilliseconds), + vsync: this); + } + + _onController() { +// print('_GZXDropDownMenuState._onController ${widget.controller.menuIndex}'); + + _showDropDownItemWidget(); + } + + @override + Widget build(BuildContext context) { +// print('_GZXDropDownMenuState.build'); + _controller.duration = Duration(milliseconds: widget.animationMilliseconds); + return _buildDropDownWidget(); + } + + dispose() { + _controller.dispose(); + _isControllerDisposed = true; + super.dispose(); + } + + _showDropDownItemWidget() { + int menuIndex = widget.controller.menuIndex; + if (menuIndex >= widget.menus.length || widget.menus[menuIndex] == null) { + return; + } + + _isShowDropDownItemWidget = !_isShowDropDownItemWidget; + _isShowMask = !_isShowMask; + + _animation = + new Tween(begin: 0.0, end: widget.menus[menuIndex].dropDownHeight) + .animate(_controller) + ..addListener(() { + //这行如果不写,没有动画效果 + setState(() {}); + }); + + if (_isControllerDisposed) return; + + if (_animation.status == AnimationStatus.completed) { + _controller.reverse(); + } else { + _controller.forward(); + } + } + + _hideDropDownItemWidget() { + _isShowDropDownItemWidget = !_isShowDropDownItemWidget; + _isShowMask = !_isShowMask; + _controller.reverse(); + widget.controller.isShow = false; + } + + Widget _mask(callback) { + if (_isShowMask) { + return GestureDetector( + onTap: () { + print('到mask了'); + _hideDropDownItemWidget(); + if (callback != null) callback(); + }, + child: Container( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 2, + color: Color.fromRGBO(0, 0, 0, 0.1), + ), + ); + } else { + return Container( + height: 0, + ); + } + } + + Widget _buildDropDownWidget() { + int menuIndex = widget.controller.menuIndex; + + return Positioned( + width: MediaQuery.of(context).size.width, + top: widget.controller.dropDownHearderHeight, + left: 0, + child: Column( + children: [ + Container( + color: Colors.white, + width: MediaQuery.of(context).size.width, + height: _animation == null ? 0 : _animation.value, + child: widget.menus[menuIndex].dropDownWidget, + ), + _mask(widget.menus[menuIndex].callback) + ], + )); + } +} diff --git a/lib/utils/FullWithButton.dart b/lib/utils/FullWithButton.dart new file mode 100644 index 0000000..9c79f01 --- /dev/null +++ b/lib/utils/FullWithButton.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; +import '../data/constants.dart' show Constants, AppColors; + +class FullWidthButton extends StatelessWidget { + static const Hor_Padding = 5.0; + static const Ver_Padding = 10.0; + + final String title; + final bool showDivider; + final VoidCallback onPressed; + final String description; + final Color descriptionColor; + final bool showRightIcon; + + final Widget extendWidget; + + const FullWidthButton( + {@required this.title, + this.description = '', + @required this.onPressed, + this.descriptionColor, + this.showRightIcon: true, + this.showDivider: false, + this.extendWidget + }) + : assert(title != null), + assert(onPressed != null); + + @override + Widget build(BuildContext context) { + final pureButton = Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(width: Hor_Padding), + Expanded( + child: Text( + title, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal + ), + ), + ), + extendWidget!=null?extendWidget: Text( + description, + textScaleFactor: 1.0, + textAlign: TextAlign.end, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.normal, + color: descriptionColor == null + ? const Color(0xFF818181) + : descriptionColor), + ), + showRightIcon + ? Padding( + padding: EdgeInsets.only(bottom: 1.5), + child: Icon( + IconData(0xe63c, fontFamily: 'iconfont'), + size: 20.0, + color: Color(AppColors.TabIconNormal), + )) + : Padding(padding: EdgeInsets.only(right: 7)), + ], + ); + + final borderButton = Container( + decoration: BoxDecoration( + border: Border( + bottom: Constants.GreyBorderSide, + ), + ), + padding: EdgeInsets.only( + bottom: Ver_Padding, + ), + child: pureButton, + ); + + return FlatButton( + onPressed: () { + this.onPressed(); + }, + padding: EdgeInsets.only( + left: Hor_Padding, + right: Hor_Padding, + top: Ver_Padding, + bottom: showDivider ? 0.0 : Ver_Padding, + ), + color: Colors.white, + child: showDivider ? borderButton : pureButton, + ); + } +} diff --git a/lib/utils/HttpUtil.dart b/lib/utils/HttpUtil.dart new file mode 100644 index 0000000..41070f2 --- /dev/null +++ b/lib/utils/HttpUtil.dart @@ -0,0 +1,1390 @@ +import 'dart:convert'; + +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/EditData.dart'; +import 'package:chat/home/IndexPage.dart'; +import 'package:chat/home/MoneyPage.dart'; +import 'package:chat/home/SelectSexPage.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/models/daily_bonus.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/NetUtil.dart'; +import 'package:chat/utils/blacklist_mgr.dart'; +import 'package:chat/utils/friend_list_mgr.dart'; +import 'package:chat/utils/image_util.dart'; +import 'package:chat/utils/local_notification_util.dart'; +import 'package:chat/utils/sp_utils.dart'; +import 'package:chat/utils/sql_util.dart'; +import 'package:chat/utils/user_info_table.dart'; +import 'dart:core'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'dart:io'; +import '../data/UserData.dart'; +import '../utils/TokenMgr.dart'; +import 'package:http_parser/http_parser.dart'; + +class HttpUtil { + static HttpUtil _instance; + Dio dio; + BaseOptions options; + + //static const String BaseUrl = 'http://192.168.0.223:7001/'; + //static const String BaseUrl = 'http://192.168.0.207:9080/'; + static const String BaseUrl = 'http://120.79.107.63:9080/'; + //static const String BaseUrl = 'http://192.168.0.177:9016/'; + //static const String BaseUrl = 'https://datasm.chengyouhd.com/'; + + static HttpUtil _getInstance() { + if (_instance == null) { + _instance = HttpUtil._(); + } + return _instance; + } + + factory HttpUtil() => _getInstance(); + Map friendCache = {}; + + HttpUtil._() { + options = BaseOptions( + baseUrl: BaseUrl, + headers: {}, + ); + dio = new Dio(options); + +// (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = +// (HttpClient client) { +// client.findProxy = (uri) { +// //proxy all request to localhost:8888 +// return "PROXY 192.168.0.181:8888"; +// }; +// client.badCertificateCallback = +// (X509Certificate cert, String host, int port) => true; +// }; + + dio.interceptors + .add(InterceptorsWrapper(onRequest: (RequestOptions options) async { + // Do something before request is sent + return options; //continue + // If you want to resolve the request with some custom data, + // you can return a `Response` object or return `dio.resolve(data)`. + // If you want to reject the request with a error message, + // you can return a `DioError` object or return `dio.reject(errMsg)` + }, onResponse: (Response response) async { + // Do something with response data + return response; // continue + }, onError: (DioError e) async { + // Do something with response error + showToast(I18n.of(LoadingManage.context).net_error); + return e; //continue + })); + } + + Future get(url, {data, options, cancelToken}) async { + print('get请求启动! url:$url ,body: $data'); + Response response; + try { + response = await dio.get( + url, + queryParameters: data, + cancelToken: cancelToken, + ); + print('get请求成功!$url'); + } on DioError catch (e) { + if (CancelToken.isCancel(e)) { + print('get请求取消! ' + e.message); + } + print('get请求发生错误:$e'); + } + return response; + } + + getFriendList(callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('friendship/friends/list', data: data); + + Map resData = res.data; + + if (resData['code'] == 0) { + if (callback != null) callback(resData['data']); + } + } + + Future getDataWX(url, {data, options, cancelToken}) async { + print('get请求启动! url:$url ,body: $data'); + Response response; + BaseOptions options = BaseOptions( + headers: {}, + ); + Dio dio = new Dio(options); + try { + response = await dio.get( + url, + queryParameters: data, + cancelToken: cancelToken, + ); + print('get请求成功!$url'); + } on DioError catch (e) { + if (CancelToken.isCancel(e)) { + print('get请求取消! ' + e.message); + } + print('get请求发生错误:$e'); + } + return response; + } + + Future post(url, + {data, + options, + cancelToken, + bool isShowLoading = false, + failback}) async { + print('post请求启动! url:$url ,body: $data'); + Response response; + if (isShowLoading) LoadingManage().showLoading(); + try { + response = await dio.post( + url, + data: data, + cancelToken: cancelToken, + ); + print('$url post请求成功! $BaseUrl'); + if (isShowLoading) LoadingManage().closeLoading(); + } on DioError catch (e) { + if (CancelToken.isCancel(e)) { + print('post请求取消! ' + e.message); + } + print('post请求发生错误:$e'); + if (isShowLoading) LoadingManage().closeLoading(); + showToast(I18n.of(LoadingManage.context).server_error_tips); + if (failback != null) failback(); + } + return response; + } + + // 上传文件 + Future uploadFile(File imgfile, data, url, contentType, + {isShowLoading = false}) async { + FormData formData = new FormData.fromMap({ + "type": data["type"], + "userId": data["userId"], + "sex": data['sex'] == null ? 0 : data['sex'], + "isBurn": data['isBurn'] == null ? 0 : data['isBurn'], + "sign": data['sign'], + "file": await getMultipartFile(imgfile, contentType) + }); + print('post请求启动! url:$url'); + if (isShowLoading) LoadingManage().showLoading(); + Response response; + try { + response = await dio.post( + url, + data: formData, + ); + print('post请求成功!response.data:${response.data}'); + if (isShowLoading) LoadingManage().closeLoading(); + } on DioError catch (e) { + if (CancelToken.isCancel(e)) { + print('post请求取消! ' + e.message); + } + print('post请求发生错误:$e'); + if (isShowLoading) LoadingManage().closeLoading(); + } + return response; + } + + Future getMultipartFile( + File imgfile, String contentType) async { + //压缩图片文件 + var size = await imgfile.length(); + String path = imgfile.path; + + var fileBytes; + if (contentType == 'image' && size > 10240) { + fileBytes = await WidgetUtil.getCompressImg(path); + } else { + fileBytes = imgfile.readAsBytesSync(); + } + var name = path.substring(path.lastIndexOf("/") + 1, path.length); + var suffix = name.substring(name.lastIndexOf(".") + 1, name.length); + return new MultipartFile.fromBytes(fileBytes, + filename: name, contentType: MediaType(contentType, suffix)); + } + + // 上传多个图片 + Future uploadFiles(List imgfileList, data, url, contentType, + {isShowLoading = false}) async { + var imgList = []; + for (int i = 0; i < imgfileList.length; i++) { + imgList.add(await getMultipartFile(imgfileList[i], contentType)); + } + FormData formData = new FormData.fromMap({ + "type": data["type"], + "userId": data["userId"], + "sex": data['sex'] == null ? 0 : data['sex'], + "isBurn": data['isBurn'] == null ? 0 : data['isBurn'], + "sign": data['sign'], + "file": imgList + }); + print('post请求启动! url:$url'); + if (isShowLoading) LoadingManage().showLoading(); + Response response; + try { + response = await dio.post( + url, + data: formData, + ); + print('post请求成功!response.data:${response.data}'); + if (isShowLoading) LoadingManage().closeLoading(); + } on DioError catch (e) { + if (CancelToken.isCancel(e)) { + print('post请求取消! ' + e.message); + } + print('post请求发生错误:$e'); + if (isShowLoading) LoadingManage().closeLoading(); + } + return response; + } + + Future getUserInfoFromServer(int friendId) async { + Map data = { + "visitUserId": UserData().basicInfo.userId, + "userId": friendId, + "language": UserData().language, + }; + data['sign'] = TokenMgr().getSign(data); + data['lat'] = UserData().latitude; + data['lng'] = UserData().longitude; + print('请求用户信息 $data}'); + print('从服务器获取用户信息$friendId'); + Response res = await HttpUtil().post('user/info/list', data: data); + + if (res == null) { + return null; + } + Map resData = res.data; + print('用户信息resData $resData'); + if (resData['code'] == 0) { + var info = UserInfo.fromJson(resData['data']); + + info.isBlackened + ? BlacklistMgr.addBlackListMe(info.userId) + : BlacklistMgr.removeBalckListMe(info.userId); + + info.isBlackList + ? BlacklistMgr.addMyBlackList(info.userId) + : BlacklistMgr.removeMyBalckList(info.userId); + + friendCache[friendId] = info; + FriendListMgr().updateFriendInfo(info); + UserInfoTable().insertUser(info); + MessageMgr().emit('UpdateUserInfo', info); + return info; + } else { + return null; + } + } + + Future getFriendInfo(int friendId, [bool isUpdate = false]) async { + print('开始获取用户信息$friendId'); + if (friendId == null) { + print('用户Id为空,无法获取信息'); + return null; + } + + if (friendCache[friendId] != null) { + print('存在用户信息$friendId 缓存'); + if (isUpdate) { + //如果需要更新,那么先读取旧数据,然后后台更新 + getUserInfoFromServer(friendId); + } + + return friendCache[friendId]; + } + + var info = await SqlUtil.userInfoTable.getUserInfoFromLocal(friendId); + print('从本地数据库读取用户$friendId 信息'); + if (info != null) { + if (isUpdate) { + //如果需要更新,那么先读取旧数据,然后后台更新 + getUserInfoFromServer(friendId); + } + + friendCache[friendId] = info; + return info; + } + + return await getUserInfoFromServer(friendId); + } + + getUserInfo(visitedUserId, [callback, failcallback, errorcallback]) async { + var data = { + "visitUserId": UserData().basicInfo.userId, + "userId": visitedUserId, + "language": UserData().language, + }; + data['sign'] = TokenMgr().getSign(data); + data['lat'] = UserData().latitude; + data['lng'] = UserData().longitude; + Response res = await HttpUtil() + .post('user/info/list', data: data, failback: errorcallback); + + if (res == null) { + print('请求异常'); + return; + } + Map resData = res.data; + + if (resData['code'] == 0) { + var info = UserInfo.fromJson(resData['data']); + + info.isBlackened + ? BlacklistMgr.addBlackListMe(info.userId) + : BlacklistMgr.removeBalckListMe(info.userId); + + info.isBlackList + ? BlacklistMgr.addMyBlackList(info.userId) + : BlacklistMgr.removeMyBalckList(info.userId); + + FriendListMgr().updateFriendInfo(info); + friendCache[info.userId] = info; + MessageMgr().emit('UpdateUserInfo', info); + if (callback != null) callback(resData['data']); + } else if (resData['code'] == -4) { + if (failcallback != null) failcallback(); + } + } + + getFirstProgram() async { + Map data = { + "userId": UserData().basicInfo.userId, + "visitUserId": UserData().basicInfo.userId, + "type": 1, + }; + data['sign'] = TokenMgr().getSign(data); + data['page'] = 1; + data['rows'] = 1; + Response res = await HttpUtil().post('station/gain/program', data: data); + + if (res == null) { + print('请求异常'); + return; + } + var resData = res.data; + if (resData['code'] == 0) { + UserData().isCanProgram = + resData['data'] == null || resData['data'][0]['Status'] == 1; + } + } + + Future getTranslateState(int sessionId) async { + Map data = { + "userId": UserData().basicInfo.userId, + "chatUserId": sessionId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = + await HttpUtil().post('translate/get/user/status', data: data); + + if (res == null) { + print('请求异常'); + return null; + } + var resData = res.data; + if (resData['code'] == 0) { + return resData['data']; + } + + return null; + } + + updateTranslateState(int sessionId, bool state) async { + Map data = { + "userId": UserData().basicInfo.userId, + "chatUserId": sessionId, + "status": state ? 1 : 0 + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('translate/set/up/status', data: data); + + if (res == null) { + print('请求异常'); + return false; + } + var resData = res.data; + if (resData['code'] == 0) { + return true; + } + + return false; + } + + changeLanguage(BuildContext context, lang, callback, + [showLoading = false]) async { + var data = { + "userid": UserData().basicInfo.userId, + "language": lang, + }; + + data['sign'] = TokenMgr().getSign(data); + + try { + Response res = await HttpUtil().post('user/setting/language', + data: data, isShowLoading: showLoading); + + if (res == null) { + print('请求异常'); + return; + } + Map resData = res.data; + if (resData['code'] == 0) { + if (callback != null) callback(); + //重新登录 + // SocketUtil().reLogin(); + NetWork().reLogin(); + } + } catch (e) {} + } + + userFreeTime(BuildContext context, var viewUserId, int type, callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + "viewUserId": viewUserId, + 'type': type, + }; + + data['sign'] = TokenMgr().getSign(data); + try { + Response res = await HttpUtil() + .post('photos/unlock/permissions', data: data, isShowLoading: true); + if (res == null) { + print('请求异常'); + return; + } + Map resData = res.data; + if (resData['code'] == 0) { + if (callback != null) callback(); + } + } catch (e) {} + } + + saveAotuLoginKey(resData, {bool isSaveUserId = true}) async { + //将用户信息存到本地 + if (resData['data']['aotuLoginKey'] != null) { + SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.setString( + Constants.AutoLoginKey, resData['data']['aotuLoginKey']); + if (isSaveUserId) { + await prefs.setInt(Constants.LocalUserId, UserData().basicInfo.userId); + } + } + } + + ///登录 + changePage(BuildContext context, Map resData) async { + UserData().basicInfo.userId = resData['data']['userid']; + UserData().basicInfo.sex = resData['data']['sex']; + + if (resData['data']['mobile'] != null && resData['data']['mobile'] != '') { + UserData().mobile = int.parse(resData['data']['mobile']); + } + + if (resData['data']['bindId'] != null) { + UserData().agentId = resData['data']['bindId']; + } + + //读取聊天信息 + await ChatDataMgr().initMsg(); + //读取群信息 + await GroupInfoMgr().initLocalGroupList(); + + print('~~~~~~~~~~~~~changePage~~~~~~~~~~~~~~~~~~~~~~'); + + changeLanguage(context, UserData().language, null); + + getRewardAndRedPacketState(); + //clearReadData(UserData().basicInfo.userId); + + if (resData['data']['sex'] == 0) { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return SelectSex(); + }, + ), + ); + saveAotuLoginKey(resData, isSaveUserId: false); + return; + } + if (resData['data']['info'] == 0) { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return EditPage( + isEditPage: false, + ); + }, + ), + ); + saveAotuLoginKey(resData, isSaveUserId: false); + return; + } + LocalNotificationUtil.instance.startPush(); + //ChatDataMgr().initMsg(); + Navigator.of(context) + .pushNamedAndRemoveUntil('/main', (route) => route == null); + + MessageMgr().emit('update_system'); + saveAotuLoginKey(resData); + getFirstProgram(); + initLocation(); + } + + initLocation() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + + var latitude = prefs.getDouble(Constants.Latitude); + var longitude = prefs.getDouble(Constants.Longitude); + + print('存贮在本地的位置: $latitude------$longitude'); + + if (latitude != null) UserData().latitude = latitude; + if (longitude != null) UserData().longitude = longitude; + } + + setPhote(BuildContext context, id, type, callback) async { + var data = { + "userId": UserData().basicInfo.userId, + "type": type, + "pId": id, + }; + data['sign'] = TokenMgr().getSign(data); + Response res = await HttpUtil() + .post('photos/setting/burns', data: data, isShowLoading: true); + + if (res == null) { + print('请求异常'); + return; + } + var resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + if (callback != null) callback(); + } + } + + clearCacheData() async { + print('######### 清除缓存key'); + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.remove(Constants.AutoLoginKey); + prefs.remove(Constants.LocalUserId); + prefs.remove(Constants.LocalUsrInfo); + } + + // clearReadData(userId) async { + // SharedPreferences prefs = await SharedPreferences.getInstance(); + + // var localUserId = prefs.getInt(Constants.LocalUserId); + // if (userId != localUserId) { + // prefs.remove(Constants.ApplyCount); + // prefs.remove(Constants.EvaluateCount); + // prefs.remove(Constants.ParkCount); + // prefs.remove(Constants.CastCount); + // prefs.remove(Constants.WalletCount); + // } + // } + + void postLoginOut(BuildContext context) async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('user/login/out', data: data); + if (res == null) { + print('请求异常'); + return; + } + Map resData = res.data; + if (resData['code'] == 0) { + clearCacheData(); + + FriendListMgr().friendList?.clear(); + + Navigator.of(context).pushAndRemoveUntil(new MaterialPageRoute( + builder: (context) { + return IndexPage(); + }, + ), (route) => route == null); + NetWork().singOut(); + + UserData().reset(); + } else { + showToast(resData['msg']); + } + } + + buyGoods(money, goodsId, detailtype, changeuserId, context, callback) async { + if (Provider.of(context).money < money) { + showToast(I18n.of(context).balance_insufficien); + return; + } + + var data = { + "userId": UserData().basicInfo.userId, + "type": 1, + "detailtype": detailtype, + }; + data['sign'] = TokenMgr().getSign(data); + data['value'] = money; + data['changeuserId'] = changeuserId; + data['membergoodsId'] = goodsId; + + Response res = await HttpUtil() + .post('wealth/user/add', data: data, isShowLoading: true); + if (res == null) { + print('请求异常'); + return; + } + Map resData = res.data; + + showToast(resData['msg']); + if (resData['code'] == 0) { + Provider.of(context, listen: false).subMoney(money); + if (callback != null) callback(); + } + } + + buyPictures(money, changeuserId, context, callback) async { + if (Provider.of(context).money < money) { + showToast(I18n.of(context).balance_insufficien); + return; + } + + var data = { + "userId": UserData().basicInfo.userId, + "viewUserId": changeuserId, + "price": money, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil() + .post('photos/user/unlock', data: data, isShowLoading: true); + + if (res == null) { + print('请求异常'); + return; + } + Map resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + Provider.of(context, listen: false).subMoney(money); + if (callback != null) callback(); + } + } + + buyVIP(int money, int gid, int type, BuildContext context, callback) async { + if (Provider.of(context).money < money) { + showToast(I18n.of(context).balance_insufficien); + return; + } + + Map data = { + "userId": UserData().basicInfo.userId, + "gid": gid, + "type": type, + "price": money, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil() + .post('goods/user/purchase', data: data, isShowLoading: true); + if (res == null) { + print('请求异常'); + return; + } + Map resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + Provider.of(context, listen: false).subMoney(money); + if (callback != null) callback(); + } + } + + buyChatAccount(money, changeuserId, context, callback) async { + if (Provider.of(context).money < money) { + showToast(I18n.of(context).balance_insufficien); + return; + } + + var data = { + "userId": UserData().basicInfo.userId, + "unlockUserId": changeuserId, + "price": money, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil() + .post('photos/pay/unlock/chat', data: data, isShowLoading: true); + + if (res == null) { + print('请求异常'); + return; + } + Map resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + Provider.of(context, listen: false).subMoney(money); + if (callback != null) callback(); + } + } + + void getMoneyInfo(BuildContext context, callback) async { + if (Platform.isIOS) { + await MoneyPageState.initPayConf(context); + } + Map data = { + "userid": UserData().basicInfo.userId, + "moneytype": + UserData().language == LanguageType.SimplifiedChinese ? 0 : 1, + "mobiletype": Platform.isIOS ? 0 : 1, + }; + if (Platform.isIOS) { + data['moneytype'] = 1; + } + print('moneytype ${data['moneytype']}'); + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil() + .post('goods/info/list', data: data, isShowLoading: true); + if (res == null) { + print('请求异常'); + return; + } + + Map resData = res.data; + if (resData['code'] == 0) { + if (callback != null) callback(resData['data']); + } + } + + void getWealth(BuildContext context, callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('wealth/user/info', data: data); + if (res == null) { + print('请求异常'); + return; + } + Map resData = res.data; + print(resData); + if (resData['code'] == 0 && resData['data'] != null) { + UserData().basicInfo.isMember = resData['data']['IsMember'] ?? 0; + UserData().incomeMoney = resData['data']['IncomeCoin']; + UserData().frozenMoney = resData['data']['FrozenCoin']; + UserData().memberEndTime = resData['data']['MemberEnd']; + if (callback != null) callback(resData['data']); + } + } + + //获取红包与打赏开关状态 + getRewardAndRedPacketState() async { + var myId = UserData().basicInfo.userId; + Map data = { + "userId": myId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('system/switch', data: data); + if (res == null) { + print('请求异常'); + return; + } + Map resData = res.data; + print('### system/switch' + resData.toString()); + if (resData['code'] == 0) { + var config = resData['data']; + + if (config != null) { + UserData().redPacketSW = config['redPacket']; + UserData().giftSwitch = config['reward']; + UserData().bannerZF = config['iapPay']; + UserData().sign = config['sign']; + UserData().groupQRCode = config['groupQRCode']; + UserData().addFdDistanceSwitch = config['distance'] ?? 0; + + UserData().stationOpenSwitch = config['station'] == 1; + UserData().myProgramOpenSwitch = config['myProgram'] == 1; + UserData().nearbyOpenSwitch = config['nearby'] == 1; + +// print('### config: start'); +// print('### config: iapPay:${config['iapPay']}'); + } + } + } + + ///检查是否有缓存的内购单-有的话向服务器发送请求重新创建订单 + void checkReceiptCache() async { + String str = await SPUtils.get(Constants.IOS_IAP_Receipt); + if (str != null && str.isNotEmpty) { + print('### 有缓存单'); + List split = str.split("@"); + createOrder(split[0], split[1], split[2]); + } else { + print('### 没有缓存单'); + } + } + + ///ios内购-创建订单 + void createOrder(String currentGoodsId, String receipt, String purchaseToken, + {BuildContext context}) async { +// String base84str = base64Encode(utf8.encode(receipt)); + + var data = { + "userid": UserData().basicInfo.userId, + "moneytype": 1, + 'gid': currentGoodsId, + "payway": 1, + }; + data['sign'] = TokenMgr().getSign(data); + data['receipt'] = receipt; + data['isenable'] = Constants.isSandbox ? 0 : 1; + + Response res = await HttpUtil().post('order/add/goods', data: data); + print('#### 创建订单-返回'); + if (res == null) { + print('请求异常'); + return; + } + Map resData = res.data; + print('#### 创建订单-返回:' + resData.toString()); + if (resData['code'] == 0) { +// String OrderNo = resData['data']['OrderNo']; + Future.delayed(Duration(seconds: 3), () { + MessageMgr().emit('refresh_money'); + }); + + if (context == null) { + await FlutterInappPurchase.instance.initConnection; + } + + FlutterInappPurchase.instance.finishTransaction(purchaseToken); + SPUtils.remove(Constants.IOS_IAP_Receipt); + } else { + ///创建订单失败- + await SPUtils.saveString(Constants.IOS_IAP_Receipt, + currentGoodsId + '@' + receipt + '@' + purchaseToken); + } + if (context != null) { + Navigator.of(context).pop(); + } + } + + ///登陆 + void login( + String _phoneNumber, String _passWorld, BuildContext context) async { + var data = { + "mobile": _phoneNumber, + "text": _passWorld, + "type": 0, + "language": UserData().language, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil() + .post('user/mobile/login', data: data, isShowLoading: true); + + if (res == null) { + print('请求异常'); + return; + } + var resData = res.data; + if (resData['code'] == 0 && resData['data'] != null) { + HttpUtil().changePage(context, resData); + } else { + showToast(resData['msg']); + } + } + + ///获取推送设置 + getSettingInfo() async { + Map data = { + "userId": UserData().basicInfo.userId, + "sex": UserData().basicInfo.sex, + }; + data['sign'] = TokenMgr().getSign(data); + try { + Response res = await HttpUtil().post('message/push/message', data: data); + + if (res == null) { + print('请求异常'); + return; + } + + Map resData = res.data; + + bool isMan = UserData().isMan(); + + ///女号 {data: {PrivacyChat: 1, NewBroadcast: 1, ApplyCheck: 1, CheckAccount: 1, CheckPhoto: 1, SendAccount: 1}, code: 0, msg: 成功} + ///男号 {data: {PrivacyChat: 1, NewBroadcast: 1, AcceptCheck: 1, ApplySuccess: 1}, code: 0, msg: 成功} + print('###settingdata res.data ${res.data}'); + if (resData['code'] == 0) { + UserData().privatyMsgPushSwitch = resData['data']['PrivacyChat'] == 1; + UserData().newDateSwitch = resData['data']['NewBroadcast'] == 1; + + if (isMan) { + UserData().acceptCheckSwitch = resData['data']['AcceptCheck'] == 1; + UserData().codeSucessSwitch = resData['data']['ApplySuccess'] == 1; + } else { + UserData().applyCheckSwitch = resData['data']['ApplyCheck'] == 1; + UserData().checkPhotoSwitch = resData['data']['CheckPhoto'] == 1; + } + } + } catch (e) {} + MessageMgr().emit(MessageMgr.REFRESH_PUSH_PERMISSION); + } + + ///版本控制 + appVersionUpdate(Function callBack) async { + Map data = { + "ditch": Constants.isStoreVersion ? 0 : 1, + "type": Platform.isAndroid ? 0 : 1, + }; + data['sign'] = TokenMgr().getSign(data); + data['language'] = UserData().language; + try { + Response res = await HttpUtil().post('system/version/info', data: data); + Map resData = res.data; + print('###appVersionUpdate res.data ${res.data}'); + if (resData['code'] == 0) { + bool needNotice = resData['data']['Notice'] == 1; + + ///是否通知更新 + bool forceUpdate = resData['data']['IsStronger'] == 1; + + ///是否通知强更 + String version = resData['data']['VersionNo']; + String describe = resData['data']['Describe']; + String downloadUrl = resData['data']['DownloadUrl']; + String appId = resData['data']['AppId']; + callBack( + needNotice, forceUpdate, version, describe, downloadUrl, appId); + } + } catch (e) {} + } + + downloadApk( + BuildContext context, + String filePath, + String downloadUrl, + Function downloadCallback, + ) async { + final file = new File(filePath); + bool isExist = await file.exists(); + if (isExist) { + print('### 文件存在 : ${file.path}'); + file.delete(); + } +// else { +// +// print('### 开始下载 $downloadUrl'); +// dio.download(downloadUrl, filePath, onReceiveProgress: downloadCallback); +// } + +// downloadUrl ='oemarket.com/app0/30/30970/apk/2085562.apk?channel_id=426&tid=d73j9ihlkucuxfqpgnxgjeif'; + dio.download(downloadUrl, filePath, onReceiveProgress: downloadCallback); + } + + ///获取用户每日签到信息 + Future getDailyBonus() async { + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + data['userId'] = UserData().basicInfo.userId; + try { + Response res = await HttpUtil().post('sign/in/user/info', data: data); + Map resData = res.data; + print('###getDailyBonus res.data ${res.data}'); + if (resData['code'] == 0) { + return DailyBonusBean.fromMap(resData['data']); + } + return null; + } catch (e) { + return null; + } + } + + ///点击签到 + Future signInBounus(int score) async { + Map data = { + "userId": UserData().basicInfo.userId, + "score": score, + }; + data['sign'] = TokenMgr().getSign(data); + data['userId'] = UserData().basicInfo.userId; + data['score'] = score; + try { + Response res = await HttpUtil().post('sign/in/user', data: data); + Map resData = res.data; + print('###signInBounus res.data ${res.data}'); + if (resData['code'] == 0) { + return true; +// bool needNotice = resData['data']['Notice']==1; ///是否通知更新 +// return DailyBonusBean.fromMap(resData['data']); + } else { + showToast(resData['msg']); + } + return false; + } catch (e) { + return false; + } + } + + /// 用户签到积分兑换商品 + Future signInExchange(GoodsBean goodsBean) async { + Map data = { + "userId": UserData().basicInfo.userId, + "id": goodsBean.id, + "score": goodsBean.s, + }; + data['sign'] = TokenMgr().getSign(data); + data['userId'] = UserData().basicInfo.userId; + data['score'] = goodsBean.s; + data['id'] = goodsBean.id; + try { + Response res = + await HttpUtil().post('sign/in/score/exchange', data: data); + Map resData = res.data; + print('###signInExchange res.data ${res.data}'); + if (resData['code'] == 0) { + return true; + } else { + showToast(resData['msg']); + } + return false; + } catch (e) { + return false; + } + } + + addFriends( + BuildContext context, int friendId, String content, callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + "friendsUserId": friendId + }; + data['sign'] = TokenMgr().getSign(data); + data['content'] = content; + Response res = await HttpUtil().post('friendship/add/friends', data: data); + + Map resData = res.data; + print(resData); + if (resData['code'] == 0) { + showToast(resData['msg']); + if (callback != null) callback(); + } + } + + //付费人工翻译 + getPersonalTranslate(MsgModel msgModel) async { + Map data = { + "suserid": msgModel.from, + "chatmsgid": msgModel.time, + "slanguage": 1, + "tlanguage": UserData().language, + "chattype": msgModel.msgType, + "chatchanneltype": msgModel.channelType, + "targetid": msgModel.sessionId + }; + data['sign'] = TokenMgr().getSign(data); + + if (msgModel.msgType == 0) { + data['content'] = base64Encode(msgModel.msgContent); + } else { + if (msgModel.localFile == null) { + showToast('请稍后再试'); + return; + } + data['content'] = + base64Encode(File(msgModel.localFile).readAsBytesSync()); + } + + data["tuserids"] = [UserData().basicInfo.userId]; + data['duration'] = + msgModel.extraInfo != null ? msgModel.extraInfo ~/ 1000 : 0; + data['ispay'] = true; + + if (msgModel.msgType == ChatType.TextChatType.value) { + int length = utf8.decode(msgModel.msgContent).length; + data['money'] = length ~/ 50 + 1; //每50个字耗费1H币 + + print('字数 $length 价格 ${length % 50 + 1}'); + } else if (msgModel.msgType == ChatType.ShortVoiceChatType.value) { + //没20秒扣除1Hb + data['money'] = + msgModel.extraInfo != null ? msgModel.extraInfo ~/ 20000 + 1 : 0; + } + + if (msgModel.translateContent != null && + msgModel.translateContent.length > 0) { + data['mcontent'] = base64Encode(msgModel.enTranslateContent); + } + + Response res = + await HttpUtil().post('service/paid/translation', data: data); + + if (res == null) { + return false; + } + Map resData = res.data; + print('付费翻译请求$resData'); + if (resData['code'] == 0) { + print('扣除 H 币 ${data['money']}'); + + return true; + } + + print(resData['msg']); + showToast(resData['msg']); + return false; + } + + //用户评价人工翻译,差评 + Future rateTranslateResult(MsgModel msg, Function callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + "chatUserId": msg.from, + "chatMsgId": msg.time, + "score": 1 + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('translate/user/score', data: data); + if (res == null) { + return false; + } + var resData = res.data; + if (resData['code'] == 0) { + msg.transTag = 10; //已评价过 + + if (callback != null) { + callback(); + } + + SqlUtil().updateUserTranslateRate(msg.sessionId, msg.time, msg.transTag); + return true; + } + + return false; + } + + //根据经纬度获取用户国家城市 + getAddress(double lon, double lat) async { + Map data = { + "lon": lon.toString(), + "lat": lat.toString(), + }; + data['sign'] = TokenMgr().getSign(data); + data['language'] = UserData().language; + + Response res = await HttpUtil().post('user/get/address', data: data); + if (res == null) return; + Map resData = res.data; + if (resData['code'] == 0 && resData['data'] != null) { + print(resData['data']); + List address = resData['data'].split(','); + if (address.length != 2) return; + String country = address[0]; + String city = address[1]; + UserData().isInChina = false; + if (country == '越南') { + UserData().currentCity = 'VietNam-'; + List citys = constData[3]['city'][0]['List']; + for (int i = 0; i < citys.length; i++) { + if (citys[i]['Value'] == city) { + UserData().currentCity += citys[i]['Key']; + break; + } + } + } else if (country == '中国') { + UserData().isInChina = true; + UserData().currentCity = 'China-ChinaRepeat'; + } else { + UserData().currentCity = 'VietNam-HoChiMinhCIty'; + } + + if (UserData().currentCity != UserData().basicInfo.meetPlace) { + UserData().basicInfo.meetPlace = UserData().currentCity; + changeCurrentCity(lon, lat, () {}); + } + + MessageMgr().emit('change_currentcity'); + } + } + + //根据经纬度更新当前城市 + changeCurrentCity(double lon, double lat, callback) async { + if (UserData().basicInfo.userId == null) return; + Map data = { + "userId": UserData().basicInfo.userId, + "lon": lon.toString(), + "lat": lat.toString(), + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().post('user/update/meetPlace', data: data); + if (res == null) return; + Map resData = res.data; + print(resData); + if (resData['code'] == 0) { + callback(); + } + } + + //通过手机号查询用户 + searchNewFrindsByPhone(String phone, callback) async { + Map data = { + "userId": UserData().basicInfo.userId, + "value": phone, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil() + .post('/friendship/search/userPhone', data: data, isShowLoading: true); + if (res == null) return; + Map resData = res.data; + print(resData); + if (resData['code'] == 0) { + callback(resData['data']['UserId']); + } + } + + //拉黑用户 + blackUser(int userId, callback) async { + Map data = { + "userid": UserData().basicInfo.userId, + "type": 1, + "followUserId": userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = + await HttpUtil().post('userfollow/follow/insert', data: data); + Map resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + BlacklistMgr.addMyBlackList(userId); + callback(); + } + } + + //取消拉黑用户 + cancleBlackUser(int userId, callback) async { + Map data = { + "userid": UserData().basicInfo.userId, + "type": 1, + "followUserId": userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil() + .post('userfollow/follow/cancel', data: data, isShowLoading: true); + Map resData = res.data; + showToast(resData['msg']); + if (resData['code'] == 0) { + BlacklistMgr.removeMyBalckList(userId); + callback(); + } + } + + //收藏用户 + setLove(int userId, callback) async { + Map data = { + "userid": UserData().basicInfo.userId, + "type": 0, + "followUserId": userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil() + .post('userfollow/follow/insert', data: data, isShowLoading: true); + Map resData = res.data; + if (resData['code'] == 0) { + showToast(resData['msg']); + callback(); + } + } + + //取消收藏用户 + cancleLove(int userId, callback) async { + Map data = { + "userid": UserData().basicInfo.userId, + "type": 0, + "followUserId": userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil() + .post('userfollow/follow/cancel', data: data, isShowLoading: true); + Map resData = res.data; + if (resData['code'] == 0) { + showToast(resData['msg']); + callback(); + } + } + + //向企业服务助手提交信息 + Future commitInfoToCompany(MsgModel msgModel) async { + Map data = { + "userid": msgModel.from, + "msgType": msgModel.msgType, + }; + data['sign'] = TokenMgr().getSign(data); + data['msgContent'] = base64Encode(msgModel.msgContent); + + msgModel.state = MsgState.Sending; + + print('commitInfoToCompany 参数 $data'); + Response res = await HttpUtil().post('feedback/user/insert', data: data); + + if (res == null) { + msgModel.state = MsgState.SendingFailed; + ChatDataMgr().updateMsgState(msgModel.sessionId, msgModel.time, + msgModel.channelType, msgModel.state); + return false; + } + Map resData = res.data; + print('commitInfoToCompany $resData'); + if (resData['code'] == 0) { + msgModel.state = MsgState.SendingSuccess; + ChatDataMgr().updateMsgState(msgModel.sessionId, msgModel.time, + msgModel.channelType, msgModel.state); + return true; + } + + showToast(resData['msg']); + return false; + } +} diff --git a/lib/utils/IconToggle.dart b/lib/utils/IconToggle.dart new file mode 100644 index 0000000..14777e8 --- /dev/null +++ b/lib/utils/IconToggle.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; + +class IconToggle extends StatefulWidget { + final IconData icon; + final IconData activeIcon; + + final Color defaultColor; + final Color activeColor; + final bool isActive; + + final double size; + final void Function(bool) onTap; + + IconToggle({ + Key key, + this.icon, + this.defaultColor, + this.activeColor, + this.onTap, + this.isActive: false, + this.activeIcon, + this.size, + }) : super(key: key); + + @override + _IconToggleState createState() => _IconToggleState(); +} + +class _IconToggleState extends State { + bool isActive; + + @override + void initState() { + super.initState(); + isActive = widget.isActive; + } + + @override + Widget build(BuildContext context) { + Color curColor = isActive ? widget.activeColor : widget.defaultColor; + IconData curIcon = isActive ? widget.activeIcon : widget.icon; + return InkWell( + child: Container( + padding: EdgeInsets.only(left: 15, right: 15, bottom: 15), + child: Icon( + curIcon, + color: curColor, + size: widget.size, + )), + onTap: () { + setState(() { + isActive = !isActive; + widget.onTap(isActive); + }); + }, + ); + } +} diff --git a/lib/utils/LoadingDialog.dart b/lib/utils/LoadingDialog.dart new file mode 100644 index 0000000..afc0ebc --- /dev/null +++ b/lib/utils/LoadingDialog.dart @@ -0,0 +1,70 @@ +/* + * 自定义等待加载提示框 + * Created by ZhangJun on 2018-11-29 + */ + +import 'package:flutter/material.dart'; +import 'package:chat/utils/my_dialog.dart' as myDialog; + +class LoadingManage { + //私有构造函数 + LoadingManage._internal(); + + //保存单例 + static LoadingManage _singleton = new LoadingManage._internal(); + + //工厂构造函数 + factory LoadingManage() => _singleton; + + static BuildContext context; + showLoading() { + myDialog.showDialog( + context: context, + barrierDismissible: true, + builder: (BuildContext context) { + return LoadingDialog(); + }); + } + + closeLoading() { + Navigator.of(context).pop(); + } +} + +class LoadingDialog extends Dialog { + final String text; + + LoadingDialog({Key key, this.text}) : super(key: key); + + @override + Widget build(BuildContext context) { + return new Material( + type: MaterialType.transparency, + child: new Center( + child: new SizedBox( + width: 120.0, + height: 120.0, + child: new Container( + decoration: ShapeDecoration( + color: Colors.black.withOpacity(0.5), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8.0), + ), + ), + ), + child: new Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + new CircularProgressIndicator( + valueColor: + AlwaysStoppedAnimation(Colors.white)), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/utils/LoveToggle.dart b/lib/utils/LoveToggle.dart new file mode 100644 index 0000000..50351bd --- /dev/null +++ b/lib/utils/LoveToggle.dart @@ -0,0 +1,61 @@ +import 'package:chat/data/constants.dart'; +import 'package:flutter/material.dart'; + +class LoveToggle extends StatefulWidget { + + + final bool isActive; + + final void Function(bool) onTap; + + LoveToggle({ + Key key, + this.onTap, + this.isActive: false, + }) : super(key: key); + + @override + _LoveToggleState createState() => _LoveToggleState(); +} + +class _LoveToggleState extends State { + bool isActive; + + @override + void initState() { + super.initState(); + isActive = widget.isActive; + } + + @override + Widget build(BuildContext context) { +// Color curColor = isActive ? widget.activeColor : widget.defaultColor; +// IconData curIcon = isActive ? widget.activeIcon : widget.icon; + return InkWell( + child: Container( + width: 100, + height: 30, + decoration: BoxDecoration(color: isActive?Color(0xffFF69B3):Colors.transparent,border: Border.all(color: Color(0xFF878787), width: 1),borderRadius: BorderRadius.circular(16)) , + padding: EdgeInsets.only( + left: 15, right: 15, bottom: 5,top: 5 ), + child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ + Icon( + IconData( + 0xe625, + fontFamily: Constants.IconFontFamily, + ), + size: 15, + color: isActive?Colors.white:Color(0xffB2B2B2), + ), + SizedBox(width: 5,), + Text('LOVE',style: TextStyle(color: isActive?Colors.white:Color(0xffB2B2B2)),) + ],)), + onTap: () { + setState(() { + isActive = !isActive; + widget.onTap(isActive); + }); + }, + ); + } +} diff --git a/lib/utils/MessageBox.dart b/lib/utils/MessageBox.dart new file mode 100644 index 0000000..4360524 --- /dev/null +++ b/lib/utils/MessageBox.dart @@ -0,0 +1,1162 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/InformUser.dart'; +import 'package:chat/home/ProfilePage.dart'; +import 'package:chat/home/ProgramDetail.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/PicSwiper.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +import 'package:image_picker/image_picker.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:chat/utils/PopUpMenu.dart' as myPopUp; +import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; + +const BlackIconColor = const Color(0xFF4D4D4F); + +class MessageBox extends StatefulWidget { + final programInfo; + final bool isDetail; + MessageBox({ + Key key, + @required this.programInfo, + this.isDetail: false, + }) : super(key: key); + + _MessageBoxState createState() => _MessageBoxState(); +} + +class _MessageBoxState extends State { + bool isMyself = false; + bool isProgram = false; + bool isCloseContent = false; + bool isShowAll = false; + + //List fabulousList = []; + + @override + Widget build(BuildContext context) { + initValue(); + return _buildMessageBox(widget.programInfo); + } + + @override + void initState() { + super.initState(); + } + + void initValue() { + isMyself = widget.programInfo['UserId'] == UserData().basicInfo.userId; + isProgram = widget.programInfo['Type'] == 0; + isCloseContent = widget.programInfo['EvaluateStatus'] == 1; + widget.programInfo['EvaluateList'] = + widget.programInfo['EvaluateList'] == null + ? [] + : widget.programInfo['EvaluateList']; + widget.programInfo['FabulousList'] = + widget.programInfo['FabulousList'] == null + ? [] + : widget.programInfo['FabulousList']; + } + + void _selectValue(str, userId, isProgram) async { + if (str == 'inform') { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return InformUserPage( + isMan: widget.programInfo['Sex'] == 1, + programId: widget.programInfo['Id'], + isProgram: isProgram, + userId: userId, + ); + }, + ), + ); + } else if (str == 'black') { + HttpUtil().blackUser(userId, () {}); + } else if (str == 'noContent') { + var data = { + "userId": UserData().basicInfo.userId, + "type": 1, + "id": userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = + await HttpUtil().post('station/settings/program', data: data); + var resData = res.data; + if (resData['code'] == 0) { + showToast(resData['msg']); + widget.programInfo['EvaluateStatus'] = 1; + MessageMgr().emit('update_dy', true); + setState(() {}); + } + } else if (str == 'delete') { + var data = { + "userId": UserData().basicInfo.userId, + "type": 2, + "id": userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = + await HttpUtil().post('station/settings/program', data: data); + var resData = res.data; + if (resData['code'] == 0) { + showToast(resData['msg']); + if (isProgram) { + UserData().isCanProgram = true; + } + MessageMgr().emit('delete_program', userId); + } + } else if (str == 'openContent') { + var data = { + "userId": UserData().basicInfo.userId, + "type": 3, + "id": userId, + }; + data['sign'] = TokenMgr().getSign(data); + + Response res = + await HttpUtil().post('station/settings/program', data: data); + var resData = res.data; + if (resData['code'] == 0) { + showToast(resData['msg']); + widget.programInfo['EvaluateStatus'] = 0; + MessageMgr().emit('update_dy', false); + setState(() {}); + } + } + } + + Widget _iconButton(code, iconColor, text, callback, + {textColor = BlackIconColor, double iconSize = 18}) { + return InkWell( + onTap: callback, + child: Container( + alignment: Alignment.center, + width: Screen.width / 4, + margin: EdgeInsets.only(bottom: 5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + child: Icon( + IconData( + code, + fontFamily: 'iconfont', + ), + color: iconColor, + size: iconSize, + )), + Container( + constraints: BoxConstraints(minHeight: 15), + + ///防止中文数字高度不一样,界面发生变化 + padding: EdgeInsets.only(top: 2, left: 1.5), + child: fixedText(text, + color: textColor, + fontSize: 9.67, + fontWeight: FontWeight.normal)) + ], + ))); + } + + Widget _iconRow(code, str, size) { + return Container( + margin: EdgeInsets.only(top: 3), + constraints: BoxConstraints(minHeight: 20), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + margin: EdgeInsets.only(right: 5), + child: Icon( + IconData( + code, + fontFamily: 'iconfont', + ), + color: BlackIconColor, + size: size, + )), + Expanded( + child: Container( + child: extendedText( + str, + selectionEnabled: false, + color: Constants.BlackTextColor, + emojisize: 17.0, + fontSize: ScreenUtil().setSp(14), + //fontWeight: FontWeight.w500, + ))), + ], + ), + ); + } + + void _sendPicture(callback) async { + if (await CustomUI.showPhotoPermissionSetting(context)) { + var tempFile = await ImagePicker.pickImage(source: ImageSource.gallery); + if (tempFile != null) { + Map data = {"type": 4, "userId": UserData().basicInfo.userId}; + data['sign'] = TokenMgr().getSign(data); + + Response res = await HttpUtil().uploadFile( + tempFile, data, 'upload/file/postflie', 'image', + isShowLoading: true); + var resData = res.data; + if (resData['code'] == 0) { + Navigator.of(context).pop(); + callback(resData['msg']); + } + } + } + } + + Widget _buildIconButtonList(data) { + bool isStop = data['Status'] == 1; + //bool isSameSex = data['Sex'] == UserData().basicInfo.sex; + //bool isMan = data['Sex'] == 1; + bool isAd = data['Type'] == 2; + Widget likeButton = _iconButton( + 0xe65b, + data['IsFabulous'] > 0 ? Constants.BlueTextColor : BlackIconColor, + // data['FabulousNum'] > 0 + // ? data['FabulousNum'].toString() + // : I18n.of(context).thumbs_up3, + I18n.of(context).thumbs_up3, + isStop + ? () { + showToast(I18n.of(context).has_ended); + } + : data['IsFabulous'] > 0 + ? () { + showToast(I18n.of(context).already_praised); + } + : () async { + if (isAd) { + Map rdata = { + "userId": UserData().basicInfo.userId, + "adId": data['Id'], + }; + rdata['sign'] = TokenMgr().getSign(rdata); + + Response res = await HttpUtil().post('adActivity/give/like', + data: rdata, isShowLoading: true); + var resData = res.data; + if (resData['code'] == 0) { + setState(() { + data['FabulousNum']++; + data['IsFabulous']++; + + widget.programInfo['FabulousList'].add({ + "UserId": UserData().basicInfo.userId, + "Headimgurl": UserData().basicInfo.headimgurl + }); + }); + } + } else { + Map rdata = { + "userId": UserData().basicInfo.userId, + "id": data['Id'], + }; + rdata['sign'] = TokenMgr().getSign(rdata); + + Response res = await HttpUtil().post('station/give/like', + data: rdata, isShowLoading: true); + var resData = res.data; + if (resData['code'] == 0) { + setState(() { + data['FabulousNum']++; + data['IsFabulous']++; + + widget.programInfo['FabulousList'].add({ + "UserId": UserData().basicInfo.userId, + "Headimgurl": UserData().basicInfo.headimgurl + }); + }); + } + } + }, + textColor: + data['IsFabulous'] > 0 ? Constants.BlueTextColor : BlackIconColor, + ); + // var str = data['EvaluateNum'] > 0 + // ? data['EvaluateNum'].toString() + // : I18n.of(context).comment; + Widget contentButton = _iconButton( + 0xe65d, + isCloseContent && !isMyself + ? BlackIconColor.withOpacity(0.5) + : BlackIconColor, + // !isCloseContent + // ? (isMyself ? str : I18n.of(context).comment) + // : isMyself ? str : I18n.of(context).comment_closed, + !isCloseContent + ? I18n.of(context).comment + : I18n.of(context).comment_closed, + isStop + ? () { + showToast(I18n.of(context).has_ended); + } + : (isCloseContent) + ? () { + showToast(I18n.of(context).comment_closed); + } + : + // isSameSex && !isMyself + // ? () { + // showToast(isMan + // ? I18n.of(context).men_cant2 + // : I18n.of(context).ms_cant2); + // } + // : + () { + CustomUI.showContentDialog(context, data['Id'], 0, 0, + (data) { + widget.programInfo['EvaluateNum']++; + widget.programInfo['EvaluateList'].insert(0, data); + + data['Id'] = widget.programInfo['Id']; + if (!isAd && widget.isDetail) + MessageMgr().emit('refresh_list', data); + setState(() {}); + }, isAd: isAd, isMyself: isMyself); + }, + textColor: isCloseContent && !isMyself + ? BlackIconColor.withOpacity(0.5) + : BlackIconColor); + + Widget stopJoin = _iconButton( + 0xe65e, + BlackIconColor, + !isStop + ? I18n.of(context).end_registration + : I18n.of(context).has_ended, + isStop + ? null + : () async { + CustomUI.buildOneConfirm(context, I18n.of(context).end_choose, + I18n.of(context).determine, () async { + Map rdata = { + "userId": UserData().basicInfo.userId, + "id": data['Id'], + }; + rdata['sign'] = TokenMgr().getSign(rdata); + + Response res = await HttpUtil() + .post('station/fin/inscriptions', data: rdata); + var resData = res.data; + if (resData['code'] == 0) { + Navigator.of(context).pop(); + UserData().isCanProgram = true; + showToast(resData['msg']); + MessageMgr().emit('refresh_list'); + widget.programInfo['Status'] = 1; + setState(() {}); + } + }); + }, + iconSize: 18); + + Widget joinButton = _iconButton( + 0xe624, + data['IsEnroll'] > 0 ? Colors.red : BlackIconColor, + isMyself + ? '${I18n.of(context).view_registration}(${data['EnrollNum']})' + : '${I18n.of(context).sign_up2}(${data['EnrollNum']})', + isMyself + ? null + : + // isSameSex + // ? () { + // showToast(isMan + // ? I18n.of(context).men_cant + // : I18n.of(context).ms_cant); + // } + // : + (data['IsEnroll'] > 0 + ? () { + showToast(I18n.of(context).alreay_join); + } + : () async { + if ((UserData().isMan() && !UserData().isVip)) { + showToast(I18n.of(context).cannot_join); + return; + } + if ((!UserData().isMan() && + !UserData().basicInfo.isAttestation)) { + CustomUI.buildNotTrue(context); + return; + } + + CustomUI.buildOneConfirm( + context, + I18n.of(context).need_photo2, + I18n.of(context).choose_photo, () { + _sendPicture((url) async { + Map rdata = { + "userId": UserData().basicInfo.userId, + "id": data['Id'], + }; + rdata['sign'] = TokenMgr().getSign(rdata); + rdata['imgUrl'] = url; + Response res = await HttpUtil() + .post('station/program/enroll', data: rdata); + var resData = res.data; + if (resData['code'] == 0) { + showToast(resData['msg']); + setState(() { + data['EnrollNum']++; + data['IsEnroll']++; + }); + } + }); + }); + }), + iconSize: 18); + return Container( + width: double.infinity, + alignment: Alignment.center, + height: 47, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: isProgram + ? (isMyself + ? [likeButton, contentButton, joinButton, stopJoin] + : [likeButton, contentButton, joinButton]) + : [likeButton, contentButton], + ), + ); + } + + //动态消息框 + Widget _buildMessageBox(data) { + bool isAd = data['Type'] == 2; + return InkWell( + onTap: () async { + if (isAd) { + if (await canLaunch(data['HopeObject'])) { + await launch(data['HopeObject']); + } else { + throw 'Could not launch ${data['HopeObject']}'; + } + return; + } + if (widget.isDetail) return; + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProgramDetailPage( + programId: data['Id'], + ); + }, + ), + ); + }, + child: Container( + margin: EdgeInsets.only(top: 10), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: Constants.GreyBorderSide, + bottom: Constants.GreyBorderSide)), + child: Column( + children: [ + _buildUserInfo(data), + _buildTimebox(data), + _buildImgSet(data), + _buildImgList(data), + widget.isDetail ? Container() : _buildDivder(), + _buildIconButtonList(data), + //_buildContent(), + ], + ), + )); + } + + Widget _buildDivder() { + return Container( + height: 1, + margin: EdgeInsets.symmetric(horizontal: 21), + decoration: + BoxDecoration(border: Border(top: Constants.GreyBorderSide))); + } + + // Widget _buildContent() { + // if (widget.programInfo['EvaluateList'].length == 0) { + // return Container(); + // } + // List list = []; + // var size = widget.programInfo['EvaluateList'].length >= 2 + // ? 2 + // : widget.programInfo['EvaluateList'].length; + // for (int i = 0; i < size; i++) { + // var data = widget.programInfo['EvaluateList'][i]; + // list.add(_buildReply(data)); + // } + // return Container( + // decoration: BoxDecoration( + // borderRadius: BorderRadius.only( + // bottomLeft: Radius.circular(10), + // bottomRight: Radius.circular(10))), + // child: Column( + // children: [ + // Container( + // padding: EdgeInsets.zero, + // margin: + // EdgeInsets.only(left: 20, right: 20, top: 11.5, bottom: 14), + // height: 0.1, + // decoration: BoxDecoration( + // border: Border(top: BorderSide(color: Color(0xFFF1F1F1)))), + // ), + // Container( + // margin: EdgeInsets.only(left: 24), + // decoration: BoxDecoration( + // borderRadius: BorderRadius.only( + // bottomLeft: Radius.circular(10), + // bottomRight: Radius.circular(10))), + // child: Row( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: list, + // ) + // ], + // )) + // ], + // )); + // } + + // Widget _buildReply(data) { + // var content = ": ${data['Content'] == null ? '' : data['Content']} "; + // return Container( + // padding: EdgeInsets.only(left: 0, bottom: 3), + // width: Screen.width - 30, + // child: RichText( + // text: TextSpan( + // children: data['ReplyUserId'] == 0 + // ? [ + // TextSpan( + // text: Provider.of(context) + // .getRefName(data['UserId'], data['NickName']), + // style: TextStyle( + // fontSize: 12.5, + // textBaseline: TextBaseline.alphabetic, + // color: const Color(0xFF739BBC), + // fontWeight: FontWeight.w500), + // ), + // TextSpan( + // text: content, + // style: TextStyle( + // color: Constants.GreyTextColor, + // textBaseline: TextBaseline.alphabetic, + // fontSize: 12.5), + // ) + // ] + // : [ + // TextSpan( + // text: WebData().subUserName( + // Provider.of(context) + // .getRefName(data['UserId'], data['NickName'])), + // style: TextStyle( + // fontSize: 12.5, + // textBaseline: TextBaseline.alphabetic, + // color: const Color(0xFF739BBC), + // fontWeight: FontWeight.w500), + // ), + // TextSpan( + // text: ' ${I18n.of(context).reply} ', + // style: TextStyle( + // fontSize: 12.5, + // textBaseline: TextBaseline.alphabetic, + // color: Constants.GreyTextColor, + // fontWeight: FontWeight.w500), + // ), + // TextSpan( + // text: WebData().subUserName(data['ReplyNickName']), + // style: TextStyle( + // fontSize: 12.5, + // textBaseline: TextBaseline.alphabetic, + // color: const Color(0xFF739BBC), + // fontWeight: FontWeight.w500), + // ), + // TextSpan( + // text: content, + // style: TextStyle( + // color: Constants.GreyTextColor, + // textBaseline: TextBaseline.alphabetic, + // fontSize: 12.5), + // ) + // ]), + // ), + // ); + // } + + Widget _buildTimebox(data) { + return Container( + padding: EdgeInsets.only(left: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + isProgram + ? _iconRow(0xe636, + WebData().getProgramName(context, data['ProgramType']), 16.0) + : Container(), + isProgram + ? _iconRow( + 0xe635, + '${data['AboutTime'].split(' ')[0]} ${WebData().getDateString(context, data['timeQuantum'])}', + 16.0) + : Container(), + isProgram + ? _iconRow( + 0xe617, + '${I18n.of(context).expect_lover}:${WebData().getLovePeople(data['HopeObject'])}', + 16.0) + : Container(), + _buildTextContent(data), + ], + ), + ); + } + + bool isExpansion(String text) { + double width = Screen.width - 25; + TextPainter _textPainter = TextPainter( + maxLines: 2, + text: TextSpan( + text: text, style: TextStyle(fontSize: 16.0, color: Colors.black)), + textDirection: TextDirection.ltr) + ..layout(maxWidth: width, minWidth: width); + if (_textPainter.didExceedMaxLines) { + //这里判断 文本是否截断 + return true; + } else { + return false; + } + } + + Widget _buildTextContent(data) { + if (data['Content'] == null || data['Content'] == '') { + return Container(); + } + bool showAllContent = isExpansion(data['Content']); + return Container( + margin: EdgeInsets.only(right: 10, top: 5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + extendedText( + data['Content'], + selectionEnabled: false, + color: Constants.BlackTextColor, + emojisize: 17.0, + maxLines: isShowAll ? 10 : 2, + fontSize: ScreenUtil().setSp(14), + fontWeight: FontWeight.w500, + ), + showAllContent + ? InkWell( + onTap: () { + setState(() { + isShowAll = !isShowAll; + }); + }, + child: Container( + padding: EdgeInsets.only(top: 5), + child: Row( + children: [ + Text( + !isShowAll + ? I18n.of(context).expand + : I18n.of(context).collapse, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 15, + color: Constants.BlueTextColor), + ), + Icon( + !isShowAll + ? Icons.keyboard_arrow_down + : Icons.keyboard_arrow_up, + size: 24, + color: Constants.BlueTextColor), + ], + ))) + : Container(), + ])); + } + + Widget _buildBigImg(int id, List imgList, width, height) { + return InkWell( + onTap: () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return PicSwiper( + id: id, + pics: imgList + .map( + (f) => PicSwiperItem(f, id: imgList.indexOf(f))) + .toList(), + ); + }, + ), + ); + }, + child: Container( + height: height, + width: width, + child: CachedNetworkImage( + imageUrl: imgList[id] == null ? "" : imgList[id], + placeholder: CustomUI.buildImgLoding, + fit: BoxFit.cover, + ), + )); + } + + Widget _buildImgSet(data) { + double height = 254.5; + List imgList = (data['ImgUrl'] == '' || data['ImgUrl'] == null) + ? [] + : data['ImgUrl'].split('|'); + Widget result; + switch (imgList.length) { + case 1: + result = _buildBigImg(0, imgList, Screen.width, height); + break; + case 2: + double paddingWidth = 3; + double imgWidth = (Screen.width - paddingWidth) / 2; + result = Row( + children: [ + _buildBigImg(0, imgList, imgWidth, height), + SizedBox( + width: paddingWidth, + ), + _buildBigImg(1, imgList, imgWidth, height) + ], + ); + break; + case 3: + double paddingWidth = 3; + double imgWidth = (Screen.width - paddingWidth) / 2; + double imgHeight = (height - paddingWidth) / 2; + result = Row( + children: [ + _buildBigImg(0, imgList, imgWidth, height), + SizedBox(width: paddingWidth), + Column( + children: [ + _buildBigImg(1, imgList, imgWidth, imgHeight), + SizedBox(height: paddingWidth), + _buildBigImg(2, imgList, imgWidth, imgHeight), + ], + ), + ], + ); + break; + case 4: + double paddingWidth = 3; + double imgWidth = (Screen.width - paddingWidth) / 2; + double imgHeight = (height - paddingWidth) / 2; + result = Row( + children: [ + Column( + children: [ + _buildBigImg(0, imgList, imgWidth, imgHeight), + SizedBox(height: paddingWidth), + _buildBigImg(1, imgList, imgWidth, imgHeight), + ], + ), + SizedBox(width: paddingWidth), + Column( + children: [ + _buildBigImg(2, imgList, imgWidth, imgHeight), + SizedBox(height: paddingWidth), + _buildBigImg(3, imgList, imgWidth, imgHeight), + ], + ), + ], + ); + break; + default: + result = Container(); + } + + return Padding(padding: EdgeInsets.only(top: 5), child: result); + } + + Widget _buildImg(data) { + double width = 25; + return InkWell( + onTap: data['UserId'] == UserData().basicInfo.userId + ? null + : () { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: data['UserId'], + ); + }, + ), + ); + }, + child: Container( + decoration: BoxDecoration(borderRadius: BorderRadius.circular(2.0)), + width: width, + height: width, + child: ClipRRect( + borderRadius: BorderRadius.circular(30), + child: CachedNetworkImage( + imageUrl: data['Headimgurl'] == null ? '' : data['Headimgurl'], + placeholder: (context, url) => Image.asset( + Constants.DefaultHeadImgUrl, + width: width, + height: width, + ), + fit: BoxFit.cover, + ), + ))); + } + + Widget _buildImgList(programInfo) { + int pictureNum = programInfo['FabulousList'].length >= 3 + ? 3 + : programInfo['FabulousList'].length; + List list = [ + Container(height: 30, width: 30, margin: EdgeInsets.only(top: 10)) + ]; + if (pictureNum != 0) { + list.add(_buildImg(programInfo['FabulousList'][0])); + for (int i = 1; i < pictureNum; i++) { + list.add(Positioned( + left: 15.0 * i, + child: _buildImg(programInfo['FabulousList'][i]), + )); + } + if (programInfo['FabulousList'].length > 3) { + list.add(Positioned( + left: 70, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.grey[400], + borderRadius: BorderRadius.circular(20.0)), + width: 25, + height: 25, + child: Text( + '+${programInfo['FabulousList'].length - pictureNum}', + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white, fontSize: 13), + )))); + } + } + + return Container( + height: 37.5, + padding: EdgeInsets.only(top: 0, left: 15, right: 23), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Stack( + alignment: Alignment.centerLeft, + children: list, + ), + ), + Container( + child: Text( + I18n.of(context) + .content_num + .replaceFirst('/s1', programInfo['EvaluateNum'].toString()), + style: TextStyle(fontSize: 12, color: BlackIconColor), + ), + ), + ], + )); + } + + Widget _buildUserInfo(data) { + Color greColor = Color(0xFF5A5A5A); + Widget otherPop = myPopUp.PopupMenuButton( + offset: Offset(-10, 40), + child: Container( + margin: EdgeInsets.only(right: 10), + padding: EdgeInsets.only(left: 8, right: 8, top: 0, bottom: 0), + decoration: BoxDecoration( + //border: Border.all(color: greColor), + borderRadius: BorderRadius.all(Radius.circular(8))), + child: Icon( + IconData(0xe621, fontFamily: Constants.IconFontFamily), + color: greColor, + size: 12, + )), + onSelected: (str) { + _selectValue(str, data['UserId'], isProgram); + }, + itemBuilder: (BuildContext context) => >[ + myPopUp.PopupMenuItem( + value: 'inform', + child: Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + child: fixedText(I18n.of(context).anonymous_report, + fontSize: 14, color: Constants.BlackTextColor)), + ) + ], + ); + + Widget myPop = myPopUp.PopupMenuButton( + offset: Offset(0, 40), + padding: EdgeInsets.zero, + child: Container( + //margin: EdgeInsets.only(right: 10), + padding: EdgeInsets.only(left: 18, right: 18, top: 3, bottom: 3), + decoration: BoxDecoration( + + //border: Border.all(color: greColor), + borderRadius: BorderRadius.all(Radius.circular(8))), + child: Icon( + IconData(0xe621, fontFamily: Constants.IconFontFamily), + color: greColor, + size: 12, + )), + onSelected: (str) { + _selectValue(str, data['Id'], isProgram); + }, + itemBuilder: (BuildContext context) => >[ + !isCloseContent + ? myPopUp.PopupMenuItem( + value: 'noContent', + child: Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + child: fixedText(I18n.of(context).prohibit_comments, + fontSize: 15, color: Constants.BlackTextColor))) + : myPopUp.PopupMenuItem( + value: 'openContent', + child: Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + child: fixedText(I18n.of(context).open_comments, + fontSize: 15, color: Constants.BlackTextColor))), + const myPopUp.PopupMenuDivider( + height: 1, + ), + myPopUp.PopupMenuItem( + value: 'delete', + child: Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + child: fixedText(I18n.of(context).delete, + fontSize: 15, color: Constants.BlackTextColor)), + ), + ], + ); + bool isMan = data['Sex'] == 1; + bool isVip = data['IsMember'] > 0; + bool isSVIP = data['IsMember'] == 2; + bool isAd = data['Type'] == 2; + double imgHeight = 45.6; + + return Container( + margin: EdgeInsets.only(top: 5, bottom: 10), + child: Stack(children: [ + InkWell( + onTap: () async { + if (isAd) { + if (await canLaunch(data['HopeObject'])) { + await launch(data['HopeObject']); + } else { + throw 'Could not launch ${data['HopeObject']}'; + } + return; + } + if (data['UserId'] == UserData().basicInfo.userId) { + return; + } + // if (data['Sex'] == UserData().basicInfo.sex) { + // showToast(UserData().isMan() + // ? I18n.of(context).cant_see + // : I18n.of(context).cant_see2); + // return; + // } + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: data['UserId'], + ); + }, + ), + ); + }, + child: Stack( + children: [ + Padding( + padding: EdgeInsets.only( + top: 8.5, right: 19, left: 15, bottom: 0), + child: ClipRRect( + borderRadius: BorderRadius.circular(imgHeight), + child: + data['HeadimgUrl'] == null || data['HeadimgUrl'] == '' + ? Image.asset( + Constants.DefaultHeadImgUrl, + width: imgHeight, + height: imgHeight, + ) + : CachedNetworkImage( + height: imgHeight, + width: imgHeight, + imageUrl: data['HeadimgUrl'], + placeholder: (context, url) => Image.asset( + Constants.DefaultHeadImgUrl, + width: imgHeight, + height: imgHeight, + ), + fit: BoxFit.cover, + ), + )), + Positioned( + right: 15, + bottom: 0, + child: Container( + padding: EdgeInsets.only(bottom: 1.3, left: 0.5), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(20))), + child: Icon( + IconData( + isMan ? 0xe639 : 0xe638, + fontFamily: 'iconfont', + ), + color: isMan + ? const Color(0xff0072ff) + : const Color(0xffff0486), + size: 13, + ), + )) + ], + )), + Container( + margin: EdgeInsets.only(top: 3, left: imgHeight + 31), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 5), + Row( + children: [ + Container( + child: Text( + data['NickName'] == null || data['NickName'] == '' + ? '' + : WebData().subUserName( + Provider.of(context).getRefName( + data['UserId'], data['NickName'])), + textScaleFactor: 1.0, + style: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 16, + ), + )), + data['IsAttestation'] == 1 && !isMan + ? Container( + margin: EdgeInsets.only(left: 5), + padding: EdgeInsets.only( + top: 2, bottom: 2, left: 5, right: 5), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(3), + color: Constants.PurpleBackgroundColor, + ), + child: Text( + 'Real', + textScaleFactor: 1.0, + style: + TextStyle(fontSize: 8, color: Colors.white), + )) + : Text(''), + isVip && isMan + ? Container( + margin: EdgeInsets.only(left: 5), + child: + isSVIP ? Constants.svipIcon : Constants.vipIcon) + : Container(), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: isAd + ? Container( + margin: EdgeInsets.only(right: 10), + padding: EdgeInsets.symmetric( + horizontal: 5.5, vertical: 2.5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(3), + border: Border.all(color: Colors.grey)), + child: Text(I18n.of(context).ad, + style: TextStyle( + fontSize: 9, color: Colors.grey)), + ) + : Container(), + ), + ), + !isAd + ? Container( + alignment: Alignment.centerRight, + child: isMyself ? myPop : otherPop) + : Container(), + ], + ), + SizedBox(height: 8), + Row( + children: [ + Text( + WebData().getLoginTime(context, data['CreateTime']), + style: TextStyle( + color: const Color(0xFF5C5C5C), fontSize: 12), + ), + Expanded( + child: isMyself + ? Align( + alignment: Alignment.centerRight, + child: Container( + margin: EdgeInsets.only(right: 10), + padding: EdgeInsets.only( + left: 4, right: 4, top: 3, bottom: 3), + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.circular(10.0), + ), + child: Text( + I18n.of(context).i_posted, + style: TextStyle( + fontSize: 10, + color: Colors.grey[600], + ), + ), + )) + : Container(), + ) + ], + ) + ], + )), + ]), + ); + } +} diff --git a/lib/utils/MessageMgr.dart b/lib/utils/MessageMgr.dart new file mode 100644 index 0000000..59abf40 --- /dev/null +++ b/lib/utils/MessageMgr.dart @@ -0,0 +1,50 @@ +//订阅者回调签名 +typedef void EventCallback(arg); + +class MessageMgr { + + static const String REFRESH_PUSH_PERMISSION ='refresh_push_permission'; + static const String RECEIVE_THIRD_SHARE ='receive_third_share'; + + + //私有构造函数 + MessageMgr._internal(); + + //保存单例 + static MessageMgr _singleton = new MessageMgr._internal(); + + //工厂构造函数 + factory MessageMgr() => _singleton; + + //保存事件订阅者队列,key:事件名(id),value: 对应事件的订阅者队列 + var _emap = new Map>(); + + //添加订阅者 + void on(eventName, EventCallback f) { + if (eventName == null || f == null) return; + _emap[eventName] ??= new List(); + _emap[eventName].add(f); + } + + //移除订阅者 + void off(eventName, [EventCallback f]) { + var list = _emap[eventName]; + if (eventName == null || list == null) return; + if (f == null) { + _emap[eventName] = null; + } else { + list.remove(f); + } + } + + //触发事件,事件触发后该事件所有订阅者会被调用 + void emit(eventName, [arg]) { + var list = _emap[eventName]; + if (list == null) return; + int len = list.length - 1; + //反向遍历,防止在订阅者在回调中移除自身带来的下标错位 + for (var i = len; i > -1; --i) { + list[i](arg); + } + } +} diff --git a/lib/utils/MsgPacketUtil.dart b/lib/utils/MsgPacketUtil.dart new file mode 100644 index 0000000..6cb5276 --- /dev/null +++ b/lib/utils/MsgPacketUtil.dart @@ -0,0 +1,52 @@ +import 'package:buffer/buffer.dart'; +import 'dart:typed_data'; + +class MsgPacketModule { + int comId; + int msgId; + + List msg; + + MsgPacketModule({this.comId, this.msgId, this.msg}); +} + +class MsgPacketUtil { + static Uint8List encode(MsgPacketModule msgModule) { + int msgLen = msgModule.msg.length; + msgLen += 9; //修改为整体长度 + + var buffWriter = ByteDataWriter(bufferLength: msgLen, endian: Endian.big); + + buffWriter.writeInt16(msgModule.comId); + buffWriter.writeInt16(msgModule.msgId); + buffWriter.writeInt8(0x24); + + buffWriter.writeUint32(msgLen); + + buffWriter.write(msgModule.msg); + + return buffWriter.toBytes(); + } + + static decode(Uint8List msg) { + var decodeMsg = new MsgPacketModule(); + var buffReader = ByteDataReader(endian: Endian.big); + buffReader.add(msg); + + int cmdId = buffReader.readInt16(); + decodeMsg.comId = cmdId; + + int msgId = buffReader.readInt16(); + decodeMsg.msgId = msgId; + + buffReader.readInt8(); + + int msgLen = buffReader.readUint32(); + + if (msgLen > 9) { + decodeMsg.msg = buffReader.read(msgLen - 9); + } + + return decodeMsg; + } +} diff --git a/lib/utils/NetUtil.dart b/lib/utils/NetUtil.dart new file mode 100644 index 0000000..32a8d0e --- /dev/null +++ b/lib/utils/NetUtil.dart @@ -0,0 +1,449 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:buffer/buffer.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/net_state_util.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:chat/utils/upload_util.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:protobuf/protobuf.dart'; +import 'package:web_socket_channel/io.dart'; + +import 'HttpUtil.dart'; +import 'MessageMgr.dart'; +import 'TokenMgr.dart'; +import 'msgHandler.dart'; + +const HeartInverval = 30000; +const ReconnectCountLimit = 5; //重连次数限制 +const MinMsgmByteLen = 9; + +class NetWork { + //私有构造函数 + NetWork._internal(); + //保存单例 + static NetWork _singleton = new NetWork._internal(); + + //工厂构造函数 + factory NetWork() => _singleton; + static IOWebSocketChannel channel; + +// enum ChatState { +// connecting, //连接中 +// connected, //连接成功 +// connectFailed, //连接失败 +// logining, //登录中 +// logined, //登录成功 +// loginFailed //登录失败 +// } + + bool isLogin = false; //是否登录聊天服务器 + + int heartOutCount = 0; //超时次数 + int reconnectCount = 0; //重连次数 + + bool isConnecting = false; //避免重复连接 + bool isConnect = false; + bool isNormalClose = false; + + NetStateBloc _stateBloc = NetStateBloc(); //监控网络状态 + + Stream get stream => _stateBloc.stream; + + Timer heartTimer; + Timer sendTimer; + Timer connectServerTimer; //尝试连接服务器 + Timer loginTimer; //登录 + + // 计时器 + Timer iosBgTimer; //登录计时器 + + bool isInit = false; + + String host; + int port; + + static String serverIp; + + initNetWithServerInfo() { + var data = { + "userid": UserData().basicInfo.userId.toString(), + }; + data['sign'] = TokenMgr().getSign(data); + + HttpUtil().post('/service/config', data: data).then((res) { + print('获取聊天服务器地址成功'); + res = json.decode(res.toString()); + if (res['code'] == 0) { + var config = res['data'][0]; + + host = config['ip']; + port = config['port']; + print('host : $host port : $port'); + + // host = '192.168.0.139'; + // port = 9091; + + serverIp = 'ws://' + host + ':' + port.toString(); + + if (host == null || host.length == 0) { + // showToast('server url error : $host : $port'); + } else { + createWebSocket(); + _stateBloc.start(); + isInit = true; + } + } + }); + } + + checkChatState() { + print('检查聊天状态'); + if (!isConnect) { + print('没有连接'); + _stateBloc.addState(ChatState.connectFailed); + } else if (!isLogin) { + print('没有登录'); + _stateBloc.addState(ChatState.loginFailed); + } + } + + onData(dynamic message) { + //任何一条消息都作为心跳包处理 + receiveHeart(); + + if (message is String) { + print(message); + } else if (message is Uint8List) { + var buffReader = ByteDataReader(endian: Endian.big); + buffReader.add(message); + + int comId = buffReader.readInt16(); + + int msgId = buffReader.readInt16(); + + buffReader.readInt8(); + + int msgLen = buffReader.readUint32(); + if (message.length < msgLen) { + print('数据没有接受完毕'); + return; + } + + int pbLen = msgLen - MinMsgmByteLen; + + var content; + if (pbLen > 0) { + content = buffReader.read(pbLen); + } + + if (comId == ComId.Heart) { + if (msgId == 3) { + onConnect(); + } + } else if (comId == ComId.Login) { + if (msgId == 2) { + //登陆成功回应 + var msgContent = LoginAccountRes.fromBuffer(content); + if (msgContent.errorCode == 0) { + print('登录成功'); + isLogin = true; + _stateBloc.addState(ChatState.logined); + loginTimer?.cancel(); + MsgHandler.flushCacheMsg(); + UploadUtil().setUploadUrl(msgContent.httpAddr); + GroupInfoMgr().checkGroupValid(); + } else { + _stateBloc.addState(ChatState.loginFailed); + print('登录失败${msgContent.errorCode}'); + showToast(I18n.of(LoadingManage.context).fail); + } + } else if (msgId == 3) { + //用户登出,其他设备替换 + isLogin = false; + + var msgContent = PushUserOutLogin.fromBuffer(content); + print('登出原因:${msgContent.errorCode}'); + MessageMgr().emit('Login Out'); + } + } else { + MsgHandler.handlerServerMsg(comId, msgId, content); + } + } else { + print("Unknown datatype recieved : " + message.runtimeType.toString()); + } + } + + + onConnect() { + print('连接服务器成功'); + + connectServerTimer?.cancel(); + isNormalClose = false; + isConnect = true; + isConnecting = false; + heartOutCount = 0; + reconnectCount = 0; + + _stateBloc.addState(ChatState.connected); + + login(); + + startHeartTimer(); + } + + reLogin() { + if (isConnect) { + login(); + } else { + initNetWithServerInfo(); + } + } + + void sendMsg(int comId, int msgId, [GeneratedMessage pb]) { + //序列化pb对象 + Uint8List pbBody; + int pbLen = 0; + if (pb != null) { + pbBody = pb.writeToBuffer(); + pbLen = pbBody.length; + } + + //包头部分 + var msgLen = pbLen + MinMsgmByteLen; //整体长度 + + var buffWriter = ByteDataWriter(bufferLength: msgLen, endian: Endian.big); + + buffWriter.writeInt16(comId); + buffWriter.writeInt16(msgId); + buffWriter.writeInt8(0x24); + + buffWriter.writeUint32(msgLen); + + if (pbLen > 0) { + buffWriter.write(pbBody); + } + + var finalMsg = buffWriter.toBytes(); + + //给服务器发消息 + try { + if (channel != null && channel.closeCode == null && isConnect) { + // print("发送消息"); + channel.sink.add(finalMsg); + } else { + reconnect(); + print('channel 为空,无法发送消息'); + } + } catch (e) { + print("send捕获异常e=${e.toString()}"); + } + } + + startHeartTimer() { + heartOutCount = 0; + + heartTimer?.cancel(); + print('开始心跳计时器'); + heartTimer = Timer.periodic(Duration(milliseconds: HeartInverval), (t) { + sendHeart(); + }); + } + + receiveHeart() { + //print('收到心跳${DateTime.now()}'); + heartOutCount = 0; + sendTimer?.cancel(); + } + + sendHeart() { + if (heartOutCount < 3) { + // print('发送心跳${DateTime.now()}'); + sendMsg(ComId.Heart, 1); + sendTimer = Timer(Duration(milliseconds: HeartInverval), () { + //超时了,次数加1 + heartOutCount += 1; + print('心跳超时$heartOutCount次'); + }); + } else { + print('心跳次数大于 $heartOutCount'); + close(); + // createWebSocket(); + } + } + + close() { + print('清除连接状态'); + if (isConnecting) { + print('连接状态,返回'); + return; + } + isConnecting = false; + isConnect = false; + isLogin = false; + heartOutCount = 0; + sendTimer?.cancel(); + heartTimer?.cancel(); + + loginTimer?.cancel(); + print('清除计时器'); + connectServerTimer?.cancel(); + + if (channel != null) { + channel.sink.close(); + channel = null; + } + } + + + + reallyClose() { + + if(iosBgTimer==null){ + debugPrint('#### ios bg 没有计时器--计时器你启动'); + iosBgTimer = Timer(Duration(seconds: 20), () async{ + debugPrint('#### ios bg ios后台关闭socket连接'); + isNormalClose=true; + isConnecting = false; + isConnect = false; + isLogin = false; + heartOutCount = 0; + sendTimer?.cancel(); + heartTimer?.cancel(); + + loginTimer?.cancel(); + connectServerTimer?.cancel(); + + if (channel != null) { + await channel.sink.close(); + channel = null; + } + }); + }else{ + debugPrint('#### ios bg 已有计时器'); + } + + + + + } + + + checkConnect() { + debugPrint(' ios bg 取消计时器'); + iosBgTimer?.cancel(); + + if (isInit && !isConnect && !isConnecting) { + reconnect(); + } else { + if (!isLogin) { + login(); + } + } + } + + createWebSocket() { + if (isConnecting) { + return; + } + if (channel != null) { + channel.sink.close(); + channel = null; + } + + connectServerTimer?.cancel(); + print('尝试连接服务器'); + isConnecting = true; + _stateBloc.addState(ChatState.connecting); + + reconnectCount += 1; + if (reconnectCount > ReconnectCountLimit) { + print('重连数次超出'); + _stateBloc.addState(ChatState.connectFailed); + isConnecting = false; + close(); + return; + } + + try { + channel = IOWebSocketChannel.connect(serverIp); + channel.stream.listen( + onData, + onDone: onDone, + onError: onError, + ); + } catch (e) { + // showToast('连接错误${e.toString()}'); + isConnecting = false; + //_stateBloc.addState(ChatState.connectFailed); + } + } + + login() { + var myId = UserData().basicInfo.userId; + if (myId == null) { + return; + } + + var data = { + "userid": UserData().basicInfo.userId, + }; + + LoginAccountReq req = LoginAccountReq.create(); + req.userId = data['userid']; + req.sigin = TokenMgr().getSign(data); + + print('发送登陆消息'); + + loginTimer = Timer(Duration(milliseconds: 3000), () { + _stateBloc.addState(ChatState.loginFailed); + }); + sendMsg(ComId.Login, 1, req); + _stateBloc.addState(ChatState.logining); + } + + singOut() { + print('用户登出'); + //清缓存 + ChatDataMgr().logout(); + MsgHandler.clear(); + + isNormalClose = true; + close(); + } + + onError(error) { + isConnecting = false; + print('ws error $error'); + } + + reconnect() { + close(); + reconnectCount = 0; + + if (host == null || host.length == 0) { + initNetWithServerInfo(); + } else { + createWebSocket(); + } + } + + onDone() { + print('ws channel closed${DateTime.now()}'); + close(); + if (!isNormalClose ) { + print('无法连接聊天服务器,5秒后重新连接'); + connectServerTimer = Timer(Duration(seconds: 5), () { + createWebSocket(); + }); + } + } +} diff --git a/lib/utils/OtherLogin.dart b/lib/utils/OtherLogin.dart new file mode 100644 index 0000000..e73fe00 --- /dev/null +++ b/lib/utils/OtherLogin.dart @@ -0,0 +1,218 @@ +import 'dart:io'; + +import 'package:apple_sign_in/apple_sign_in.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_facebook_login/flutter_facebook_login.dart'; +import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx; +import 'package:oktoast/oktoast.dart'; +import 'package:wifi_info_plugin/wifi_info_plugin.dart'; +import 'HttpUtil.dart'; +import 'LoadingDialog.dart'; +import 'TokenMgr.dart'; +import 'apple_sign_in_btn.dart' as apple; + +class OtherLogin { + static final FacebookLogin facebookSignIn = new FacebookLogin(); + + static bool isAvailableForAppleSignIn = false; + + ///是否支持苹果登录-ios苹果登录只支持ios13+手机 + + Widget _buildSelection(context) { + List loginList = []; + + if(Platform.isAndroid ){ +// fluwx.isWeChatInstalled() 这里ios要判断是否已经安装 + loginList.add(InkWell( + borderRadius: BorderRadius.all(Radius.circular(30.0)), + child: new Image.asset( + 'assets/images/login/dly_icon2.png', + height: 24, + ), + onTap: () { + print('微信登陆'); + fluwx.sendAuth( + scope: "snsapi_userinfo", state: "wechat_sdk_demo_test"); + }, + )); + } + loginList.add(InkWell( + borderRadius: BorderRadius.all(Radius.circular(30.0)), + child: new Image.asset( + 'assets/images/login/dly_icon3.png', + height: 24, + ), + onTap: () async { + print('facebook'); + facebookSignIn.loginBehavior = FacebookLoginBehavior.webViewOnly; + final FacebookLoginResult result = + await facebookSignIn.logIn(['email']); + + switch (result.status) { + case FacebookLoginStatus.loggedIn: + final FacebookAccessToken accessToken = result.accessToken; + thirdLogin(context, accessToken.userId, 0); + + break; + case FacebookLoginStatus.cancelledByUser: + break; + case FacebookLoginStatus.error: + break; + } + }, + )); + if (isAvailableForAppleSignIn) { + loginList.add(apple.AppleSignInBtn( + style: apple.ButtonStyle.black, + type: apple.ButtonType.signIn, + onPressed: () async { + print('apple sign in'); + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return LoadingDialog( + text: "", + ); + }); + final AuthorizationResult result = await AppleSignIn.performRequests([ + AppleIdRequest(requestedScopes: [Scope.fullName]) + ]); + Navigator.of(context).pop(); + switch (result.status) { + case AuthorizationStatus.authorized: + print('result.credential.user:${result.credential.user}'); + // Store user ID + thirdLogin(context, result.credential.user, 2); + break; + case AuthorizationStatus.error: + print("Sign in failed: ${result.error.localizedDescription}"); + break; + case AuthorizationStatus.cancelled: + print('User cancelled'); + break; + } + }, + )); +// loginList.add(InkWell( +// borderRadius: BorderRadius.all(Radius.circular(30.0)), +// child: new Image.asset( +// 'assets/images/login/dly_icon4.png', +// height: 24, +// ), +// onTap: () async { +// print('apple sign in'); +// showDialog( +// context: context, +// barrierDismissible: false, +// builder: (BuildContext context) { +// return LoadingDialog( +// text: "", +// ); +// }); +// final AuthorizationResult result = await AppleSignIn.performRequests([ +// AppleIdRequest(requestedScopes: [Scope.fullName]) +// ]); +// Navigator.of(context).pop(); +// switch (result.status) { +// case AuthorizationStatus.authorized: +// print('result.credential.user:${result.credential.user}'); +// // Store user ID +// thirdLogin(context, result.credential.user, 2); +// break; +// case AuthorizationStatus.error: +// print("Sign in failed: ${result.error.localizedDescription}"); +// break; +// case AuthorizationStatus.cancelled: +// print('User cancelled'); +// break; +// } +// }, +// )); + } + + return new Container( + width: MediaQuery.of(context).size.width * 0.7, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: loginList, + ), + ); + } + + thirdLogin(BuildContext context, String onlyId, int type) async { + var data = { + "onlyid": onlyId, + "type": type, + "language": UserData().language, + }; + data['sign'] = TokenMgr().getSign(data); + data['openid'] = onlyId; + data['lng'] = UserData().longitude; + data['lat'] = UserData().latitude; + + try { + WifiInfoWrapper wifiObject = await WifiInfoPlugin.wifiDetails; + if (wifiObject != null) { + data['routerName'] = wifiObject.ssid; + data['mac'] = wifiObject.bssId; + } + } catch (e) { + print(e); + } + + Response res = await HttpUtil() + .post('user/auth/login', data: data, isShowLoading: true); + var resData = res.data; + print('user/auth/login $resData'); + if (resData['code'] != 0) { + showToast(resData['msg']); + return; + } + if (resData['data'] != null) { + HttpUtil().changePage(context, resData); + } + } + + Widget builder(context) { + return Column( + children: [ + _buildBottomLabel(context), + SizedBox(height: 10), + _buildSelection(context), + SizedBox(height: 20), + ], + ); + } + + Widget _buildBottomLabel(context) { + return new Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + new SizedBox( + width: MediaQuery.of(context).size.width * 0.3, + child: Divider( + height: 1.0, + color: Colors.grey, + ), + ), + fixedText( + I18n.of(context).other_login, + color: Colors.grey[500], + fontSize: 11.34, + ), + new SizedBox( + width: MediaQuery.of(context).size.width * 0.3, + child: Divider( + height: 1.0, + color: Colors.grey, + ), + ), + ], + ); + } +} diff --git a/lib/utils/PicSwiper.dart b/lib/utils/PicSwiper.dart new file mode 100644 index 0000000..eda75e9 --- /dev/null +++ b/lib/utils/PicSwiper.dart @@ -0,0 +1,908 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:math'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/VipPage.dart'; +import 'package:chat/models/money_change.dart'; +import 'package:chat/utils/CustomUI.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:chat/utils/flutter_windowmanager.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:dio/dio.dart'; +import 'package:extended_image/extended_image.dart'; +import 'dart:ui' as ui; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:provider/provider.dart'; +import 'ChargeMoney.dart'; + +double initScale({Size imageSize, Size size, double initialScale}) { + var n1 = imageSize.height / imageSize.width; + var n2 = size.height / size.width; + if (n1 > n2) { + final FittedSizes fittedSizes = + applyBoxFit(BoxFit.contain, imageSize, size); + //final Size sourceSize = fittedSizes.source; + Size destinationSize = fittedSizes.destination; + return size.width / destinationSize.width; + } else if (n1 / n2 < 1 / 4) { + final FittedSizes fittedSizes = + applyBoxFit(BoxFit.contain, imageSize, size); + //final Size sourceSize = fittedSizes.source; + Size destinationSize = fittedSizes.destination; + return size.height / destinationSize.height; + } + + return initialScale; +} + +class PicSwiper extends StatefulWidget { + final int id; + final List pics; + PicSwiper({this.id, this.pics}); + @override + _PicSwiperState createState() => _PicSwiperState(); +} + +class _PicSwiperState extends State + with SingleTickerProviderStateMixin { + var rebuildIndex = StreamController.broadcast(); + var rebuildSwiper = StreamController.broadcast(); + AnimationController _animationController; + Animation _animation; + Function animationListener; + +// CancellationToken _cancelToken; +// CancellationToken get cancelToken { +// if (_cancelToken == null || _cancelToken.isCanceled) +// _cancelToken = CancellationToken(); +// +// return _cancelToken; +// } + List doubleTapScales = [1.0, 2.0]; + GlobalKey slidePagekey = + GlobalKey(); + int currentIndex; + bool _showSwiper = true; + int _seconds = 0; + bool isMyself = false; + @override + void initState() { + setDisableScreenshots(); + for (int i = 0; i < widget.pics.length; i++) { + if (widget.id == widget.pics[i].id) { + currentIndex = i; + break; + } + } + isMyself = widget.pics[0].userId == UserData().basicInfo.userId; + _animationController = AnimationController( + duration: const Duration(milliseconds: 150), vsync: this); + + super.initState(); + } + + setDisableScreenshots() async { + print('Platform.isAndroid ${Platform.isAndroid}'); + if (Platform.isAndroid) { + await FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE); + } + } + + clearFalgs() async { + if (Platform.isAndroid) { + await FlutterWindowManager.clearFlags(FlutterWindowManager.FLAG_SECURE); + } + } + + @override + void dispose() { + rebuildIndex.close(); + rebuildSwiper.close(); + _animationController?.dispose(); + clearGestureDetailsCache(); + clearFalgs(); + //cancelToken?.cancel(); + super.dispose(); + } + + void browsePhoto(id, userId, type, callback, {price = 0}) async { + if (Provider.of(context).money < price) { + CustomUI.buildOneConfirm(context, I18n.of(context).balance_insufficien, + I18n.of(context).recharge, () { + Navigator.of(context).pop(); + ChargeMoney.showChargeSheet(context, () { + setState(() {}); + }); + }); + return; + } + var data = { + "visitUserId": UserData().basicInfo.userId, + "userId": userId, + "pId": id, + 'type': type, + }; + data['sign'] = TokenMgr().getSign(data); + data['price'] = price; + Response res = await HttpUtil().post('user/browse/photo', data: data); + Map resData = res.data; + print(resData); + if (resData['code'] == 0) { + MessageMgr().emit('refresh_photo', id); + callback(); + } + } + + @override + Widget build(BuildContext context) { + var size = MediaQuery.of(context).size; + bool isAgree = (widget.pics[currentIndex].type == PhotoType.destroy.index || + widget.pics[currentIndex].type == PhotoType.destroyMoney.index); + var id = widget.pics[currentIndex].id; + Widget result = Scaffold( + // StreamBuilder( + // builder: (BuildContext context, data) {}, + // initialData: true, + // stream: rebuildSwiper.stream, + // ), + appBar: AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: StreamBuilder( + builder: (BuildContext context, data) { + return Text( + '${data.data + 1} / ${widget.pics.length}', + style: TextStyle( + fontSize: 16, color: AppColors.NewAppbarTextColor), + textScaleFactor: 1.0, + ); + }, + initialData: currentIndex, + stream: rebuildIndex.stream, + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + elevation: 1, + actions: [ + isMyself + ? InkWell( + onTap: () { + CustomUI.buildOneConfirm( + context, + I18n.of(context).sure_delete, + I18n.of(context).determine, () { + var id = widget.pics[currentIndex].id; + HttpUtil().setPhote(context, id, 2, () { + widget.pics.removeAt(currentIndex); + MessageMgr().emit('refresh_photo', id); + if (widget.pics.length == 0) { + Navigator.of(context).pop(); + } else { + setState(() { + if (currentIndex != 0) currentIndex--; + }); + } + }); + Navigator.of(context).pop(); + }); + }, + child: Container( + margin: EdgeInsets.only(right: 10), + child: CircleAvatar( + backgroundColor: Constants.GreyBackgroundColor, + radius: 13.75, + child: Icon( + Icons.delete, + color: Constants.BlackTextColor, + size: 20, + ))), + ) + : Container() + ], + ), + backgroundColor: Colors.black, + + /// if you use ExtendedImageSlidePage and slideType =SlideType.onlyImage, + /// make sure your page is transparent background + // color: Colors.white, + // shadowColor: Colors.transparent, + bottomNavigationBar: isMyself + ? Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border(top: Constants.GreyBorderSide)), + height: 40, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Checkbox( + value: isAgree, + activeColor: Colors.blue, + onChanged: (bool val) { + HttpUtil().setPhote(context, id, isAgree ? 0 : 1, () { + this.setState(() { + isAgree = !isAgree; + //如果是红包照片焚阅照片则变成红包照片 + //如果是普通焚阅照片则变成普通照片 + MessageMgr().emit('refresh_photo'); + if (isAgree) { + if (widget.pics[currentIndex].type == + PhotoType.free.index) { + widget.pics[currentIndex].type = + PhotoType.destroy.index; + } + if (widget.pics[currentIndex].type == + PhotoType.money.index) { + widget.pics[currentIndex].type = + PhotoType.destroyMoney.index; + } + } else { + if (widget.pics[currentIndex].type == + PhotoType.destroy.index) { + widget.pics[currentIndex].type = + PhotoType.free.index; + } + if (widget.pics[currentIndex].type == + PhotoType.destroyMoney.index) { + widget.pics[currentIndex].type = + PhotoType.money.index; + } + } + }); + }); + }, + ), + fixedText(I18n.of(context).destroy_after) + ], + ), + ) + : Container( + height: 0, + ), + body: Stack( + //fit: StackFit.expand, + children: [ + ExtendedImageGesturePageView.builder( + itemBuilder: (BuildContext context, int index) { + var item = widget.pics[index]; + var picUrl = item.picUrl; + var file = item.file; + var _timer; + + bool isShow = _seconds != 0; + + _cancelTimer() { + item.isWatch = true; + _seconds = 0; + _timer?.cancel(); + } + + _startTimer() { + if (UserData().isMan()) { + _seconds = + UserData().isSuperVip ? 6 : (UserData().isVip ? 4 : 2); + } else { + _seconds = UserData().basicInfo.isAttestation ? 6 : 2; + } + + _timer = + new Timer.periodic(new Duration(seconds: 1), (timer) { + _seconds--; + + setState(() {}); + if (_seconds <= 0) { + _cancelTimer(); + } + }); + } + + Widget image; + if (file != null) { + image = ExtendedImage.file( + file, + fit: BoxFit.contain, + //enableSlideOutPage: true, + mode: ExtendedImageMode.gesture, + initGestureConfigHandler: (state) { + double initialScale = 1.0; + + if (state.extendedImageInfo != null && + state.extendedImageInfo.image != null) { + initialScale = initScale( + size: size, + initialScale: initialScale, + imageSize: Size( + state.extendedImageInfo.image.width.toDouble(), + state.extendedImageInfo.image.height + .toDouble())); + } + return GestureConfig( + inPageView: true, + initialScale: initialScale, + maxScale: max(initialScale, 5.0), + initialAlignment: InitialAlignment.topCenter, + animationMaxScale: max(initialScale, 5.0), + //you can cache gesture state even though page view page change. + //remember call clearGestureDetailsCache() method at the right time.(for example,this page dispose) + cacheGesture: false); + }, + onDoubleTap: (ExtendedImageGestureState state) { + //you can use define pointerDownPosition as you can, + //default value is double tap pointer down postion. + var pointerDownPosition = state.pointerDownPosition; + double begin = state.gestureDetails.totalScale; + double end; + + //remove old + _animation?.removeListener(animationListener); + + //stop pre + _animationController.stop(); + + //reset to use + _animationController.reset(); + + if (begin == doubleTapScales[0]) { + end = doubleTapScales[1]; + } else { + end = doubleTapScales[0]; + } + + animationListener = () { + //print(_animation.value); + state.handleDoubleTap( + scale: _animation.value, + doubleTapPosition: pointerDownPosition); + }; + _animation = _animationController + .drive(Tween(begin: begin, end: end)); + + _animation.addListener(animationListener); + + _animationController.forward(); + }, + ); + } else { + image = ExtendedImage.network( + picUrl, + fit: BoxFit.contain, + // enableSlideOutPage: true, + mode: ExtendedImageMode.gesture, + initGestureConfigHandler: (state) { + double initialScale = 1.0; + + if (state.extendedImageInfo != null && + state.extendedImageInfo.image != null) { + initialScale = initScale( + size: size, + initialScale: initialScale, + imageSize: Size( + state.extendedImageInfo.image.width.toDouble(), + state.extendedImageInfo.image.height + .toDouble())); + } + return GestureConfig( + inPageView: true, + initialScale: initialScale, + maxScale: max(initialScale, 5.0), + initialAlignment: InitialAlignment.topCenter, + animationMaxScale: max(initialScale, 5.0), + //you can cache gesture state even though page view page change. + //remember call clearGestureDetailsCache() method at the right time.(for example,this page dispose) + cacheGesture: false); + }, + onDoubleTap: (ExtendedImageGestureState state) { + //you can use define pointerDownPosition as you can, + //default value is double tap pointer down postion. + var pointerDownPosition = state.pointerDownPosition; + double begin = state.gestureDetails.totalScale; + double end; + + //remove old + _animation?.removeListener(animationListener); + + //stop pre + _animationController.stop(); + + //reset to use + _animationController.reset(); + + if (begin == doubleTapScales[0]) { + end = doubleTapScales[1]; + } else { + end = doubleTapScales[0]; + } + + animationListener = () { + //print(_animation.value); + state.handleDoubleTap( + scale: _animation.value, + doubleTapPosition: pointerDownPosition); + }; + _animation = _animationController + .drive(Tween(begin: begin, end: end)); + + _animation.addListener(animationListener); + + _animationController.forward(); + }, + ); + } + + image = GestureDetector( + child: Container( + child: image, + ), + onTap: () { + slidePagekey.currentState.popPage(); + Navigator.pop(context); + }, + ); + //滤镜背景 + var bg = Center( + child: ClipRect( + //裁切长方形 + child: BackdropFilter( + //背景滤镜器 + filter: ui.ImageFilter.blur( + sigmaX: 20.0, sigmaY: 20.0), //图片模糊过滤,横向竖向都设置5.0 + child: Opacity( + //透明控件 + opacity: 0.5, + child: Container( + alignment: Alignment.center, + width: Screen.width, + height: Screen.height, + color: Colors.black, + ), + ), + ), + ), + ); + + //焚阅照片 + if ((item.type == PhotoType.destroy.index || + item.type == PhotoType.destroyMoney.index && + item.isBuy) && + item.userId != UserData().basicInfo.userId) { + image = GestureDetector( + onLongPress: item.isWatch + ? null + : () { + browsePhoto(item.id, item.userId, 1, () { + _startTimer(); + setState(() {}); + }); + }, + onLongPressEnd: item.isWatch + ? null + : (detail) { + _cancelTimer(); + setState(() {}); + }, + onTap: () { + slidePagekey.currentState.popPage(); + Navigator.pop(context); + }, + child: Container( + color: Colors.grey.shade200, + child: Stack( + alignment: Alignment.center, + children: [ + image, + isShow + ? Container() + : Stack( + alignment: Alignment.center, + children: [ + bg, + item.isWatch + ? Container( + height: 211, + width: 275.5, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.all( + Radius.circular( + 5))), + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + IconData( + 0xe634, + fontFamily: 'iconfont', + ), + color: const Color( + 0xFFA7A7A7), + size: 50, + ), + fixedText( + I18n.of(context) + .destroyed, + fontSize: 16, + color: const Color( + 0xFFA7A7A7)), + UserData().isVip || + UserData() + .basicInfo + .sex == + 2 + ? Container() + : fixedText( + I18n.of(context) + .longTime, + color: Colors + .grey[700], + fontSize: 12), + UserData().isVip || + UserData() + .basicInfo + .sex == + 2 + ? Container() + : SizedBox(height: 10), + UserData().isVip || + UserData() + .basicInfo + .sex == + 2 + ? Container() + : RaisedButton( + color: Colors.blue, + onPressed: () { + Navigator.of( + context) + .push( + new MaterialPageRoute( + builder: + (context) { + return VipPage(); + }, + ), + ); + }, + child: fixedText( + I18n.of(context) + .joinvip, + color: Colors + .white), + ) + ], + )) + : Container( + height: 211, + width: 275.5, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.all( + Radius.circular( + 5))), + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Padding( + padding: + EdgeInsets.only( + top: 10, + bottom: 2), + child: Icon( + IconData( + 0xe634, + fontFamily: + 'iconfont', + ), + color: const Color( + 0xFFF44236), + size: 50, + )), + fixedText( + I18n.of(context) + .destroy_after, + color: const Color( + 0xFFF44236), + fontSize: 15), + Padding( + padding: EdgeInsets.only( + top: 25, bottom: 15), + child: fixedText( + I18n.of(context) + .longClick, + color: const Color( + 0xFFFA8880), + fontSize: 12), + ), + Image.asset( + 'assets/images/zhiwen.png', + height: 55, + ) + ], + )) + ], + ) + ], + ))); + } + + //红包照片 + if ((item.type == PhotoType.money.index || + (item.type == PhotoType.destroyMoney.index && + !item.isBuy)) && + item.userId != UserData().basicInfo.userId) { + image = GestureDetector( + onTap: () { + slidePagekey.currentState.popPage(); + Navigator.pop(context); + }, + child: Container( + color: Colors.grey.shade200, + child: Stack( + alignment: Alignment.center, + children: [ + image, + item.isBuy + ? Container() + : Stack( + alignment: Alignment.center, + children: [ + bg, + Stack( + alignment: Alignment.center, + children: [ + Image.asset( + 'assets/images/login/money.png', + fit: BoxFit.fitWidth, + width: 220, + ), + Container( + margin: EdgeInsets.only(top: 65), + child: fixedText( + I18n.of(context) + .less_coin + .replaceFirst( + '/s1', + UserData() + .redPhotoPrice + .toString()), + color: + const Color(0xFFFAE6B4), + fontSize: 25), + ), + InkWell( + onTap: () { + CustomUI.buildOneConfirm( + context, + I18n.of(context) + .pay_unlock + .replaceFirst( + '/s1', + UserData() + .redPhotoPrice + .toString()), + I18n.of(context) + .confirm_pay, () { + browsePhoto( + item.id, item.userId, 2, + () { + setState(() { + Navigator.of(context) + .pop(); + MessageMgr().emit( + 'refresh_photo', + item.id); + item.isBuy = true; + }); + }, + price: UserData() + .redPhotoPrice); + }); + }, + child: Container( + decoration: BoxDecoration( + color: const Color( + 0xFFFAE6B4), + borderRadius: + BorderRadius.all( + Radius.circular( + 30))), + padding: EdgeInsets.only( + left: 40, + right: 40, + top: 5, + bottom: 5), + margin: + EdgeInsets.only(top: 140), + child: fixedText( + I18n.of(context) + .determine, + color: const Color( + 0xFF7B0408)), + )) + ], + ) + ], + ) + ], + ))); + } + + if (index == currentIndex) { + return Hero( + tag: picUrl + index.toString(), + child: image, + flightShuttleBuilder: (BuildContext flightContext, + Animation animation, + HeroFlightDirection flightDirection, + BuildContext fromHeroContext, + BuildContext toHeroContext) { + final Hero hero = + flightDirection == HeroFlightDirection.pop + ? fromHeroContext.widget + : toHeroContext.widget; + return hero.child; + }, + ); + } else { + return image; + } + }, + itemCount: widget.pics.length, + onPageChanged: (int index) { + currentIndex = index; + rebuildIndex.add(index); + }, + controller: PageController( + initialPage: currentIndex, + ), + scrollDirection: Axis.horizontal, + physics: BouncingScrollPhysics(), + ), + _seconds == 0 + ? Container() + : Container( + padding: EdgeInsets.only(bottom: 30), + alignment: Alignment.bottomCenter, + child: Stack( + alignment: Alignment.center, + children: [ + CircularProgressIndicator( + strokeWidth: 4.0, + backgroundColor: Colors.grey, + value: _seconds / 6, + valueColor: + new AlwaysStoppedAnimation(Colors.red), + ), + fixedText(_seconds.toString(), color: Colors.red) + // Positioned( + // top: 8, + // left: 13, + // child: + // fixedText(_seconds.toString(), color: Colors.red), + // ) + ], + )), + ], + )); + + result = ExtendedImageSlidePage( + key: slidePagekey, + child: result, + slideAxis: SlideAxis.both, + slideType: SlideType.onlyImage, + onSlidingPage: (state) { + ///you can change other widgets' state on page as you want + ///base on offset/isSliding etc + //var offset= state.offset; + var showSwiper = !state.isSliding; + if (showSwiper != _showSwiper) { + // do not setState directly here, the image state will change, + // you should only notify the widgets which are needed to change + // setState(() { + // _showSwiper = showSwiper; + // }); + + _showSwiper = showSwiper; + rebuildSwiper.add(_showSwiper); + } + }, + ); + + return result; + } +} + +class MySwiperPlugin extends StatelessWidget { + final List pics; + final int index; + final StreamController reBuild; + final bool isMyself; + final callback; + MySwiperPlugin( + this.pics, this.index, this.reBuild, this.isMyself, this.callback); + @override + Widget build(BuildContext context) { + return StreamBuilder( + builder: (BuildContext context, data) { + return DefaultTextStyle( + style: TextStyle(color: Colors.white), + child: Container( + //alignment: Alignment.center, + height: 50.0, + width: double.infinity, + color: Colors.white, + child: Row( + children: [ + InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + margin: EdgeInsets.only(left: 10), + child: Icon( + Icons.chevron_left, + color: Constants.BlackTextColor, + )), + ), + Expanded( + child: Container( + alignment: Alignment.center, + child: fixedText("${data.data + 1} / ${pics.length}", + color: Constants.BlackTextColor))), + isMyself + ? InkWell( + onTap: () { + CustomUI.buildOneConfirm( + context, + I18n.of(context).sure_delete, + I18n.of(context).determine, () { + callback(index); + Navigator.of(context).pop(); + }); + }, + child: Container( + margin: EdgeInsets.only(right: 10), + child: Icon( + Icons.delete, + color: Constants.BlackTextColor, + )), + ) + : Container(), + ], + )), + ); + }, + initialData: index, + stream: reBuild.stream, + ); + } +} + +class PicSwiperItem { + var userId; + int id; + String picUrl; + String des; + File file; + int type; + bool isBuy; //是否购买 + bool isWatch; //是否观看 + PicSwiperItem( + this.picUrl, { + this.file, + this.id, + this.des = "", + this.type = 0, + this.isBuy = false, + this.isWatch = false, + this.userId, + }); +} diff --git a/lib/utils/PopUpMenu.dart b/lib/utils/PopUpMenu.dart new file mode 100644 index 0000000..a636ebe --- /dev/null +++ b/lib/utils/PopUpMenu.dart @@ -0,0 +1,967 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +// Examples can assume: +// enum Commands { heroAndScholar, hurricaneCame } +// dynamic _heroAndScholar; +// dynamic _selection; +// BuildContext context; +// void setState(VoidCallback fn) { } + +const Duration _kMenuDuration = Duration(milliseconds: 300); +const double _kMenuCloseIntervalEnd = 2.0 / 3.0; +const double _kMenuItemHeight = 48.0; +const double _kMenuDividerHeight = 16.0; +const double _kMenuMaxWidth = 5.0 * _kMenuWidthStep; +const double _kMenuMinWidth = 2.0 * _kMenuWidthStep; +const double _kMenuVerticalPadding = 0; // 8.0; +const double _kMenuWidthStep = 56.0; +const double _kMenuScreenPadding = 8.0; + +/// A base class for entries in a material design popup menu. +/// +/// The popup menu widget uses this interface to interact with the menu items. +/// To show a popup menu, use the [showMenu] function. To create a button that +/// shows a popup menu, consider using [PopupMenuButton]. +/// +/// The type `T` is the type of the value(s) the entry represents. All the +/// entries in a given menu must represent values with consistent types. +/// +/// A [PopupMenuEntry] may represent multiple values, for example a row with +/// several icons, or a single entry, for example a menu item with an icon (see +/// [PopupMenuItem]), or no value at all (for example, [PopupMenuDivider]). +/// +/// See also: +/// +/// * [PopupMenuItem], a popup menu entry for a single value. +/// * [PopupMenuDivider], a popup menu entry that is just a horizontal line. +/// * [CheckedPopupMenuItem], a popup menu item with a checkmark. +/// * [showMenu], a method to dynamically show a popup menu at a given location. +/// * [PopupMenuButton], an [IconButton] that automatically shows a menu when +/// it is tapped. +abstract class PopupMenuEntry extends StatefulWidget { + /// Abstract const constructor. This constructor enables subclasses to provide + /// const constructors so that they can be used in const expressions. + const PopupMenuEntry({Key key}) : super(key: key); + + /// The amount of vertical space occupied by this entry. + /// + /// This value is used at the time the [showMenu] method is called, if the + /// `initialValue` argument is provided, to determine the position of this + /// entry when aligning the selected entry over the given `position`. It is + /// otherwise ignored. + double get height; + + /// Whether this entry represents a particular value. + /// + /// This method is used by [showMenu], when it is called, to align the entry + /// representing the `initialValue`, if any, to the given `position`, and then + /// later is called on each entry to determine if it should be highlighted (if + /// the method returns true, the entry will have its background color set to + /// the ambient [ThemeData.highlightColor]). If `initialValue` is null, then + /// this method is not called. + /// + /// If the [PopupMenuEntry] represents a single value, this should return true + /// if the argument matches that value. If it represents multiple values, it + /// should return true if the argument matches any of them. + bool represents(T value); +} + +/// A horizontal divider in a material design popup menu. +/// +/// This widget adapts the [Divider] for use in popup menus. +/// +/// See also: +/// +/// * [PopupMenuItem], for the kinds of items that this widget divides. +/// * [showMenu], a method to dynamically show a popup menu at a given location. +/// * [PopupMenuButton], an [IconButton] that automatically shows a menu when +/// it is tapped. +// ignore: prefer_void_to_null, https://github.com/dart-lang/sdk/issues/34416 +class PopupMenuDivider extends PopupMenuEntry { + /// Creates a horizontal divider for a popup menu. + /// + /// By default, the divider has a height of 16 logical pixels. + const PopupMenuDivider({Key key, this.height = _kMenuDividerHeight}) + : super(key: key); + + /// The height of the divider entry. + /// + /// Defaults to 16 pixels. + @override + final double height; + + @override + bool represents(void value) => false; + + @override + _PopupMenuDividerState createState() => _PopupMenuDividerState(); +} + +class _PopupMenuDividerState extends State { + @override + Widget build(BuildContext context) => Divider(height: widget.height); +} + +/// An item in a material design popup menu. +/// +/// To show a popup menu, use the [showMenu] function. To create a button that +/// shows a popup menu, consider using [PopupMenuButton]. +/// +/// To show a checkmark next to a popup menu item, consider using +/// [CheckedPopupMenuItem]. +/// +/// Typically the [child] of a [PopupMenuItem] is a [Text] widget. More +/// elaborate menus with icons can use a [ListTile]. By default, a +/// [PopupMenuItem] is 48 pixels high. If you use a widget with a different +/// height, it must be specified in the [height] property. +/// +/// {@tool sample} +/// +/// Here, a [Text] widget is used with a popup menu item. The `WhyFarther` type +/// is an enum, not shown here. +/// +/// ```dart +/// const PopupMenuItem( +/// value: WhyFarther.harder, +/// child: Text('Working a lot harder'), +/// ) +/// ``` +/// {@end-tool} +/// +/// See the example at [PopupMenuButton] for how this example could be used in a +/// complete menu, and see the example at [CheckedPopupMenuItem] for one way to +/// keep the text of [PopupMenuItem]s that use [Text] widgets in their [child] +/// slot aligned with the text of [CheckedPopupMenuItem]s or of [PopupMenuItem] +/// that use a [ListTile] in their [child] slot. +/// +/// See also: +/// +/// * [PopupMenuDivider], which can be used to divide items from each other. +/// * [CheckedPopupMenuItem], a variant of [PopupMenuItem] with a checkmark. +/// * [showMenu], a method to dynamically show a popup menu at a given location. +/// * [PopupMenuButton], an [IconButton] that automatically shows a menu when +/// it is tapped. +class PopupMenuItem extends PopupMenuEntry { + /// Creates an item for a popup menu. + /// + /// By default, the item is [enabled]. + /// + /// The `height` and `enabled` arguments must not be null. + const PopupMenuItem({ + Key key, + this.value, + this.enabled = true, + this.height = _kMenuItemHeight, + @required this.child, + }) : assert(enabled != null), + assert(height != null), + super(key: key); + + /// The value that will be returned by [showMenu] if this entry is selected. + final T value; + + /// Whether the user is permitted to select this entry. + /// + /// Defaults to true. If this is false, then the item will not react to + /// touches. + final bool enabled; + + /// The height of the entry. + /// + /// Defaults to 48 pixels. + @override + final double height; + + /// The widget below this widget in the tree. + /// + /// Typically a single-line [ListTile] (for menus with icons) or a [Text]. An + /// appropriate [DefaultTextStyle] is put in scope for the child. In either + /// case, the text should be short enough that it won't wrap. + final Widget child; + + @override + bool represents(T value) => value == this.value; + + @override + PopupMenuItemState> createState() => + PopupMenuItemState>(); +} + +/// The [State] for [PopupMenuItem] subclasses. +/// +/// By default this implements the basic styling and layout of Material Design +/// popup menu items. +/// +/// The [buildChild] method can be overridden to adjust exactly what gets placed +/// in the menu. By default it returns [PopupMenuItem.child]. +/// +/// The [handleTap] method can be overridden to adjust exactly what happens when +/// the item is tapped. By default, it uses [Navigator.pop] to return the +/// [PopupMenuItem.value] from the menu route. +/// +/// This class takes two type arguments. The second, `W`, is the exact type of +/// the [Widget] that is using this [State]. It must be a subclass of +/// [PopupMenuItem]. The first, `T`, must match the type argument of that widget +/// class, and is the type of values returned from this menu. +class PopupMenuItemState> extends State { + /// The menu item contents. + /// + /// Used by the [build] method. + /// + /// By default, this returns [PopupMenuItem.child]. Override this to put + /// something else in the menu entry. + @protected + Widget buildChild() => widget.child; + + /// The handler for when the user selects the menu item. + /// + /// Used by the [InkWell] inserted by the [build] method. + /// + /// By default, uses [Navigator.pop] to return the [PopupMenuItem.value] from + /// the menu route. + @protected + void handleTap() { + Navigator.pop(context, widget.value); + } + + @override + Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); + TextStyle style = theme.textTheme.subhead; + if (!widget.enabled) style = style.copyWith(color: theme.disabledColor); + + Widget item = AnimatedDefaultTextStyle( + style: style, + duration: kThemeChangeDuration, + child: buildChild(), + ); + if (!widget.enabled) { + final bool isDark = theme.brightness == Brightness.dark; + item = IconTheme.merge( + data: IconThemeData(opacity: isDark ? 0.5 : 0.38), + child: item, + ); + } + + return InkWell( + onTap: widget.enabled ? handleTap : null, + child: Container( + decoration: + BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(20))), + alignment: Alignment.center, + child: item, + ), + ); + } +} + +/// An item with a checkmark in a material design popup menu. +/// +/// To show a popup menu, use the [showMenu] function. To create a button that +/// shows a popup menu, consider using [PopupMenuButton]. +/// +/// A [CheckedPopupMenuItem] is 48 pixels high, which matches the default height +/// of a [PopupMenuItem]. The horizontal layout uses a [ListTile]; the checkmark +/// is an [Icons.done] icon, shown in the [ListTile.leading] position. +/// +/// {@tool sample} +/// +/// Suppose a `Commands` enum exists that lists the possible commands from a +/// particular popup menu, including `Commands.heroAndScholar` and +/// `Commands.hurricaneCame`, and further suppose that there is a +/// `_heroAndScholar` member field which is a boolean. The example below shows a +/// menu with one menu item with a checkmark that can toggle the boolean, and +/// one menu item without a checkmark for selecting the second option. (It also +/// shows a divider placed between the two menu items.) +/// +/// ```dart +/// PopupMenuButton( +/// onSelected: (Commands result) { +/// switch (result) { +/// case Commands.heroAndScholar: +/// setState(() { _heroAndScholar = !_heroAndScholar; }); +/// break; +/// case Commands.hurricaneCame: +/// // ...handle hurricane option +/// break; +/// // ...other items handled here +/// } +/// }, +/// itemBuilder: (BuildContext context) => >[ +/// CheckedPopupMenuItem( +/// checked: _heroAndScholar, +/// value: Commands.heroAndScholar, +/// child: const Text('Hero and scholar'), +/// ), +/// const PopupMenuDivider(), +/// const PopupMenuItem( +/// value: Commands.hurricaneCame, +/// child: ListTile(leading: Icon(null), title: Text('Bring hurricane')), +/// ), +/// // ...other items listed here +/// ], +/// ) +/// ``` +/// {@end-tool} +/// +/// In particular, observe how the second menu item uses a [ListTile] with a +/// blank [Icon] in the [ListTile.leading] position to get the same alignment as +/// the item with the checkmark. +/// +/// See also: +/// +/// * [PopupMenuItem], a popup menu entry for picking a command (as opposed to +/// toggling a value). +/// * [PopupMenuDivider], a popup menu entry that is just a horizontal line. +/// * [showMenu], a method to dynamically show a popup menu at a given location. +/// * [PopupMenuButton], an [IconButton] that automatically shows a menu when +/// it is tapped. +class CheckedPopupMenuItem extends PopupMenuItem { + /// Creates a popup menu item with a checkmark. + /// + /// By default, the menu item is [enabled] but unchecked. To mark the item as + /// checked, set [checked] to true. + /// + /// The `checked` and `enabled` arguments must not be null. + const CheckedPopupMenuItem({ + Key key, + T value, + this.checked = false, + bool enabled = true, + Widget child, + }) : assert(checked != null), + super( + key: key, + value: value, + enabled: enabled, + child: child, + ); + + /// Whether to display a checkmark next to the menu item. + /// + /// Defaults to false. + /// + /// When true, an [Icons.done] checkmark is displayed. + /// + /// When this popup menu item is selected, the checkmark will fade in or out + /// as appropriate to represent the implied new state. + final bool checked; + + /// The widget below this widget in the tree. + /// + /// Typically a [Text]. An appropriate [DefaultTextStyle] is put in scope for + /// the child. The text should be short enough that it won't wrap. + /// + /// This widget is placed in the [ListTile.title] slot of a [ListTile] whose + /// [ListTile.leading] slot is an [Icons.done] icon. + @override + Widget get child => super.child; + + @override + _CheckedPopupMenuItemState createState() => + _CheckedPopupMenuItemState(); +} + +class _CheckedPopupMenuItemState + extends PopupMenuItemState> + with SingleTickerProviderStateMixin { + static const Duration _fadeDuration = Duration(milliseconds: 150); + AnimationController _controller; + Animation get _opacity => _controller.view; + + @override + void initState() { + super.initState(); + _controller = AnimationController(duration: _fadeDuration, vsync: this) + ..value = widget.checked ? 1.0 : 0.0 + ..addListener(() => setState(() {/* animation changed */})); + } + + @override + void handleTap() { + // This fades the checkmark in or out when tapped. + if (widget.checked) + _controller.reverse(); + else + _controller.forward(); + super.handleTap(); + } + + @override + Widget buildChild() { + return ListTile( + enabled: widget.enabled, + leading: FadeTransition( + opacity: _opacity, + child: Icon(_controller.isDismissed ? null : Icons.done), + ), + title: widget.child, + ); + } +} + +class _PopupMenu extends StatelessWidget { + const _PopupMenu({ + Key key, + this.route, + this.semanticLabel, + }) : super(key: key); + + final _PopupMenuRoute route; + final String semanticLabel; + + @override + Widget build(BuildContext context) { + final double unit = 1.0 / + (route.items.length + + 1.5); // 1.0 for the width and 0.5 for the last item's fade. + final List children = []; + + for (int i = 0; i < route.items.length; i += 1) { + final double start = (i + 1) * unit; + final double end = (start + 1.5 * unit).clamp(0.0, 1.0); + final CurvedAnimation opacity = CurvedAnimation( + parent: route.animation, + curve: Interval(start, end), + ); + Widget item = route.items[i]; + if (route.initialValue != null && + route.items[i].represents(route.initialValue)) { + item = Container( + color: Theme.of(context).highlightColor, + child: item, + ); + } + children.add(FadeTransition( + opacity: opacity, + child: item, + )); + } + + final CurveTween opacity = + CurveTween(curve: const Interval(0.0, 1.0 / 3.0)); + final CurveTween width = CurveTween(curve: Interval(0.0, unit)); + final CurveTween height = + CurveTween(curve: Interval(0.0, unit * route.items.length)); + + final Widget child = ConstrainedBox( + constraints: const BoxConstraints( + minWidth: _kMenuMinWidth, + maxWidth: _kMenuMaxWidth, + ), + child: IntrinsicWidth( + stepWidth: _kMenuWidthStep, + child: Semantics( + scopesRoute: true, + namesRoute: true, + explicitChildNodes: true, + label: semanticLabel, + child: SingleChildScrollView( + padding: + const EdgeInsets.symmetric(vertical: _kMenuVerticalPadding), + child: ListBody(children: children), + ), + ), + ), + ); + + return AnimatedBuilder( + animation: route.animation, + builder: (BuildContext context, Widget child) { + return Opacity( + opacity: opacity.evaluate(route.animation), + child: Material( + type: MaterialType.card, + elevation: route.elevation, + child: Align( + alignment: AlignmentDirectional.topEnd, + widthFactor: width.evaluate(route.animation), + heightFactor: height.evaluate(route.animation), + child: child, + ), + ), + ); + }, + child: child, + ); + } +} + +// Positioning of the menu on the screen. +class _PopupMenuRouteLayout extends SingleChildLayoutDelegate { + _PopupMenuRouteLayout( + this.position, this.selectedItemOffset, this.textDirection); + + // Rectangle of underlying button, relative to the overlay's dimensions. + final RelativeRect position; + + // The distance from the top of the menu to the middle of selected item. + // + // This will be null if there's no item to position in this way. + final double selectedItemOffset; + + // Whether to prefer going to the left or to the right. + final TextDirection textDirection; + + // We put the child wherever position specifies, so long as it will fit within + // the specified parent size padded (inset) by 8. If necessary, we adjust the + // child's position so that it fits. + + @override + BoxConstraints getConstraintsForChild(BoxConstraints constraints) { + // The menu can be at most the size of the overlay minus 8.0 pixels in each + // direction. + return BoxConstraints.loose(constraints.biggest - + const Offset(_kMenuScreenPadding * 2.0, _kMenuScreenPadding * 2.0)); + } + + @override + Offset getPositionForChild(Size size, Size childSize) { + // size: The size of the overlay. + // childSize: The size of the menu, when fully open, as determined by + // getConstraintsForChild. + + // Find the ideal vertical position. + double y; + if (selectedItemOffset == null) { + y = position.top; + } else { + y = position.top + + (size.height - position.top - position.bottom) / 2.0 - + selectedItemOffset; + } + + // Find the ideal horizontal position. + double x; + if (position.left > position.right) { + // Menu button is closer to the right edge, so grow to the left, aligned to the right edge. + x = size.width - position.right - childSize.width; + } else if (position.left < position.right) { + // Menu button is closer to the left edge, so grow to the right, aligned to the left edge. + x = position.left; + } else { + // Menu button is equidistant from both edges, so grow in reading direction. + assert(textDirection != null); + switch (textDirection) { + case TextDirection.rtl: + x = size.width - position.right - childSize.width; + break; + case TextDirection.ltr: + x = position.left; + break; + } + } + + // Avoid going outside an area defined as the rectangle 8.0 pixels from the + // edge of the screen in every direction. + if (x < _kMenuScreenPadding) + x = _kMenuScreenPadding; + else if (x + childSize.width > size.width - _kMenuScreenPadding) + x = size.width - childSize.width - _kMenuScreenPadding; + if (y < _kMenuScreenPadding) + y = _kMenuScreenPadding; + else if (y + childSize.height > size.height - _kMenuScreenPadding) + y = size.height - childSize.height - _kMenuScreenPadding; + return Offset(x, y); + } + + @override + bool shouldRelayout(_PopupMenuRouteLayout oldDelegate) { + return position != oldDelegate.position; + } +} + +class _PopupMenuRoute extends PopupRoute { + _PopupMenuRoute({ + this.position, + this.items, + this.initialValue, + this.elevation, + this.theme, + this.barrierLabel, + this.semanticLabel, + }); + + final RelativeRect position; + final List> items; + final dynamic initialValue; + final double elevation; + final ThemeData theme; + final String semanticLabel; + + @override + Animation createAnimation() { + return CurvedAnimation( + parent: super.createAnimation(), + curve: Curves.linear, + reverseCurve: const Interval(0.0, _kMenuCloseIntervalEnd), + ); + } + + @override + Duration get transitionDuration => _kMenuDuration; + + @override + bool get barrierDismissible => true; + + @override + Color get barrierColor => null; + + @override + final String barrierLabel; + + @override + Widget buildPage(BuildContext context, Animation animation, + Animation secondaryAnimation) { + double selectedItemOffset; + if (initialValue != null) { + double y = _kMenuVerticalPadding; + for (PopupMenuEntry entry in items) { + if (entry.represents(initialValue)) { + selectedItemOffset = y + entry.height / 2.0; + break; + } + y += entry.height; + } + } + + Widget menu = _PopupMenu(route: this, semanticLabel: semanticLabel); + if (theme != null) menu = Theme(data: theme, child: menu); + + return MediaQuery.removePadding( + context: context, + removeTop: true, + removeBottom: true, + removeLeft: true, + removeRight: true, + child: Builder( + builder: (BuildContext context) { + return CustomSingleChildLayout( + delegate: _PopupMenuRouteLayout( + position, + selectedItemOffset, + Directionality.of(context), + ), + child: menu, + ); + }, + ), + ); + } +} + +/// Show a popup menu that contains the `items` at `position`. +/// +/// `items` should be non-null and not empty. +/// +/// If `initialValue` is specified then the first item with a matching value +/// will be highlighted and the value of `position` gives the rectangle whose +/// vertical center will be aligned with the vertical center of the highlighted +/// item (when possible). +/// +/// If `initialValue` is not specified then the top of the menu will be aligned +/// with the top of the `position` rectangle. +/// +/// In both cases, the menu position will be adjusted if necessary to fit on the +/// screen. +/// +/// Horizontally, the menu is positioned so that it grows in the direction that +/// has the most room. For example, if the `position` describes a rectangle on +/// the left edge of the screen, then the left edge of the menu is aligned with +/// the left edge of the `position`, and the menu grows to the right. If both +/// edges of the `position` are equidistant from the opposite edge of the +/// screen, then the ambient [Directionality] is used as a tie-breaker, +/// preferring to grow in the reading direction. +/// +/// The positioning of the `initialValue` at the `position` is implemented by +/// iterating over the `items` to find the first whose +/// [PopupMenuEntry.represents] method returns true for `initialValue`, and then +/// summing the values of [PopupMenuEntry.height] for all the preceding widgets +/// in the list. +/// +/// The `elevation` argument specifies the z-coordinate at which to place the +/// menu. The elevation defaults to 8, the appropriate elevation for popup +/// menus. +/// +/// The `context` argument is used to look up the [Navigator] and [Theme] for +/// the menu. It is only used when the method is called. Its corresponding +/// widget can be safely removed from the tree before the popup menu is closed. +/// +/// The `semanticLabel` argument is used by accessibility frameworks to +/// announce screen transitions when the menu is opened and closed. If this +/// label is not provided, it will default to +/// [MaterialLocalizations.popupMenuLabel]. +/// +/// See also: +/// +/// * [PopupMenuItem], a popup menu entry for a single value. +/// * [PopupMenuDivider], a popup menu entry that is just a horizontal line. +/// * [CheckedPopupMenuItem], a popup menu item with a checkmark. +/// * [PopupMenuButton], which provides an [IconButton] that shows a menu by +/// calling this method automatically. +/// * [SemanticsConfiguration.namesRoute], for a description of edge triggered +/// semantics. +Future showMenu({ + @required BuildContext context, + @required RelativeRect position, + @required List> items, + T initialValue, + double elevation = 8.0, + String semanticLabel, +}) { + assert(context != null); + assert(position != null); + assert(items != null && items.isNotEmpty); + assert(debugCheckHasMaterialLocalizations(context)); + String label = semanticLabel; + switch (defaultTargetPlatform) { + case TargetPlatform.iOS: + label = semanticLabel; + break; + case TargetPlatform.android: + case TargetPlatform.fuchsia: + label = + semanticLabel ?? MaterialLocalizations.of(context)?.popupMenuLabel; + } + + return Navigator.push( + context, + _PopupMenuRoute( + position: position, + items: items, + initialValue: initialValue, + elevation: elevation, + semanticLabel: label, + theme: Theme.of(context, shadowThemeOnly: true), + barrierLabel: + MaterialLocalizations.of(context).modalBarrierDismissLabel, + )); +} + +/// Signature for the callback invoked when a menu item is selected. The +/// argument is the value of the [PopupMenuItem] that caused its menu to be +/// dismissed. +/// +/// Used by [PopupMenuButton.onSelected]. +typedef PopupMenuItemSelected = void Function(T value); + +/// Signature for the callback invoked when a [PopupMenuButton] is dismissed +/// without selecting an item. +/// +/// Used by [PopupMenuButton.onCanceled]. +typedef PopupMenuCanceled = void Function(); + +/// Signature used by [PopupMenuButton] to lazily construct the items shown when +/// the button is pressed. +/// +/// Used by [PopupMenuButton.itemBuilder]. +typedef PopupMenuItemBuilder = List> Function( + BuildContext context); + +/// Displays a menu when pressed and calls [onSelected] when the menu is dismissed +/// because an item was selected. The value passed to [onSelected] is the value of +/// the selected menu item. +/// +/// One of [child] or [icon] may be provided, but not both. If [icon] is provided, +/// then [PopupMenuButton] behaves like an [IconButton]. +/// +/// If both are null, then a standard overflow icon is created (depending on the +/// platform). +/// +/// {@tool sample} +/// +/// This example shows a menu with four items, selecting between an enum's +/// values and setting a `_selection` field based on the selection. +/// +/// ```dart +/// // This is the type used by the popup menu below. +/// enum WhyFarther { harder, smarter, selfStarter, tradingCharter } +/// +/// // This menu button widget updates a _selection field (of type WhyFarther, +/// // not shown here). +/// PopupMenuButton( +/// onSelected: (WhyFarther result) { setState(() { _selection = result; }); }, +/// itemBuilder: (BuildContext context) => >[ +/// const PopupMenuItem( +/// value: WhyFarther.harder, +/// child: Text('Working a lot harder'), +/// ), +/// const PopupMenuItem( +/// value: WhyFarther.smarter, +/// child: Text('Being a lot smarter'), +/// ), +/// const PopupMenuItem( +/// value: WhyFarther.selfStarter, +/// child: Text('Being a self-starter'), +/// ), +/// const PopupMenuItem( +/// value: WhyFarther.tradingCharter, +/// child: Text('Placed in charge of trading charter'), +/// ), +/// ], +/// ) +/// ``` +/// {@end-tool} +/// +/// See also: +/// +/// * [PopupMenuItem], a popup menu entry for a single value. +/// * [PopupMenuDivider], a popup menu entry that is just a horizontal line. +/// * [CheckedPopupMenuItem], a popup menu item with a checkmark. +/// * [showMenu], a method to dynamically show a popup menu at a given location. +class PopupMenuButton extends StatefulWidget { + /// Creates a button that shows a popup menu. + /// + /// The [itemBuilder] argument must not be null. + const PopupMenuButton({ + Key key, + @required this.itemBuilder, + this.initialValue, + this.onSelected, + this.onCanceled, + this.tooltip, + this.elevation = 8.0, + this.padding = const EdgeInsets.all(8.0), + this.child, + this.icon, + this.offset = Offset.zero, + this.enabled = true, + }) : assert(itemBuilder != null), + assert(offset != null), + assert(enabled != null), + assert(!(child != null && + icon != null)), // fails if passed both parameters + super(key: key); + + /// Called when the button is pressed to create the items to show in the menu. + final PopupMenuItemBuilder itemBuilder; + + /// The value of the menu item, if any, that should be highlighted when the menu opens. + final T initialValue; + + /// Called when the user selects a value from the popup menu created by this button. + /// + /// If the popup menu is dismissed without selecting a value, [onCanceled] is + /// called instead. + final PopupMenuItemSelected onSelected; + + /// Called when the user dismisses the popup menu without selecting an item. + /// + /// If the user selects a value, [onSelected] is called instead. + final PopupMenuCanceled onCanceled; + + /// Text that describes the action that will occur when the button is pressed. + /// + /// This text is displayed when the user long-presses on the button and is + /// used for accessibility. + final String tooltip; + + /// The z-coordinate at which to place the menu when open. This controls the + /// size of the shadow below the menu. + /// + /// Defaults to 8, the appropriate elevation for popup menus. + final double elevation; + + /// Matches IconButton's 8 dps padding by default. In some cases, notably where + /// this button appears as the trailing element of a list item, it's useful to be able + /// to set the padding to zero. + final EdgeInsetsGeometry padding; + + /// If provided, the widget used for this button. + final Widget child; + + /// If provided, the icon used for this button. + final Icon icon; + + /// The offset applied to the Popup Menu Button. + /// + /// When not set, the Popup Menu Button will be positioned directly next to + /// the button that was used to create it. + final Offset offset; + + /// Whether this popup menu button is interactive. + /// + /// Must be non-null, defaults to `true` + /// + /// If `true` the button will respond to presses by displaying the menu. + /// + /// If `false`, the button is styled with the disabled color from the + /// current [Theme] and will not respond to presses or show the popup + /// menu and [onSelected], [onCanceled] and [itemBuilder] will not be called. + /// + /// This can be useful in situations where the app needs to show the button, + /// but doesn't currently have anything to show in the menu. + final bool enabled; + + @override + _PopupMenuButtonState createState() => _PopupMenuButtonState(); +} + +class _PopupMenuButtonState extends State> { + void showButtonMenu() { + final RenderBox button = context.findRenderObject(); + final RenderBox overlay = Overlay.of(context).context.findRenderObject(); + final RelativeRect position = RelativeRect.fromRect( + Rect.fromPoints( + button.localToGlobal(widget.offset, ancestor: overlay), + button.localToGlobal(button.size.bottomRight(Offset.zero), + ancestor: overlay), + ), + Offset.zero & overlay.size, + ); + final List> items = widget.itemBuilder(context); + // Only show the menu if there is something to show + if (items.isNotEmpty) { + showMenu( + context: context, + elevation: widget.elevation, + items: items, + initialValue: widget.initialValue, + position: position, + ).then((T newValue) { + if (!mounted) return null; + if (newValue == null) { + if (widget.onCanceled != null) widget.onCanceled(); + return null; + } + if (widget.onSelected != null) widget.onSelected(newValue); + }); + } + } + + Icon _getIcon(TargetPlatform platform) { + assert(platform != null); + switch (platform) { + case TargetPlatform.android: + case TargetPlatform.fuchsia: + return const Icon(Icons.more_vert); + case TargetPlatform.iOS: + return const Icon(Icons.more_horiz); + } + return null; + } + + @override + Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); + return widget.child != null + ? InkWell( + onTap: widget.enabled ? showButtonMenu : null, + child: widget.child, + ) + : IconButton( + icon: widget.icon ?? _getIcon(Theme.of(context).platform), + padding: widget.padding, + tooltip: widget.tooltip ?? + MaterialLocalizations.of(context).showMenuTooltip, + onPressed: widget.enabled ? showButtonMenu : null, + ); + } +} diff --git a/lib/utils/ShadowButton.dart b/lib/utils/ShadowButton.dart new file mode 100644 index 0000000..8f4bb61 --- /dev/null +++ b/lib/utils/ShadowButton.dart @@ -0,0 +1,25 @@ +import 'package:chat/data/constants.dart'; +import 'package:flutter/material.dart'; + +class ShadowButton { + Widget builder(Gradient gradientColor, Text text, callback) { + return new RaisedButton( + padding: EdgeInsets.zero, + elevation: 3.0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(Constants.BigButtonRadius)), + ), + onPressed: () { + callback(); + }, + child: new Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(Constants.BigButtonRadius), + gradient: gradientColor, + ), + child: text, + padding: EdgeInsets.fromLTRB(16, 8, 16, 8), + alignment: Alignment.center, + )); + } +} diff --git a/lib/utils/SnakeBar.dart b/lib/utils/SnakeBar.dart new file mode 100644 index 0000000..f6f9180 --- /dev/null +++ b/lib/utils/SnakeBar.dart @@ -0,0 +1,8 @@ +import 'package:flutter/material.dart'; + +class CommonSnakeBar { + static buildSnakeBar(BuildContext context, String str) { + final snackBar = new SnackBar(content: new Text(str)); + Scaffold.of(context).showSnackBar(snackBar); + } +} diff --git a/lib/utils/TempUserCard.dart b/lib/utils/TempUserCard.dart new file mode 100644 index 0000000..1e78dd3 --- /dev/null +++ b/lib/utils/TempUserCard.dart @@ -0,0 +1,429 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/ProfilePage.dart'; +import 'package:chat/utils/LoveToggle.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' as prefix0; +import 'package:oktoast/oktoast.dart'; +import '../utils/HttpUtil.dart'; +import 'package:dio/dio.dart'; +import "../data/UserData.dart"; +import '../utils/TokenMgr.dart'; +import 'TempUserChips.dart'; + +class TempUserCard extends StatelessWidget { + final String userName; + final bool isReal; + final String city; //城市 + final int age; //年龄 + final String constellation; //星座 + final String professional; //职业 + final String isOnline; + final double distance; + final int userId; + final bool isLove; + final bool isBalck; + final String headUrl; + final bool payImg; + final int imgNum; + final int sex; + final bool isHidden; + final int member; + final bool hiddenDistince; + final int nameSize; + + TempUserCard( + {Key key, + this.userName, + this.isReal: false, + this.city, + this.age, + this.constellation, + this.professional, + this.isOnline, + this.distance, + this.userId, + this.isLove: false, + this.sex, + this.headUrl: '', + this.payImg: false, + this.imgNum: 0, + this.isHidden: false, + this.member: 0, + this.hiddenDistince: false, + this.nameSize = 8, + this.isBalck: false}) + : super(key: key); + + @override + Widget build(BuildContext context) { + bool isVIP = member > 0; + bool isSVIP = member == 2; + + //头像 + Widget headImg() { + double height = Screen.width; + return Stack( + children: [ + Container( + height: height - 40, + width: height - 40, + child: ClipRRect( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(15), + topRight: Radius.circular(15)), + child: headUrl == '' || headUrl == null + ? Image.asset( + Constants.DefaultHeadImgUrl, + width: height - 40, + height: height - 40, + ) + : CachedNetworkImage( + imageUrl: headUrl, + placeholder: (context, url) => Image.asset( + Constants.DefaultHeadImgUrl, + width: height - 40, + height: height - 40, + ), + fit: BoxFit.cover, + )), + ), + Positioned( + left: 0, + bottom: 0, + child: Container( + height: 27, + width: 54, + decoration: BoxDecoration( + color: Colors.black54, + borderRadius: + BorderRadius.only(topRight: Radius.circular(10))), + child: Row( + //mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + padding: EdgeInsets.only(left: 6), + child: + Icon(Icons.image, size: 15, color: Colors.white)), + Padding( + padding: EdgeInsets.only(left: 5, top: 2), + child: fixedText(imgNum.toString(), + color: Colors.white, fontSize: 14), + ), + ], + ), + )) + ], + ); + } + +//名字以及认证状态 + Widget nameState() { + return Row( + children: [ + fixedText(WebData().subUserName(userName, size: nameSize), + fontSize: 15), + isReal && sex == 2 + ? Container( + margin: EdgeInsets.only(left: 5), + padding: + EdgeInsets.only(top: 2, bottom: 2, left: 5, right: 5), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Constants.PurpleBackgroundColor, + ), + child: fixedText('Real', fontSize: 8, color: Colors.white)) + : Container(), + isVIP && sex == 1 + ? Container( + margin: EdgeInsets.only(left: 5), + child: isSVIP ? Constants.svipIcon : Constants.vipIcon) + : Container(), + ], + ); + } + + //距离、在线以及相册 + Widget otherWidget() { + var greyColor = const Color(0xFFB2B2B2); + return Row( + children: [ + InfoTile( + icon: IconData(0xe630, fontFamily: Constants.IconFontFamily), + title: hiddenDistince + ? I18n.of(context).secrecy + : (UserData().hasLocationPermission + ? WebData().getDistanceString(distance) + : I18n.of(context).unknown), + titleColor: greyColor, + isDivider: true), + InfoTile( + title: isOnline, + titleColor: greyColor, + isDivider: payImg || isHidden), + isHidden + ? InfoTile( + icon: IconData(0xe645, fontFamily: 'iconfont'), + iconHeight: 22, + title: I18n.of(context).application_view, + titleColor: greyColor, + isDivider: false, + onTap: () { + print('click'); + }) + : Container(), + payImg + ? InfoTile( + icon: IconData(0xe632, fontFamily: Constants.IconFontFamily), + title: I18n.of(context).paid_photo, + titleColor: greyColor, + isDivider: false, + onTap: () { + print('click'); + }) + : Container(), + ], + ); + } + + return InkWell( + onTap: () { + // if (sex == UserData().basicInfo.sex) { + // showToast(UserData().basicInfo.sex == 1 + // ? I18n.of(context).cant_see + // : I18n.of(context).cant_see2); + // return; + // } + + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: userId, + ); + }, + ), + ); + }, + child: Container( + alignment: Alignment.center, + color: AppColors.NewAppbarBgColor, + width: Screen.width, + child: Container( + width: Screen.width - 40, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: 23, + ), + headImg(), + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(15), + bottomRight: Radius.circular(15))), + child: Column( + children: [ + Container( + //背景 + padding: EdgeInsets.only( + left: 15, right: 10, bottom: 14.5, top: 5), + child: Column( + children: [ + Stack( + children: [ + Row( + children: [ + //头像图片 + + //信息 + Container( + width: MediaQuery.of(context) + .size + .width - + 104, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + nameState(), //名字以及状态 + //用户的信息标记 + Padding( + padding: + EdgeInsets.only(top: 9)), + TempUserChips( + city: city, + age: age, + constellation: constellation, + professional: professional), + Padding( + padding: + EdgeInsets.only(top: 4)), + otherWidget(), + ], + )), + ], + ), + ], + ) + ], + )), + SizedBox( + height: 5, + ), + Container( + child: //赞 + sex == UserData().basicInfo.sex + ? InkWell( + onTap: () { + showToast(UserData().isMan() + ? I18n.of(context).not_love + : I18n.of(context).not_love2); + }, + child: Container( + width: 100, + height: 30, + decoration: BoxDecoration( + border: Border.all( + color: Color(0xFF878787), + width: 1), + borderRadius: + BorderRadius.circular(16)), + padding: EdgeInsets.only( + left: 15, + right: 15, + bottom: 5, + top: 5), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + IconData( + 0xe625, + fontFamily: + Constants.IconFontFamily, + ), + size: 15, + color: Color(0xffB2B2B2), + ), + SizedBox( + width: 5, + ), + Text( + 'LOVE', + style: prefix0.TextStyle( + color: Color(0xffB2B2B2)), + ) + ], + ))) + : LoveToggle( + isActive: isLove, + onTap: (bool isActive) async { + if (isActive) { + HttpUtil().setLove(userId, () { + MessageMgr().emit('refresh_love_list', + {'UserId': userId, 'flag': 0}); + }); + } else { + HttpUtil().cancleLove(userId, () { + MessageMgr().emit('refresh_love_list', + {'UserId': userId, 'flag': 2}); + }); + } + }), + ), + SizedBox( + height: 15, + ), + ], + ), + ), + ], + ), + ), + )); + } +} + +const double TileHeight = 14; + +class InfoTile extends StatelessWidget { + @required + final String title; + final Color titleColor; + final IconData icon; + final double iconHeight; + final VoidCallback onTap; + final bool isDivider; + + const InfoTile( + {Key key, + this.title, + this.titleColor, + this.icon, + this.onTap, + this.iconHeight: TileHeight, + this.isDivider = false}) + : super(key: key); + + @override + Widget build(BuildContext context) { + List elements = []; + + if (icon != null) { + elements.add(Padding( + padding: EdgeInsets.only(bottom: 2), + child: Icon(icon, size: TileHeight, color: titleColor))); + } + + elements.add( + Container( + constraints: BoxConstraints(maxWidth: 140), + padding: EdgeInsets.only(right: 5), + child: Text(title, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 11, + color: titleColor, + fontWeight: FontWeight.normal), + textAlign: TextAlign.center)), + ); + + if (isDivider) { + elements.add(Container( + height: 12, + child: VerticalDivider( + width: 1, + indent: 0, + endIndent: 0, + color: Colors.black26, + ))); + } + + var tileWidget = Container( + padding: EdgeInsets.only(right: 5), + child: Row( + //crossAxisAlignment: CrossAxisAlignment.start, + children: elements, + )); + + if (onTap != null) { + return InkWell( + child: tileWidget, + onTap: onTap, + ); + } else { + return tileWidget; + } + } +} diff --git a/lib/utils/TempUserChips.dart b/lib/utils/TempUserChips.dart new file mode 100644 index 0000000..0a1316a --- /dev/null +++ b/lib/utils/TempUserChips.dart @@ -0,0 +1,58 @@ +import 'package:chat/generated/i18n.dart'; +import 'package:flutter/material.dart'; + +class TempUserChips extends StatelessWidget { + final String city; //城市 + final int age; //年龄 + final String constellation; //星座 + final String professional; //职业 + final Color bgColor; + final TextStyle fontStyle; + final bool isCenter; + const TempUserChips( + {Key key, + this.city, + this.age, + this.constellation, + this.professional, + this.bgColor, + this.fontStyle, + this.isCenter: false}) + : super(key: key); + + Widget _buildChip(str,Color tempColor) { + return Container( + margin: EdgeInsets.only(bottom: 5, right: 5), + padding: EdgeInsets.symmetric(horizontal: 10, vertical: 3), + decoration: BoxDecoration( +// color: bgColor == null ? Constants.LightBlueBackgroundColor : bgColor, + border: Border.all(color: Color(0xFFEC4163), width: 1), + borderRadius: BorderRadius.circular(15.0), + ), + child: Text( + str, + textScaleFactor: 1.0, + style: fontStyle == null + ? TextStyle( + fontSize: 11, + color: Color(0xFFEC4163), + ) + : fontStyle, + textAlign: TextAlign.center, + ), + ); + } + + @override + Widget build(BuildContext context) { + return Wrap( + alignment: isCenter ? WrapAlignment.center : WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + _buildChip(city,Color(0xff96C7FF)), + _buildChip(professional,Color(0xffAC51F3)), + _buildChip('$age ${I18n.of(context).years_old}-$constellation',Color(0xffF5A623)), + ], + ); + } +} diff --git a/lib/utils/Toggle.dart b/lib/utils/Toggle.dart new file mode 100644 index 0000000..bb8295c --- /dev/null +++ b/lib/utils/Toggle.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; + +class ToggleButton extends StatefulWidget { + final IconData activeIcon; + final IconData unActiveIcon; + final Color activeColor; + final Color unActiveColor; + final bool active; + final double size; + + final void Function(bool status) onChange; + + ToggleButton( + {this.activeIcon, + this.unActiveIcon, + this.activeColor, + this.unActiveColor, + this.onChange, + this.size = 25, + this.active = false}); + + @override + _ToggleButtonState createState() => _ToggleButtonState(); +} + +class _ToggleButtonState extends State { + bool isActive; + @override + void initState() { + super.initState(); + isActive = widget.active; + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + child: Container( + child: Stack( + children: [ + //左边选择,右边未选择 + Icon(widget.unActiveIcon, + size: widget.size, + color: isActive ? widget.unActiveColor : widget.activeColor), + + Icon(widget.activeIcon, + size: widget.size, + color: isActive ? widget.activeColor : widget.unActiveColor), + ], + ), + ), + onTap: () { + setState(() { + isActive = !isActive; + widget.onChange(isActive); + }); + }, + ); + } +} diff --git a/lib/utils/TokenMgr.dart b/lib/utils/TokenMgr.dart new file mode 100644 index 0000000..cdd3138 --- /dev/null +++ b/lib/utils/TokenMgr.dart @@ -0,0 +1,37 @@ +import 'dart:convert'; +import 'package:convert/convert.dart'; +import 'package:crypto/crypto.dart'; + +class TokenMgr { + //私有构造函数 + TokenMgr._internal(); + + //保存单例 + static TokenMgr _singleton = new TokenMgr._internal(); + + //工厂构造函数 + factory TokenMgr() => _singleton; + + String getSign(Map parameter) { + String k = ''; + var keyList = []; + for (var key in parameter.keys) { + keyList.add(key); + } + keyList.sort(); + + for (var key in keyList) { + k += '$key=${parameter[key]}&'; + } + k += 'key=O@MlSxWaeAlc5CYu'; + + print(k); + return generateMd5(k); + } + + String generateMd5(String data) { + var content = new Utf8Encoder().convert(data); + var digest = md5.convert(content); + return hex.encode(digest.bytes); + } +} diff --git a/lib/utils/TutorialOverlay.dart b/lib/utils/TutorialOverlay.dart new file mode 100644 index 0000000..952725d --- /dev/null +++ b/lib/utils/TutorialOverlay.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; + +class TutorialOverlay extends ModalRoute { + @override + Duration get transitionDuration => Duration(milliseconds: 100); + + @override + bool get opaque => false; + + @override + bool get barrierDismissible => false; + + @override + Color get barrierColor => Colors.black.withOpacity(0.5); + + @override + String get barrierLabel => null; + + @override + bool get maintainState => true; + + final child; + + TutorialOverlay({this.child}); + + @override + Widget buildPage( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + ) { + // This makes sure that text and other content follows the material style + return Material( + type: MaterialType.transparency, + // make sure that the overlay content is not cut off + child: SafeArea( + child: child, //_buildOverlayContent(context), + ), + ); + } + + @override + Widget buildTransitions(BuildContext context, Animation animation, + Animation secondaryAnimation, Widget child) { + return FadeTransition( + opacity: animation, + child: child, + ); + } +} diff --git a/lib/utils/UserCard.dart b/lib/utils/UserCard.dart new file mode 100644 index 0000000..90eab15 --- /dev/null +++ b/lib/utils/UserCard.dart @@ -0,0 +1,382 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/WebData.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/ProfilePage.dart'; +import 'package:chat/utils/IconToggle.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:chat/utils/UserChips.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; +import '../utils/HttpUtil.dart'; +import 'package:dio/dio.dart'; +import "../data/UserData.dart"; +import '../utils/TokenMgr.dart'; + +class UserCard extends StatelessWidget { + final String userName; + final bool isReal; + final String city; //城市 + final int age; //年龄 + final String constellation; //星座 + final String professional; //职业 + final String isOnline; + final double distance; + final int userId; + final bool isLove; + final bool isBalck; + final String headUrl; + final bool payImg; + final int imgNum; + final int sex; + final bool isHidden; + final int member; + final bool hiddenDistince; + final int nameSize; + + UserCard( + {Key key, + this.userName, + this.isReal: false, + this.city, + this.age, + this.constellation, + this.professional, + this.isOnline, + this.distance, + this.userId, + this.isLove: false, + this.sex, + this.headUrl: '', + this.payImg: false, + this.imgNum: 0, + this.isHidden: false, + this.member: 0, + this.hiddenDistince: false, + this.nameSize = 8, + this.isBalck: false}) + : super(key: key); + + @override + Widget build(BuildContext context) { + bool isVIP = member > 0; + bool isSVIP = member == 2; + + //头像 + Widget headImg() { + double height = 69.4; + return Stack( + children: [ + Container( + height: height, + width: height, + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: headUrl == '' || headUrl == null + ? Image.asset( + Constants.DefaultHeadImgUrl, + ) + : CachedNetworkImage( + imageUrl: headUrl, + placeholder: (context, url) => Image.asset( + Constants.DefaultHeadImgUrl, + width: height, + height: height, + ), + fit: BoxFit.cover, + )), + ), + Positioned( + left: 0, + bottom: 0, + child: Container( + height: 15, + width: 40, + decoration: BoxDecoration( + color: Colors.black54, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(10), + topRight: Radius.circular(10))), + child: Row( + //mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + padding: EdgeInsets.only(left: 6), + child: + Icon(Icons.image, size: 12, color: Colors.white)), + Padding( + padding: EdgeInsets.only(left: 5, top: 2), + child: fixedText(imgNum.toString(), + color: Colors.white, fontSize: 12), + ), + ], + ), + )) + ], + ); + } + +//名字以及认证状态 + Widget nameState() { + return Row( + children: [ + fixedText(WebData().subUserName(userName, size: nameSize), + fontSize: 15), + isReal && sex == 2 + ? Container( + margin: EdgeInsets.only(left: 5), + padding: + EdgeInsets.only(top: 2, bottom: 2, left: 5, right: 5), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Constants.PurpleBackgroundColor, + ), + child: fixedText('Real', fontSize: 8, color: Colors.white)) + : Container(), + isVIP && sex == 1 + ? Container( + margin: EdgeInsets.only(left: 5), + child: isSVIP ? Constants.svipIcon : Constants.vipIcon) + : Container(), + ], + ); + } + + //距离、在线以及相册 + Widget otherWidget() { + var greyColor = const Color(0xFFB2B2B2); + return Row( + children: [ + InfoTile( + icon: IconData(0xe630, fontFamily: Constants.IconFontFamily), + title: hiddenDistince + ? I18n.of(context).secrecy + : (UserData().hasLocationPermission + ? WebData().getDistanceString(distance) + : I18n.of(context).unknown), + titleColor: greyColor, + isDivider: true), + InfoTile( + title: isOnline, + titleColor: greyColor, + isDivider: payImg || isHidden), + isHidden + ? InfoTile( + icon: IconData(0xe645, fontFamily: 'iconfont'), + iconHeight: 22, + title: I18n.of(context).application_view, + titleColor: greyColor, + isDivider: false, + onTap: () { + print('click'); + }) + : Container(), + payImg + ? InfoTile( + icon: IconData(0xe632, fontFamily: Constants.IconFontFamily), + title: I18n.of(context).paid_photo, + titleColor: greyColor, + isDivider: false, + onTap: () { + print('click'); + }) + : Container(), + ], + ); + } + + return InkWell( + onTap: () { + // if (sex == UserData().basicInfo.sex) { + // showToast(UserData().basicInfo.sex == 1 + // ? I18n.of(context).cant_see + // : I18n.of(context).cant_see2); + // return; + // } + + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return ProfilePage( + userId: userId, + ); + }, + ), + ); + }, + child: Column( + children: [ + Container( + //背景 + padding: EdgeInsets.only(left: 18, top: 14.5, bottom: 14.5), + color: Colors.white, + child: Stack( + children: [ + Row( + children: [ + //头像图片 + Padding( + padding: + EdgeInsets.only(right: 16.5, top: 5, bottom: 5), + child: headImg()), + //信息 + Container( + width: MediaQuery.of(context).size.width - 104, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + nameState(), //名字以及状态 + //用户的信息标记 + Padding(padding: EdgeInsets.only(top: 9)), + UserChips( + city: city, + age: age, + constellation: constellation, + professional: professional), + Padding(padding: EdgeInsets.only(top: 4)), + otherWidget(), + ], + )), + ], + ), + Positioned( + child: //赞 + sex == UserData().basicInfo.sex + ? InkWell( + onTap: () { + showToast(UserData().isMan() + ? I18n.of(context).not_love + : I18n.of(context).not_love2); + }, + child: Container( + padding: EdgeInsets.only( + left: 15, right: 15, bottom: 15), + child: Icon( + IconData( + 0xe625, + fontFamily: Constants.IconFontFamily, + ), + size: 15, + color: Constants.GreyTextColor, + ))) + : IconToggle( + key: key, + icon: IconData( + 0xe625, + fontFamily: Constants.IconFontFamily, + ), + activeIcon: IconData( + 0xe623, + fontFamily: Constants.IconFontFamily, + ), + defaultColor: Constants.GreyTextColor, + activeColor: Constants.RedTextColor, + isActive: isLove, + size: 16, + onTap: (bool isActive) async { + if (isActive) { + HttpUtil().setLove(userId, () { + MessageMgr().emit('refresh_love_list', + {'UserId': userId, 'flag': 0}); + }); + } else { + HttpUtil().cancleLove(userId, () { + MessageMgr().emit('refresh_love_list', + {'UserId': userId, 'flag': 2}); + }); + } + }), + right: 0, + top: 1, + ) + ], + )), + Container( + color: Colors.white, + padding: EdgeInsets.only( + left: Screen.width * 0.1, right: Screen.width * 0.1), + child: Divider( + height: 1, + color: Constants.DividerLineColor, + ), + ) + ], + )); + } +} + +const double TileHeight = 14; + +class InfoTile extends StatelessWidget { + @required + final String title; + final Color titleColor; + final IconData icon; + final double iconHeight; + final VoidCallback onTap; + final bool isDivider; + + const InfoTile( + {Key key, + this.title, + this.titleColor, + this.icon, + this.onTap, + this.iconHeight: TileHeight, + this.isDivider = false}) + : super(key: key); + + @override + Widget build(BuildContext context) { + List elements = []; + + if (icon != null) { + elements.add(Padding( + padding: EdgeInsets.only(bottom: 2), + child: Icon(icon, size: TileHeight, color: titleColor))); + } + + elements.add( + Container( + alignment: Alignment.bottomCenter, + constraints: BoxConstraints(minHeight: 17), + padding: EdgeInsets.only(right: 5, bottom: 1.5), + child: Text(title, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: 11, + color: titleColor, + fontWeight: FontWeight.normal))), + ); + + if (isDivider) { + elements.add(Container( + height: 16, + child: VerticalDivider( + width: 1, + indent: 0, + endIndent: 0, + color: Colors.black26, + ))); + } + + var tileWidget = Container( + padding: EdgeInsets.only(right: 5), + child: Row( + //crossAxisAlignment: CrossAxisAlignment.start, + children: elements, + )); + + if (onTap != null) { + return InkWell( + child: tileWidget, + onTap: onTap, + ); + } else { + return tileWidget; + } + } +} diff --git a/lib/utils/UserChips.dart b/lib/utils/UserChips.dart new file mode 100644 index 0000000..4f182c5 --- /dev/null +++ b/lib/utils/UserChips.dart @@ -0,0 +1,58 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:flutter/material.dart'; + +class UserChips extends StatelessWidget { + final String city; //城市 + final int age; //年龄 + final String constellation; //星座 + final String professional; //职业 + final Color bgColor; + final TextStyle fontStyle; + final bool isCenter; + const UserChips( + {Key key, + this.city, + this.age, + this.constellation, + this.professional, + this.bgColor, + this.fontStyle, + this.isCenter: false}) + : super(key: key); + + Widget _buildChip(str) { + return Container( + margin: EdgeInsets.only(bottom: 5, right: 5), + padding: EdgeInsets.symmetric(horizontal: 10, vertical: 3), + decoration: BoxDecoration( + color: bgColor == null ? Constants.LightBlueBackgroundColor : bgColor, + borderRadius: BorderRadius.circular(15.0), + ), + child: Text( + str, + textScaleFactor: 1.0, + style: fontStyle == null + ? TextStyle( + fontSize: 11, + color: Constants.LightBlueTextColor, + ) + : fontStyle, + textAlign: TextAlign.center, + ), + ); + } + + @override + Widget build(BuildContext context) { + return Wrap( + alignment: isCenter ? WrapAlignment.center : WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + _buildChip(city), + _buildChip(professional), + _buildChip('$age ${I18n.of(context).years_old}-$constellation'), + ], + ); + } +} diff --git a/lib/utils/analyze_utils.dart b/lib/utils/analyze_utils.dart new file mode 100644 index 0000000..4fef94a --- /dev/null +++ b/lib/utils/analyze_utils.dart @@ -0,0 +1,36 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/TokenMgr.dart'; +import 'package:dio/dio.dart'; + +class AnalyzeUtils { + //访问页面 + static vistPage(int pageIndex) { + print('vistPage'); + } + + //聊天时长 + static Future commitChatDuration(int startTime, int endTime) async { + print('commitChatDuration ${endTime - startTime}'); + + Map data = { + "userId": UserData().basicInfo.userId, + }; + data['sign'] = TokenMgr().getSign(data); + + data["startTime"] = startTime; + data["endTime"] = endTime; + + Response res = await HttpUtil().post('duration/user/insert', data: data); + if (res == null) { + return false; + } + Map resData = res.data; + if (resData['code'] == 0) { + print('提交时长${endTime - startTime}秒成功'); + return true; + } + + return false; + } +} diff --git a/lib/utils/anim_effect_overlay.dart b/lib/utils/anim_effect_overlay.dart new file mode 100644 index 0000000..cc01223 --- /dev/null +++ b/lib/utils/anim_effect_overlay.dart @@ -0,0 +1,83 @@ +import 'package:chat/generated/i18n.dart'; +import 'package:chat/r.dart'; +import 'package:chat/utils/image_frame_animation.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; + +class AnimEffect { + static showEffect(BuildContext context, int giftId) { + var overlayState = Overlay.of(context); + OverlayEntry overlayEntry = OverlayEntry(builder: (context) { + return LayoutBuilder(builder: (context, constraints) { + var item; + if (giftId == 2) { + var imgList = [ + R.assetsImagesGiftShow21, + R.assetsImagesGiftShow22, + R.assetsImagesGiftShow23, + R.assetsImagesGiftShow24 + ].map((imgName) => Image.asset(imgName)).toList(); + + item = ImgFrameAnimation(imgList: imgList); + } else { + var imgPath = 'assets/images/gift_anim_$giftId.gif'; + item = Image.asset(imgPath); + } + + return IgnorePointer( + ignoring: true, + child: Container( + child: Material( + color: Colors.black.withOpacity(0.7), + child: Center(child: item)), + alignment: Alignment.center, + ), + ); + }); + }); + overlayState.insert(overlayEntry); + + //两秒后,移除Toast + Future.delayed(Duration(seconds: 3)).then((value) { + overlayEntry.remove(); + }); + } + + static showDashangEffect( + BuildContext context, bool isMe, int amount, String itemName) { + var overlayState = Overlay.of(context); + OverlayEntry overlayEntry = OverlayEntry(builder: (context) { + return Positioned( + // left: isMe ? 10 : null, + // right: !isMe ? 10 : null, + bottom: 150, + child: Container( + width: Screen.width, + alignment: Alignment + .center, //isMe ? Alignment.centerLeft : Alignment.centerRight, + child: Material( + color: Colors.black.withOpacity(0), + child: isMe + ? fixedText( + I18n.of(context) + .send_gift + .replaceFirst('/s1', amount.toString()) + .replaceFirst('/s2', itemName), + color: Colors.white) + : fixedText( + I18n.of(context) + .receive_gift + .replaceFirst('/s1', amount.toString()) + .replaceFirst('/s2', itemName), + color: Colors.white)), + ), + ); + }); + overlayState.insert(overlayEntry); + + //两秒后,移除Toast + Future.delayed(Duration(seconds: 3)).then((value) { + overlayEntry.remove(); + }); + } +} diff --git a/lib/utils/app_navigator.dart b/lib/utils/app_navigator.dart new file mode 100644 index 0000000..041a561 --- /dev/null +++ b/lib/utils/app_navigator.dart @@ -0,0 +1,219 @@ +import 'package:chat/chat/ChatPage.dart'; +import 'package:chat/chat/coin_bag_info.dart'; +import 'package:chat/chat/coin_bag_view.dart'; +import 'package:chat/chat/company_server_view.dart'; +import 'package:chat/chat/group_chat_view.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/InformUser.dart'; +import 'package:chat/home/ProfilePage.dart'; +import 'package:chat/home/SearchPage.dart'; +import 'package:chat/home/audio_chat_view.dart'; +import 'package:chat/home/create_group_view.dart'; +import 'package:chat/home/group_all_member.dart'; +import 'package:chat/home/group_qr_view.dart'; +import 'package:chat/home/homeMain.dart'; +import 'package:chat/home/qr_scanner_view.dart'; +import 'package:chat/home/qr_view.dart'; +import 'package:chat/home/service_view.dart'; +import 'package:chat/home/translate_robot.dart'; +import 'package:chat/home/webview_page.dart'; +import 'package:chat/map/location_result.dart'; +import 'package:chat/map/map_view.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/utils/NetUtil.dart'; +import 'package:chat/utils/conversation_table.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; + +class AppNavigator { + static SlideTransition createTransition( + Animation animation, Widget child) { + return new SlideTransition( + position: new Tween( + begin: const Offset(1.0, 0.0), + end: const Offset(0.0, 0.0), + ).animate(animation), + child: child, + ); + } + + static FadeTransition createFadeTransition( + Animation animation, Widget child) { + return FadeTransition( + opacity: Tween(begin: 1.0, end: 0.0).animate( + CurvedAnimation(parent: animation, curve: Curves.fastOutSlowIn)), + child: child, + ); + } + + static SlideTransition createUpTransition( + Animation animation, Widget child) { + return SlideTransition( + position: new Tween( + begin: const Offset(0.0, 1.0), + end: const Offset(0.0, 0.0), + ).animate(animation), + child: child, + ); + } + + static defaultPush(BuildContext context, Widget scene) { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return scene; + }, + ), + ); + } + + static push(BuildContext context, Widget scene) { + Navigator.push(context, PageRouteBuilder(pageBuilder: (BuildContext context, + Animation animation, Animation secondaryAnimation) { + // 跳转的路由对象 + return createTransition(animation, scene); + })); + } + + //主页 + static pushHomePage(BuildContext context) { + Navigator.pushAndRemoveUntil(context, PageRouteBuilder(pageBuilder: + (BuildContext context, Animation animation, + Animation secondaryAnimation) { + // 跳转的路由对象 + return createTransition(animation, HomeMain()); + }), (route) => route == null); + } + + //search + static pushSearchPage(BuildContext context) { + AppNavigator.push(context, SearchPage()); + } + + //扫描 + static pushScannerPage(BuildContext context) { + AppNavigator.defaultPush(context, QrScannerPage()); + } + + //聊天 + static pushChatPage(BuildContext context, int friendId,{enterType=0,enterContent}) async { + if(enterType==1){ + Navigator.of(context).pop(context); + } + AppNavigator.push(context, ChatPage(key: Key('Chat'), friendId: friendId,enterType: enterType,enterContent: enterContent,)); + } + + //群聊 + static pushGroupChatPage( + BuildContext context, GroupInfoModel groupInfoModel,{enterType=0,enterContent}) async { + + if(enterType==1){ + Navigator.of(context).pop(context); + } + + AppNavigator.defaultPush(context, + GroupChatPage(key: Key('GroupChat'), groupInfoModel: groupInfoModel,enterType: enterType,enterContent: enterContent,)); + } + + //客服 + static pushServicePage(BuildContext context, {questionIndex = -1}) async { + AppNavigator.push(context, ServiceCenterPage(questionIndex)); + } + + //群成员列表 + static pushGroupAllMember(BuildContext context, GroupInfoModel model) async { + AppNavigator.push(context, GroupAllMember(groupInfoModel: model)); + } + + //群聊二维码 + static pushGroupQrPage(BuildContext context,GroupInfoModel model) { + AppNavigator.push(context, GroupQrPage(model)); + } + + //内部webview + static pushWebview(BuildContext context, String url) async { + AppNavigator.push(context, WebviewPage(url)); + } + + //连麦 + static pushAudioChatPage(BuildContext context, UserInfo userInfo, + [bool isReply = false]) { + //if (SocketUtil().isConnect && SocketUtil().isLogin) { + if (NetWork().isConnect && NetWork().isLogin) { + AppNavigator.push( + context, AudioChatPage(userInfo: userInfo, isReplay: isReply)); + } else { + showToast(I18n.of(context).net_error); + } + } + + //红包发送界面 + static pushCoinBagPage(context) { + Navigator.push(context, PageRouteBuilder(pageBuilder: (BuildContext context, + Animation animation, Animation secondaryAnimation) { + // 跳转的路由对象 + return createUpTransition(animation, CoinBagPage()); + })); + } + + //红包打开界面 + static pushCoinBagInfoPage(context, MsgModel msgModel, titleStr) { + AppNavigator.push(context, CoinBagInfoPage(msgModel, titleStr: titleStr)); + } + + //打开个人信息页面 fromWhere- 0私聊 1首页 2 群聊 addMode : 0不添加,1添加朋友,2新朋友 + static pushProfileInfoPage(BuildContext context, int userId, + {int fromWhere = 0, int addMode = 0}) { + AppNavigator.push( + context, + ProfilePage( + userId: userId, + fromWhere: fromWhere, + addMode: addMode, + )); + } + + //打开地图界面 + static pushMapPage(BuildContext context, LocationResult result) { + AppNavigator.push(context, MapView(locationResult: result)); + } + + //打开举报界面 + static pushInformUserPage(BuildContext context, bool isMale, int userId) { + Navigator.of(context).push( + new MaterialPageRoute( + builder: (context) { + return InformUserPage( + isMan: isMale, + userId: userId, + ); + }, + ), + ); + } + + //我的二维码 + static pushQrPage(BuildContext context) { + AppNavigator.push(context, QrPage()); + } + + //进入翻译机器人页面 + static pushTranslateRobotPage(BuildContext context) { + AppNavigator.push(context, TranslateRobotPage()); + } + + //进入反馈小助手页面 + static pushCompanyServerPage(BuildContext context) { + AppNavigator.push(context, CompanyServerPage()); + } + + //发起群聊界面 + static pushGroupCreatePage( + BuildContext context, List friendList) { + AppNavigator.push( + context, CreateGroupPage(GroupOperatingPageType.CreateGroup, [], null)); + } +} diff --git a/lib/utils/apple_sign_in_btn.dart b/lib/utils/apple_sign_in_btn.dart new file mode 100644 index 0000000..9974440 --- /dev/null +++ b/lib/utils/apple_sign_in_btn.dart @@ -0,0 +1,160 @@ +import 'package:chat/generated/i18n.dart'; +import 'package:flutter/material.dart'; + +/// A type for the authorization button. +enum ButtonType { defaultButton, continueButton, signIn } + +/// A style for the authorization button. +enum ButtonStyle { black, whiteOutline, white } + +/// A button for Sign in With Apple +class AppleSignInBtn extends StatefulWidget { + /// The callback that is called when the button is tapped or otherwise activated. + /// + /// If this is set to null, the button will be disabled. + final VoidCallback onPressed; + + /// A type for the authorization button. + final ButtonType type; + + /// A style for the authorization button. + final ButtonStyle style; + + /// A custom corner radius to be used by this button. + final double cornerRadius; + + const AppleSignInBtn({ + this.onPressed, + this.type = ButtonType.defaultButton, + this.style = ButtonStyle.white, + this.cornerRadius = 20, + }) : assert(type != null), + assert(style != null), + assert(cornerRadius != null); + + @override + State createState() => _AppleSignInBtnState(); +} + +class _AppleSignInBtnState extends State { + bool _isTapDown = false; + + @override + Widget build(BuildContext context) { + final bgColor = + widget.style == ButtonStyle.black ? Colors.black : Colors.white; + final textColor = + widget.style == ButtonStyle.black ? Colors.white : Colors.black; + final borderColor = + widget.style == ButtonStyle.white ? Colors.white : Colors.black; + + return GestureDetector( + onTapDown: (_) => setState(() => _isTapDown = true), + onTapUp: (_) { + setState(() => _isTapDown = false); + widget?.onPressed(); + }, + onTapCancel: () => setState(() => _isTapDown = false), + child: AnimatedContainer( + duration: Duration(milliseconds: 100), + constraints: BoxConstraints( + minHeight: 32, + maxHeight: 64, + minWidth: 150, + ), + height: 20, + decoration: BoxDecoration( + color: _isTapDown ? Colors.grey : bgColor, + borderRadius: BorderRadius.all( + Radius.circular(widget.cornerRadius), + ), + border: Border.all(width: .7, color: borderColor), + ), + child: Center( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 1 , right: 6), + child: SizedBox( + height: 14, + child: AspectRatio( + aspectRatio: 25 / 31, + child: CustomPaint( + painter: _AppleLogoPainter(color: textColor), + ), + ), + ), + ), + Text( + widget.type == ButtonType.continueButton + ? 'Continue with Apple' + : I18n.of(context).sign_in_apple, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + letterSpacing: .3, + wordSpacing: -.5, + color: textColor, + ), + ), + ], + )), + ), + ); + } +} + +class _AppleLogoPainter extends CustomPainter { + final Color color; + + _AppleLogoPainter({@required this.color}); + + @override + void paint(Canvas canvas, Size size) { + final paint = Paint()..color = color; + canvas.drawPath(_getApplePath(size.width, size.height), paint); + } + + static Path _getApplePath(double w, double h) { + return Path() + ..moveTo(w * .50779, h * .28732) + ..cubicTo( + w * .4593, h * .28732, w * .38424, h * .24241, w * .30519, h * .24404) + ..cubicTo( + w * .2009, h * .24512, w * .10525, h * .29328, w * .05145, h * .36957) + ..cubicTo(w * -.05683, h * .5227, w * .02355, h * .74888, w * .12916, + h * .87333) + ..cubicTo(w * .18097, h * .93394, w * .24209, h * 1.00211, w * .32313, + h * .99995) + ..cubicTo(w * .40084, h * .99724, w * .43007, h * .95883, w * .52439, + h * .95883) + ..cubicTo(w * .61805, h * .95883, w * .64462, h * .99995, w * .72699, + h * .99833) + ..cubicTo( + w * .81069, h * .99724, w * .86383, h * .93664, w * .91498, h * .8755) + ..cubicTo( + w * .97409, h * .80515, w * .99867, h * .73698, w * 1, h * .73319) + ..cubicTo(w * .99801, h * .73265, w * .83726, h * .68233, w * .83526, + h * .53082) + ..cubicTo( + w * .83394, h * .4042, w * .96214, h * .3436, w * .96812, h * .34089) + ..cubicTo( + w * .89505, h * .25378, w * .78279, h * .24404, w * .7436, h * .24187) + ..cubicTo( + w * .6413, h * .23538, w * .55561, h * .28732, w * .50779, h * .28732) + ..close() + ..moveTo(w * .68049, h * .15962) + ..cubicTo(w * .72367, h * .11742, w * .75223, h * .05844, w * .74426, 0) + ..cubicTo(w * .68249, h * .00216, w * .60809, h * .03355, w * .56359, + h * .07575) + ..cubicTo(w * .52373, h * .11309, w * .48919, h * .17315, w * .49849, + h * .23051) + ..cubicTo(w * .56691, h * .23484, w * .63732, h * .20183, w * .68049, + h * .15962) + ..close(); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) => false; +} diff --git a/lib/utils/blacklist_mgr.dart b/lib/utils/blacklist_mgr.dart new file mode 100644 index 0000000..cef6f1c --- /dev/null +++ b/lib/utils/blacklist_mgr.dart @@ -0,0 +1,36 @@ +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:oktoast/oktoast.dart'; + +class BlacklistMgr { + //我拉黑的用户id + static Set myBlacklistSet = new Set(); + //拉黑我的用户Id + static Set blacklistMeSet = new Set(); + + //--------------------我的黑名单相关操作 + static addMyBlackList(int userId) { + myBlacklistSet.add(userId); + } + + static removeMyBalckList(int userId) { + myBlacklistSet.remove(userId); + } + + static bool isInMyblaklist(int userId) { + return myBlacklistSet.contains(userId); + } + + //------------------被拉黑名单相关操作 + static addBlackListMe(int userId) { + blacklistMeSet.add(userId); + } + + static removeBalckListMe(int userId) { + blacklistMeSet.remove(userId); + } + + static bool isBlaklistMe(int userId) { + return blacklistMeSet.contains(userId); + } +} diff --git a/lib/utils/chat_data_table.dart b/lib/utils/chat_data_table.dart new file mode 100644 index 0000000..198b5a1 --- /dev/null +++ b/lib/utils/chat_data_table.dart @@ -0,0 +1,245 @@ +import 'dart:typed_data'; + +import 'package:chat/data/UserData.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/utils/sql_model.dart'; + +class ChatDataTableModel { + final String table = 'record'; + Sql sql; + + ChatDataTableModel() { + sql = Sql.setTable(table); + } + + createTable() async { + print('创建表$table'); + await sql.createTable(table, '''rowId INTEGER PRIMARY KEY, + userId INTEGER, + transTag INTEGER, + fromId INTEGER, + friendId INTEGER, + msgType INTEGER, + msgContent BLOB, + time INTEGER, + sessionId INTEGER, + readState INTEGER, + extraInfo INTEGER, + extraFile TEXT, + translateContent BLOB, + enTranslateContent BLOB, + localFile TEXT, + msgState INTEGER, + soundListened INTEGER, + refMsgContent BLOB, + altUsers BLOB'''); + } + + Future clear() { + return sql.clearTable(table); + } + +//查询未读消息条数 + Future> getUnreadCount() async { + var curUserId = UserData().basicInfo.userId; + var lists = await sql.query(table, + columns: ['count(sessionId) as unread'], + where: 'userId = $curUserId and readState = 1', + groupBy: 'sessionId'); + + print('数据库未读数:${lists.length}'); + Map result = {}; + for (var i = 0; i < lists.length; i++) { + Map row = lists[i]; + + int session = row['sessionId']; + if (session != null) { + int count = row['unread']; + result[session] = count; + } + } + + return result; + } + + //查询记录 + Future>> getAllRecord({int count = 100}) async { + var curUserId = UserData().basicInfo.userId; + print('数据库curUserId : $curUserId'); + var lists = await sql.query(table, + where: + 'userId = $curUserId and sessionId in (select DISTINCT sessionId from $table where userId = $curUserId)', + orderBy: 'rowId desc'); + + print('数据库记录数:${lists.length}'); + Map> result = {}; + for (var i = 0; i < lists.length; i++) { + int session = lists[i]['sessionId']; + + if (session != null) { + List msgList = result[session]; + if (msgList == null) { + msgList = []; + result[session] = msgList; + } + msgList.add(MsgModel.fromJson(lists[i])); + } + } + + return result; + } + + ///插入到数据库 + Future insert(MsgModel msgModel) async { + print('插入私聊数据库'); + if (msgModel.sessionId == null) { + print('sessionId 为空.............................'); + return; + } + + var curUserId = UserData().basicInfo.userId; + await sql.insert({ + 'userId': curUserId, + 'transTag': msgModel.transTag, + 'fromId': msgModel.from, + 'friendId': msgModel.friendId, + 'msgType': msgModel.msgType, + 'msgContent': Uint8List.fromList(msgModel.msgContent), + 'time': msgModel.time, + 'sessionId': msgModel.sessionId, + 'readState': msgModel.readState ?? 0, + 'extraFile': msgModel.extraFile, + 'extraInfo': msgModel.extraInfo ?? 0, + 'translateContent': msgModel.translateContent == null + ? Uint8List(0) + : Uint8List.fromList(msgModel.translateContent), + 'enTranslateContent': msgModel.enTranslateContent == null + ? Uint8List(0) + : Uint8List.fromList(msgModel.enTranslateContent), + 'localFile': msgModel.localFile, + 'msgState': 0, + 'soundListened': 0, + 'refMsgContent': msgModel.refMsgContent == null + ? Uint8List(0) + : Uint8List.fromList(msgModel.refMsgContent), + 'altUsers': msgModel.altUsers == null + ? Uint8List(0) + : Uint8List.fromList(msgModel.altUsers), + }); + } + + //更新人工翻译内容 + updateUserTranslateContent( + int session, int sendTime, List transContent, int tranState) async { + var curUserId = UserData().basicInfo.userId; + + if (transContent == null || transContent.length == 0) { + return; + } + var trans = Uint8List.fromList(transContent); + sql.db.update( + table, + { + 'translateContent': trans, + 'enTranslateContent': Uint8List(0), + 'transTag': tranState + }, + where: 'userId=? and sessionId = ? and time = ?', + whereArgs: [curUserId, session, sendTime]); + } + + //更新机器翻译内容 + updateMachineTranslateContent(int session, int sendTime, + List transContent, List enTransContent, int tranState) async { + var curUserId = UserData().basicInfo.userId; + + var trans = + transContent == null ? Uint8List(0) : Uint8List.fromList(transContent); + var enTrans = enTransContent == null + ? Uint8List(0) + : Uint8List.fromList(enTransContent); + sql.db.update( + table, + { + 'translateContent': trans, + 'enTranslateContent': enTrans, + 'transTag': tranState + }, + where: 'userId=? and sessionId = ? and time = ?', + whereArgs: [curUserId, session, sendTime]); + } + + //更新人工翻译评价 + updateUserTranslateRate(int session, int sendTime, int tranState) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'transTag': tranState}, + where: 'userId=? and sessionId = ? and time = ?', + whereArgs: [curUserId, session, sendTime]); + } + + //更新消息发送状态 + updateMsgState(int session, int sendTime, int state) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'msgState': state}, + where: 'userId=? and sessionId = ? and time = ?', + whereArgs: [curUserId, session, sendTime]); + } + + //更新红包状态 + updateWalletState(MsgModel msgModel) async { + var curUserId = UserData().basicInfo.userId; + var content = Uint8List.fromList(msgModel.msgContent); + var session = msgModel.sessionId; + var msgTime = msgModel.time; + + sql.db.update(table, {'msgContent': content}, + where: 'userId=? and sessionId = ? and time = ?', + whereArgs: [curUserId, session, msgTime]); + } + + //更新数据是否已被读取 + updateReadState(int session) async { + print('更新数据$session 已读状态 '); + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'readState': 0}, + where: 'userId=? and sessionId = ? and readState = ?', + whereArgs: [curUserId, session, 1]); + } + + //更新文件本地路径 + updateLocalFile(String extraData, String local) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'localFile': local}, + where: 'userId=? and extraFile = ?', whereArgs: [curUserId, extraData]); + } + + //语音是否听过 + updateSoundListened(MsgModel msg){ + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'soundListened': 1}, + where: 'userId=? and sessionId = ? and time = ?', + whereArgs: [curUserId, msg.sessionId ,msg.time]); + } + + deleteSigleRecordWith(int session, int timeatmp) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.delete(table, + where: 'userId=? and sessionId = ? and time=?', + whereArgs: [curUserId, session, timeatmp]); + } + + //删除聊天数据 + delteRecord(int session) async { + var curUserId = UserData().basicInfo.userId; + print('删除数据 $session'); + + sql.db.delete(table, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, session]); + } +} diff --git a/lib/utils/controller_widget_builder.dart b/lib/utils/controller_widget_builder.dart new file mode 100755 index 0000000..6351de6 --- /dev/null +++ b/lib/utils/controller_widget_builder.dart @@ -0,0 +1,756 @@ +import 'dart:async'; + +import 'package:chat/data/constants.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_ijkplayer/flutter_ijkplayer.dart'; +import 'package:flutter_ijkplayer/src/helper/full_screen_helper.dart'; +import 'package:flutter_ijkplayer/src/helper/logutil.dart'; +import 'package:flutter_ijkplayer/src/helper/time_helper.dart'; +import 'package:flutter_ijkplayer/src/helper/ui_helper.dart'; +import 'package:flutter_ijkplayer/src/route/fullscreen_route.dart'; +import 'package:flutter_ijkplayer/src/widget/progress_bar.dart'; + +part 'full_screen.part.dart'; + +/// Using mediaController to Construct a Controller UI +typedef Widget IJKControllerWidgetBuilder(IjkMediaController controller); + +/// default create IJK Controller UI +Widget defaultBuildIjkControllerWidget(IjkMediaController controller) { + return MyDefaultIJKControllerWidget( + controller: controller, + fullscreenControllerWidgetBuilder: (ctl) => + buildFullscreenMediaController(ctl), + ); +} + +/// Default Controller Widget +/// +/// see [IjkPlayer] and [IJKControllerWidgetBuilder] +class MyDefaultIJKControllerWidget extends StatefulWidget { + final IjkMediaController controller; + + /// If [doubleTapPlay] is true, can double tap to play or pause media. + final bool doubleTapPlay; + + /// If [verticalGesture] is false, vertical gesture will be ignored. + final bool verticalGesture; + + /// If [horizontalGesture] is false, horizontal gesture will be ignored. + final bool horizontalGesture; + + /// Controlling [verticalGesture] is controlling system volume or media volume. + final VolumeType volumeType; + + final bool playWillPauseOther; + + /// Control whether there is a full-screen button. + final bool showFullScreenButton; + + /// The current full-screen button style should not be changed by users. + final bool currentFullScreenState; + + final IJKControllerWidgetBuilder fullscreenControllerWidgetBuilder; + + /// See [FullScreenType] + final FullScreenType fullScreenType; + + + ///自定义全屏布局 + final Widget myFullScreenWidget; + + final bool hideBackButton; + + /// The UI of the controller. + const MyDefaultIJKControllerWidget({ + Key key, + @required this.controller, + this.doubleTapPlay = false, + this.verticalGesture = true, + this.horizontalGesture = true, + this.volumeType = VolumeType.system, + this.playWillPauseOther = true, + this.currentFullScreenState = false, + this.showFullScreenButton = true, + this.fullscreenControllerWidgetBuilder, + this.fullScreenType = FullScreenType.rotateBox, + this.myFullScreenWidget, + this.hideBackButton=false + }) : super(key: key); + + @override + _MyDefaultIJKControllerWidgetState createState() => + _MyDefaultIJKControllerWidgetState(); + + MyDefaultIJKControllerWidget copyWith({ + Key key, + IjkMediaController controller, + bool doubleTapPlay, + bool verticalGesture, + bool horizontalGesture, + VolumeType volumeType, + bool playWillPauseOther, + bool currentFullScreenState, + bool showFullScreenButton, + IJKControllerWidgetBuilder fullscreenControllerWidgetBuilder, + FullScreenType fullScreenType, + }) { + return MyDefaultIJKControllerWidget( + controller: controller ?? this.controller, + doubleTapPlay: doubleTapPlay ?? this.doubleTapPlay, + fullscreenControllerWidgetBuilder: fullscreenControllerWidgetBuilder ?? + this.fullscreenControllerWidgetBuilder, + horizontalGesture: horizontalGesture ?? this.horizontalGesture, + currentFullScreenState: + currentFullScreenState ?? this.currentFullScreenState, + key: key, + volumeType: volumeType ?? this.volumeType, + playWillPauseOther: playWillPauseOther ?? this.playWillPauseOther, + showFullScreenButton: showFullScreenButton ?? this.showFullScreenButton, + verticalGesture: verticalGesture ?? this.verticalGesture, + fullScreenType: fullScreenType ?? this.fullScreenType, + ); + } +} + +class _MyDefaultIJKControllerWidgetState + extends State implements TooltipDelegate { + IjkMediaController get controller => widget.controller; + + GlobalKey currentKey = GlobalKey(); + + bool _isShow = false; + + set isShow(bool value) { + _isShow = value; + setState(() {}); + if (value == true) { + controller.refreshVideoInfo(); + } + } + + bool get isShow => _isShow; + + Timer progressTimer; + + StreamSubscription controllerSubscription; + + @override + void initState() { + super.initState(); + startTimer(); + controllerSubscription = + controller.textureIdStream.listen(_onTextureIdChange); + } + + void _onTextureIdChange(int textureId) { + LogUtils.debug("onTextureChange $textureId"); + if (textureId != null) { + startTimer(); + } else { + stopTimer(); + } + } + + @override + void deactivate() { + super.deactivate(); + } + + @override + void dispose() { + controllerSubscription.cancel(); + stopTimer(); + IjkManager.resetBrightness(); + super.dispose(); + } + + void startTimer() { + if (controller.textureId == null) { + return; + } + + progressTimer?.cancel(); + progressTimer = Timer.periodic(Duration(milliseconds: 350), (timer) { + LogUtils.verbose("timer will call refresh info"); + controller.refreshVideoInfo(); + }); + } + + void stopTimer() { + progressTimer?.cancel(); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + behavior: HitTestBehavior.opaque, + child: buildContent(), + onDoubleTap: onDoubleTap(), + onHorizontalDragStart: wrapHorizontalGesture(_onHorizontalDragStart), + onHorizontalDragUpdate: wrapHorizontalGesture(_onHorizontalDragUpdate), + onHorizontalDragEnd: wrapHorizontalGesture(_onHorizontalDragEnd), + onVerticalDragStart: wrapVerticalGesture(_onVerticalDragStart), + onVerticalDragUpdate: wrapVerticalGesture(_onVerticalDragUpdate), + onVerticalDragEnd: wrapVerticalGesture(_onVerticalDragEnd), + onTap: onTap, + key: currentKey, + ); + } + + Widget buildContent() { + if (!isShow) { + return Container(child: GestureDetector(onTap: (){ + onTap(); + + },child: Container(child: widget.myFullScreenWidget,),),); + } + return StreamBuilder( + stream: controller.videoInfoStream, + builder: (context, snapshot) { + var info = snapshot.data; + if (info == null || !info.hasData) { + return Container(); + } + return buildPortrait(info); + }, + ); + } + + Widget _buildFullScreenButton() { + if (widget.showFullScreenButton != true) { + return Container(); + } + var isFull = widget.currentFullScreenState; + + IJKControllerWidgetBuilder fullscreenBuilder = + widget.fullscreenControllerWidgetBuilder ?? + (ctx) => widget.copyWith(currentFullScreenState: true); + + return IconButton( + color: Colors.white, + icon: Icon(isFull ? Icons.fullscreen_exit : Icons.fullscreen), + onPressed: () { + if (isFull) { + Navigator.pop(context); + } else { + showFullScreenIJKPlayer( + context, + controller, + fullscreenControllerWidgetBuilder: fullscreenBuilder, + fullScreenType: widget.fullScreenType, + ); + } + }, + ); + } + + int _overlayTurns = 0; + + Widget buildPortrait(VideoInfo info) { + _overlayTurns = FullScreenHelper.getQuarterTurns(info, context); + return PortraitController( + controller: controller, + myFullScreenWidget: widget.myFullScreenWidget, + info: info, + tooltipDelegate: this, + playWillPauseOther: widget.playWillPauseOther, + fullScreenWidget: _buildFullScreenButton(), + hideBackButton: widget.hideBackButton, + ); + } + + OverlayEntry _tipOverlay; + + Widget createTooltipWidgetWrapper(Widget widget) { + var typography = Typography(platform: TargetPlatform.android); + var theme = typography.white; + const style = const TextStyle( + fontSize: 15.0, + color: Colors.white, + fontWeight: FontWeight.normal, + ); + var mergedTextStyle = theme.body2.merge(style); + return Container( + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.5), + borderRadius: BorderRadius.circular(20.0), + ), + height: 100.0, + width: 100.0, + child: DefaultTextStyle( + child: widget, + style: mergedTextStyle, + ), + ); + } + + void showTooltip(Widget widget) { + hideTooltip(); + _tipOverlay = OverlayEntry( + builder: (BuildContext context) { + Widget w = IgnorePointer( + child: Center( + child: widget, + ), + ); + + if (this.widget.fullScreenType == FullScreenType.rotateBox && + this.widget.currentFullScreenState && + _overlayTurns != 0) { + w = RotatedBox( + child: w, + quarterTurns: _overlayTurns, + ); + } + + return w; + }, + ); + Overlay.of(context).insert(_tipOverlay); + } + + void hideTooltip() { + _tipOverlay?.remove(); + _tipOverlay = null; + } + + _ProgressCalculator _calculator; + + onTap() => isShow = !isShow; + + Function onDoubleTap() { + return widget.doubleTapPlay + ? () { + LogUtils.debug("ondouble tap"); + controller.playOrPause(); + } + : null; + } + + Function wrapHorizontalGesture(Function function) => + widget.horizontalGesture == true ? function : null; + + Function wrapVerticalGesture(Function function) => + widget.verticalGesture == true ? function : null; + + void _onHorizontalDragStart(DragStartDetails details) async { + var videoInfo = await controller.getVideoInfo(); + _calculator = _ProgressCalculator(details, videoInfo); + } + + void _onHorizontalDragUpdate(DragUpdateDetails details) { + if (_calculator == null || details == null) { + return; + } + var updateText = _calculator.calcUpdate(details); + + var offsetPosition = _calculator.getOffsetPosition(); + + IconData iconData = + offsetPosition > 0 ? Icons.fast_forward : Icons.fast_rewind; + var w = Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + iconData, + color: Colors.white, + size: 40.0, + ), + Text( + updateText, + textAlign: TextAlign.center, + ), + ], + ); + + showTooltip(createTooltipWidgetWrapper(w)); + } + + void _onHorizontalDragEnd(DragEndDetails details) async { + hideTooltip(); + var targetSeek = _calculator?.getTargetSeek(details); + _calculator = null; + if (targetSeek == null) { + return; + } + await controller.seekTo(targetSeek); + var videoInfo = await controller.getVideoInfo(); + if (targetSeek < videoInfo.duration) await controller.play(); + } + + bool verticalDragging = false; + bool leftVerticalDrag; + + void _onVerticalDragStart(DragStartDetails details) { + verticalDragging = true; + var width = UIHelper.findGlobalRect(currentKey).width; + var dx = + UIHelper.globalOffsetToLocal(currentKey, details.globalPosition).dx; + leftVerticalDrag = dx / width <= 0.5; + } + + void _onVerticalDragUpdate(DragUpdateDetails details) async { + if (verticalDragging == false) return; + + String text = ""; + IconData iconData = Icons.volume_up; + + if (leftVerticalDrag == false) { + if (details.delta.dy > 0) { + await volumeDown(); + } else if (details.delta.dy < 0) { + await volumeUp(); + } + + var currentVolume = await getVolume(); + + if (currentVolume <= 0) { + iconData = Icons.volume_mute; + } else if (currentVolume < 50) { + iconData = Icons.volume_down; + } else { + iconData = Icons.volume_up; + } + + text = currentVolume.toString(); + } else if (leftVerticalDrag == true) { + var currentBright = await IjkManager.getSystemBrightness(); + double target; + if (details.delta.dy > 0) { + target = currentBright - 0.03; + } else { + target = currentBright + 0.03; + } + + if (target > 1) { + target = 1; + } else if (target < 0) { + target = 0; + } + + await IjkManager.setSystemBrightness(target); + + if (target >= 0.66) { + iconData = Icons.brightness_high; + } else if (target < 0.66 && target > 0.33) { + iconData = Icons.brightness_medium; + } else { + iconData = Icons.brightness_low; + } + + text = (target * 100).toStringAsFixed(0); + } else { + return; + } + var column = Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + iconData, + color: Colors.white, + size: 25.0, + ), + Padding( + padding: const EdgeInsets.only(top: 10.0), + child: Text(text), + ), + ], + ); + + showTooltip(createTooltipWidgetWrapper(column)); + } + + void _onVerticalDragEnd(DragEndDetails details) async { + verticalDragging = false; + leftVerticalDrag = null; + hideTooltip(); + + Future.delayed(const Duration(milliseconds: 2000), () { + hideTooltip(); + }); + } + + Future getVolume() async { + switch (widget.volumeType) { + case VolumeType.media: + return controller.volume; + case VolumeType.system: + return controller.getSystemVolume(); + } + return 0; + } + + Future volumeUp() async { + var volume = await getVolume(); + volume++; + switch (widget.volumeType) { + case VolumeType.media: + controller.volume = volume; + break; + case VolumeType.system: + await IjkManager.systemVolumeUp(); + break; + } + } + + Future volumeDown() async { + var volume = await getVolume(); + volume--; + switch (widget.volumeType) { + case VolumeType.media: + controller.volume = volume; + break; + case VolumeType.system: + await IjkManager.systemVolumeDown(); + break; + } + } +} + +class _ProgressCalculator { + DragStartDetails startDetails; + VideoInfo info; + + double dx; + + _ProgressCalculator(this.startDetails, this.info); + + String calcUpdate(DragUpdateDetails details) { + dx = details.globalPosition.dx - startDetails.globalPosition.dx; + var f = dx > 0 ? "+" : "-"; + var offset = getOffsetPosition().round().abs(); + return "$f${offset}s"; + } + + double getTargetSeek(DragEndDetails details) { + var target = info.currentPosition + getOffsetPosition(); + if (target < 0) { + target = 0; + } else if (target > info.duration) { + target = info.duration; + } + return target; + } + + double getOffsetPosition() { + return dx / 10; + } +} + +class PortraitController extends StatelessWidget { + final IjkMediaController controller; + final VideoInfo info; + final TooltipDelegate tooltipDelegate; + final bool playWillPauseOther; + final Widget fullScreenWidget; + final Widget myFullScreenWidget; + final bool hideBackButton; + const PortraitController({ + Key key, + this.controller, + this.info, + this.tooltipDelegate, + this.playWillPauseOther = true, + this.fullScreenWidget, + this.myFullScreenWidget, + this.hideBackButton + }) : super(key: key); + + bool get haveTime { + return info.hasData && info.duration > 0; + } + + + + @override + Widget build(BuildContext context) { + if (!info.hasData) { + return Container(); + } + ///播放器定制页面--- + Widget bottomBar = buildBottomBar(context); + + return Column(crossAxisAlignment: CrossAxisAlignment.start,children: [ + Offstage(offstage: hideBackButton,child: InkWell( + onTap: () { + Navigator.pop(context); + }, + child: Container(padding: EdgeInsets.only(top: 10),width: 80,height: 80,child: Icon( + + IconData(0xe615, fontFamily: Constants.IconFontFamily), + size: 35, + color: Color(0xFFeeeeee), + ),), + ),), + Expanded( + child: Container(), + ), + bottomBar, + ],); +// return Stack(children: [ +// +// Positioned.fill(child: Container(child: myFullScreenWidget,)), +// +// Positioned.fill(child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [ +// Container( +// width: ScreenUtil().setWidth(80), +// height: ScreenUtil().setWidth(80), +// padding: EdgeInsets.all(ScreenUtil().setWidth(20)), +// child: InkWell( +// onTap: () { +// Navigator.pop(context); +// }, +// child: Image.asset('assets/images/img_player_back.png'), +// ), +// ), +// Expanded( +// child: Container(), +// ), +// bottomBar, +// ],)) +// +// +// ],); + } + + Widget buildBottomBar(BuildContext context) { + var currentTime = buildCurrentText(); + var maxTime = buildMaxTimeText(); + var progress = buildProgress(info); + + var playButton = buildPlayButton(context); + + var fullScreenButton = buildFullScreenButton(); + + Widget widget = Row( + children: [ + playButton, + Padding( + padding: const EdgeInsets.all(8.0), + child: currentTime, + ), + Expanded(child: progress), + Padding( + padding: const EdgeInsets.all(8.0), + child: maxTime, + ), + fullScreenButton, + ], + ); + widget = DefaultTextStyle( + style: const TextStyle( + color: Colors.white, + ), + child: widget, + ); + widget = Container( + color: Colors.black.withOpacity(0.12), + child: widget, + ); + return widget; + } + + Widget buildProgress(VideoInfo info) { + if (!info.hasData || info.duration == 0) { + return Container(); + } + return Container( + height: 22, + child: ProgressBar( + current: info.currentPosition, + max: info.duration, + changeProgressHandler: (progress) async { + await controller.seekToProgress(progress); + tooltipDelegate?.hideTooltip(); + }, + tapProgressHandler: (progress) { + showProgressTooltip(info, progress); + }, + ), + ); + } + + buildCurrentText() { + return haveTime + ? Text( + TimeHelper.getTimeText(info.currentPosition), + ) + : Container(); + } + + buildMaxTimeText() { + return haveTime + ? Text( + TimeHelper.getTimeText(info.duration), + ) + : Container(); + } + + buildPlayButton(BuildContext context) { + return IconButton( + onPressed: () { + controller.playOrPause(pauseOther: playWillPauseOther); + }, + color: Colors.white, + icon: Icon(info.isPlaying ? Icons.pause : Icons.play_arrow), + iconSize: 25.0, + ); + } + + void showProgressTooltip(VideoInfo info, double progress) { + var target = info.duration * progress; + + var diff = info.currentPosition - target; + + String diffString; + if (diff < 1 && diff > -1) { + diffString = "0s"; + } else if (diff < 0) { + diffString = "+${TimeHelper.getTimeText(diff.abs())}"; + } else if (diff > 0) { + diffString = "-${TimeHelper.getTimeText(diff.abs())}"; + } else { + diffString = "0s"; + } + + Widget text = Container( + alignment: Alignment.center, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + TimeHelper.getTimeText(target), + style: TextStyle(fontSize: 20), + ), + Container( + height: 10, + ), + Text(diffString), + ], + ), + ); + + var tooltip = tooltipDelegate?.createTooltipWidgetWrapper(text); + tooltipDelegate?.showTooltip(tooltip); + } + + Widget buildFullScreenButton() { + return fullScreenWidget ?? Container(); + } +} + +abstract class TooltipDelegate { + void showTooltip(Widget widget); + + Widget createTooltipWidgetWrapper(Widget widget); + + void hideTooltip(); +} + +enum VolumeType { + system, + media, +} diff --git a/lib/utils/conversation_table.dart b/lib/utils/conversation_table.dart new file mode 100644 index 0000000..f0ef076 --- /dev/null +++ b/lib/utils/conversation_table.dart @@ -0,0 +1,154 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/models/ref_name_provider.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/sql_model.dart'; +import 'package:flutter/material.dart'; +import 'package:lpinyin/lpinyin.dart'; +import 'package:provider/provider.dart'; + +class FriendModel { + @required + int friendId; + @required + String avatar; + @required + String name; + String refName; + String nameTag; + int state; + String creatTime; + int applyId; + + FriendModel( + {this.avatar, + this.name, + this.friendId, + this.refName, + this.state = 0, + this.applyId = 0, + this.creatTime = ''}) + : assert(avatar != null), + assert(name != null), + assert(friendId != null) { + nameTag = getNameTag(); + } + + getTitle() { + return refName ?? name; + } + + updataRefName() { + refName = Provider.of(LoadingManage.context, listen: false) + .getRefName(friendId, name); + nameTag = getNameTag(); + } + + FriendModel.fromJson(Map json) { + friendId = json['friendId']; + avatar = json['avatar']; + name = json['name']; + updataRefName(); + } + + FriendModel.fromServerJson(Map json) { + friendId = json['UserId']; + avatar = json['ImgUrl']; + name = json['UserName']; + state = json['ApplyStatus']; + updataRefName(); + } + + FriendModel.fromApplyServerJson(Map json) { + friendId = json['ApplyUserId']; + avatar = json['ApplyUrl']; + name = json['ApplyName']; + state = json['Status']; + creatTime = json['CreatTime']; + applyId = json['Id']; + updataRefName(); + } + + getNameTag() { + var origin = refName; + if (origin == null || origin.length == 0) { + origin = name; + } + String pinyin = PinyinHelper.getPinyinE(origin); + if (pinyin == null || pinyin.length == 0) { + return '#'; + } + var tag = pinyin.substring(0, 1).toUpperCase(); + if (tag == 'Ẩ') { + return 'A'; + } else if (tag == 'Đ') { + return 'D'; + } else if (tag.compareTo("A") < 0 || tag.compareTo("Z") > 0) { + return '#'; + } + return tag; + } +} + +class FriendTableModel { + final String table = 'friend'; + Sql sql; + + FriendTableModel() { + sql = Sql.setTable(table); + } + + createTable() async { + print('创建表$table'); + await sql.createTable( + table, 'friendId INTEGER, userId INTEGER, avatar TEXT,name TEXT'); + } + + Future clear() { + return sql.clearTable(table); + } + + Future insert(FriendModel friendModel) async { + var myId = UserData().basicInfo.userId; + var response = await sql.insert({ + 'avatar': friendModel.avatar, + 'userId': myId, + 'name': friendModel.name, + 'friendId': friendModel.friendId + }); + return response; + } + + Future insertWithUserInfo(UserInfo friendInfo) async { + var response = await sql.insert({ + 'avatar': friendInfo.headimgurl, + 'name': friendInfo.nickName, + 'userId': UserData().basicInfo.userId, + 'friendId': friendInfo.userId + }); + return response; + } + + deleteFriend(int friendId) async { + var curUserId = UserData().basicInfo.userId; + var res = await sql.db.delete(table, + where: 'userId=? and friendId = ?', whereArgs: [curUserId, friendId]); + print('删除好友结果$res'); + return res; + } + + Future> getAllConversation() async { + List resultList = []; + + var curUserId = UserData().basicInfo.userId; + var list = await sql.query(table, where: 'userId = $curUserId'); + + for (var i = 0; i < list.length; i++) { + Map row = list[i]; + + resultList.add(FriendModel.fromJson(row)); + } + + return resultList; + } +} diff --git a/lib/utils/counter_overlay.dart b/lib/utils/counter_overlay.dart new file mode 100644 index 0000000..efd9c33 --- /dev/null +++ b/lib/utils/counter_overlay.dart @@ -0,0 +1,50 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +class CounterOverlay extends StatefulWidget { + @override + CounterOverlayState createState() => CounterOverlayState(); +} + +class CounterOverlayState extends State + with TickerProviderStateMixin { + Timer counter; + int totalCount = 0; + + @override + void initState() { + super.initState(); + + counter = Timer.periodic(Duration(seconds: 1), (Timer timer) { + totalCount += 1; + setState(() {}); + }); + } + + void hide() { + counter.cancel(); + counter = null; + } + + @override + void dispose() { + counter?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + + int h = totalCount ~/ 3600; + int m = (totalCount % 3600) ~/ 60; + int s = totalCount % 60; + + var hStr = h >= 10 ? h.toString() : '0' + h.toString(); + var mStr = m >= 10 ? m.toString() : '0' + m.toString(); + var sStr = s >= 10 ? s.toString() : '0' + s.toString(); + return Text('$hStr:$mStr:$sStr', + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white, fontSize: 30)); + } +} diff --git a/lib/utils/date_utils.dart b/lib/utils/date_utils.dart new file mode 100644 index 0000000..0db491e --- /dev/null +++ b/lib/utils/date_utils.dart @@ -0,0 +1,138 @@ + +import 'package:intl/intl.dart'; + +class DateUtils { + // 工厂模式 + factory DateUtils() => _getInstance(); + + static DateUtils get instance => _getInstance(); + static DateUtils _instance; + + DateUtils._internal() { + // 初始化 + } + + static DateUtils _getInstance() { + if (_instance == null) { + _instance = new DateUtils._internal(); + } + return _instance; + } + + ///将时间日期格式转化为时间戳 + ///2018年12月11日 + ///2019-12-11 + ///2018年11月15 11:14分89 + ///结果是毫秒 + int getTimeStap({formartData: String}) { + var result = formartData.substring(0, 4) + "-" + formartData.substring(5, 7) + "-" + formartData.substring(8, 10); + if (formartData.toString().length>=13&&formartData.substring(10, 13) != null) { + result += "" + formartData.substring(10, 13); + } + if (formartData.toString().length>=17&&formartData.toString().substring(14, 16) != null) { + result += ":" + formartData.substring(14, 16); + } + if (formartData.toString().length>=19&&formartData.substring(17, 19) != null) { + result += ":" + formartData.substring(17, 19); + } + + var dataTime = DateTime.parse(result); + print(dataTime.millisecondsSinceEpoch); + return dataTime.millisecondsSinceEpoch; + } + + ///1.获取从某一天开始到某一天结束的所有的中间日期,例如输入 startTime:2019:07:31 endTime:2019:08:31 就会返回所有的中间天数。 + ///startTime和endTime格式如下都可以 + ///使用: List mdata=DataUtils.instance.getTimeBettwenStartTimeAndEnd(startTime:"2019-07-11",endTime:"2019-08-29",format:"yyyy年MM月dd"); + ///结果:[2019年07月11, 2019年07月12, 2019年07月13, 2019年07月14, 2019年07月15, 2019年07月16, 2019年07月17, 2019年07月18, 2019年07月19, 2019年07月20, 2019年07月21, 2019年07月22, 2019年07月23, 2019年07月24, 2019年07月25, 2019年07月26, 2019年07月27, 2019年07月28, 2019年07月29, 2019年07月30, 2019年07月31, 2019年08月01, 2019年08月02, 2019年08月03, 2019年08月04, 2019年08月05, 2019年08月06, 2019年08月07, 2019年08月08, 2019年08月09, 2019年08月10, 2019年08月11, 2019年08月12, 2019年08月13, 2019年08月14, 2019年08月15, 2019年08月16, 2019年08月17, 2019年08月18, 2019年08月19, 2019年08月20, 2019年08月21, 2019年08月22, 2019年08月23, 2019年08月24, 2019年08月25, 2019年08月26, 2019年08月27, 2019年08月28, 2019年08月29] + List getTimeBettwenStartTimeAndEnd( + {startTime: String, endTime: String, format: String}) { + var mDataList = List(); + //记录往后每一天的时间搓,用来和最后一天到做对比。这样就能知道什么时候停止了。 + int allTimeEnd = 0; + //记录当前到个数(相当于天数) + int currentFlag = 0; + DateTime startData = DateTime.parse(startTime); + DateTime endData = DateTime.parse(endTime); + var mothFormatFlag = new DateFormat(format); + while (endData.millisecondsSinceEpoch > allTimeEnd) { + allTimeEnd = + startData.millisecondsSinceEpoch + currentFlag * 24 * 60 * 60 * 1000; + var dateTime = new DateTime.fromMillisecondsSinceEpoch( + startData.millisecondsSinceEpoch + currentFlag * 24 * 60 * 60 * 1000); + String nowMoth = mothFormatFlag.format(dateTime); + mDataList.add(nowMoth); + currentFlag++; + } + return mDataList; + } + + ///传入starTime格式 2012-02-27 13:27:00 或者 "2012-02-27等.... + ///dayNumber:从startTime往后面多少天你需要输出 + ///formart:获取到的日期格式。"yyyy年MM月dd" "yyyy-MM-dd" "yyyy年" "yyyy年MM月" "yyyy年\nMM月dd" 等等 + ///使用:DataUtils.instance.getTimeStartTimeAndEnd(startTime:"2019-07-11",dayNumber:10,format:"yyyy年MM月dd"); + ///结果:[2019年07月11, 2019年07月12, 2019年07月13, 2019年07月14, 2019年07月15, 2019年07月16, 2019年07月17, 2019年07月18, 2019年07月19, 2019年07月20, 2019年07月21] + List getTimeStartTimeAndEnd( + {startTime: String, dayNumber: int, format: String}) { + var mDataList = List(); + //记录往后每一天的时间搓,用来和最后一天到做对比。这样就能知道什么时候停止了。 + //记录当前到个数(相当于天数) + int currentFlag = 0; + DateTime startData = DateTime.parse(startTime); + var mothFormatFlag = new DateFormat(format); + while (dayNumber >= currentFlag) { + var dateTime = new DateTime.fromMillisecondsSinceEpoch( + startData.millisecondsSinceEpoch + currentFlag * 24 * 60 * 60 * 1000); + String nowMoth = mothFormatFlag.format(dateTime); + mDataList.add(nowMoth); + currentFlag++; + } + return mDataList; + } + + ///格式化时间戳 + ///timeSamp:毫秒值 + ///format:"yyyy年MM月dd hh:mm:ss" "yyy😄MM👌dd hh🙅MM🐶dd" "yyyy:MM:dd"...... + ///结果: 2019😄08👌04 02🙅08🐶02 + getFormartData({timeSamp: int, format: String}) { + var dataFormart = new DateFormat(format); + var dateTime = new DateTime.fromMillisecondsSinceEpoch(timeSamp); + String formartResult = dataFormart.format(dateTime); + return formartResult; + } + + ///获取某一个月的最后一天。 + ///我们能提供和知道的条件有:(当天的时间,) + ///timeSamp:时间戳 单位(毫秒) + ///format:想要的格式 "yyyy年MM月dd hh:mm:ss" "yyy😄MM👌dd hh🙅MM🐶dd" "yyyy:MM:dd" + getEndMoth({timeSamp: int, format: String}) { + var dataFormart = new DateFormat(format); + var dateTime = new DateTime.fromMillisecondsSinceEpoch(timeSamp); + var dataNextMonthData = new DateTime(dateTime.year, dateTime.month + 1, 1); + int nextTimeSamp = + dataNextMonthData.millisecondsSinceEpoch - 24 * 60 * 60 * 1000; + //取得了下一个月1号码时间戳 + var dateTimeeee = new DateTime.fromMillisecondsSinceEpoch(nextTimeSamp); + String formartResult = dataFormart.format(dateTimeeee); + return formartResult; + } + + ///获取某一个月的最后一天。 + ///我们能提供和知道的条件有:(当天的时间,) + ///timeSamp:时间戳 单位(毫秒) + ///format:想要的格式 "yyyy年MM月dd hh:mm:ss" "yyy😄MM👌dd hh🙅MM🐶dd" "yyyy:MM:dd" + getEndMothFor({mothFormart: String, format: String}) { + DateTime startData = DateTime.parse(mothFormart); + var dataFormart = new DateFormat(format); + var dateTime = new DateTime.fromMillisecondsSinceEpoch( + startData.millisecondsSinceEpoch); + var dataNextMonthData = new DateTime(dateTime.year, dateTime.month + 1, 1); + int nextTimeSamp = + dataNextMonthData.millisecondsSinceEpoch - 24 * 60 * 60 * 1000; + //取得了下一个月1号码时间戳 + var dateTimeeee = new DateTime.fromMillisecondsSinceEpoch(nextTimeSamp); + String formartResult = dataFormart.format(dateTimeeee); + return formartResult; + } + +} diff --git a/lib/utils/file_cache_mgr.dart b/lib/utils/file_cache_mgr.dart new file mode 100644 index 0000000..43ae94c --- /dev/null +++ b/lib/utils/file_cache_mgr.dart @@ -0,0 +1,84 @@ +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:path/path.dart' as p; +import 'package:path_provider/path_provider.dart'; + +class FileCacheMgr { + static const key = "libCachedImageData"; + + static FileCacheMgr _instance; + + /// The DefaultCacheManager that can be easily used directly. The code of + /// this implementation can be used as inspiration for more complex cache + /// managers. + factory FileCacheMgr() { + if (_instance == null) { + _instance = new FileCacheMgr._(); + } + return _instance; + } + + FileCacheMgr._(); + + Future getFilePath() async { + var directory = await getTemporaryDirectory(); + return p.join(directory.path, key); + } + + Future genFilePath(String fileId) async { + var filePath = p.join(await getFilePath(), fileId); + var folder = new File(filePath).parent; + if (!(await folder.exists())) { + folder.createSync(recursive: true); + } + return filePath; + } + + Future writeFile(String fileId, Uint8List fileBytes) async { + var path = p.join(await getFilePath(), fileId); + print('receive path : $path'); + var folder = new File(path).parent; + if (!(await folder.exists())) { + folder.createSync(recursive: true); + } + var file = await File(path).writeAsBytes(fileBytes); + + return file; + } + + Future getFile(String fileId) async { + var filePath = p.join(await getFilePath(), fileId); + var file = File(filePath); + if (await file.exists()) { + return file; + } + return null; + } + + + static String pathKey; + static initPathKey()async{ + if(pathKey==null && Platform.isIOS){ + Directory dir = await getTemporaryDirectory(); + String path =dir.path; + int start = path.indexOf('Application')+12; + int end = start+36; + pathKey = path.substring(start,end); + } + } + ///给ios文件路径替换成正确的 + static replacePath(String filePath) { + if(Platform.isIOS && filePath!=null){ +// print('filePath $filePath'); + int start = filePath.indexOf('Application')+12; + int end = start+36; + filePath = filePath.replaceRange(start, end, pathKey); +// print('after : $gg'); + + } + return filePath; + } + + +} diff --git a/lib/utils/file_preview.dart b/lib/utils/file_preview.dart new file mode 100644 index 0000000..f8eafa6 --- /dev/null +++ b/lib/utils/file_preview.dart @@ -0,0 +1,47 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class FilePreview extends StatefulWidget{ + @override + State createState() { + + return FilePreviewState(); + } + +} + +class FilePreviewState extends State{ + + + String fileUrl=''; + + @override + void initState() { + + super.initState(); + + fileUrl= 'newteach.pbworks.com%2Ff%2Fele%2Bnewsletter.docx'; + + } + + @override + Widget build(BuildContext context) { + + return SafeArea(child: Scaffold(body: Column(children: [ + + + ///在线预览 + InkWell(onTap: () async{ +// String url ='https://view.officeapps.live.com/op/view.aspx?src='+Uri.encodeComponent(fileUrl); + String url ='https://view.officeapps.live.com/op/view.aspx?src='+fileUrl; + print('url:$url'); + await launch(url); + + },child: Container(child: Text('跳转--',style: TextStyle(fontSize: 30),),),) + + + ],),)); + } + +} \ No newline at end of file diff --git a/lib/utils/file_transfer_page.dart b/lib/utils/file_transfer_page.dart new file mode 100644 index 0000000..933ddab --- /dev/null +++ b/lib/utils/file_transfer_page.dart @@ -0,0 +1,134 @@ +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/group_item_widget.dart'; +import 'package:chat/home/last_chat_record_widget.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/utils/receive_share_file.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'CustomUI.dart'; + +class FileTransferPage extends StatefulWidget { + final String filePath; + FileTransferPage(this.filePath); + + @override + State createState() { + + return FileTransferPageState(); + } +} + +class FileTransferPageState extends State + with SingleTickerProviderStateMixin { + ScrollController _scrollController = ScrollController(); + + List groupList = []; + var lastMsgList = ChatDataMgr().lastMsgProvider.lastMsgList; + + TabController tabCtrl; + + @override + void initState() { + super.initState(); + + tabCtrl = TabController(length: 2, vsync: this); + groupList = GroupInfoMgr().groupInfoList; + if (groupList.length == 0) { + Future.delayed(Duration(seconds: 3), () { + setState(() { + groupList = GroupInfoMgr().groupInfoList; + }); + }); + } + } + + @override + Widget build(BuildContext context) { + Widget appBar = new AppBar( + backgroundColor: AppColors.NewAppbarBgColor, + title: new Text( + I18n.of(context).send_to, + style: TextStyle(color: AppColors.NewAppbarTextColor), + textScaleFactor: 1.0, + ), + leading: CustomUI.buildCustomLeading(context), + centerTitle: true, + bottom: PreferredSize( + preferredSize: Size.fromHeight(28), + child: Container( + padding: EdgeInsets.only(left: 2), + decoration: BoxDecoration( + color: Constants.LightGreyBackgroundColor, + border: Border(bottom: BorderSide(color: Color(0xffeaeaea)))), + alignment: Alignment.centerLeft, + child: TabBar( + isScrollable: true, + indicatorPadding: EdgeInsets.only(left: 9, right: 9), + tabs: [ + Container( + margin: EdgeInsets.only(right: 4), + child: + Text(I18n.of(context).text_chat, textScaleFactor: 1.0), + ), + Container( + margin: EdgeInsets.only(right: 4), + child: Text(I18n.of(context).group_chat, + textScaleFactor: 1.0)), + ], + controller: tabCtrl, + ), + ))); + + return Material( + child: SafeArea( + child: Scaffold( + appBar: appBar, + body: TabBarView( + children: [ + LastChatPage( + needRobot: false, + enterType: 1, + enterContent: widget.filePath, + ), + + ///群聊 + groupList.length == 0 + ? Container() + : Container( + child: ListView.builder( + controller: _scrollController, + itemBuilder: (BuildContext context, int index) { + var info = groupList[index]; + return GroupItem( + ValueKey(info), + groupInfoModel: info, + enterType: 1, + enterContent: widget.filePath, + ); + }, + itemCount: groupList.length, + )) + ], + controller: tabCtrl, + ), + ), + ), + ); + +// return SafeArea(child: Scaffold(body: FileReaderView( +// filePath: widget.filePath, +// ),)); + } + + @override + void dispose() { + + super.dispose(); + ReceiveShareFile.tempFilePath = null; + tabCtrl.dispose(); + } +} diff --git a/lib/utils/flutter_windowmanager.dart b/lib/utils/flutter_windowmanager.dart new file mode 100644 index 0000000..8fecf3a --- /dev/null +++ b/lib/utils/flutter_windowmanager.dart @@ -0,0 +1,54 @@ +import 'dart:async'; + +import 'package:flutter/services.dart'; + +class FlutterWindowManager { + // Flags for WindowManager.LayoutParams, as per + // https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html + static const int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001; + static const int FLAG_ALT_FOCUSABLE_IM = 0x00020000; + static const int FLAG_DIM_BEHIND = 0x00000002; + static const int FLAG_FORCE_NOT_FULLSCREEN = 0x00000800; + static const int FLAG_FULLSCREEN = 0x00000400; + static const int FLAG_HARDWARE_ACCELERATED = 0x01000000; + static const int FLAG_IGNORE_CHEEK_PRESSES = 0x00008000; + static const int FLAG_KEEP_SCREEN_ON = 0x00000080; + static const int FLAG_LAYOUT_INSET_DECOR = 0x00010000; + static const int FLAG_LAYOUT_IN_SCREEN = 0x00000100; + static const int FLAG_LAYOUT_NO_LIMITS = 0x00000200; + static const int FLAG_NOT_FOCUSABLE = 0x00000008; + static const int FLAG_NOT_TOUCHABLE = 0x00000010; + static const int FLAG_NOT_TOUCH_MODAL = 0x00000020; + static const int FLAG_SCALED = 0x00004000; + static const int FLAG_SECURE = 0x00002000; + static const int FLAG_SHOW_WALLPAPER = 0x00100000; + static const int FLAG_SPLIT_TOUCH = 0x00800000; + static const int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000; + static const int FLAG_BLUR_BEHIND = 0x00000004; + static const int FLAG_DISMISS_KEYGUARD = 0x00400000; + static const int FLAG_DITHER = 0x00001000; + static const int FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = 0x80000000; + static const int FLAG_LAYOUT_ATTACHED_IN_DECOR = 0x40000000; + static const int FLAG_LAYOUT_IN_OVERSCAN = 0x02000000; + static const int FLAG_LOCAL_FOCUS_MODE = 0x10000000; + static const int FLAG_SHOW_WHEN_LOCKED = 0x00080000; + static const int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040; + static const int FLAG_TRANSLUCENT_NAVIGATION = 0x08000000; + static const int FLAG_TRANSLUCENT_STATUS = 0x04000000; + static const int FLAG_TURN_SCREEN_ON = 0x00200000; + + static const MethodChannel _channel = + const MethodChannel('flutter_windowmanager'); + + static Future addFlags(int flags) async { + return await _channel.invokeMethod("addFlags", { + "flags": flags, + }); + } + + static Future clearFlags(int flags) async { + return await _channel.invokeMethod("clearFlags", { + "flags": flags, + }); + } +} diff --git a/lib/utils/frame_animation.dart b/lib/utils/frame_animation.dart new file mode 100644 index 0000000..ed19c84 --- /dev/null +++ b/lib/utils/frame_animation.dart @@ -0,0 +1,82 @@ +import 'package:chat/data/constants.dart'; +import 'package:flutter/material.dart'; + +class FrameAnimation extends StatefulWidget { + final List codeList; + final double size; + final Color color; + final int interval; + final bool isRepeat; + + FrameAnimation( + {this.codeList, + this.size, + this.interval = 200, + this.isRepeat = true, this.color, + }); + + @override + _FrameAnimationState createState() => _FrameAnimationState(); +} + +class _FrameAnimationState extends State + with SingleTickerProviderStateMixin { + Animation _animation; + AnimationController _controller; + int interval = 1000; + List frames = []; + + @override + void initState() { + super.initState(); + + interval = widget.interval; + + final int iconCount = widget.codeList.length; + final int maxTime = interval * iconCount; + + for (var i = 0; i < iconCount; i++) { + frames.add(Icon( + IconData(widget.codeList[i], fontFamily: Constants.IconFontFamily), + size: widget.size, + color:widget.color)); + } + + // 启动动画controller + _controller = new AnimationController( + duration: Duration(milliseconds: maxTime), vsync: this); + _controller.addStatusListener((AnimationStatus status) { + if (status == AnimationStatus.completed) { + _controller.forward(from: 0.0); // 完成后重新开始 + } + }); + + _animation = new Tween(begin: 0, end: iconCount.toDouble()) + .animate(_controller) + ..addListener(() { + setState(() {}); + }); + + _controller.forward(); + } + + @override + void dispose() { + _controller.stop(); + _controller.dispose(); + print('frame animation dipos'); + super.dispose(); + + } + + @override + Widget build(BuildContext context) { + int index = _animation.value.floor() % widget.codeList.length; + + return IndexedStack( + alignment: Alignment.centerRight, + children: frames, + index: index, + ); + } +} diff --git a/lib/utils/friend_list_mgr.dart b/lib/utils/friend_list_mgr.dart new file mode 100644 index 0000000..61962d3 --- /dev/null +++ b/lib/utils/friend_list_mgr.dart @@ -0,0 +1,115 @@ +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/utils/HttpUtil.dart'; +import 'package:chat/utils/conversation_table.dart'; +import 'package:chat/utils/sql_util.dart'; + +class FriendListMgr { + // 工厂模式 + factory FriendListMgr() => _getInstance(); + + static FriendListMgr get instance => _getInstance(); + static FriendListMgr _instance; + + FriendListMgr._internal(); + + static FriendListMgr _getInstance() { + if (_instance == null) { + _instance = FriendListMgr._internal(); + } + return _instance; + } + + List friendList = []; + + //获取好友列表 + getFriendList() async { + if (friendList != null && friendList.length > 0) { + return friendList; + } + friendList = await SqlUtil.friendTableModel.getAllConversation(); + if (friendList.length == 0) { + //从服务器拉取 + print('从服务器获取好友数据'); + getFriendListFromServer(); + } + + return friendList; + } + + getFriendListFromServer() { + HttpUtil().getFriendList((List data) { + Set oldUserId = new Set(); + for (var friendModel in friendList) { + oldUserId.add(friendModel.friendId); + } + data.forEach((f) { + var friend = FriendModel.fromServerJson(f); + if (!oldUserId.contains(friend.friendId)) { + addFriend(friend); + } + oldUserId.remove(friend.friendId); + }); + for (var friendId in oldUserId) { + delteFriend(friendId); + } + }); + } + + //添加好友 + addFriend(FriendModel friendModel) { + if (isMyFriend(friendModel.friendId)) { + return; + } + friendList.add(friendModel); + SqlUtil.friendTableModel.insert(friendModel); + } + + //删除好友 + delteFriend(int friendId) { + for (var friendModel in friendList) { + if (friendModel.friendId == friendId) { + friendList.remove(friendModel); + break; + } + } + SqlUtil.friendTableModel.deleteFriend(friendId); + } + + //删除所有好友 + deleteAllFriend(){ + + friendList.clear(); + SqlUtil.friendTableModel.clear(); + } + + //是否是我的朋友 + isMyFriend(int userId) { + for (var friendModel in friendList) { + if (friendModel.friendId == userId) { + return true; + } + } + return false; + } + + //同步好友信息 + updateFriendInfo(UserInfo info) { + for (int i = 0; i < friendList.length; i++) { + if (friendList[i].friendId == info.userId) { + SqlUtil.friendTableModel.deleteFriend(info.userId); + friendList[i].name = info.nickName; + friendList[i].avatar = info.headimgurl; + friendList[i].nameTag = friendList[i].getNameTag(); + SqlUtil.friendTableModel.insert(friendList[i]); + } + } + } + + updateRefNmae(int userId) { + for (int i = 0; i < friendList.length; i++) { + if (friendList[i].friendId == userId) { + friendList[i].updataRefName(); + } + } + } +} diff --git a/lib/utils/full_screen.part.dart b/lib/utils/full_screen.part.dart new file mode 100755 index 0000000..387925d --- /dev/null +++ b/lib/utils/full_screen.part.dart @@ -0,0 +1,152 @@ +part of './controller_widget_builder.dart'; + +enum FullScreenType { + rotateScreen, + rotateBox, +} + +showFullScreenIJKPlayer( + BuildContext context, + IjkMediaController controller, { + IJKControllerWidgetBuilder fullscreenControllerWidgetBuilder, + FullScreenType fullScreenType = FullScreenType.rotateBox, +}) async { + if (fullScreenType == FullScreenType.rotateBox) { + _showFullScreenWithRotateBox( + context, + controller, + fullscreenControllerWidgetBuilder: fullscreenControllerWidgetBuilder, + ); + return; + } + + _showFullScreenWithRotateScreen( + context, + controller, + fullscreenControllerWidgetBuilder, + ); +} + +_showFullScreenWithRotateScreen( + BuildContext context, + IjkMediaController controller, + IJKControllerWidgetBuilder fullscreenControllerWidgetBuilder) async { + Navigator.push( + context, + FullScreenRoute( + builder: (c) { + return IjkPlayer( + mediaController: controller, + controllerWidgetBuilder: (ctl) => + fullscreenControllerWidgetBuilder(ctl), + ); + }, + ), + ).then((_) { + IjkManager.unlockOrientation(); + IjkManager.setCurrentOrientation(DeviceOrientation.portraitUp); + }); + + var info = await controller.getVideoInfo(); + + Axis axis; + + if (info.width == 0 || info.height == 0) { + axis = Axis.horizontal; + } else if (info.width > info.height) { + if (info.degree == 90 || info.degree == 270) { + axis = Axis.vertical; + } else { + axis = Axis.horizontal; + } + } else { + if (info.degree == 90 || info.degree == 270) { + axis = Axis.horizontal; + } else { + axis = Axis.vertical; + } + } + + if (axis == Axis.horizontal) { + IjkManager.setLandScape(); + } else { + IjkManager.setPortrait(); + } +} + +_showFullScreenWithRotateBox( + BuildContext context, + IjkMediaController controller, { + IJKControllerWidgetBuilder fullscreenControllerWidgetBuilder, +}) async { + var info = await controller.getVideoInfo(); + + Axis axis; + + if (info.width == 0 || info.height == 0) { + axis = Axis.horizontal; + } else if (info.width > info.height) { + if (info.degree == 90 || info.degree == 270) { + axis = Axis.vertical; + } else { + axis = Axis.horizontal; + } + } else { + if (info.degree == 90 || info.degree == 270) { + axis = Axis.horizontal; + } else { + axis = Axis.vertical; + } + } + + Navigator.push( + context, + FullScreenRoute( + builder: (ctx) { + var mediaQueryData = MediaQuery.of(ctx); + + int quarterTurns; + + if (axis == Axis.horizontal) { + if (mediaQueryData.orientation == Orientation.landscape) { + quarterTurns = 0; + } else { + quarterTurns = 1; + } + } else { + quarterTurns = 0; + } + /*else { + if (mediaQueryData.orientation == Orientation.portrait) { + quarterTurns = 0; + } else { + quarterTurns = -1; + } + }*/ + + return SafeArea( + child: RotatedBox( + quarterTurns: quarterTurns, + child: IjkPlayer( + mediaController: controller, + controllerWidgetBuilder: (ctl) => + fullscreenControllerWidgetBuilder(ctl), + ), + ), + ); + }, + ), + ); +} + +Widget _buildFullScreenMediaController( + IjkMediaController controller, bool fullScreen) { + return MyDefaultIJKControllerWidget( + controller: controller, + currentFullScreenState: true, + ); +} + +Widget buildFullscreenMediaController(IjkMediaController controller) { + return _buildFullScreenMediaController(controller, true); +} diff --git a/lib/utils/group_chat_table.dart b/lib/utils/group_chat_table.dart new file mode 100644 index 0000000..dab6bb5 --- /dev/null +++ b/lib/utils/group_chat_table.dart @@ -0,0 +1,247 @@ +import 'dart:typed_data'; + +import 'package:chat/data/UserData.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/utils/sql_model.dart'; + +class GroupChatTableModel { + final String table = 'group_data'; + Sql sql; + + GroupChatTableModel() { + sql = Sql.setTable(table); + } + + createTable() async { + print('创建表$table'); + await sql.createTable(table, '''rowId INTEGER PRIMARY KEY, + userId INTEGER, + transTag INTEGER, + fromId INTEGER, + friendId INTEGER, + msgType INTEGER, + msgContent BLOB, + time INTEGER, + sessionId INTEGER, + readState INTEGER, + extraInfo INTEGER, + extraFile TEXT, + translateContent BLOB, + enTranslateContent BLOB, + localFile TEXT, + msgState INTEGER, + soundListened INTEGER, + refMsgContent BLOB, + altUsers BLOB'''); + } + + Future clear() { + return sql.clearTable(table); + } + + Future clearSelfData() async { + var curUserId = UserData().basicInfo.userId; + var res = + await sql.db.delete(table, where: 'userId=?', whereArgs: [curUserId]); + print('删除结果$res'); + } + +//查询未读消息条数 + Future> getUnreadCount() async { + var curUserId = UserData().basicInfo.userId; + var lists = await sql.query(table, + columns: ['count(sessionId) as unread'], + where: 'userId = $curUserId and readState = 1', + groupBy: 'sessionId'); + + print('数据库未读数:${lists.length}'); + Map result = {}; + for (var i = 0; i < lists.length; i++) { + Map row = lists[i]; + + int session = row['sessionId']; + if (session != null) { + int count = row['unread']; + result[session] = count; + } + } + + return result; + } + + //查询记录 + Future>> getAllRecord({int count = 100}) async { + var curUserId = UserData().basicInfo.userId; + print('数据库curUserId : $curUserId'); + var lists = await sql.query(table, + where: + 'userId = $curUserId and sessionId in (select DISTINCT sessionId from $table where userId = $curUserId)', + orderBy: 'rowId desc'); + + print('数据库记录数:${lists.length}'); + Map> result = {}; + for (var i = 0; i < lists.length; i++) { + int session = lists[i]['sessionId']; + + if (session != null) { + List msgList = result[session]; + if (msgList == null) { + msgList = []; + result[session] = msgList; + } + + msgList.add(MsgModel.fromJson(lists[i], true)); + } + } + + return result; + } + + ///插入到数据库 + Future insert(MsgModel msgModel) async { + print('插入消息到群聊数据库'); + if (msgModel.sessionId == null) { + print('sessionId 为空.............................'); + return; + } + + var curUserId = UserData().basicInfo.userId; + await sql.insert({ + 'userId': curUserId, + 'transTag': msgModel.transTag, + 'fromId': msgModel.from, + 'friendId': msgModel.friendId, + 'msgType': msgModel.msgType, + 'msgContent': Uint8List.fromList(msgModel.msgContent), + 'time': msgModel.time, + 'sessionId': msgModel.sessionId, + 'readState': msgModel.readState ?? 0, + 'extraFile': msgModel.extraFile, + 'extraInfo': msgModel.extraInfo ?? 0, + 'translateContent': msgModel.translateContent == null + ? Uint8List(0) + : Uint8List.fromList(msgModel.translateContent), + 'enTranslateContent': msgModel.enTranslateContent == null + ? Uint8List(0) + : Uint8List.fromList(msgModel.enTranslateContent), + 'localFile': msgModel.localFile, + 'msgState': 0, + 'soundListened': 0, + 'refMsgContent': msgModel.refMsgContent == null + ? Uint8List(0) + : Uint8List.fromList(msgModel.refMsgContent), + 'altUsers': msgModel.altUsers == null + ? Uint8List(0) + : Uint8List.fromList(msgModel.altUsers), + }); + } + + //更新人工翻译内容 + updateUserTranslateContent( + int session, int sendTime, List transContent, int tranState) async { + var curUserId = UserData().basicInfo.userId; + + if (transContent == null || transContent.length == 0) { + return; + } + var trans = Uint8List.fromList(transContent); + sql.db.update(table, {'translateContent': trans, 'transTag': tranState}, + where: 'userId=? and sessionId = ? and time = ?', + whereArgs: [curUserId, session, sendTime]); + } + + //更新机器翻译内容 + updateMachineTranslateContent(int session, int sendTime, + List transContent, List enTransContent, int tranState) async { + var curUserId = UserData().basicInfo.userId; + + var trans = + transContent == null ? Uint8List(0) : Uint8List.fromList(transContent); + var enTrans = enTransContent == null + ? Uint8List(0) + : Uint8List.fromList(enTransContent); + sql.db.update( + table, + { + 'translateContent': trans, + 'enTranslateContent': enTrans, + 'transTag': tranState + }, + where: 'userId=? and sessionId = ? and time = ?', + whereArgs: [curUserId, session, sendTime]); + } + + //更新人工翻译评价 + updateUserTranslateRate(int session, int sendTime, int tranState) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'transTag': tranState}, + where: 'userId=? and sessionId = ? and time = ?', + whereArgs: [curUserId, session, sendTime]); + } + + //更新消息发送状态 + updateMsgState(int session, int sendTime, int state) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'msgState': state}, + where: 'userId=? and sessionId = ? and time = ?', + whereArgs: [curUserId, session, sendTime]); + } + + //更新红包状态 + updateWalletState(MsgModel msgModel) async { + var curUserId = UserData().basicInfo.userId; + var content = Uint8List.fromList(msgModel.msgContent); + var session = msgModel.sessionId; + var msgTime = msgModel.time; + + sql.db.update(table, {'msgContent': content}, + where: 'userId=? and sessionId = ? and time = ?', + whereArgs: [curUserId, session, msgTime]); + } + + //更新数据是否已被读取 + updateReadState(int session) async { + print('更新数据$session 已读状态 '); + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'readState': 0}, + where: 'userId=? and sessionId = ? and readState = ?', + whereArgs: [curUserId, session, 1]); + } + + //更新文件本地路径 + updateLocalFile(String extraData, String local) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'localFile': local}, + where: 'userId=? and extraFile = ?', whereArgs: [curUserId, extraData]); + } + + //语音是否听过 + updateSoundListened(MsgModel msg) { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'soundListened': 1}, + where: 'userId=? and sessionId = ? and time = ?', + whereArgs: [curUserId, msg.sessionId, msg.time]); + } + + deleteSigleRecordWith(int session, int timeatmp) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.delete(table, + where: 'userId=? and sessionId = ? and time=?', + whereArgs: [curUserId, session, timeatmp]); + } + + //删除聊天数据 + delteRecord(int session) async { + var curUserId = UserData().basicInfo.userId; + print('删除数据 $session'); + + sql.db.delete(table, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, session]); + } +} diff --git a/lib/utils/group_info_table.dart b/lib/utils/group_info_table.dart new file mode 100644 index 0000000..f437197 --- /dev/null +++ b/lib/utils/group_info_table.dart @@ -0,0 +1,245 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/utils/sql_model.dart'; +import 'package:chat/utils/sql_util.dart'; +import 'package:sqflite/sqflite.dart'; + +class GroupInfoTableModel { + final String table = 'group_info'; + Sql sql; + + GroupInfoTableModel() { + sql = Sql.setTable(table); + } + + createTable() async { + print('创建表$table'); + await sql.createTable(table, '''rowId INTEGER PRIMARY KEY, + userId INTEGER, + sessionId INTEGER, + topTag INTEGER, + describe TEXT, + decribeTime INTEGER, + name TEXT, + hosterId INTEGER, + image TEXT, + my_name TEXT, + messageFree INTEGER, + ask_switch INTEGER, + is_idle INTEGER, + is_save INTEGER, + show_name INTEGER'''); + } + + Future clear() async { + return sql.clearTable(table); + } + + Future clearSelfData() async { + var curUserId = UserData().basicInfo.userId; + var res = + await sql.db.delete(table, where: 'userId=?', whereArgs: [curUserId]); + print('删除结果$res'); + } + + //获取群的数量 + Future getGroupCount() async { + var curUserId = UserData().basicInfo.userId; + var res = await sql.db.rawQuery( + 'select count(*) as count from $table where userId=$curUserId'); + var count = Sqflite.firstIntValue(res); + print('本地数据群数量$count'); + return count; + } + + //查询群信息 + Future> getGroupList() async { + var curUserId = UserData().basicInfo.userId; + List lists = await sql.query(table, where: 'userId = $curUserId '); + + print('群查询结果${lists.length}'); + List result = []; + + for (var i = 0; i < lists.length; i++) { + var info = GroupInfoModel.fromJson(lists[i]); + //查询群成员 + var members = + await SqlUtil.groupMemberTableModel.getMemberInfo(info.sessionId); + + var lastMsg = ChatDataMgr().getLastMsg(info.sessionId, true); + + for (var i = 0; i < members.length; i++) { + if (members[i].memberId == curUserId) { + info.isInGroup = members[i].inGroup > 0; + break; + } + } + info.members = members; + info.updateLastMsg(lastMsg); + result.add(info); + } + + return result; + } + + //清楚群缓存 + Future clearGroupCache() async { + print('clearGroupCache'); + + var curUserId = UserData().basicInfo.userId; + var res = + await sql.db.delete(table, where: 'userId=?', whereArgs: [curUserId]); + print('clearGroupCache $res'); + } + + //删除群 + Future deleteGroup(int sessionId) async { + print('DB删除群 $sessionId'); + + var curUserId = UserData().basicInfo.userId; + var res = await sql.db.delete(table, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, sessionId]); + print('删除结果$res'); + } + + //该群是否存在 + Future isExistGroup(int sessionId) async { + print('该群是否存在 $sessionId'); + var curUserId = UserData().basicInfo.userId; + var res = await sql.db.rawQuery( + 'select count(*) as count from $table where userId=$curUserId and sessionId = $sessionId'); + var count = res[0]['count']; + print('该群是否存在 ${count > 0}'); + + return count > 0; + } + + //插入新的群 + Future addGroup(GroupInfoModel groupInfo) async { + if (groupInfo.sessionId == null) { + print('sessionId 为空.............................'); + return; + } + print('DB插入新群:${groupInfo.sessionId}'); + var curUserId = UserData().basicInfo.userId; + await sql.insert({ + 'userId': curUserId, + 'sessionId': groupInfo.sessionId, + 'topTag': groupInfo.topTag, + 'describe': groupInfo.describe, + 'decribeTime': groupInfo.decribeTime ?? 0, + 'name': groupInfo.name, + 'hosterId': groupInfo.hosterId, + 'image': groupInfo.image, + 'my_name': groupInfo.myName, + 'messageFree': groupInfo.messageFree, + 'is_save': groupInfo.isSave, + 'show_name': groupInfo.isShowName + }); + } + + Future updateGroup(GroupInfoModel groupInfo) async { + print('更新群:${groupInfo.sessionId}'); + if (groupInfo.sessionId == null) { + print('sessionId 为空.............................'); + return; + } + + var curUserId = UserData().basicInfo.userId; + await sql.insert({ + 'userId': curUserId, + 'sessionId': groupInfo.sessionId, + 'topTag': groupInfo.topTag, + 'describe': groupInfo.describe, + 'decribeTime': groupInfo.decribeTime ?? 0, + 'name': groupInfo.name, + 'hosterId': groupInfo.hosterId, + 'image': groupInfo.image, + 'my_name': groupInfo.myName, + 'messageFree': groupInfo.messageFree, + 'is_save': groupInfo.isSave, + 'show_name': groupInfo.isShowName + }); + } + + //修改群名称 + updateGroupName(int session, String groupName) async { + print('Db修改群名称'); + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'name': groupName}, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, session]); + } + + //修改群头像 + updateImage(int sessionId, String img) async { + print('修改群头像'); + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'image': img}, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, sessionId]); + } + + //修改群验证开关 + updateAskSwitch(int sessionId, int ask) { + print('修改群验证开关'); + + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'ask_switch': ask}, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, sessionId]); + } + + //修改置顶设置 + updateTopTag(int sessionId, int topTag) { + print('修改置顶设置'); + + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'topTag': topTag}, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, sessionId]); + } + + //修改是否在聊天中展示用户名称 + updateShowNameSwitch(int sessionId, int isShow) { + print('修改是否在聊天中展示用户名称'); + + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'show_name': isShow}, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, sessionId]); + } + + //修改群主 + updateHoster(int session, int hostId) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'hosterId': hostId}, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, session]); + } + + //修改自己的别名 + updateMyName(int session, String myName) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'my_name': myName}, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, session]); + } + + //修改群公告 + updateGroupNotice(int session, String description) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'describe': description}, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, session]); + } + + //修改群免打扰 + updateGroupMesssageFree(int session, int isOpen) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'messageFree': isOpen}, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, session]); + } +} diff --git a/lib/utils/group_member_model.dart b/lib/utils/group_member_model.dart new file mode 100644 index 0000000..2c5f854 --- /dev/null +++ b/lib/utils/group_member_model.dart @@ -0,0 +1,81 @@ +import 'package:chat/models/group_info_server_model.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:lpinyin/lpinyin.dart'; + +class GroupMemberModel { + int memberId; + int identity; + String refName; + String nickName; + String avtar; + int inGroup; + String nameTag; + + GroupMemberModel( + {this.memberId, + this.identity, + this.refName, + this.nickName, + this.inGroup, + this.nameTag, + this.avtar}); + + GroupMemberModel.fromPb(GroupMember member) { + memberId = member.info.id; + identity = member.identity.value; + refName = member.name; + nickName = member.info.niceName; + avtar = member.info.headUrl; + inGroup = member.effectiveUser ? 1 : 0; + } + + GroupMemberModel.fromServerMember(GroupServerMembers member) { + memberId = member.info.id; + identity = member.identity; + refName = member.name; + nickName = member.info.niceName; + avtar = member.info.headUrl; + inGroup = member.effectiveUser ? 1 : 0; + } + + GroupMemberModel.fromBaseInfo(BaseUserInfo baseInfo) { + memberId = baseInfo.id; + identity = 0; + inGroup = 1; + refName = baseInfo.niceName; + nickName = baseInfo.niceName; + avtar = baseInfo.headUrl; + } + + GroupMemberModel.fromJson(Map json) { + memberId = json['memberId']; + identity = json['identity'] ?? 0; + refName = json['refName']; + nickName = json['nickName']; + avtar = json['avtar']; + inGroup = json['inGroup'] ?? 1; + } + + getNameTag() { + var origin = refName; + if (origin == null || origin.length == 0) { + origin = nickName; + } + String pinyin = PinyinHelper.getPinyinE(origin); + + String tag = '#'; + if (pinyin == null || pinyin.length == 0) { + tag = '#'; + } else { + tag = pinyin.substring(0, 1).toUpperCase(); + } + + if (tag == 'Ẩ') { + tag = 'A'; + } else if (tag == 'Đ') { + tag = 'D'; + } + + this.nameTag = tag; + } +} diff --git a/lib/utils/group_member_table.dart b/lib/utils/group_member_table.dart new file mode 100644 index 0000000..249252a --- /dev/null +++ b/lib/utils/group_member_table.dart @@ -0,0 +1,137 @@ +import 'package:chat/data/UserData.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/utils/sql_model.dart'; + +import 'group_member_model.dart'; + +class GroupMemberTableModel { + final String table = 'group_member'; + Sql sql; + + GroupMemberTableModel() { + sql = Sql.setTable(table); + } + + createTable() async { + print('创建表$table'); + await sql.createTable(table, '''rowId INTEGER PRIMARY KEY, + userId INTEGER, + sessionId INTEGER, + memberId INTEGER, + identity INTEGER, + refName TEXT, + nickName TEXT, + inGroup INTEGER, + avtar TEXT'''); + } + + Future clear() { + return sql.clearTable(table); + } + + Future clearSelfData() async { + var curUserId = UserData().basicInfo.userId; + var res = + await sql.db.delete(table, where: 'userId=?', whereArgs: [curUserId]); + print('删除结果$res'); + } + + void addSingleMember(int sessionId, GroupMemberModel memberModel) async { + var curUserId = UserData().basicInfo.userId; + + await sql.insert({ + 'userId': curUserId, + 'sessionId': sessionId, + 'memberId': memberModel.memberId, + 'identity': memberModel.identity, + 'refName': memberModel.refName, + 'nickName': memberModel.nickName, + 'inGroup': memberModel.inGroup, + 'avtar': memberModel.avtar, + }); + } + + //更改成员在群状态 + void updateMemberState(int sessionId, int uId, int state) { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'inGroup': state}, + where: 'userId=? and sessionId = ? and memberId = ?', + whereArgs: [curUserId, sessionId, uId]); + } + + //批量插入群成员 + void addMembers(GroupInfoModel infoModel) { + print('插入群成员到数据库'); + for (var i = 0; i < infoModel.members.length; i++) { + addSingleMember(infoModel.sessionId, infoModel.members[i]); + } + } + + //批量删除群成员 + void deleteMembers(int sessionId) { + var curUserId = UserData().basicInfo.userId; + + sql.db.delete(table, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, sessionId]); + } + +//删除群成员缓存 + void clearMemberCache() { + var curUserId = UserData().basicInfo.userId; + + sql.db.delete(table, where: 'userId=?', whereArgs: [curUserId]); + } + + //删除群成员 + void deleteMember(int sessionId, int uId) { + var curUserId = UserData().basicInfo.userId; + print('数据库删除成员$uId'); + sql.db.delete(table, + where: 'userId=? and sessionId = ? and memberId = ?', + whereArgs: [curUserId, sessionId, uId]); + } + + //查询群成员信息 + Future> getMemberInfo(int sessionId) async { + var curUserId = UserData().basicInfo.userId; + List lists = await sql.query(table, + where: 'userId = ? and sessionId = ?', + whereArgs: [curUserId, sessionId]); + + List result = []; + + for (var i = 0; i < lists.length; i++) { + var info = GroupMemberModel.fromJson(lists[i]); + result.add(info); + } + + return result; + } + + //修改成员身份 + updateMemberIdentity(int session, int uId, int identity) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'identity': identity}, + where: 'userId=? and sessionId = ? and memberId = ?', + whereArgs: [curUserId, session, uId]); + } + + //修改群成员的别名 + updateMemberRefName(int session, int uId, String refName) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'refName': refName}, + where: 'userId=? and sessionId = ? and memberId = ?', + whereArgs: [curUserId, session, uId]); + } + + //修改群公告 + updateDescription(int session, String description, int time) async { + var curUserId = UserData().basicInfo.userId; + + sql.db.update(table, {'describe': description, 'decribeTime': time}, + where: 'userId=? and sessionId = ?', whereArgs: [curUserId, session]); + } +} diff --git a/lib/utils/image_frame_animation.dart b/lib/utils/image_frame_animation.dart new file mode 100644 index 0000000..b30c331 --- /dev/null +++ b/lib/utils/image_frame_animation.dart @@ -0,0 +1,72 @@ + +import 'package:flutter/material.dart'; + +class ImgFrameAnimation extends StatefulWidget { + final List imgList; + final int interval; + final bool isRepeat; + + ImgFrameAnimation( + {this.imgList, + this.interval = 200, + this.isRepeat = true, + }); + + @override + _ImgFrameAnimationState createState() => _ImgFrameAnimationState(); +} + +class _ImgFrameAnimationState extends State + with SingleTickerProviderStateMixin { + Animation _animation; + AnimationController _controller; + int interval = 1000; + + @override + void initState() { + super.initState(); + + interval = widget.interval; + + final int itemCount = widget.imgList.length; + final int maxTime = interval * itemCount; + + + // 启动动画controller + _controller = new AnimationController( + duration: Duration(milliseconds: maxTime), vsync: this); + _controller.addStatusListener((AnimationStatus status) { + if (status == AnimationStatus.completed) { + _controller.forward(from: 0.0); // 完成后重新开始 + } + }); + + _animation = new Tween(begin: 0, end: itemCount.toDouble()) + .animate(_controller) + ..addListener(() { + setState(() {}); + }); + + _controller.forward(); + } + + @override + void dispose() { + _controller.stop(); + _controller.dispose(); + print('frame animation dipos'); + super.dispose(); + + } + + @override + Widget build(BuildContext context) { + int index = _animation.value.floor() % widget.imgList.length; + + return IndexedStack( + alignment: Alignment.centerRight, + children: widget.imgList, + index: index, + ); + } +} diff --git a/lib/utils/image_util.dart b/lib/utils/image_util.dart new file mode 100644 index 0000000..0c1fc00 --- /dev/null +++ b/lib/utils/image_util.dart @@ -0,0 +1,359 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:typed_data'; +import 'dart:ui'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_image_compress/flutter_image_compress.dart'; + +import '../r.dart'; +import 'file_cache_mgr.dart'; +import 'group_member_model.dart'; + + +const ImgSizeLimit = 60 * 1024; + + +/// Widget Util. +class WidgetUtil { + bool _hasMeasured = false; + double _width; + double _height; + + /// Widget rendering listener. + /// Widget渲染监听. + /// context: Widget context. + /// isOnce: true,Continuous monitoring false,Listen only once. + /// onCallBack: Widget Rect CallBack. + void asyncPrepare( + BuildContext context, bool isOnce, ValueChanged onCallBack) { + if (_hasMeasured) return; + WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) { + RenderBox box = context.findRenderObject(); + if (box != null && box.semanticBounds != null) { + if (isOnce) _hasMeasured = true; + double width = box.semanticBounds.width; + double height = box.semanticBounds.height; + if (_width != width || _height != height) { + _width = width; + _height = height; + if (onCallBack != null) onCallBack(box.semanticBounds); + } + } + }); + } + + /// Widget渲染监听. + void asyncPrepares(bool isOnce, ValueChanged onCallBack) { + if (_hasMeasured) return; + WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) { + if (isOnce) _hasMeasured = true; + if (onCallBack != null) onCallBack(null); + }); + } + + ///get Widget Bounds (width, height, left, top, right, bottom and so on).Widgets must be rendered completely. + ///获取widget Rect + static Rect getWidgetBounds(BuildContext context) { + RenderBox box = context.findRenderObject(); + return (box != null && box.semanticBounds != null) + ? box.semanticBounds + : Rect.zero; + } + + static getCompressImg(String imgPath) async { + var compressImg = await FlutterImageCompress.compressWithFile(imgPath, + quality: 20, minWidth: Screen.width.toInt()); + print('图片压缩完毕 : ${compressImg.length}'); + if (compressImg.length > ImgSizeLimit) { + //仍大于,再压缩一次 + compressImg = await FlutterImageCompress.compressWithFile(imgPath, + quality: 20, minWidth: (Screen.width * 0.5).toInt()); + } + + return compressImg; + } + + ///Get the coordinates of the widget on the screen.Widgets must be rendered completely. + ///获取widget在屏幕上的坐标,widget必须渲染完成 + static Offset getWidgetLocalToGlobal(BuildContext context) { + RenderBox box = context.findRenderObject(); + return box == null ? Offset.zero : box.localToGlobal(Offset.zero); + } + + /// get image width height,load error return Rect.zero.(unit px) + /// 获取图片宽高,加载错误情况返回 Rect.zero.(单位 px) + /// image + /// url network + /// local url , package + static Future getImageWH( + {Image image, String url, String localUrl, String package}) { + if (image == null && url == null && localUrl == null) { + return Future.value(Rect.zero); + } + Completer completer = Completer(); + Image img = image != null + ? image + : ((url != null && url.isNotEmpty) + ? Image.network(url) + : Image.asset(localUrl, package: package)); + img.image + .resolve(new ImageConfiguration()) + .addListener(new ImageStreamListener( + (ImageInfo info, bool _) { + completer.complete(Rect.fromLTWH(0, 0, info.image.width.toDouble(), + info.image.height.toDouble())); + }, + onError: (dynamic exception, StackTrace stackTrace) { + completer.completeError(exception, stackTrace); + }, + )); + return completer.future; + } + + /// get image width height, load error throw exception.(unit px) + /// 获取图片宽高,加载错误会抛出异常.(单位 px) + /// image + /// url network + /// local url (full path/全路径,example:"assets/images/ali_connors.png",""assets/images/3.0x/ali_connors.png"" ); + /// package + static Future getImageWHE( + {Image image, String url, String localUrl, String package}) { + if (image == null && url == null && localUrl == null) { + return Future.value(Rect.zero); + } + Completer completer = Completer(); + Image img = image != null + ? image + : ((url != null && url.isNotEmpty) + ? Image.network(url) + : Image.asset(localUrl, package: package)); + img.image + .resolve(new ImageConfiguration()) + .addListener(new ImageStreamListener( + (ImageInfo info, bool _) { + completer.complete(Rect.fromLTWH(0, 0, info.image.width.toDouble(), + info.image.height.toDouble())); + }, + onError: (dynamic exception, StackTrace stackTrace) { + completer.completeError(exception, stackTrace); + }, + )); + + return completer.future; + } + + + + + + + + + + static ImageProvider groupAvatar(String path ) { + + path = FileCacheMgr.replacePath(path); + Uint8List fileData = File(path).readAsBytesSync(); +// print('fileData ${fileData.length}'); + return MemoryImage(fileData); + + + } + + + static Widget getAvatarNew(GroupInfoModel model,GlobalKey key,Function backPath) { + + List members =[]; + + for(int k=0;k< model.members.length;k++){ //只加入存在群的 + GroupMemberModel mo = model.members[k]; + if(mo.inGroup==1){ + members.add(mo); + } + } + + + + + if(model.image!=null && model.image.length>2){ + print('${model.name} 群头像地址:${model.image}'); + + File file = new File(model.image); + +// int filelength = file.readAsBytesSync().length; +// print('群头像地址file size : $filelength'); + if( file.existsSync()){ //防止头像文件被清除后 + + Uint8List pngBytes =file.readAsBytesSync(); + print('pngBytes.lengthInBytes length;${pngBytes.lengthInBytes}'); + if(pngBytes.lengthInBytes>8000){ + return ClipRRect( borderRadius: BorderRadius.circular(5),child:Container(color: Color(0xffE9E9E9),width: 52,height: 52,child: + Image.file( + File(FileCacheMgr.replacePath(model.image)), + fit: BoxFit.contain, + width: 50, + height: 50, + ),) ,); + } + + + }else{ + backPath(''); + } + + + } + + + ///先让下面的图片显示,5秒后截图保存图片 + Future.delayed(Duration(seconds: 3),() async{ +// print('没有群图片-开始生成保存到本地:${model.members.length}'); + try { + + RenderRepaintBoundary boundary = + key.currentContext.findRenderObject(); + var image = await boundary.toImage(pixelRatio:2); + ByteData byteData = await image.toByteData(format: ImageByteFormat.png); + Uint8List pngBytes = byteData.buffer.asUint8List(); + File file =await FileCacheMgr().writeFile(model.sessionId.toString(),pngBytes); + print('图片地址byteData${byteData.lengthInBytes}'); + if(byteData.lengthInBytes>8000 && members.length>1){ //图片保存成功 + GroupInfoMgr().updateAvatar(model.sessionId,file.path); + backPath(file.path); + } + +// ImageGallerySaver.saveImage(pngBytes); +// return pngBytes;//这个对象就是图片数据 + } catch (e) { + print(e); + } + + }); + + if(members.length>9){ + members = members.sublist(0,9); + } + + + + + + if (members.length > 0) { + double itemSize = 10; + switch (members.length) { + case 1: + + return RepaintBoundary(key: key,child: ClipRRect(borderRadius: BorderRadius.circular(3),child: Container(color: Color(0xffE9E9E9),width: 52,height: 52,child: Padding(padding: EdgeInsets.all(1),child: CachedNetworkImage( + imageUrl: members[0].avtar, + width: 45, + height: 45, + placeholder: (context, url) => + Image.asset(R.assetsImagesDefaultNorAvatar,width: 45, + height: 45,) + ),),),),); + break; + case 2: + return RepaintBoundary(key: key,child: ClipRRect(borderRadius: BorderRadius.circular(3),child: Container(color: Color(0xffE9E9E9),width: 52,height: 52,child: Row(children: [ + Padding(padding: EdgeInsets.all(1),child: ClipRRect( + borderRadius: BorderRadius.circular(3), + child: CachedNetworkImage( + imageUrl: members[0].avtar, + width: 23, + height: 23, + placeholder: (context, url) => + Image.asset(R.assetsImagesDefaultNorAvatar, width: 23, + height: 23,) + ), + ),), + Padding(padding: EdgeInsets.all(1),child: ClipRRect( + borderRadius: BorderRadius.circular(3), + child: CachedNetworkImage( + imageUrl: members[1].avtar, + width: 23, + height: 23,placeholder: (context, url) => + Image.asset(R.assetsImagesDefaultNorAvatar,width: 23, + height: 23,) + ), + ),) + ],),),),); + case 3: + return RepaintBoundary(key: key,child: ClipRRect(borderRadius: BorderRadius.circular(3),child: Container(color: Color(0xffE9E9E9),width: 52,height: 52,child: Column(children: [ + + Padding(padding: EdgeInsets.all(1),child: ClipRRect( + borderRadius: BorderRadius.circular(3), + child: CachedNetworkImage( + imageUrl: members[0].avtar, + width: 23, + height: 23,placeholder: (context, url) => + Image.asset(R.assetsImagesDefaultNorAvatar,width: 23, + height: 23,) + ), + ),), + + + Row(children: [ + Padding(padding: EdgeInsets.all(1),child: ClipRRect( + borderRadius: BorderRadius.circular(3), + child: CachedNetworkImage( + imageUrl: members[1].avtar, + width: 23, + height: 23,placeholder: (context, url) => + Image.asset(R.assetsImagesDefaultNorAvatar,width: 23, + height: 23,) + ), + ),), + Padding(padding: EdgeInsets.all(1),child: ClipRRect( + borderRadius: BorderRadius.circular(3), + child: CachedNetworkImage( + imageUrl: members[2].avtar, + width: 23, + height: 23,placeholder: (context, url) => + Image.asset(R.assetsImagesDefaultNorAvatar,width: 23, + height: 23,) + ), + ),) + ],) + + ],),),),); + } + + if (members.length == 4) { + itemSize = 23; + } else { + itemSize = 15; + } + + List widgetList = []; + for (int k = 0; k < members.length; k++) { + widgetList.add(Padding(padding: EdgeInsets.all(1),child: ClipRRect( + borderRadius: BorderRadius.circular(3), + child: CachedNetworkImage( + imageUrl: members[k].avtar, + width: itemSize, + height: itemSize,placeholder: (context, url) => + Image.asset(R.assetsImagesDefaultNorAvatar,width: itemSize, + height: itemSize,) + ), + ),)); + } + + return RepaintBoundary(key: key,child: ClipRRect(borderRadius: BorderRadius.circular(3),child: Container( + color: Color(0xffE9E9E9), + width: 52, + height: 52, + alignment: Alignment.center, + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.start, children: widgetList), + ),),); + } else { + return ClipRRect(borderRadius: BorderRadius.circular(3),child: Container(color: Color(0xffE9E9E9),),); + } + } + +} diff --git a/lib/utils/keyboard/bottom_area_avoider.dart b/lib/utils/keyboard/bottom_area_avoider.dart new file mode 100644 index 0000000..49eaec3 --- /dev/null +++ b/lib/utils/keyboard/bottom_area_avoider.dart @@ -0,0 +1,214 @@ +import 'dart:collection'; +import 'package:flutter/widgets.dart'; +import 'package:flutter/rendering.dart'; + +/// Helps [child] stay visible by resizing it to avoid the given [areaToAvoid]. +/// +/// Wraps the [child] in a [AnimatedContainer] that adjusts its bottom [padding] to accommodate the given area. +/// +/// If [autoScroll] is true and the [child] contains a focused widget such as a [TextField], +/// automatically scrolls so that it is just visible above the keyboard, plus any additional [overscroll]. +class BottomAreaAvoider extends StatefulWidget { + static const Duration defaultDuration = Duration(milliseconds: 100); + static const Curve defaultCurve = Curves.easeIn; + static const double defaultOverscroll = 12.0; + static const bool defaultAutoScroll = false; + + /// The child to embed. + /// + /// If the [child] is not a [ScrollView], it is automatically embedded in a [SingleChildScrollView]. + /// If the [child] is a [ScrollView], it must have a [ScrollController]. + final Widget child; + + /// Amount of bottom area to avoid. For example, the height of the currently-showing system keyboard, or + /// any custom bottom overlays. + final double areaToAvoid; + + /// Whether to auto-scroll to the focused widget after the keyboard appears. Defaults to false. + /// Could be expensive because it searches all the child objects in this widget's render tree. + final bool autoScroll; + + /// Extra amount to scroll past the focused widget. Defaults to [defaultOverscroll]. + /// Useful in case the focused widget is inside a parent widget that you also want to be visible. + final double overscroll; + + /// Duration of the resize animation. Defaults to [defaultDuration]. To disable, set to [Duration.zero]. + final Duration duration; + + /// Animation curve. Defaults to [defaultCurve] + final Curve curve; + + ScrollController scrollTo; + + BottomAreaAvoider({ + Key key, + @required this.child, + @required this.areaToAvoid, + this.autoScroll = false, + this.duration = defaultDuration, + this.curve = defaultCurve, + this.scrollTo, + this.overscroll = defaultOverscroll, + }) : //assert(child is ScrollView ? child.controller != null : true), + assert(areaToAvoid >= 0, 'Cannot avoid a negative area'), + super(key: key); + + BottomAreaAvoiderState createState() => BottomAreaAvoiderState(); +} + +class BottomAreaAvoiderState extends State { + final _animationKey = new GlobalKey(); + Function(AnimationStatus) _animationListener; + ScrollController _scrollController; + double _previousAreaToAvoid; + + scroll() { + _scrollController.position.moveTo( + 200, + duration: Duration(milliseconds: 100), + curve: widget.curve, + ); + } + + @override + void initState() { + super.initState(); + } + + @override + void didUpdateWidget(BottomAreaAvoider oldWidget) { + _previousAreaToAvoid = oldWidget.areaToAvoid; + super.didUpdateWidget(oldWidget); + } + + @override + void dispose() { + _animationKey.currentState?.animation + ?.removeStatusListener(_animationListener); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + // Add a status listener to the animation after the initial build. + // Wait a frame so that _animationKey.currentState is not null. + if (_animationListener == null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + _animationListener = _paddingAnimationStatusChanged; + _animationKey.currentState.animation + .addStatusListener(_animationListener); + }); + } + + // If [child] is a [ScrollView], get its [ScrollController] + // and embed the [child] directly in an [AnimatedContainer]. + if (widget.child is ScrollView) { + var scrollView = widget.child as ScrollView; + _scrollController = + scrollView.controller ?? PrimaryScrollController.of(context); + + return _buildAnimatedContainer(widget.child); + } + // If [child] is not a [ScrollView], and [autoScroll] is true, + // embed the [child] in a [SingleChildScrollView] to make + // it possible to scroll to the focused widget. + if (widget.autoScroll) { + _scrollController = widget.scrollTo; +// widget.scrollTo =_scrollController; + return _buildAnimatedContainer( + LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + controller: _scrollController, + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: widget.child, + ), + ); + }, + ), + ); + } + // Just embed the [child] directly in an [AnimatedContainer]. + return _buildAnimatedContainer(widget.child); + } + + Widget _buildAnimatedContainer(Widget child) { + return AnimatedContainer( + key: _animationKey, + padding: EdgeInsets.only(bottom: widget.areaToAvoid), + duration: widget.duration, + curve: widget.curve, + child: child, + ); + } + + /// Called whenever the status of our padding animation changes. + /// + /// If the animation has completed, we added overlap, and scroll is on, scroll to that. + void _paddingAnimationStatusChanged(AnimationStatus status) { + if (status != AnimationStatus.completed) { + return; // Only check when the animation is finishing + } + if (!widget.autoScroll) { + return; // auto scroll is not enabled, do nothing + } + if (widget.areaToAvoid <= _previousAreaToAvoid) { + return; // decreased-- do nothing. We only scroll when area to avoid is added (keyboard shown). + } + + // Need to wait a frame to get the new size (todo: is this still needed? we dont use mediaquery anymore) + WidgetsBinding.instance.addPostFrameCallback((_) { + if (context == null || !mounted) { + return; // context is no longer valid + } + final focused = findFocusedObject(context.findRenderObject()); + if (focused == null) { + return; // no focused object found + } + scrollToObject(focused, _scrollController, widget.duration, widget.curve, + widget.overscroll); + }); + } +} + +/// Utility helper methods + +/// Finds the first focused focused child of [root] using a breadth-first search. +RenderObject findFocusedObject(RenderObject root) { + final q = Queue(); + q.add(root); + while (q.isNotEmpty) { + final node = q.removeFirst(); + final config = SemanticsConfiguration(); + node.describeSemanticsConfiguration(config); + if (config.isFocused) { + return node; + } + node.visitChildrenForSemantics((child) { + q.add(child); + }); + } + return null; +} + +/// Scroll to the given [object], which must be inside [scrollController]s viewport. +scrollToObject(RenderObject object, ScrollController scrollController, + Duration duration, Curve curve, double overscroll) { + // Calculate the offset needed to show the object in the [ScrollView] + // so that its bottom touches the top of the keyboard. + final viewport = RenderAbstractViewport.of(object); + final offset = viewport.getOffsetToReveal(object, 1.0).offset + overscroll; + + // If the object is covered by the keyboard, scroll to reveal it, + // and add [focusPadding] between it and top of the keyboard. + if (offset > scrollController.position.pixels) { + scrollController.position.moveTo( + offset, + duration: duration, + curve: curve, + ); + } +} diff --git a/lib/utils/keyboard_utils.dart b/lib/utils/keyboard_utils.dart new file mode 100644 index 0000000..45fa107 --- /dev/null +++ b/lib/utils/keyboard_utils.dart @@ -0,0 +1,35 @@ +import 'dart:async'; + +import 'package:chat/data/constants.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:keyboard_utils/keyboard_listener.dart'; +import 'package:keyboard_utils/keyboard_utils.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class KeyboardBloc { + KeyboardUtils _keyboardUtils = KeyboardUtils(); + StreamController _streamController = StreamController(); + Stream get stream => _streamController.stream; + + KeyboardUtils get keyboardUtils => _keyboardUtils; + + void start() { + _keyboardUtils.add(listener: + KeyboardListener(willShowKeyboard: (double keyboardHeight) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + + if (keyboardHeight > 10) { + _streamController.sink.add(keyboardHeight); + prefs.setDouble(Constants.KeyboardHeight, keyboardHeight); + } + },willHideKeyboard: () async{ + print('~~~~willHideKeyboard~~~~~~'); + MessageMgr().emit('Keyboard Hide'); + })); + } + + void dispose() { + _keyboardUtils.dispose(); + _streamController.close(); + } +} diff --git a/lib/utils/loading_builder.dart b/lib/utils/loading_builder.dart new file mode 100644 index 0000000..ac19557 --- /dev/null +++ b/lib/utils/loading_builder.dart @@ -0,0 +1,102 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import 'log.dart'; + +typedef WidgetBuilder = Widget Function(BuildContext context, T snapshot); + +class FutureLoadingBuilder extends StatefulWidget { + const FutureLoadingBuilder({ + Key key, + @required this.future, + this.initialData, + @required this.builder, + this.mutable = false, + this.loadingIndicator, + }) : assert(builder != null), + super(key: key); + + /// The asynchronous computation to which this builder is currently connected, + /// possibly null. + /// + /// If no future has yet completed, including in the case where [future] is + /// null, the data provided to the [builder] will be set to [initialData]. + final Future future; + + final WidgetBuilder builder; + + /// The data that will be used to create the snapshots provided until a + /// non-null [future] has completed. + /// + /// If the future completes with an error, the data in the [AsyncSnapshot] + /// provided to the [builder] will become null, regardless of [initialData]. + /// (The error itself will be available in [AsyncSnapshot.error], and + /// [AsyncSnapshot.hasError] will be true.) + final T initialData; + + /// default is true + /// + /// set to false if the future will change. + final bool mutable; + + final Widget loadingIndicator; + + @override + _FutureLoadingBuilderState createState() => + _FutureLoadingBuilderState(); +} + +class _FutureLoadingBuilderState extends State> { + Future future; + + @override + void initState() { + super.initState(); + future = widget.future; + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: widget.mutable ? widget.future : future, + initialData: widget.initialData, + builder: (BuildContext context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.none: + case ConnectionState.active: + case ConnectionState.waiting: + return widget.loadingIndicator ?? + Center(child: CircularProgressIndicator()); + + case ConnectionState.done: + if (snapshot.hasError) { + var error = snapshot.error; + if (error is SocketException) { + d('SocketException-> ${error.message}'); + return Center( + child: Text( + 'Please check your connection', + overflow: TextOverflow.fade, + ), + ); + } else if (error is PlatformException && + error.code == 'ERROR_GEOCODING_COORDINATES') { + return Text( + 'Please check your connection', + overflow: TextOverflow.fade, + ); + } else { + d('Unknow error: $error'); + return Center(child: Text('Unknown error')); + } + } + + return widget.builder(context, snapshot.data); + } + return widget.builder(context, snapshot.data); + }, + ); + } +} \ No newline at end of file diff --git a/lib/utils/local_notification_util.dart b/lib/utils/local_notification_util.dart new file mode 100644 index 0000000..95004a7 --- /dev/null +++ b/lib/utils/local_notification_util.dart @@ -0,0 +1,441 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; + +import 'package:chat/data/UserData.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/InfoList.dart'; +import 'package:chat/home/ProgramDetail.dart'; +import 'package:chat/home/rich_title.dart'; +import 'package:chat/models/received_notification.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_app_badger/flutter_app_badger.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:jpush_flutter/jpush_flutter.dart'; +import 'package:rxdart/rxdart.dart'; + +import 'MessageMgr.dart'; + +class LocalNotificationUtil { + static bool isBackground = false; + + ///是否在后台 + static int badgerCount = 0; + + ///角标计数 + + BuildContext mContext; + + factory LocalNotificationUtil() => _getInstance(); + static LocalNotificationUtil get instance => _getInstance(); + static LocalNotificationUtil _instance; + + static const String PAYLOAD_DATE = 'date'; + static const String PAYLOAD_FRIENDS = 'friends'; + + /// date+@+节目id + static const String PAYLOAD_OTHER = 'other'; + + /// 其他 + + LocalNotificationUtil._internal() { + // 初始化 + } + static LocalNotificationUtil _getInstance() { + if (_instance == null) { + _instance = new LocalNotificationUtil._internal(); + } + return _instance; + } + + FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); +// Streams are created so that app can respond to notification-related events since the plugin is initialised in the `main` function + BehaviorSubject didReceiveLocalNotificationSubject = + BehaviorSubject(); + + BehaviorSubject selectNotificationSubject = BehaviorSubject(); + + void initJPush() { + JPush jpush = new JPush(); + + ///ios一定要加这句 + jpush.applyPushAuthority( + new NotificationSettingsIOS(sound: true, alert: true, badge: true)); + jpush.addEventHandler( + // 接收通知回调方法。 + onReceiveNotification: (Map message) async { + print("flutter onReceiveNotification: $message"); + }, + // 点击通知回调方法。 + onOpenNotification: (Map message) async { + print("flutter onOpenNotification: $message"); + print("flutter onOpenNotification extras: ${message['extras']}"); + +// flutter onOpenNotification: {aps: {alert: {title: ddd, body: 大幅度发}, badge: 1, sound: default}, payload: other@1, extras: {payload: other@1}, _j_uid: 33833979419, _j_msgid: 29273440739312177, _j_business: 1} + Map jExtra = message['extras']; + print('onOpenNotification jExtra:$jExtra'); + if (jExtra.containsKey('cn.jpush.android.EXTRA')) { + ///android + Map map = json.decode(jExtra['cn.jpush.android.EXTRA']); + print('map: $map'); + String payload = getPayload(map); + print('onOpenNotification payload:$payload'); + goPage(payload); + return; + } else { + ///ios + print("flutter jExtra : $jExtra"); + String payload = getPayload(jExtra); + print('onOpenNotification payload:$payload'); + goPage(payload); + } + }, + // 接收自定义消息回调方法。 + onReceiveMessage: (Map message) async { + print("flutter自定义 onReceiveMessage: $message"); + }, + ); + jpush.setup( + appKey: "13dd603952a6632d1dd3ac54", + channel: "theChannel", + production: false, + debug: true, // 设置是否打印 debug 日志 + ); + jpush.getRegistrationID().then((rid) { + print('jpush getRegistrationID $rid '); + }); + } + + void setAlias() { + JPush jpush = new JPush(); + print('flutter jpush setAlias ${UserData().basicInfo.userId.toString()}'); + jpush.setAlias(UserData().basicInfo.userId.toString()).then((map) {}); + jpush.addTags( + ["yueliao", 'yueliao_' + UserData().language.toString()], + ).then((map) {}); + + if (Platform.isIOS) { + jpush.getLaunchAppNotification().then((map) { + print('getLaunchAppNotification $map'); + Map jExtra = map['extras']; + String payload = getPayload(jExtra); + print('onOpenNotification payload:$payload'); + goPage(payload); + FlutterAppBadger.removeBadge(); + }).catchError((error) { + print('getLaunchAppNotificationerror $error'); + }); + } + } + + void removeAlias() { + JPush jpush = new JPush(); + jpush.deleteAlias(); + jpush.stopPush(); + } + + void initState(BuildContext context) { + this.mContext = context; + if (hasInit) { + return; + } + hasInit = true; + didReceiveLocalNotificationSubject.stream + .listen((ReceivedNotification receivedNotification) async { + print('ios低版本推送点击:${receivedNotification.payload}'); + + await showDialog( + context: mContext, + builder: (BuildContext context) => CupertinoAlertDialog( + title: receivedNotification.title != null + ? Text(receivedNotification.title) + : null, + content: receivedNotification.body != null + ? Text(receivedNotification.body) + : null, + actions: [ + CupertinoDialogAction( + isDefaultAction: false, + child: Text(I18n.of(mContext).cancel), + onPressed: () async { + Navigator.of(mContext, rootNavigator: true).pop(); + }, + ), + CupertinoDialogAction( + isDefaultAction: true, + child: Text(I18n.of(mContext).determine), + onPressed: () async { + Navigator.of(mContext, rootNavigator: true).pop(); + goPage(receivedNotification.payload); + }, + ), + ], + ), + ); + }); + print('点击事件----selectNotificationSubject --'); + selectNotificationSubject.stream.listen((String payload) async { + print('这里---推送点击'); + goPage(payload); + }); + + setAlias(); + } + + static bool hasInit = false; + void initLocalPush() async { + // needed if you intend to initialize in the `main` function + WidgetsFlutterBinding.ensureInitialized(); + // NOTE: if you want to find out if the app was launched via notification then you could use the following call and then do something like + // change the default route of the app + // var notificationAppLaunchDetails = + // await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails(); + + var initializationSettingsAndroid = + AndroidInitializationSettings('ic_launcher_1'); + + ///android推送图标在drawable文件夹 + var initializationSettingsIOS = IOSInitializationSettings( + onDidReceiveLocalNotification: + (int id, String title, String body, String payload) async { + print('onDidReceiveLocalNotification $payload'); + didReceiveLocalNotificationSubject.add(ReceivedNotification( + id: id, title: title, body: body, payload: payload)); + }); + var initializationSettings = InitializationSettings( + initializationSettingsAndroid, initializationSettingsIOS); + print('点击事件初始化'); + bool isOK =await flutterLocalNotificationsPlugin.initialize(initializationSettings, + onSelectNotification: (String payload) async { + print('AAA这里---推送点击'); + selectNotificationSubject.add(payload); + }); + print('点击事件初始化----$isOK'); + } + + String getPayload(Map notifition) { + String payload = 'default'; + int type = int.parse(notifition['Type'].toString()); + print('onOpenNotification type:$type'); + switch (type) { + case 1: + payload = PAYLOAD_DATE + '@' + notifition['Id'].toString(); + break; + case 2: + payload = PAYLOAD_OTHER + '@' + InfoType.Apply.toString(); + + break; + case 3: + payload = PAYLOAD_OTHER + '@' + InfoType.Apply.toString(); + break; + case 4: + payload = PAYLOAD_OTHER + '@' + InfoType.Money.toString(); + break; + case 5: + payload = PAYLOAD_OTHER + '@' + InfoType.System.toString(); + break; + case 6: + payload = PAYLOAD_FRIENDS + '@' + InfoType.Apply.toString(); + break; + + case 7: + payload = PAYLOAD_OTHER + '@' + InfoType.System.toString(); + break; + + default: + payload = 'default'; + break; + } + return payload; + } + + void goPage(String payload) { + print('goPage payload: $payload'); + print('### 开始跳转'); + if (payload != null) { + if (payload == 'default') { + return; + } + + if (payload.startsWith(PAYLOAD_DATE)) { + Navigator.of(mContext).push( + MaterialPageRoute( + builder: (mContext) { + return ProgramDetailPage( + programId: int.parse(payload.split('@')[1]), + ); + }, + ), + ); + } else if (payload.startsWith(PAYLOAD_FRIENDS)) { + MessageMgr().emit('goto_new_friends'); + } else { + int type = int.parse(payload.split('@')[1]); + String title = ''; + switch (type) { + case InfoType.Apply: + title = I18n.of(mContext).application_notice; + break; + + case InfoType.Money: + title = I18n.of(mContext).wallet_reminder; + break; + + case InfoType.System: + title = I18n.of(mContext).appName; + break; + } + + Navigator.of(mContext).push( + new MaterialPageRoute( + builder: (context) { + return InfoListPage( + title: title, + type: type, + ); + }, + ), + ); + } + + print('notification payload: ' + payload); + } + } + + Future show(String title, String content,{int id}) async { + if (!isBackground || !UserData().privatyMsgPushSwitch) { + print('程序在前台,不发生推送通知 || 用户关闭推送'); + return; + } + showNotification(title, content,id: id); + } + + Future showOtherNotification( + Map notifition, String defaultTitle, String defaultContent) async { + int type = notifition['Type']; + + String payload = 'default'; + bool needPush = true; + switch (type) { + case 1: + needPush = UserData().newDateSwitch; + payload = PAYLOAD_DATE + '@' + notifition['Id'].toString(); + break; + case 2: + needPush = UserData().applyCheckSwitch; + payload = PAYLOAD_OTHER + '@' + InfoType.Apply.toString(); + + break; + case 3: + needPush = UserData().acceptCheckSwitch; + payload = PAYLOAD_OTHER + '@' + InfoType.Apply.toString(); + break; + case 4: + needPush = UserData().checkPhotoSwitch; + payload = PAYLOAD_OTHER + '@' + InfoType.Money.toString(); + break; + case 5: + needPush = UserData().codeSucessSwitch; + payload = PAYLOAD_OTHER + '@' + InfoType.System.toString(); + break; + case 6: + +// needPush = UserData().codeSucessSwitch; + payload = PAYLOAD_FRIENDS + '@' + InfoType.Apply.toString(); + break; + + case 7: + payload = PAYLOAD_OTHER + '@' + InfoType.System.toString(); + break; + default: + payload = 'default'; + break; + } + print('showOtherNotification payload $payload'); + + if(selectNotificationSubject==null){ + print('selectNotificationSubject == null'); + }else{ + print('selectNotificationSubject 不空'); + } + + if(flutterLocalNotificationsPlugin==null){ + print('flutterLocalNotificationsPlugin == null'); + }else{ + print('flutterLocalNotificationsPlugin 不空'); + } + + + + if (needPush) { + showNotification(defaultTitle, defaultContent, payload: payload); + } + } + + void showNotification(String title, String content, + {payload = 'default',int id}) async { + if(id == null){ + id = Random().nextInt(1000); + } + var androidPlatformChannelSpecifics = AndroidNotificationDetails( + '668123', 'com.cyhd.henhoandroid.push', 'private message push', + importance: Importance.Max, priority: Priority.High, ticker: title); + var iOSPlatformChannelSpecifics = IOSNotificationDetails(); + var platformChannelSpecifics = NotificationDetails( + androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics); + print('payload- $payload'); + await flutterLocalNotificationsPlugin.show( + id, title, content, platformChannelSpecifics, + payload: payload); + badgerCount++; + FlutterAppBadger.updateBadgeCount(badgerCount); + + ///等极光修复了iOS本地推送点击事件后改为下面的方法 +// var fireDate = DateTime.fromMillisecondsSinceEpoch( +// DateTime.now().millisecondsSinceEpoch + 3000); +// var localNotification = LocalNotification( +// id: 234, +// title: 'fadsfa', +// buildId: 1, +// content: 'fdas', +// fireTime: fireDate, +// subtitle: 'fasf', +// badge: 5, +// extra: {"fa": "0"}); +// JPush jpush = new JPush(); +// jpush.sendLocalNotification(localNotification); + + } + + Future cleanAllNotifications() async { + await flutterLocalNotificationsPlugin.cancelAll(); + FlutterAppBadger.removeBadge(); + JPush jpush = new JPush(); + if (Platform.isIOS) { + jpush.setBadge(0); + } + badgerCount = 0; + FlutterAppBadger.updateBadgeCount(badgerCount); + } + + + void startPush(){ + JPush jpush = new JPush(); + jpush.resumePush(); + } + + void pausePush(){ + JPush jpush = new JPush(); + jpush.stopPush(); + } + + + void dispose() { +// if(didReceiveLocalNotificationSubject !=null && selectNotificationSubject !=null){ +// didReceiveLocalNotificationSubject.close(); +// selectNotificationSubject.close(); +// } + } +} diff --git a/lib/utils/log.dart b/lib/utils/log.dart new file mode 100644 index 0000000..f9dc173 --- /dev/null +++ b/lib/utils/log.dart @@ -0,0 +1,10 @@ +import 'package:flutter/foundation.dart'; +import 'package:stack_trace/stack_trace.dart'; + +void d(Object object) { + var output = "${Trace.current().frames[1].location} | $object"; + + // the console prints the first 1000+ char and discard the rest so this work around. + final pattern = RegExp('.{1,1000}'); // 1000 is the size of each chunk + pattern.allMatches(output).forEach((match) => debugPrint(match.group(0))); +} \ No newline at end of file diff --git a/lib/utils/msgHandler.dart b/lib/utils/msgHandler.dart new file mode 100644 index 0000000..9358997 --- /dev/null +++ b/lib/utils/msgHandler.dart @@ -0,0 +1,1319 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:typed_data'; +import 'package:chat/chat/group_chat_view.dart'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/data/chat_data_mgr.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/data/group_data_mgr.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/home/IndexPage.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/NetUtil.dart'; +import 'package:chat/utils/blacklist_mgr.dart'; +import 'package:chat/utils/friend_list_mgr.dart'; +import 'package:chat/utils/group_member_model.dart'; +import 'package:chat/utils/local_notification_util.dart'; +import 'package:chat/utils/sound_util.dart'; +import 'package:chat/utils/sql_util.dart'; +import 'package:chat/utils/upload_util.dart'; +import 'package:flutter/material.dart'; +import 'package:oktoast/oktoast.dart'; + +import 'package:fixnum/fixnum.dart'; +import 'MessageMgr.dart'; + +const MaxMsgContentSize = 1024 * 1024 * 3; + +class MsgHandler { + //当前会话ID + static int curActiveSession; + static bool isTranslate = false; + + static bool isAudioConnect = false; + + static BuildContext context; + + static List sendCache = []; + + static Timer ringTimer; + + static int audioChatRequestFriendId = 0; + + static Function createGroupComplete; + + static updateActiveSesstion(int session, {bool isGroup = false}) { + curActiveSession = session; + getUnreadMsgDetail(isGroup); + ChatDataMgr().signRead(curActiveSession, isGroup: isGroup); + } + + static getActiveSesstion(List memberList) { + var seq = CreateSessionReq(); + + var member = seq.memberIds; + member.addAll(memberList); + + NetWork().sendMsg(ComId.Chat, 101, seq); + } + + //根据会话获取会话成员信息 + static getSessionInfo(int sessionId) { + var seq = QuerySessionReq(); + seq.sessionId = sessionId; + NetWork().sendMsg(ComId.Chat, 102, seq); + } + + //创建群 + static createGroup(List members, Function complete) { + var seq = CreateChatGroupReq.create(); + seq.members.addAll(members); + + createGroupComplete = complete; + + var curTime = DateTime.now(); + print('发送建群消息 $curTime'); + NetWork().sendMsg(ComId.Chat, 201, seq); + } + + //创建群结果 + static handleCreateGroup(List content) async { + var res = CreateChatGroupRes.fromBuffer(content); + + if (res.errorCode == 0) { + var curTime = DateTime.now(); + print('建群成功 $curTime'); + GroupInfoModel infoModel = GroupInfoModel.fromInfo(res.group); + GroupInfoMgr().addGroup(infoModel); + + if (createGroupComplete != null) { + createGroupComplete(infoModel); + createGroupComplete = null; + } + MessageMgr().emit('Update Group List'); + } else { + print('建群失败'); + } + } + + static createCoinBagMsg(Map args) { + MsgModel msg; + + Int64 time = Int64((DateTime.now()).millisecondsSinceEpoch); + + var friendId = args['friendId']; + + RedWallet wallet = RedWallet.create(); + wallet.amount = args['amount']; + wallet.title = args['title']; + wallet.orderId = args['redNo']; + wallet.tuId = friendId; + wallet.suId = UserData().basicInfo.userId; + wallet.state = RedWalletState.Uncollected; + var myId = UserData().basicInfo.userId; + msg = MsgModel(myId, friendId, ChatType.RedWalletChatType.value, + wallet.writeToBuffer(), time.toInt(), curActiveSession); + + return msg; + } + + static createSendMsg(ChatType chatType, content, + {int extra, + int friendId, + String localFile, + MsgModel refMsg, + String refShortTxt, + List altUsers, + ChatChannelType channelType = ChatChannelType.Session}) { + MsgModel msg; + + if (content is String) { + content = utf8.encode(content); + } + Int64 time = Int64((DateTime.now()).millisecondsSinceEpoch); + + var myId = UserData().basicInfo.userId; + if (channelType == ChatChannelType.Group) { + msg = MsgModel( + myId, 0, chatType.value, content, time.toInt(), curActiveSession, + channelType: channelType.value); + } else { + msg = MsgModel(myId, friendId, chatType.value, content, time.toInt(), + curActiveSession, + channelType: channelType.value); + } + + if (localFile != null) { + var fileId = curActiveSession.toString() + time.toString(); + msg.localFile = localFile; + msg.extraFile = fileId; + } + + if (extra != null) { + msg.extraInfo = extra; + } + + if (refMsg != null) { + QuoteMsg quoteMsg = QuoteMsg.create(); + quoteMsg.sendUserId = refMsg.from; + quoteMsg.sendTime = Int64(refMsg.time); + quoteMsg.targetId = refMsg.sessionId; + quoteMsg.content = refShortTxt; + quoteMsg.channelType = ChatChannelType.valueOf(refMsg.channelType); + + msg.refMsgContent = quoteMsg.writeToBuffer(); + } + + if (altUsers != null && altUsers.length > 0) { + msg.altUsers = altUsers; + } + + return msg; + } + + static insertMsgToDB(MsgModel msg) { + //缓存消息,发送成功之后清理 + if (!sendCache.contains(msg)) { + sendCache.add(msg); + ChatDataMgr().saveMsg(msg); + } + } + + //登录成功之后重新发送缓存的消息 + static flushCacheMsg() { + for (var i = 0; i < sendCache.length; i++) { + sendChatMsg(sendCache[i]); + } + } + + static sendChatMsg(MsgModel msg) { + var seq = ChatSendReq.create(); + seq.targetId = msg.sessionId; + seq.sendTime = Int64(msg.time); + seq.cType = ChatType.valueOf(msg.msgType); + seq.channelType = ChatChannelType.valueOf(msg.channelType); + + if (msg.extraFile != null) { + seq.enclosureUrl = msg.extraFile; + } + + if (msg.extraInfo != null) { + seq.contentSzie = msg.extraInfo; + } + + if (msg.refMsgContent != null && msg.refMsgContent.length > 0) { + seq.quoteMsg = msg.refMsgContent; + } + + if (msg.altUsers != null && msg.altUsers.length > 0) { + print('设置@信息 ${msg.altUsers.toString()}'); + seq.altUserIds.addAll(msg.altUsers); + } + seq.contentBuff = msg.msgContent; + + if (msg.msgContent.length > MaxMsgContentSize) { + showToast(I18n.of(context).server_error_tips); + print('消息包大小超过3M'); + } + + if (msg.localFile == null || msg.state >= MsgState.Uploaded) { + Future.delayed(Duration(seconds: 60), () { + if (msg.state != MsgState.SendingSuccess) { + msg.state = MsgState.SendingFailed; + ChatDataMgr().updateMsgState( + msg.sessionId, msg.time, msg.channelType, msg.state); + } + }); + + NetWork().sendMsg(ComId.Chat, 1, seq); + msg.state = MsgState.Sending; + } + } + + //获取会话未读消息 + static getUnreadMsgDetail(bool isGroup) { + print('获取未读消息 群$isGroup'); + var seq = RequestTargetUnreadReq.create(); + + seq.targetId = curActiveSession; + if (curActiveSession == 10000) { + seq.channelType = ChatChannelType.CSD; + } else { + seq.channelType = + isGroup ? ChatChannelType.Group : ChatChannelType.Session; + } + + NetWork().sendMsg(ComId.Chat, 5, seq); + } + + static handlerReceiveMsg(PushChat chat) async { + bool isGroup = false; + if (chat.channelType == ChatChannelType.Group) { + print('群聊消息'); + isGroup = true; + } + + MsgModel msgModel; + if (chat.sendUserId == 1) { + //更新消息 + print('服务器更新消息'); + MsgModel findMsg; + + var msgList; + if (isGroup) { + msgList = ChatDataMgr().getGroupRecord(); + } else { + msgList = ChatDataMgr().getRecord(); + } + + for (var i = 0; i < msgList.length; i++) { + var msg = msgList[i]; + if (msg.time == chat.sendTime.toInt()) { + findMsg = msg; + } + } + //更新翻译 + if (findMsg != null) { + findMsg.transTag = chat.translateState; + + if (chat.translateState == 4) { + print('人工翻译结果更新${chat.targetId},${chat.translateState}'); + findMsg.translateContent = chat.humanTranslate; + + findMsg.enTranslateContent = chat.googleTranslate ?? Uint8List(0); + + ChatDataMgr().updateLastMsgWithTranslateMsg(chat); + SqlUtil().updateUserTranslateContent(chat.targetId, + chat.sendTime.toInt(), chat.humanTranslate, chat.translateState); + } else if (chat.translateState == 3 || chat.translateState == 2) { + print('机器翻译结果更新'); + + ChatDataMgr().updateLastMsgWithTranslateMsg(chat); + + findMsg.translateContent = chat.tencentTranslate; + findMsg.enTranslateContent = chat.googleTranslate; + SqlUtil().updateMachineTranslateContent( + chat.targetId, + chat.sendTime.toInt(), + chat.tencentTranslate, + chat.googleTranslate, + chat.translateState); + } + + MessageMgr().emit('Update Translate Message', findMsg); + } + } else { + if (chat.sendUserId == 0) { + print('服务器通知消息 ${chat.sendTime.toInt()}'); + + if (isGroup) { + if (chat.cType == ChatType.GroupChatNoticeType) { + //检查是否存在群信息 + var info = await GroupInfoMgr().getGroupInfo(chat.targetId); + if (info == null) { + print('群不存在'); + return; + } + + var myId = UserData().basicInfo.userId; + var notice = GroupChatNotice.fromBuffer(chat.contentBuff); + + print('群改变消息 changeType ${notice.changeType.toString()}'); + + bool isShow = true; + switch (notice.changeType) { + case GroupChangeType.AddMember: + GroupInfoMgr().addMembers(chat.targetId, notice.operateduId); + break; + case GroupChangeType.RemoveMember: + var isMeIn = isContainMe(notice.operateduId); + if (!isMeIn) { + //别人,这个自己有群信息 + GroupInfoMgr() + .removeMembers(chat.targetId, notice.operateduId); + } else { + //自己 + GroupInfoMgr().removeSelf(chat.targetId); + print('已被移出该群,不能发消息了'); + } + + break; + case GroupChangeType.GroupNameChange: + print('更改群名 ${notice.changeStr}'); + GroupInfoMgr().updateGroupName(chat.targetId, notice.changeStr); + break; + case GroupChangeType.GroupNoticeChange: + print('更改群公告 ${notice.changeStr}'); + GroupInfoMgr() + .updateGroupDescription(chat.targetId, notice.changeStr); + break; + case GroupChangeType.GroupMemberAliasChange: + isShow = false; + print('修改别名 ${notice.operatuId.id} ${notice.changeStr}'); + GroupInfoMgr().updateMemberRefName( + chat.targetId, notice.operatuId.id, notice.changeStr); + //该消息不用显示和保存 + break; + + case GroupChangeType.MasterTrans: + print( + '转让群主 转让人${notice.operatuId.id},被转让人${notice.operateduId[0].id}'); + GroupInfoMgr().updateGroupMaster(chat.targetId, + notice.operatuId.id, notice.operateduId[0].id); + break; + case GroupChangeType.QRCodeAddMemberNotice: + if (notice.operatuId.id != myId) { + //别人在此处理,自己走回应消息 + GroupInfoMgr().addMembers(chat.targetId, [notice.operatuId]); + } else {} + break; + + case GroupChangeType.GroupIsOpenMemberCheckChange: + print('群主开启了群验证: ${notice.changeBool}'); + GroupInfoMgr() + .updateAskSwitch(chat.targetId, notice.changeBool); + + break; + case GroupChangeType.GroupMemberCheckAddMemberNotice: + print('群主确认进群: ${notice.operateduId.length}'); + GroupInfoMgr().addMembers(chat.targetId, notice.operateduId); + break; + case GroupChangeType.GroupMemberLeave: + print('有人离开群: ${notice.operatuId}'); + isShow = false; + GroupInfoMgr().removeMembers(chat.targetId, [notice.operatuId]); + break; + default: + } + + //不需要展示给用户看 + if (!isShow) { + print('该消息不用展示'); + return; + } + + msgModel = MsgModel(0, chat.sendUserId, chat.cType.value, + chat.contentBuff, chat.sendTime.toInt(), chat.targetId, + channelType: ChatChannelType.Group.value); + } + } else {//私聊通知消息 + if (chat.cType == ChatType.RedWalletChatType) { + //系统红包通知消息 + RedWallet wallet = RedWallet.fromBuffer(chat.contentBuff); + var myId = UserData().basicInfo.userId; + + var friendId; + if (myId == wallet.suId) { + friendId = wallet.tuId; + } else { + friendId = wallet.suId; + } + + int sessionId = chat.targetId; + msgModel = MsgModel(0, friendId, chat.cType.value, chat.contentBuff, + chat.sendTime.toInt(), sessionId, + channelType: ChatChannelType.Group.value); + + //更新红包信息 + ChatDataMgr() + .updateRedWalletMsg(sessionId, wallet.orderId, wallet.state); + } else { + print('未知私聊通知消息'); + } + } + } else { //聊天消息 + int sessionId = chat.targetId; + print('sessionId $sessionId'); + if (isGroup) { + GroupInfoMgr() + .getGroupInfo(sessionId) + .then((GroupInfoModel groupInfo) { + bool showGroup = false; + if (groupInfo != null) { + showGroup = groupInfo.messageFree == 0; + } + if (showGroup) { + LocalNotificationUtil.instance.show( + I18n.of(context).notice, I18n.of(context).new_chat_msg, + id: sessionId > 1000 + ? int.parse(sessionId.toString().substring(0, 3)) + : sessionId); + } + }); + } else { + LocalNotificationUtil.instance + .show(I18n.of(context).notice, I18n.of(context).new_chat_msg); + } + + msgModel = MsgModel(chat.sendUserId, chat.sendUserId, chat.cType.value, + chat.contentBuff, chat.sendTime.toInt(), chat.targetId, + channelType: chat.channelType.value); + + if (chat.hasTencentTranslate()) { + msgModel.translateContent = chat.tencentTranslate; + } + + if (chat.hasGoogleTranslate()) { + msgModel.enTranslateContent = chat.googleTranslate; + } + + if (chat.hasContentSzie()) { + msgModel.extraInfo = chat.contentSzie; + } + + if (chat.targetId != curActiveSession) { + msgModel.readState = 1; //未读标记 + } + + //视频附件 + if (chat.hasEnclosureUrl()) { + msgModel.extraFile = chat.enclosureUrl; + } + + if (chat.hasQuoteMsg()) { + print('存在引用消息'); + msgModel.refMsgContent = chat.quoteMsg; + } + + if (chat.altUserIds.length > 0) { + print('存在@消息'); + msgModel.altUsers = chat.altUserIds; + + var myId = UserData().basicInfo.userId; + for (var i = 0; i < msgModel.altUsers.length; i++) { + if (msgModel.altUsers[i] == myId) { + print('有人@了你'); + //to do + } + } + + print(chat.altUserIds.toString()); + } + + if (chat.cType == ChatType.TextChatType || + chat.cType == ChatType.ShortVoiceChatType || + chat.cType == ChatType.RedWalletChatType) { + if (chat.hasTranslateState()) { + //是否有人工翻译 + msgModel.transTag = chat.translateState; + print('翻译标记:${chat.translateState}'); + } + } else { + msgModel.transTag = 0; + } + } + + if (msgModel == null) { + print('消息为空,无法保存'); + return; + } + print('收到消息,准备保存 会话Id:${msgModel.sessionId}'); + ChatDataMgr().saveMsg(msgModel); + if (msgModel.msgType == ChatType.ShortVoiceChatType.value) { + //如果是语音消息,自动下载 + msgModel.state = MsgState.Downloading; + var filePath = await UploadUtil().downloadFile(msgModel); + + if (filePath != null) { + msgModel.localFile = filePath; + SqlUtil().updateLocalFile(msgModel.extraFile, filePath, + isGroup: msgModel.channelType == ChatChannelType.Group.value); + + msgModel.state = MsgState.DownloadSuccess; + } else { + print('下载文件失败'); + msgModel.state = MsgState.DownloadFailed; + } + } + if (msgModel.sessionId == curActiveSession) { + MessageMgr().emit('New Chat Message', msgModel.sessionId); + } + } + } + + static isContainMe(List members) { + var myId = UserData().basicInfo.userId; + for (var i = 0; i < members.length; i++) { + if (myId == members[i].id) { + print('我在其中'); + return true; + } + } + + return false; + } + + static getGroupNoticeMsg( + GroupChatNotice notice, GroupInfoModel groupInfoModel) { + var showStr = ''; + + if (groupInfoModel == null) { + print('群不存在'); + return ''; + } + + var myId = UserData().basicInfo.userId; + var optId = notice.operatuId; + List optedIds = notice.operateduId; + + switch (notice.changeType) { + case GroupChangeType.AddMember: + + if (optId.id == myId) { + var otherNames = ''; + for (var i = 0; i < optedIds.length; i++) { + //获取用户名 + var nickName = _getUserName(optedIds[i].id, groupInfoModel.members); + if (otherNames.length == 0) { + otherNames = nickName; + } else { + otherNames = '$otherNames、$nickName'; + } + } + showStr = I18n.of(context).you_invite.replaceFirst('/s1', otherNames); + } else { + bool isMySelf = false; + var otherNames = ''; + for (var i = 0; i < optedIds.length; i++) { + //获取用户名 + isMySelf = myId == optedIds[i].id; + var nickName = _getUserName(optedIds[i].id, groupInfoModel.members); + if (otherNames.length == 0) { + otherNames = nickName; + } else { + otherNames = '$otherNames、$nickName'; + } + } + var optName = _getUserName(optId.id, groupInfoModel.members); + if (isMySelf) { + showStr = I18n.of(context).invite_you.replaceFirst('/s1', optName); + } else { + showStr = I18n.of(context) + .invite_someone + .replaceFirst('/s1', optName) + .replaceFirst('/s2', otherNames); + } + } + break; + case GroupChangeType.RemoveMember: + var optName = _getUserName(optId.id, groupInfoModel.members); + if (optId.id == myId) { + optName = I18n.of(context).you; + } + + var otherNames = ''; + + for (var i = 0; i < optedIds.length; i++) { + if (optedIds[i].id == myId) { + otherNames = I18n.of(context).you; + } else { + //获取用户名 + var nickName = _getUserName(optedIds[i].id, groupInfoModel.members); + if (otherNames.length == 0) { + otherNames = nickName; + } else { + otherNames = '$otherNames,$nickName'; + } + } + } + showStr = I18n.of(context) + .delete_group + .replaceFirst('/s1', optName) + .replaceFirst('/s2', otherNames); + break; + case GroupChangeType.MasterTrans: + var optedName = _getUserName(optedIds.first.id, groupInfoModel.members); + + if (optedIds.first.id == myId) { + showStr = I18n.of(context).you_group_owner; + } else { + showStr = I18n.of(context) + .someone_group_owner + .replaceFirst('/s1', optedName); + } + break; + + case GroupChangeType.GroupNameChange: + var groupName = notice.changeStr; + + var optName = _getUserName(notice.operatuId.id, groupInfoModel.members); + if (notice.operatuId.id == myId) { + showStr = '你 更改群名为 $groupName'; + } else { + showStr = '$optName 更改群名为 $groupName'; + } + // I18n.of(context).change_group_owner1.replaceFirst('/s1', groupName); + break; + case GroupChangeType.GroupNoticeChange: + print('optId.id ${optId.id}'); + showStr = I18n.of(context).update_group_announce; + break; + case GroupChangeType.QRCodeAddMemberNotice: + var optName = _getUserName(optId.id, groupInfoModel.members); + print('optId.id ${optId.id}'); + showStr = optId.id == UserData().basicInfo.userId + ? I18n.of(context).you_qr + : I18n.of(context).others_qr.replaceFirst('/s1', optName); + break; + + case GroupChangeType.GroupMemberCheckNotice: + var optedName = _getUserName(optId.id, groupInfoModel.members); + print('groupInfoModel.hosterId:${groupInfoModel.hosterId}'); + if (myId == groupInfoModel.hosterId) { + showStr = I18n.of(context) + .invite_confirm + .replaceFirst('/s1', optedName) + .replaceFirst('/s2', optedIds.length.toString()); + } else { + //获取用户名 + var otherNames = ''; + for (var i = 0; i < optedIds.length; i++) { + //获取用户名 + var nickName = optedIds[i].niceName; + if (otherNames.length == 0) { + otherNames = nickName; + } else { + otherNames = '$otherNames、$nickName'; + } + } + showStr = I18n.of(context) + .want_invite_confirm + .replaceFirst('/s1', optedName) + .replaceFirst('/s2', otherNames); + } + + break; + + case GroupChangeType.GroupMemberCheckAddMemberNotice: +// var optedName = _getUserName(optId.id, groupInfoModel.members); + bool isMy = false; + var otherNames = ''; + for (var i = 0; i < optedIds.length; i++) { + if (optedIds[i].id == myId) { + isMy = true; + } + //获取用户名 + var nickName = optedIds[i].niceName; + if (otherNames.length == 0) { + otherNames = nickName; + } else { + otherNames = '$otherNames、$nickName'; + } + } + if (myId == groupInfoModel.hosterId) { + showStr = I18n.of(context) + .join_group_confirm + .replaceFirst('/s1', otherNames); + } else { + if (isMy) { + showStr = I18n.of(context) + .you_invite_gourp + .replaceFirst('/s1', optId.niceName); + } else { + showStr = I18n.of(context) + .someone_join_group + .replaceFirst('/s1', otherNames); + } + } + + break; + + case GroupChangeType.GroupIsOpenMemberCheckChange: + showStr = notice.changeBool + ? I18n.of(context).group_setting_tips1 + : I18n.of(context).group_setting_tips2; + + break; + + default: + } + + return showStr; + } + + static _getUserName(int uId, List members) { + for (var uItem in members) { + if (uItem.memberId == uId) { + print('用户$uId 的名字 是 ${uItem.refName}'); + return uItem.refName; + } + } + return ''; + } + + static void handlerUnreadMsg(msg) { + var msgContent = PushUserUnreadMsgNotice.fromBuffer(msg); + var noticeList = msgContent.notices; + + ChatDataMgr().updateRecordWithUnreadMsg(noticeList); + } + + static handlerServerMsg(int comId, int msgId, List content) { + switch (comId) { + case ComId.Chat: + if (msgId == 2) { + //发送消息成功回应 + var msgContent = ChatSendRes.fromBuffer(content); + if (msgContent.errorCode == 0 || + msgContent.errorCode == 17 || + msgContent.errorCode == 16) { + print('发送聊天消息成功'); + + ChatDataMgr().updateMsgState( + msgContent.targetId, + msgContent.sendTime.toInt(), + msgContent.channelType.value, + MsgState.SendingSuccess); + + //去除缓存 + for (var i = 0; i < sendCache.length; i++) { + MsgModel msg = sendCache[i]; + if (msgContent.targetId == msg.sessionId && + msgContent.sendTime.toInt() == msg.time) { + msg.state = MsgState.SendingSuccess; + sendCache.remove(msg); + break; + } + } + } else { + if (msgContent.errorCode == 3001) { + print('用户没有登录,重新登录'); + NetWork().reLogin(); + } else { + ChatDataMgr().updateMsgState( + msgContent.targetId, + msgContent.sendTime.toInt(), + msgContent.channelType.value, + MsgState.SendingFailed); + + for (var i = 0; i < sendCache.length; i++) { + MsgModel msg = sendCache[i]; + if (msgContent.targetId == msg.sessionId && + msgContent.sendTime.toInt() == msg.time) { + msg.state = MsgState.SendingFailed; + break; + } + } + } + } + } else if (msgId == 3) { + var msgContent = PushChat.fromBuffer(content); + print('收到聊天消息'); + ackServerMsg(msgContent.sendTime); + handlerReceiveMsg(msgContent); + } else if (msgId == 4) { + print('处理未读消息汇总'); + handlerUnreadMsg(content); + } else if (msgId == 9) { + print('切换人工翻译状态通知'); + receiveTranslateState(content); + } else if (msgId == 11) { + // + var msgContent = RequestRealtimeCallRes.fromBuffer(content); + if (msgContent.errorCode == 0) { + print('发送连麦消息成功'); + // showToast('发送连麦消息成功'); + } else { + print('发送连麦消息失败'); + MessageMgr().emit('AudioChat Failed'); + } + } else if (msgId == 12) { + var msgContent = PushRealtimeCall.fromBuffer(content); + + var friendId = msgContent.sUserId; + print('收到连麦消息 $friendId'); + + //只能一次接收一个人的连麦 + if (!isAudioConnect) { + LocalNotificationUtil.instance + .show(I18n.of(context).notice, I18n.of(context).new_video_msg); + playAudioRing(); + MessageMgr().emit('Receive AudioChat Request', friendId); + } + } else if (msgId == 14) { + var msgContent = PushRealtimeCallRespond.fromBuffer(content); + + var friendId = msgContent.tUserId; + print('收到连麦消息 $friendId'); + bool isAnswer = msgContent.isAnswer; + stopAudioRing(); + + if (!isAnswer) { + audioChatRequestFriendId = 0; + } + + MessageMgr().emit( + 'AudioChat State', {'fdId': friendId, 'isAnswer': isAnswer}); + } else if (msgId == 18) { + var res = PushGiftGiving.fromBuffer(content); + print('收到礼物:${res.sendUserId} , ${res.giftId} ,${res.giftAmount}'); + MessageMgr().emit("Receive Gift", res); + } else if (msgId == 103) { + print('收到会话成员信息'); + } else if (msgId == 202) { + handleCreateGroup(content); + } else if (msgId == 204) { + handlerQuitGroup(content); + } else if (msgId == 206) { + handelerQueryGroupInfoRes(content); + } else if (msgId == 208) { + handlerAddGroupMemberRes(content); + } else if (msgId == 210) { + handlerRemoveGroupMemberRes(content); + } else if (msgId == 212) { + handlerUpdateGroupNoticeRes(content); + } else if (msgId == 214) { + handlerUpdateGroupNameRes(content); + } else if (msgId == 216) { + handlerUpdateMemberRefName(content); + } else if (msgId == 218) { + handlerGetGroupListRes(content); + } else if (msgId == 220) { + handlerSetGroupSwitch(content); + } else if (msgId == 222) { + handlerJoinGroupRes(content); + } else if (msgId == 224) { + handlerUpdateGroupHoster(content); + } else if (msgId == 226) { + handlerAgreeMember(content); + } else if (msgId == 228) { + handlerUpdateMemberMsgFree(content); + } + break; + case ComId.PushMsg: + String msg = PushNetRelay.fromBuffer(content).msg; + print('接受的推送消息:msg $msg'); + Map map = json.decode(msg); + String type = map['type']; + + switch (type) { + case 'notice': + + ///由于极光本地推送点击事件无反应,暂时不走这,由远端推 + String messageJson = map['message']; + Map messageMap = json.decode(messageJson); + + Map ext = json.decode(messageMap['extparameters']); + print('ext $ext}'); + LocalNotificationUtil.instance.showOtherNotification( + ext, messageMap['title'], messageMap['content']); + break; + case 'friends': + FriendListMgr().getFriendListFromServer(); + MessageMgr().emit('Add friend'); + break; + case 'deletedata': + print('收到清空用户聊天记录通知'); + GroupInfoMgr().deleteAllGroup(); + ChatDataMgr().deleteAllRecord(); + FriendListMgr().deleteAllFriend(); + + Navigator.of(context).pushAndRemoveUntil(new MaterialPageRoute( + builder: (context) { + return IndexPage(); + }, + ), (route) => route == null); + NetWork().singOut(); + UserData().reset(); + break; + case 'blacklist': + String messageJson = map['message']; + Map messageMap = json.decode(messageJson); + if (messageMap['Status'] == 0) { + BlacklistMgr.addBlackListMe(messageMap['UserId']); + } else { + BlacklistMgr.removeBalckListMe(messageMap['UserId']); + } + + break; + } + + break; + default: + } + } + + //设置群验证开关 + static setGroupSwitch(int groupId, bool isCheck) { + print('设置群验证开关 $isCheck'); + var seq = SettingGroupReq.create(); + seq.groupId = groupId; + seq.isOpenMemberCheck = isCheck; + + NetWork().sendMsg(ComId.Chat, 219, seq); + } + + //设置群验证开关结果 + static handlerSetGroupSwitch(List msgContent) { + print('设置群验证开关结果'); + var res = SettingGroupRes.fromBuffer(msgContent); + + if (res.errorCode == 0) { + print('设置群验证开关结果成功'); + } else { + print('设置群验证开关结果失败${res.errorCode}'); + } + } + + //退出群 + static quitGroup(int groupId) { + print('退出群'); + var seq = QuitChatGroupReq.create(); + seq.groupId = groupId; + + NetWork().sendMsg(ComId.Chat, 203, seq); + } + + static handlerQuitGroup(List msgContent) { + print('退出群结果'); + var res = QuitChatGroupRes.fromBuffer(msgContent); + + if (res.errorCode == 0) { + print('退出群结果成功 ${res.groupId}'); + } else { + print('退出群结果失败${res.errorCode}'); + } + } + + //添加群成员 + static addGroupMember(int groupId, List uIdList) { + print('##发送207 添加群成员------'); + var seq = AddGroupMemberReq.create(); + seq.groupId = groupId; + seq.userIds.addAll(uIdList); + + NetWork().sendMsg(ComId.Chat, 207, seq); + } + + //添加群成员结果 + static handlerAddGroupMemberRes(List msgContent) { + var res = AddGroupMemberRes.fromBuffer(msgContent); + print('##发送返回 添加群成员 res.errorCode:${res.errorCode}'); + if (res.errorCode == 0) { + MessageMgr().emit('Update Group Info'); + print('添加群成员成功'); + } else { + switch (res.errorCode) { + case 3007: + showToast(I18n.of(context).members_max); + break; + default: + } + print('添加群成员失败'); + } + } + + //扫码加入群 + static joinGroup(int groupId) { + print('添加群成员'); + var seq = GroupQRcodeAddMemberReq.create(); + seq.groupId = groupId; + + NetWork().sendMsg(ComId.Chat, 221, seq); + } + + //扫码加入群结果 + static handlerJoinGroupRes(List msgContent) async { + print('扫码加入群结果'); + var res = GroupQRcodeAddMemberRes.fromBuffer(msgContent); + if (res.errorCode == 0) { + print('扫码加入群结果成功'); + var groupInfoModel = GroupInfoModel.fromInfo(res.group); + GroupInfoMgr().addGroup(groupInfoModel); + + Navigator.pushReplacement(context, + MaterialPageRoute(builder: (BuildContext context) { + return GroupChatPage( + key: Key('GroupChat'), groupInfoModel: groupInfoModel); + })); + } else { + switch (res.errorCode) { + case 3007: + showToast(I18n.of(context).members_max); + break; + default: + } + print('扫码加入群结果失败${res.errorCode}'); + } + } + + //移出群成员 + static removeGroupMember(int groupId, List uIdList) { + print('添加群成员'); + var seq = RemoveGroupMemberReq.create(); + seq.groupId = groupId; + seq.userIds.addAll(uIdList); + + NetWork().sendMsg(ComId.Chat, 209, seq); + } + + //移出群成员结果 + static handlerRemoveGroupMemberRes(List msgContent) { + print('移出群成员结果'); + var res = RemoveGroupMemberRes.fromBuffer(msgContent); + if (res.errorCode == 0) { + MessageMgr().emit('Update Group Info'); + print('移出群成员结果成功'); + } else { + print('移出群成员结果失败${res.errorCode}'); + } + } + + //修改群公告 + static updateGroupNotice(int groupId, String notice) { + print('修改群公告'); + var seq = ModifyGroupNoticeReq.create(); + seq.groupId = groupId; + seq.notice = notice; + + NetWork().sendMsg(ComId.Chat, 211, seq); + } + + //修改群公告结果 + static handlerUpdateGroupNoticeRes(List msgContent) { + print('修改群公告结果'); + var res = ModifyGroupNoticeRes.fromBuffer(msgContent); + if (res.errorCode == 0) { + print('修改群公告结果成功'); + } else { + print('修改群公告结果失败${res.errorCode}'); + } + } + + //修改群名称请求 + static updateGroupName(int groupId, String name) { + print('修改群名称请求'); + var seq = ModifyGroupNameReq.create(); + seq.groupId = groupId; + seq.name = name; + + NetWork().sendMsg(ComId.Chat, 213, seq); + } + + //修改群名称请求结果 + static handlerUpdateGroupNameRes(List msgContent) { + print('修改群名称请求结果'); + var res = ModifyGroupNameRes.fromBuffer(msgContent); + if (res.errorCode == 0) { + print('修改群名称请求成功'); + } else { + showToast(I18n.of(context).fail); + print('修改群名称请求失败${res.errorCode}'); + } + } + + //修改群个人别名请求 + static updateMemberRefName(int groupId, String refName) { + print('修改群个人别名请求$groupId'); + var seq = GroupMemberModifyAliasReq.create(); + seq.groupId = groupId; + seq.name = refName; + + NetWork().sendMsg(ComId.Chat, 215, seq); + } + + //修改群个人别名请求结果 + static handlerUpdateMemberRefName(List msgContent) { + print('修改群个人别名请求结果'); + var res = GroupMemberModifyAliasRes.fromBuffer(msgContent); + if (res.errorCode == 0) { + print('修改群个人别名请求结果成功'); + } else { + print('修改群个人别名请求结果失败${res.errorCode}'); + } + } + + //群主转让其他人 + static updateGroupHoster(int groupId, int uId) { + print('群主转让其他人'); + var seq = GroupMasterTransReq.create(); + seq.groupId = groupId; + seq.userId = uId; + + NetWork().sendMsg(ComId.Chat, 223, seq); + } + + //群主转让其他人结果 + static handlerUpdateGroupHoster(List msgContent) { + print('群主转让其他人结果'); + var res = GroupMasterTransRes.fromBuffer(msgContent); + if (res.errorCode == 0) { + MessageMgr().emit('Update Group Info'); + print('群主转让其他人结果成功'); + } else { + print('群主转让其他人结果失败${res.errorCode}'); + } + } + + //群主批准其他人加入群 + static agreeMember(int groupId, List uId) { + print('群主批准其他人加入群 groupId:$groupId uId: $uId}'); + var seq = GroupMasterCheckAddMemberReq.create(); + seq.groupId = groupId; + seq.userIds.addAll(uId); + + NetWork().sendMsg(ComId.Chat, 225, seq); + } + + //群主批准其他人加入群结果 + static handlerAgreeMember(List msgContent) { + print('群主批准其他人加入群结果'); + var res = GroupMasterCheckAddMemberRes.fromBuffer(msgContent); + if (res.errorCode == 0) { + print('群主批准其他人加入群结果成功'); + } else { + switch (res.errorCode) { + case 3007: + showToast('群成员已满'); + break; + default: + } + } + } + + //消息免打扰请求 + static updateMemberMsgFreeReq(int groupId, bool isAvoid) { + print('消息免打扰请求'); + var seq = SetGroupMasterMessageFreeReq.create(); + seq.groupId = groupId; + seq.messageFree = isAvoid; + + NetWork().sendMsg(ComId.Chat, 227, seq); + } + + //消息免打扰请求结果 + static handlerUpdateMemberMsgFree(List msgContent) { + print('消息免打扰请求结果'); + var res = SetGroupMasterMessageFreeRes.fromBuffer(msgContent); + if (res.errorCode == 0) { + GroupInfoMgr().updateMemberMsgFree(res.groupId, res.messageFree); + print('消息免打扰请求结果成功'); + } else { + print('消息免打扰请求结果失败${res.errorCode}'); + } + } + + //请求群列表求结果 + static handlerGetGroupListRes(List msgContent) async { + var res = QueryUserRelationGroupRes.fromBuffer(msgContent); + + if (res.relationGroup == null) { + print('服务器也没有群存在'); + return; + } + for (var i = 0; i < res.relationGroup.length; i++) { + var group = GroupInfoModel.fromInfo(res.relationGroup[i]); + print('群id ${group.sessionId}'); + GroupInfoMgr().addGroup(group); + } + + MessageMgr().emit('Update Group List'); + } + + //查询聊天群信息 + static queryGroupInfo(int groupId) { + print('查询聊天群信息'); + var seq = QueryChatGroupReq.create(); + seq.groupId = groupId; + + NetWork().sendMsg(ComId.Chat, 205, seq); + } + + //查询聊天群信息结果 + static handelerQueryGroupInfoRes(List msgContent) async { + print('处理查询聊天群信息结果'); + var res = QueryChatGroupRes.fromBuffer(msgContent); + + if (res.errorCode == 0) { + print('获取群信息成功'); + var groupInfo = GroupInfoModel.fromInfo(res.group); + print('开始创建群头像'); + + GroupInfoMgr().addGroup(groupInfo); + } else { + print('获取群信息失败'); + switch (res.errorCode) { + case 3006: + showToast(I18n.of(context).group_max); + break; + + default: + showToast(I18n.of(context).fail); + } + } + } + + static playAudioRing() { + ringTimer = Timer.periodic(Duration(milliseconds: 2200), (timer) { + SoundUtils().play( + 'http://testcyhd.chengyouhd.com/Upload/Audio/even_wheat_sound.mp3', + isLocal: false); + }); + } + + static stopAudioRing() { + ringTimer?.cancel(); + } + + static ackServerMsg(Int64 msgId) { + var seq = AnswerPushChat.create(); + seq.msgId = msgId; + + NetWork().sendMsg(ComId.Chat, 100, seq); + } + + static swtichTranslateState(TranslateState transState) { + print('请求切换人工翻译状态'); + var seq = RequestSetHTranslReq.create(); + seq.sessionId = curActiveSession; + seq.hTransl = transState; + + NetWork().sendMsg(ComId.Chat, 7, seq); + } + + static void receiveTranslateState(msg) { + var res = PushHTranslState.fromBuffer(msg); + + if (res.sessionId == curActiveSession) { + MessageMgr().emit("Update Translate State", res); + } + } + + static void sendAudioChatReq(int friendId) { + var seq = RequestRealtimeCallReq.create(); + seq.tUserId = friendId; + seq.cType = ChatType.RealtimeCallVoiceType; + + NetWork().sendMsg(ComId.Chat, 10, seq); + } + + static void sendReplyAudioChatReq(int friendId, bool isReply) { + var seq = RespondRealtimeCallReq.create(); + seq.sUserId = friendId; + seq.isAnswer = isReply; + + NetWork().sendMsg(ComId.Chat, 13, seq); + } + + //打赏礼物 + static sendGiftTo(int friendId, int giftId, int giftAmount, int total) { + var seq = RequestGiftGivingReq.create(); + seq.targetUserId = friendId; + seq.giftId = giftId; + seq.giftAmount = giftAmount; + seq.money = total; + + NetWork().sendMsg(ComId.Chat, 17, seq); + } + + static clear() { + curActiveSession = 0; + isTranslate = false; + + isAudioConnect = false; + + sendCache.clear(); + } +} diff --git a/lib/utils/my_bottom_navigation_bar.dart b/lib/utils/my_bottom_navigation_bar.dart new file mode 100644 index 0000000..86bb8d9 --- /dev/null +++ b/lib/utils/my_bottom_navigation_bar.dart @@ -0,0 +1,914 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:collection' show Queue; +import 'dart:math' as math; + +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +/// Defines the layout and behavior of a [BottomNavigationBar]. +/// +/// See also: +/// +/// * [BottomNavigationBar] +/// * [BottomNavigationBarItem] +/// * +enum BottomNavigationBarType { + /// The [BottomNavigationBar]'s [BottomNavigationBarItem]s have fixed width. + fixed, + + /// The location and size of the [BottomNavigationBar] [BottomNavigationBarItem]s + /// animate and labels fade in when they are tapped. + shifting, +} + +/// A material widget that's displayed at the bottom of an app for selecting +/// among a small number of views, typically between three and five. +/// +/// The bottom navigation bar consists of multiple items in the form of +/// text labels, icons, or both, laid out on top of a piece of material. It +/// provides quick navigation between the top-level views of an app. For larger +/// screens, side navigation may be a better fit. +/// +/// A bottom navigation bar is usually used in conjunction with a [Scaffold], +/// where it is provided as the [Scaffold.bottomNavigationBar] argument. +/// +/// The bottom navigation bar's [type] changes how its [items] are displayed. +/// If not specified, then it's automatically set to +/// [BottomNavigationBarType.fixed] when there are less than four items, and +/// [BottomNavigationBarType.shifting] otherwise. +/// +/// * [BottomNavigationBarType.fixed], the default when there are less than +/// four [items]. The selected item is rendered with the +/// [selectedItemColor] if it's non-null, otherwise the theme's +/// [ThemeData.primaryColor] is used. If [backgroundColor] is null, The +/// navigation bar's background color defaults to the [Material] background +/// color, [ThemeData.canvasColor] (essentially opaque white). +/// * [BottomNavigationBarType.shifting], the default when there are four +/// or more [items]. If [selectedItemColor] is null, all items are rendered +/// in white. The navigation bar's background color is the same as the +/// [BottomNavigationBarItem.backgroundColor] of the selected item. In this +/// case it's assumed that each item will have a different background color +/// and that background color will contrast well with white. +/// +/// {@tool snippet --template=stateful_widget_material} +/// This example shows a [BottomNavigationBar] as it is used within a [Scaffold] +/// widget. The [BottomNavigationBar] has three [BottomNavigationBarItem] +/// widgets and the [currentIndex] is set to index 0. The selected item is +/// amber. The `_onItemTapped` function changes the selected item's index +/// and displays a corresponding message in the center of the [Scaffold]. +/// +/// ![A scaffold with a bottom navigation bar containing three bottom navigation +/// bar items. The first one is selected.](https://flutter.github.io/assets-for-api-docs/assets/material/bottom_navigation_bar.png) +/// +/// ```dart +/// int _selectedIndex = 0; +/// static const TextStyle optionStyle = TextStyle(fontSize: 30, fontWeight: FontWeight.bold); +/// static const List _widgetOptions = [ +/// Text( +/// 'Index 0: Home', +/// style: optionStyle, +/// ), +/// Text( +/// 'Index 1: Business', +/// style: optionStyle, +/// ), +/// Text( +/// 'Index 2: School', +/// style: optionStyle, +/// ), +/// ]; +/// +/// void _onItemTapped(int index) { +/// setState(() { +/// _selectedIndex = index; +/// }); +/// } +/// +/// @override +/// Widget build(BuildContext context) { +/// return Scaffold( +/// appBar: AppBar( +/// title: const Text('BottomNavigationBar Sample'), +/// ), +/// body: Center( +/// child: _widgetOptions.elementAt(_selectedIndex), +/// ), +/// bottomNavigationBar: BottomNavigationBar( +/// items: const [ +/// BottomNavigationBarItem( +/// icon: Icon(Icons.home), +/// title: Text('Home'), +/// ), +/// BottomNavigationBarItem( +/// icon: Icon(Icons.business), +/// title: Text('Business'), +/// ), +/// BottomNavigationBarItem( +/// icon: Icon(Icons.school), +/// title: Text('School'), +/// ), +/// ], +/// currentIndex: _selectedIndex, +/// selectedItemColor: Colors.amber[800], +/// onTap: _onItemTapped, +/// ), +/// ); +/// } +/// ``` +/// {@end-tool} +/// +/// See also: +/// +/// * [BottomNavigationBarItem] +/// * [Scaffold] +/// * +class BottomNavigationBar extends StatefulWidget { + /// Creates a bottom navigation bar which is typically used as a + /// [Scaffold]'s [Scaffold.bottomNavigationBar] argument. + /// + /// The length of [items] must be at least two and each item's icon and title + /// must not be null. + /// + /// If [type] is null then [BottomNavigationBarType.fixed] is used when there + /// are two or three [items], [BottomNavigationBarType.shifting] otherwise. + /// + /// The [iconSize], [selectedFontSize], [unselectedFontSize], and [elevation] + /// arguments must be non-null and non-negative. + /// + /// If [selectedLabelStyle.color] and [unselectedLabelStyle.color] values + /// are non-null, they will be used instead of [selectedItemColor] and + /// [unselectedItemColor]. + /// + /// If custom [IconThemData]s are used, you must provide both + /// [selectedIconTheme] and [unselectedIconTheme], and both + /// [IconThemeData.color] and [IconThemeData.size] must be set. + /// + /// If both [selectedLabelStyle.fontSize] and [selectedFontSize] are set, + /// [selectedLabelStyle.fontSize] will be used. + /// + /// Only one of [selectedItemColor] and [fixedColor] can be specified. The + /// former is preferred, [fixedColor] only exists for the sake of + /// backwards compatibility. + /// + /// The [showSelectedLabels] argument must not be non-null. + /// + /// The [showUnselectedLabels] argument defaults to `true` if [type] is + /// [BottomNavigationBarType.fixed] and `false` if [type] is + /// [BottomNavigationBarType.shifting]. + BottomNavigationBar({ + Key key, + @required this.items, + this.onTap, + this.currentIndex = 0, + this.elevation = 8.0, + BottomNavigationBarType type, + Color fixedColor, + this.backgroundColor, + this.iconSize = 24.0, + Color selectedItemColor, + this.unselectedItemColor, + this.selectedIconTheme = const IconThemeData(), + this.unselectedIconTheme = const IconThemeData(), + this.selectedFontSize = 14.0, + this.unselectedFontSize = 12.0, + this.selectedLabelStyle, + this.unselectedLabelStyle, + this.showSelectedLabels = true, + bool showUnselectedLabels, + }) : assert(items != null), + assert(items.length >= 2), + assert( + items.every((BottomNavigationBarItem item) => item.title != null) == + true, + 'Every item must have a non-null title', + ), + assert(0 <= currentIndex && currentIndex < items.length), + assert(elevation != null && elevation >= 0.0), + assert(iconSize != null && iconSize >= 0.0), + assert(selectedItemColor == null || fixedColor == null, + 'Either selectedItemColor or fixedColor can be specified, but not both'), + assert(selectedFontSize != null && selectedFontSize >= 0.0), + assert(unselectedFontSize != null && unselectedFontSize >= 0.0), + assert(showSelectedLabels != null), + type = _type(type, items), + selectedItemColor = selectedItemColor ?? fixedColor, + showUnselectedLabels = + showUnselectedLabels ?? _defaultShowUnselected(_type(type, items)), + super(key: key); + + /// Defines the appearance of the button items that are arrayed within the + /// bottom navigation bar. + final List items; + + /// Called when one of the [items] is tapped. + /// + /// The stateful widget that creates the bottom navigation bar needs to keep + /// track of the index of the selected [BottomNavigationBarItem] and call + /// `setState` to rebuild the bottom navigation bar with the new [currentIndex]. + final ValueChanged onTap; + + /// The index into [items] for the current active [BottomNavigationBarItem]. + final int currentIndex; + + /// The z-coordinate of this [BottomNavigationBar]. + /// + /// If null, defaults to `8.0`. + /// + /// {@macro flutter.material.material.elevation} + final double elevation; + + /// Defines the layout and behavior of a [BottomNavigationBar]. + /// + /// See documentation for [BottomNavigationBarType] for information on the + /// meaning of different types. + final BottomNavigationBarType type; + + /// The value of [selectedItemColor]. + /// + /// This getter only exists for backwards compatibility, the + /// [selectedItemColor] property is preferred. + Color get fixedColor => selectedItemColor; + + /// The color of the [BottomNavigationBar] itself. + /// + /// If [type] is [BottomNavigationBarType.shifting] and the + /// [items]s, have [BottomNavigationBarItem.backgroundColor] set, the [item]'s + /// backgroundColor will splash and overwrite this color. + final Color backgroundColor; + + /// The size of all of the [BottomNavigationBarItem] icons. + /// + /// See [BottomNavigationBarItem.icon] for more information. + final double iconSize; + + /// The color of the selected [BottomNavigationBarItem.icon] and + /// [BottomNavigationBarItem.label]. + /// + /// If null then the [ThemeData.primaryColor] is used. + final Color selectedItemColor; + + /// The color of the unselected [BottomNavigationBarItem.icon] and + /// [BottomNavigationBarItem.label]s. + /// + /// If null then the [TextTheme.caption]'s color is used. + final Color unselectedItemColor; + + /// The size, opacity, and color of the icon in the currently selected + /// [BottomNavigationBarItem.icon]. + /// + /// If this is not provided, the size will default to [iconSize], the color + /// will default to [selectedItemColor]. + /// + /// It this field is provided, it must contain non-null [IconThemeData.size] + /// and [IconThemeData.color] properties. Also, if this field is supplied, + /// [unselectedIconTheme] must be provided. + final IconThemeData selectedIconTheme; + + /// The size, opacity, and color of the icon in the currently unselected + /// [BottomNavigationBarItem.icon]s + /// + /// If this is not provided, the size will default to [iconSize], the color + /// will default to [unselectedItemColor]. + /// + /// It this field is provided, it must contain non-null [IconThemeData.size] + /// and [IconThemeData.color] properties. Also, if this field is supplied, + /// [unselectedIconTheme] must be provided. + final IconThemeData unselectedIconTheme; + + /// The [TextStyle] of the [BottomNavigationBarItem] labels when they are + /// selected. + final TextStyle selectedLabelStyle; + + /// The [TextStyle] of the [BottomNavigationBarItem] labels when they are not + /// selected. + final TextStyle unselectedLabelStyle; + + /// The font size of the [BottomNavigationBarItem] labels when they are selected. + /// + /// If [selectedLabelStyle.fontSize] is non-null, it will be used instead of this. + /// + /// Defaults to `14.0`. + final double selectedFontSize; + + /// The font size of the [BottomNavigationBarItem] labels when they are not + /// selected. + /// + /// If [unselectedLabelStyle.fontSize] is non-null, it will be used instead of this. + /// + /// Defaults to `12.0`. + final double unselectedFontSize; + + /// Whether the labels are shown for the selected [BottomNavigationBarItem]. + final bool showUnselectedLabels; + + /// Whether the labels are shown for the unselected [BottomNavigationBarItem]s. + final bool showSelectedLabels; + + // Used by the [BottomNavigationBar] constructor to set the [type] parameter. + // + // If type is provided, it is returned. Otherwise, + // [BottomNavigationBarType.fixed] is used for 3 or fewer items, and + // [BottomNavigationBarType.shifting] is used for 4+ items. + static BottomNavigationBarType _type( + BottomNavigationBarType type, + List items, + ) { + if (type != null) { + return type; + } + return items.length <= 3 + ? BottomNavigationBarType.fixed + : BottomNavigationBarType.shifting; + } + + // Used by the [BottomNavigationBar] constructor to set the [showUnselected] + // parameter. + // + // Unselected labels are shown by default for [BottomNavigationBarType.fixed], + // and hidden by default for [BottomNavigationBarType.shifting]. + static bool _defaultShowUnselected(BottomNavigationBarType type) { + switch (type) { + case BottomNavigationBarType.shifting: + return false; + case BottomNavigationBarType.fixed: + return true; + } + assert(false); + return false; + } + + @override + _BottomNavigationBarState createState() => _BottomNavigationBarState(); +} + +// This represents a single tile in the bottom navigation bar. It is intended +// to go into a flex container. +class _BottomNavigationTile extends StatelessWidget { + const _BottomNavigationTile( + this.type, + this.item, + this.animation, + this.iconSize, { + this.onTap, + this.colorTween, + this.flex, + this.selected = false, + @required this.selectedLabelStyle, + @required this.unselectedLabelStyle, + @required this.selectedIconTheme, + @required this.unselectedIconTheme, + this.showSelectedLabels, + this.showUnselectedLabels, + this.indexLabel, + }) : assert(type != null), + assert(item != null), + assert(animation != null), + assert(selected != null), + assert(selectedLabelStyle != null), + assert(unselectedLabelStyle != null); + + final BottomNavigationBarType type; + final BottomNavigationBarItem item; + final Animation animation; + final double iconSize; + final VoidCallback onTap; + final ColorTween colorTween; + final double flex; + final bool selected; + final IconThemeData selectedIconTheme; + final IconThemeData unselectedIconTheme; + final TextStyle selectedLabelStyle; + final TextStyle unselectedLabelStyle; + final String indexLabel; + final bool showSelectedLabels; + final bool showUnselectedLabels; + + @override + Widget build(BuildContext context) { + // In order to use the flex container to grow the tile during animation, we + // need to divide the changes in flex allotment into smaller pieces to + // produce smooth animation. We do this by multiplying the flex value + // (which is an integer) by a large number. + int size; + + final double selectedFontSize = selectedLabelStyle.fontSize; + + final double selectedIconSize = selectedIconTheme?.size ?? iconSize; + final double unselectedIconSize = unselectedIconTheme?.size ?? iconSize; + // The amount that the selected icon is bigger than the unselected icons, + // (or zero if the selected icon is not bigger than the unselected icons). + final double selectedIconDiff = + math.max(selectedIconSize - unselectedIconSize, 0); + // The amount that the unselected icons are bigger than the selected icon, + // (or zero if the unselected icons are not any bigger than the selected icon). + final double unselectedIconDiff = + math.max(unselectedIconSize - selectedIconSize, 0); + + // Defines the padding for the animating icons + labels. + // + // The animations go from "Unselected": + // ======= + // | <-- Padding equal to the text height + 1/2 selectedIconDiff. + // | ☆ + // | text <-- Invisible text + padding equal to 1/2 selectedIconDiff. + // ======= + // + // To "Selected": + // + // ======= + // | <-- Padding equal to 1/2 text height + 1/2 unselectedIconDiff. + // | ☆ + // | text + // | <-- Padding equal to 1/2 text height + 1/2 unselectedIconDiff. + // ======= + double bottomPadding; + //double topPadding; + if (showSelectedLabels && !showUnselectedLabels) { + bottomPadding = Tween( + begin: selectedIconDiff / 2.0, + end: selectedFontSize / 2.0 - unselectedIconDiff / 2.0, + ).evaluate(animation); + // topPadding = Tween( + // begin: selectedFontSize + selectedIconDiff / 2.0, + // end: selectedFontSize / 2.0 - unselectedIconDiff / 2.0, + // ).evaluate(animation); + } else if (!showSelectedLabels && !showUnselectedLabels) { + bottomPadding = Tween( + begin: selectedIconDiff / 2.0, + end: unselectedIconDiff / 2.0, + ).evaluate(animation); + // topPadding = Tween( + // begin: selectedFontSize + selectedIconDiff / 2.0, + // end: selectedFontSize + unselectedIconDiff / 2.0, + // ).evaluate(animation); + } else { + bottomPadding = Tween( + begin: selectedFontSize / 2.0 + selectedIconDiff / 2.0, + end: selectedFontSize / 2.0 + unselectedIconDiff / 2.0, + ).evaluate(animation); + // topPadding = Tween( + // begin: selectedFontSize / 2.0 + selectedIconDiff / 2.0, + // end: selectedFontSize / 2.0 + unselectedIconDiff / 2.0, + // ).evaluate(animation); + } + + switch (type) { + case BottomNavigationBarType.fixed: + size = 1; + break; + case BottomNavigationBarType.shifting: + size = (flex * 1000.0).round(); + break; + } + + return Expanded( + flex: size, + child: Semantics( + container: true, + selected: selected, + child: Focus( + child: Stack( + children: [ + InkResponse( + onTap: onTap, + child: Padding( + padding: + EdgeInsets.only(top: 8, bottom: bottomPadding), + child: _TileIcon( + colorTween: colorTween, + animation: animation, + iconSize: iconSize, + selected: selected, + item: item, + selectedIconTheme: selectedIconTheme, + unselectedIconTheme: unselectedIconTheme, + )), + ), + Semantics( + label: indexLabel, + ), + ], + ), + ), + ), + ); + } +} + +class _TileIcon extends StatelessWidget { + const _TileIcon({ + Key key, + @required this.colorTween, + @required this.animation, + @required this.iconSize, + @required this.selected, + @required this.item, + @required this.selectedIconTheme, + @required this.unselectedIconTheme, + }) : assert(selected != null), + assert(item != null), + super(key: key); + + final ColorTween colorTween; + final Animation animation; + final double iconSize; + final bool selected; + final BottomNavigationBarItem item; + final IconThemeData selectedIconTheme; + final IconThemeData unselectedIconTheme; + + @override + Widget build(BuildContext context) { + final Color iconColor = colorTween.evaluate(animation); + final IconThemeData defaultIconTheme = IconThemeData( + color: iconColor, + size: iconSize, + ); + final IconThemeData iconThemeData = IconThemeData.lerp( + defaultIconTheme.merge(unselectedIconTheme), + defaultIconTheme.merge(selectedIconTheme), + animation.value, + ); + + return Align( + alignment: Alignment.topCenter, + heightFactor: 1.0, + child: Container( + child: IconTheme( + data: iconThemeData, + child: selected ? item.activeIcon : item.icon, + ), + ), + ); + } +} + + +class _BottomNavigationBarState extends State + with TickerProviderStateMixin { + List _controllers = []; + List _animations; + + // A queue of color splashes currently being animated. + final Queue<_Circle> _circles = Queue<_Circle>(); + + // Last splash circle's color, and the final color of the control after + // animation is complete. + Color _backgroundColor; + + static final Animatable _flexTween = + Tween(begin: 1.0, end: 1.5); + + void _resetState() { + for (AnimationController controller in _controllers) controller.dispose(); + for (_Circle circle in _circles) circle.dispose(); + _circles.clear(); + + _controllers = + List.generate(widget.items.length, (int index) { + return AnimationController( + duration: kThemeAnimationDuration, + vsync: this, + )..addListener(_rebuild); + }); + _animations = + List.generate(widget.items.length, (int index) { + return CurvedAnimation( + parent: _controllers[index], + curve: Curves.fastOutSlowIn, + reverseCurve: Curves.fastOutSlowIn.flipped, + ); + }); + _controllers[widget.currentIndex].value = 1.0; + _backgroundColor = widget.items[widget.currentIndex].backgroundColor; + } + + @override + void initState() { + super.initState(); + _resetState(); + } + + void _rebuild() { + setState(() { + // Rebuilding when any of the controllers tick, i.e. when the items are + // animated. + }); + } + + @override + void dispose() { + for (AnimationController controller in _controllers) controller.dispose(); + for (_Circle circle in _circles) circle.dispose(); + super.dispose(); + } + + double _evaluateFlex(Animation animation) => + _flexTween.evaluate(animation); + + void _pushCircle(int index) { + if (widget.items[index].backgroundColor != null) { + _circles.add( + _Circle( + state: this, + index: index, + color: widget.items[index].backgroundColor, + vsync: this, + )..controller.addStatusListener( + (AnimationStatus status) { + switch (status) { + case AnimationStatus.completed: + setState(() { + final _Circle circle = _circles.removeFirst(); + _backgroundColor = circle.color; + circle.dispose(); + }); + break; + case AnimationStatus.dismissed: + case AnimationStatus.forward: + case AnimationStatus.reverse: + break; + } + }, + ), + ); + } + } + + @override + void didUpdateWidget(BottomNavigationBar oldWidget) { + super.didUpdateWidget(oldWidget); + + // No animated segue if the length of the items list changes. + if (widget.items.length != oldWidget.items.length) { + _resetState(); + return; + } + + if (widget.currentIndex != oldWidget.currentIndex) { + switch (widget.type) { + case BottomNavigationBarType.fixed: + break; + case BottomNavigationBarType.shifting: + _pushCircle(widget.currentIndex); + break; + } + _controllers[oldWidget.currentIndex].reverse(); + _controllers[widget.currentIndex].forward(); + } else { + if (_backgroundColor != widget.items[widget.currentIndex].backgroundColor) + _backgroundColor = widget.items[widget.currentIndex].backgroundColor; + } + } + + // If the given [TextStyle] has a non-null `fontSize`, it should be used. + // Otherwise, the [selectedFontSize] parameter should be used. + static TextStyle _effectiveTextStyle(TextStyle textStyle, double fontSize) { + textStyle ??= const TextStyle(); + // Prefer the font size on textStyle if present. + return textStyle.fontSize == null + ? textStyle.copyWith(fontSize: fontSize) + : textStyle; + } + + List _createTiles() { + final MaterialLocalizations localizations = + MaterialLocalizations.of(context); + assert(localizations != null); + + final ThemeData themeData = Theme.of(context); + + final TextStyle effectiveSelectedLabelStyle = + _effectiveTextStyle(widget.selectedLabelStyle, widget.selectedFontSize); + final TextStyle effectiveUnselectedLabelStyle = _effectiveTextStyle( + widget.unselectedLabelStyle, widget.unselectedFontSize); + + Color themeColor; + switch (themeData.brightness) { + case Brightness.light: + themeColor = themeData.primaryColor; + break; + case Brightness.dark: + themeColor = themeData.accentColor; + break; + } + + ColorTween colorTween; + switch (widget.type) { + case BottomNavigationBarType.fixed: + colorTween = ColorTween( + begin: + widget.unselectedItemColor ?? themeData.textTheme.caption.color, + end: widget.selectedItemColor ?? widget.fixedColor ?? themeColor, + ); + break; + case BottomNavigationBarType.shifting: + colorTween = ColorTween( + begin: widget.unselectedItemColor ?? Colors.white, + end: widget.selectedItemColor ?? Colors.white, + ); + break; + } + + final List tiles = []; + for (int i = 0; i < widget.items.length; i++) { + tiles.add(_BottomNavigationTile( + widget.type, + widget.items[i], + _animations[i], + widget.iconSize, + selectedIconTheme: widget.selectedIconTheme, + unselectedIconTheme: widget.unselectedIconTheme, + selectedLabelStyle: effectiveSelectedLabelStyle, + unselectedLabelStyle: effectiveUnselectedLabelStyle, + onTap: () { + if (widget.onTap != null) widget.onTap(i); + }, + colorTween: colorTween, + flex: _evaluateFlex(_animations[i]), + selected: i == widget.currentIndex, + showSelectedLabels: widget.showSelectedLabels, + showUnselectedLabels: widget.showUnselectedLabels, + indexLabel: localizations.tabLabel( + tabIndex: i + 1, tabCount: widget.items.length), + )); + } + return tiles; + } + + Widget _createContainer(List tiles) { + return DefaultTextStyle.merge( + overflow: TextOverflow.ellipsis, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: tiles, + ), + ); + } + + @override + Widget build(BuildContext context) { + assert(debugCheckHasDirectionality(context)); + assert(debugCheckHasMaterialLocalizations(context)); + assert(debugCheckHasMediaQuery(context)); + + // Labels apply up to _bottomMargin padding. Remainder is media padding. + final double additionalBottomPadding = math.max( + MediaQuery.of(context).padding.bottom - widget.selectedFontSize / 2.0, + 0.0); + Color backgroundColor; + switch (widget.type) { + case BottomNavigationBarType.fixed: + backgroundColor = widget.backgroundColor; + break; + case BottomNavigationBarType.shifting: + backgroundColor = _backgroundColor; + break; + } + return Semantics( + explicitChildNodes: true, + child: Material( + elevation: widget.elevation, + color: backgroundColor, + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: kBottomNavigationBarHeight + additionalBottomPadding), + child: CustomPaint( + painter: _RadialPainter( + circles: _circles.toList(), + textDirection: Directionality.of(context), + ), + child: Material( + // Splashes. + type: MaterialType.transparency, + child: Padding( + padding: EdgeInsets.only(bottom: additionalBottomPadding), + child: MediaQuery.removePadding( + context: context, + removeBottom: true, + child: _createContainer(_createTiles()), + ), + ), + ), + ), + ), + ), + ); + } +} + +// Describes an animating color splash circle. +class _Circle { + _Circle({ + @required this.state, + @required this.index, + @required this.color, + @required TickerProvider vsync, + }) : assert(state != null), + assert(index != null), + assert(color != null) { + controller = AnimationController( + duration: kThemeAnimationDuration, + vsync: vsync, + ); + animation = CurvedAnimation( + parent: controller, + curve: Curves.fastOutSlowIn, + ); + controller.forward(); + } + + final _BottomNavigationBarState state; + final int index; + final Color color; + AnimationController controller; + CurvedAnimation animation; + + double get horizontalLeadingOffset { + double weightSum(Iterable> animations) { + // We're adding flex values instead of animation values to produce correct + // ratios. + return animations + .map(state._evaluateFlex) + .fold(0.0, (double sum, double value) => sum + value); + } + + final double allWeights = weightSum(state._animations); + // These weights sum to the start edge of the indexed item. + final double leadingWeights = + weightSum(state._animations.sublist(0, index)); + + // Add half of its flex value in order to get to the center. + return (leadingWeights + + state._evaluateFlex(state._animations[index]) / 2.0) / + allWeights; + } + + void dispose() { + controller.dispose(); + } +} + +// Paints the animating color splash circles. +class _RadialPainter extends CustomPainter { + _RadialPainter({ + @required this.circles, + @required this.textDirection, + }) : assert(circles != null), + assert(textDirection != null); + + final List<_Circle> circles; + final TextDirection textDirection; + + // Computes the maximum radius attainable such that at least one of the + // bounding rectangle's corners touches the edge of the circle. Drawing a + // circle larger than this radius is not needed, since there is no perceivable + // difference within the cropped rectangle. + static double _maxRadius(Offset center, Size size) { + final double maxX = math.max(center.dx, size.width - center.dx); + final double maxY = math.max(center.dy, size.height - center.dy); + return math.sqrt(maxX * maxX + maxY * maxY); + } + + @override + bool shouldRepaint(_RadialPainter oldPainter) { + if (textDirection != oldPainter.textDirection) return true; + if (circles == oldPainter.circles) return false; + if (circles.length != oldPainter.circles.length) return true; + for (int i = 0; i < circles.length; i += 1) + if (circles[i] != oldPainter.circles[i]) return true; + return false; + } + + @override + void paint(Canvas canvas, Size size) { + for (_Circle circle in circles) { + final Paint paint = Paint()..color = circle.color; + final Rect rect = Rect.fromLTWH(0.0, 0.0, size.width, size.height); + canvas.clipRect(rect); + double leftFraction; + switch (textDirection) { + case TextDirection.rtl: + leftFraction = 1.0 - circle.horizontalLeadingOffset; + break; + case TextDirection.ltr: + leftFraction = circle.horizontalLeadingOffset; + break; + } + final Offset center = + Offset(leftFraction * size.width, size.height / 2.0); + final Tween radiusTween = Tween( + begin: 0.0, + end: _maxRadius(center, size), + ); + canvas.drawCircle( + center, + radiusTween.transform(circle.animation.value), + paint, + ); + } + } +} diff --git a/lib/utils/my_dialog.dart b/lib/utils/my_dialog.dart new file mode 100644 index 0000000..cc8de8d --- /dev/null +++ b/lib/utils/my_dialog.dart @@ -0,0 +1,739 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +// Examples can assume: +// enum Department { treasury, state } +// BuildContext context; + +/// A material design dialog. +/// +/// This dialog widget does not have any opinion about the contents of the +/// dialog. Rather than using this widget directly, consider using [AlertDialog] +/// or [SimpleDialog], which implement specific kinds of material design +/// dialogs. +/// +/// See also: +/// +/// * [AlertDialog], for dialogs that have a message and some buttons. +/// * [SimpleDialog], for dialogs that offer a variety of options. +/// * [showDialog], which actually displays the dialog and returns its result. +/// * +class Dialog extends StatelessWidget { + /// Creates a dialog. + /// + /// Typically used in conjunction with [showDialog]. + const Dialog({ + Key key, + this.backgroundColor, + this.elevation, + this.insetAnimationDuration = const Duration(milliseconds: 100), + this.insetAnimationCurve = Curves.decelerate, + this.shape, + this.child, + }) : super(key: key); + + /// {@template flutter.material.dialog.backgroundColor} + /// The background color of the surface of this [Dialog]. + /// + /// This sets the [Material.color] on this [Dialog]'s [Material]. + /// + /// If `null`, [ThemeData.cardColor] is used. + /// {@endtemplate} + final Color backgroundColor; + + /// {@template flutter.material.dialog.elevation} + /// The z-coordinate of this [Dialog]. + /// + /// If null then [DialogTheme.elevation] is used, and if that's null then the + /// dialog's elevation is 24.0. + /// {@endtemplate} + /// {@macro flutter.material.material.elevation} + final double elevation; + + /// The duration of the animation to show when the system keyboard intrudes + /// into the space that the dialog is placed in. + /// + /// Defaults to 100 milliseconds. + final Duration insetAnimationDuration; + + /// The curve to use for the animation shown when the system keyboard intrudes + /// into the space that the dialog is placed in. + /// + /// Defaults to [Curves.fastOutSlowIn]. + final Curve insetAnimationCurve; + + /// {@template flutter.material.dialog.shape} + /// The shape of this dialog's border. + /// + /// Defines the dialog's [Material.shape]. + /// + /// The default shape is a [RoundedRectangleBorder] with a radius of 2.0. + /// {@endtemplate} + final ShapeBorder shape; + + /// The widget below this widget in the tree. + /// + /// {@macro flutter.widgets.child} + final Widget child; + + static const RoundedRectangleBorder _defaultDialogShape = + RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(2.0))); + static const double _defaultElevation = 24.0; + + @override + Widget build(BuildContext context) { + final DialogTheme dialogTheme = DialogTheme.of(context); + return AnimatedPadding( + padding: MediaQuery.of(context).viewInsets + + const EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0), + duration: insetAnimationDuration, + curve: insetAnimationCurve, + child: MediaQuery.removeViewInsets( + removeLeft: true, + removeTop: true, + removeRight: true, + removeBottom: true, + context: context, + child: Center( + child: ConstrainedBox( + constraints: const BoxConstraints(minWidth: 280.0), + child: Material( + color: backgroundColor ?? + dialogTheme.backgroundColor ?? + Theme.of(context).dialogBackgroundColor, + elevation: + elevation ?? dialogTheme.elevation ?? _defaultElevation, + shape: shape ?? dialogTheme.shape ?? _defaultDialogShape, + type: MaterialType.card, + child: child, + ), + ), + ), + ), + ); + } +} + +/// A material design alert dialog. +/// +/// An alert dialog informs the user about situations that require +/// acknowledgement. An alert dialog has an optional title and an optional list +/// of actions. The title is displayed above the content and the actions are +/// displayed below the content. +/// +/// If the content is too large to fit on the screen vertically, the dialog will +/// display the title and the actions and let the content overflow, which is +/// rarely desired. Consider using a scrolling widget for [content], such as +/// [SingleChildScrollView], to avoid overflow. (However, be aware that since +/// [AlertDialog] tries to size itself using the intrinsic dimensions of its +/// children, widgets such as [ListView], [GridView], and [CustomScrollView], +/// which use lazy viewports, will not work. If this is a problem, consider +/// using [Dialog] directly.) +/// +/// For dialogs that offer the user a choice between several options, consider +/// using a [SimpleDialog]. +/// +/// Typically passed as the child widget to [showDialog], which displays the +/// dialog. +/// +/// {@tool sample} +/// +/// This snippet shows a method in a [State] which, when called, displays a dialog box +/// and returns a [Future] that completes when the dialog is dismissed. +/// +/// ```dart +/// Future _neverSatisfied() async { +/// return showDialog( +/// context: context, +/// barrierDismissible: false, // user must tap button! +/// builder: (BuildContext context) { +/// return AlertDialog( +/// title: Text('Rewind and remember'), +/// content: SingleChildScrollView( +/// child: ListBody( +/// children: [ +/// Text('You will never be satisfied.'), +/// Text('You\’re like me. I’m never satisfied.'), +/// ], +/// ), +/// ), +/// actions: [ +/// FlatButton( +/// child: Text('Regret'), +/// onPressed: () { +/// Navigator.of(context).pop(); +/// }, +/// ), +/// ], +/// ); +/// }, +/// ); +/// } +/// ``` +/// {@end-tool} +/// +/// See also: +/// +/// * [SimpleDialog], which handles the scrolling of the contents but has no [actions]. +/// * [Dialog], on which [AlertDialog] and [SimpleDialog] are based. +/// * [CupertinoAlertDialog], an iOS-styled alert dialog. +/// * [showDialog], which actually displays the dialog and returns its result. +/// * +class AlertDialog extends StatelessWidget { + /// Creates an alert dialog. + /// + /// Typically used in conjunction with [showDialog]. + /// + /// The [contentPadding] must not be null. The [titlePadding] defaults to + /// null, which implies a default that depends on the values of the other + /// properties. See the documentation of [titlePadding] for details. + const AlertDialog({ + Key key, + this.title, + this.titlePadding, + this.titleTextStyle, + this.content, + this.contentPadding = const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0), + this.contentTextStyle, + this.actions, + this.backgroundColor, + this.elevation, + this.semanticLabel, + this.shape, + }) : assert(contentPadding != null), + super(key: key); + + /// The (optional) title of the dialog is displayed in a large font at the top + /// of the dialog. + /// + /// Typically a [Text] widget. + final Widget title; + + /// Padding around the title. + /// + /// If there is no title, no padding will be provided. Otherwise, this padding + /// is used. + /// + /// This property defaults to providing 24 pixels on the top, left, and right + /// of the title. If the [content] is not null, then no bottom padding is + /// provided (but see [contentPadding]). If it _is_ null, then an extra 20 + /// pixels of bottom padding is added to separate the [title] from the + /// [actions]. + final EdgeInsetsGeometry titlePadding; + + /// Style for the text in the [title] of this [AlertDialog]. + /// + /// If null, [DialogTheme.titleTextStyle] is used, if that's null, defaults to + /// [ThemeData.textTheme.title]. + final TextStyle titleTextStyle; + + /// The (optional) content of the dialog is displayed in the center of the + /// dialog in a lighter font. + /// + /// Typically this is a [SingleChildScrollView] that contains the dialog's + /// message. As noted in the [AlertDialog] documentation, it's important + /// to use a [SingleChildScrollView] if there's any risk that the content + /// will not fit. + final Widget content; + + /// Padding around the content. + /// + /// If there is no content, no padding will be provided. Otherwise, padding of + /// 20 pixels is provided above the content to separate the content from the + /// title, and padding of 24 pixels is provided on the left, right, and bottom + /// to separate the content from the other edges of the dialog. + final EdgeInsetsGeometry contentPadding; + + /// Style for the text in the [content] of this [AlertDialog]. + /// + /// If null, [DialogTheme.contentTextStyle] is used, if that's null, defaults + /// to [ThemeData.textTheme.subhead]. + final TextStyle contentTextStyle; + + /// The (optional) set of actions that are displayed at the bottom of the + /// dialog. + /// + /// Typically this is a list of [FlatButton] widgets. + /// + /// These widgets will be wrapped in a [ButtonBar], which introduces 8 pixels + /// of padding on each side. + /// + /// If the [title] is not null but the [content] _is_ null, then an extra 20 + /// pixels of padding is added above the [ButtonBar] to separate the [title] + /// from the [actions]. + final List actions; + + /// {@macro flutter.material.dialog.backgroundColor} + final Color backgroundColor; + + /// {@macro flutter.material.dialog.elevation} + /// {@macro flutter.material.material.elevation} + final double elevation; + + /// The semantic label of the dialog used by accessibility frameworks to + /// announce screen transitions when the dialog is opened and closed. + /// + /// If this label is not provided, a semantic label will be inferred from the + /// [title] if it is not null. If there is no title, the label will be taken + /// from [MaterialLocalizations.alertDialogLabel]. + /// + /// See also: + /// + /// * [SemanticsConfiguration.isRouteName], for a description of how this + /// value is used. + final String semanticLabel; + + /// {@macro flutter.material.dialog.shape} + final ShapeBorder shape; + + @override + Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); + final ThemeData theme = Theme.of(context); + final DialogTheme dialogTheme = DialogTheme.of(context); + final List children = []; + String label = semanticLabel; + + if (title != null) { + children.add(Padding( + padding: titlePadding ?? + EdgeInsets.fromLTRB(24.0, 24.0, 24.0, content == null ? 20.0 : 0.0), + child: DefaultTextStyle( + style: titleTextStyle ?? + dialogTheme.titleTextStyle ?? + theme.textTheme.title, + child: Semantics( + child: title, + namesRoute: true, + container: true, + ), + ), + )); + } else { + switch (defaultTargetPlatform) { + case TargetPlatform.iOS: + label = semanticLabel; + break; + case TargetPlatform.android: + case TargetPlatform.fuchsia: + label = semanticLabel ?? + MaterialLocalizations.of(context)?.alertDialogLabel; + } + } + + if (content != null) { + children.add(Flexible( + child: Padding( + padding: contentPadding, + child: DefaultTextStyle( + style: contentTextStyle ?? + dialogTheme.contentTextStyle ?? + theme.textTheme.subhead, + child: content, + ), + ), + )); + } + + if (actions != null) { + // children.add(ButtonTheme.bar( + // child: ButtonBar( + // children: actions, + // ), + // )); + + children.add(ButtonBarTheme( + data: ButtonBarTheme.of(context), + child: ButtonBar( + children: actions, + ), + )); + } + + Widget dialogChild = IntrinsicWidth( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: children, + ), + ); + + if (label != null) + dialogChild = Semantics( + namesRoute: true, + label: label, + child: dialogChild, + ); + + return Dialog( + backgroundColor: backgroundColor, + elevation: elevation, + shape: shape, + child: dialogChild, + ); + } +} + +/// An option used in a [SimpleDialog]. +/// +/// A simple dialog offers the user a choice between several options. This +/// widget is commonly used to represent each of the options. If the user +/// selects this option, the widget will call the [onPressed] callback, which +/// typically uses [Navigator.pop] to close the dialog. +/// +/// The padding on a [SimpleDialogOption] is configured to combine with the +/// default [SimpleDialog.contentPadding] so that each option ends up 8 pixels +/// from the other vertically, with 20 pixels of spacing between the dialog's +/// title and the first option, and 24 pixels of spacing between the last option +/// and the bottom of the dialog. +/// +/// {@tool sample} +/// +/// ```dart +/// SimpleDialogOption( +/// onPressed: () { Navigator.pop(context, Department.treasury); }, +/// child: const Text('Treasury department'), +/// ) +/// ``` +/// {@end-tool} +/// +/// See also: +/// +/// * [SimpleDialog], for a dialog in which to use this widget. +/// * [showDialog], which actually displays the dialog and returns its result. +/// * [FlatButton], which are commonly used as actions in other kinds of +/// dialogs, such as [AlertDialog]s. +/// * +class SimpleDialogOption extends StatelessWidget { + /// Creates an option for a [SimpleDialog]. + const SimpleDialogOption({ + Key key, + this.onPressed, + this.child, + }) : super(key: key); + + /// The callback that is called when this option is selected. + /// + /// If this is set to null, the option cannot be selected. + /// + /// When used in a [SimpleDialog], this will typically call [Navigator.pop] + /// with a value for [showDialog] to complete its future with. + final VoidCallback onPressed; + + /// The widget below this widget in the tree. + /// + /// Typically a [Text] widget. + final Widget child; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onPressed, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 24.0), + child: child, + ), + ); + } +} + +/// A simple material design dialog. +/// +/// A simple dialog offers the user a choice between several options. A simple +/// dialog has an optional title that is displayed above the choices. +/// +/// Choices are normally represented using [SimpleDialogOption] widgets. If +/// other widgets are used, see [contentPadding] for notes regarding the +/// conventions for obtaining the spacing expected by Material Design. +/// +/// For dialogs that inform the user about a situation, consider using an +/// [AlertDialog]. +/// +/// Typically passed as the child widget to [showDialog], which displays the +/// dialog. +/// +/// {@tool sample} +/// +/// In this example, the user is asked to select between two options. These +/// options are represented as an enum. The [showDialog] method here returns +/// a [Future] that completes to a value of that enum. If the user cancels +/// the dialog (e.g. by hitting the back button on Android, or tapping on the +/// mask behind the dialog) then the future completes with the null value. +/// +/// The return value in this example is used as the index for a switch statement. +/// One advantage of using an enum as the return value and then using that to +/// drive a switch statement is that the analyzer will flag any switch statement +/// that doesn't mention every value in the enum. +/// +/// ```dart +/// Future _askedToLead() async { +/// switch (await showDialog( +/// context: context, +/// builder: (BuildContext context) { +/// return SimpleDialog( +/// title: const Text('Select assignment'), +/// children: [ +/// SimpleDialogOption( +/// onPressed: () { Navigator.pop(context, Department.treasury); }, +/// child: const Text('Treasury department'), +/// ), +/// SimpleDialogOption( +/// onPressed: () { Navigator.pop(context, Department.state); }, +/// child: const Text('State department'), +/// ), +/// ], +/// ); +/// } +/// )) { +/// case Department.treasury: +/// // Let's go. +/// // ... +/// break; +/// case Department.state: +/// // ... +/// break; +/// } +/// } +/// ``` +/// {@end-tool} +/// +/// See also: +/// +/// * [SimpleDialogOption], which are options used in this type of dialog. +/// * [AlertDialog], for dialogs that have a row of buttons below the body. +/// * [Dialog], on which [SimpleDialog] and [AlertDialog] are based. +/// * [showDialog], which actually displays the dialog and returns its result. +/// * +class SimpleDialog extends StatelessWidget { + /// Creates a simple dialog. + /// + /// Typically used in conjunction with [showDialog]. + /// + /// The [titlePadding] and [contentPadding] arguments must not be null. + const SimpleDialog({ + Key key, + this.title, + this.titlePadding = const EdgeInsets.fromLTRB(24.0, 24.0, 24.0, 0.0), + this.children, + this.contentPadding = const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 16.0), + this.backgroundColor, + this.elevation, + this.semanticLabel, + this.shape, + }) : assert(titlePadding != null), + assert(contentPadding != null), + super(key: key); + + /// The (optional) title of the dialog is displayed in a large font at the top + /// of the dialog. + /// + /// Typically a [Text] widget. + final Widget title; + + /// Padding around the title. + /// + /// If there is no title, no padding will be provided. + /// + /// By default, this provides the recommend Material Design padding of 24 + /// pixels around the left, top, and right edges of the title. + /// + /// See [contentPadding] for the conventions regarding padding between the + /// [title] and the [children]. + final EdgeInsetsGeometry titlePadding; + + /// The (optional) content of the dialog is displayed in a + /// [SingleChildScrollView] underneath the title. + /// + /// Typically a list of [SimpleDialogOption]s. + final List children; + + /// Padding around the content. + /// + /// By default, this is 12 pixels on the top and 16 pixels on the bottom. This + /// is intended to be combined with children that have 24 pixels of padding on + /// the left and right, and 8 pixels of padding on the top and bottom, so that + /// the content ends up being indented 20 pixels from the title, 24 pixels + /// from the bottom, and 24 pixels from the sides. + /// + /// The [SimpleDialogOption] widget uses such padding. + /// + /// If there is no [title], the [contentPadding] should be adjusted so that + /// the top padding ends up being 24 pixels. + final EdgeInsetsGeometry contentPadding; + + /// {@macro flutter.material.dialog.backgroundColor} + final Color backgroundColor; + + /// {@macro flutter.material.dialog.elevation} + /// {@macro flutter.material.material.elevation} + final double elevation; + + /// The semantic label of the dialog used by accessibility frameworks to + /// announce screen transitions when the dialog is opened and closed. + /// + /// If this label is not provided, a semantic label will be inferred from the + /// [title] if it is not null. If there is no title, the label will be taken + /// from [MaterialLocalizations.dialogLabel]. + /// + /// See also: + /// + /// * [SemanticsConfiguration.isRouteName], for a description of how this + /// value is used. + final String semanticLabel; + + /// {@macro flutter.material.dialog.shape} + final ShapeBorder shape; + + @override + Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); + final List body = []; + String label = semanticLabel; + + if (title != null) { + body.add(Padding( + padding: titlePadding, + child: DefaultTextStyle( + style: Theme.of(context).textTheme.title, + child: Semantics(namesRoute: true, child: title), + ), + )); + } else { + switch (defaultTargetPlatform) { + case TargetPlatform.iOS: + label = semanticLabel; + break; + case TargetPlatform.android: + case TargetPlatform.fuchsia: + label = + semanticLabel ?? MaterialLocalizations.of(context)?.dialogLabel; + } + } + + if (children != null) { + body.add(Flexible( + child: SingleChildScrollView( + padding: contentPadding, + child: ListBody(children: children), + ), + )); + } + + Widget dialogChild = IntrinsicWidth( + stepWidth: 56.0, + child: ConstrainedBox( + constraints: const BoxConstraints(minWidth: 280.0), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: body, + ), + ), + ); + + if (label != null) + dialogChild = Semantics( + namesRoute: true, + label: label, + child: dialogChild, + ); + return Dialog( + backgroundColor: backgroundColor, + elevation: elevation, + shape: shape, + child: dialogChild, + ); + } +} + +Widget _buildMaterialDialogTransitions( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child) { + return FadeTransition( + opacity: CurvedAnimation( + parent: animation, + curve: Curves.easeOut, + ), + child: child, + ); +} + +/// Displays a Material dialog above the current contents of the app, with +/// Material entrance and exit animations, modal barrier color, and modal +/// barrier behavior (dialog is dismissible with a tap on the barrier). +/// +/// This function takes a `builder` which typically builds a [Dialog] widget. +/// Content below the dialog is dimmed with a [ModalBarrier]. The widget +/// returned by the `builder` does not share a context with the location that +/// `showDialog` is originally called from. Use a [StatefulBuilder] or a +/// custom [StatefulWidget] if the dialog needs to update dynamically. +/// +/// The `context` argument is used to look up the [Navigator] and [Theme] for +/// the dialog. It is only used when the method is called. Its corresponding +/// widget can be safely removed from the tree before the dialog is closed. +/// +/// The `child` argument is deprecated, and should be replaced with `builder`. +/// +/// Returns a [Future] that resolves to the value (if any) that was passed to +/// [Navigator.pop] when the dialog was closed. +/// +/// The dialog route created by this method is pushed to the root navigator. +/// If the application has multiple [Navigator] objects, it may be necessary to +/// call `Navigator.of(context, rootNavigator: true).pop(result)` to close the +/// dialog rather than just `Navigator.pop(context, result)`. +/// +/// See also: +/// +/// * [AlertDialog], for dialogs that have a row of buttons below a body. +/// * [SimpleDialog], which handles the scrolling of the contents and does +/// not show buttons below its body. +/// * [Dialog], on which [SimpleDialog] and [AlertDialog] are based. +/// * [showCupertinoDialog], which displays an iOS-style dialog. +/// * [showGeneralDialog], which allows for customization of the dialog popup. +/// * +Future showDialog({ + @required + BuildContext context, + bool barrierDismissible = true, + @Deprecated( + 'Instead of using the "child" argument, return the child from a closure ' + 'provided to the "builder" argument. This will ensure that the BuildContext ' + 'is appropriate for widgets built in the dialog.') + Widget child, + WidgetBuilder builder, +}) { + assert(child == null || builder == null); + assert(debugCheckHasMaterialLocalizations(context)); + + final ThemeData theme = Theme.of(context, shadowThemeOnly: true); + return showGeneralDialog( + context: context, + pageBuilder: (BuildContext buildContext, Animation animation, + Animation secondaryAnimation) { + final Widget pageChild = child ?? Builder(builder: builder); + return WillPopScope(onWillPop: () { + return new Future.value(false); + }, child: SafeArea( + child: Builder(builder: (BuildContext context) { + return theme != null + ? Theme(data: theme, child: pageChild) + : pageChild; + }), + )); + }, + barrierDismissible: barrierDismissible, + barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel, + transitionDuration: const Duration(milliseconds: 150), + transitionBuilder: _buildMaterialDialogTransitions, + ); +} diff --git a/lib/utils/net_state_util.dart b/lib/utils/net_state_util.dart new file mode 100644 index 0000000..b2902ae --- /dev/null +++ b/lib/utils/net_state_util.dart @@ -0,0 +1,41 @@ +import 'dart:async'; + +import 'package:chat/data/constants.dart'; +import 'package:connectivity/connectivity.dart'; + +import 'NetUtil.dart'; + +class NetStateBloc { + Connectivity _connectivity = Connectivity(); + + ConnectivityResult lastNet; + StreamController _streamController = StreamController.broadcast(); + Stream get stream => _streamController.stream; + + void start() { + _connectivity.onConnectivityChanged.listen(_updateConnectionStatus); + } + + _updateConnectionStatus(ConnectivityResult result) async { + print('网络状态改变$result'); + if (result == ConnectivityResult.none) { + lastNet = result; + _streamController.sink.add(ChatState.connecting.index); + } else { + if (lastNet != result) { + lastNet = result; + if (NetWork().isInit && !NetWork().isConnecting) { + NetWork().reconnect(); + } + } + } + } + + addState(ChatState state) { + _streamController.sink.add(state.index); + } + + void dispose() { + _streamController.close(); + } +} diff --git a/lib/utils/net_state_widget.dart b/lib/utils/net_state_widget.dart new file mode 100644 index 0000000..138564a --- /dev/null +++ b/lib/utils/net_state_widget.dart @@ -0,0 +1,71 @@ +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'NetUtil.dart'; + +class NetStateWidget extends StatelessWidget { + @override + Widget build(BuildContext context) { + + return StreamBuilder( + stream: NetWork().stream, + initialData: ChatState.connecting, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.data == ChatState.connecting.index) { + return Container( + color: Colors.white70, + padding: EdgeInsets.symmetric(vertical: 5), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CupertinoActivityIndicator(), + SizedBox(width: 10), + fixedText(I18n.of(context).connecting, color: Colors.grey[300]) + ])); + } else if (snapshot.data == ChatState.logining.index) { + return Container( + color: Colors.white70, + padding: EdgeInsets.symmetric(vertical: 5), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CupertinoActivityIndicator(), + SizedBox(width: 10), + fixedText(I18n.of(context).logining, color: Colors.grey[300]) + ])); + } else if (snapshot.data == ChatState.connectFailed.index || + snapshot.data == ChatState.loginFailed.index) { + return InkWell( + onTap: () { + if (snapshot.data == ChatState.connectFailed.index) { + NetWork().reconnect(); + } else { + NetWork().reLogin(); + } + }, + child: Container( + color: Colors.white70, + padding: EdgeInsets.symmetric(vertical: 5), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + IconData(0xe649, + fontFamily: Constants.IconFontFamily), + color: Colors.grey), + SizedBox(width: 10), + fixedText(I18n.of(context).net_error, + color: Colors.grey) + ]))); + } else { + return Container( + height: 0, + ); + } + }, + ); + } +} diff --git a/lib/utils/placeholder.dart b/lib/utils/placeholder.dart new file mode 100644 index 0000000..953c539 --- /dev/null +++ b/lib/utils/placeholder.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +class PlaceholderWidget extends StatelessWidget { + const PlaceholderWidget(this.title, this.message); + + final String title; + final String message; + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(title, + style: const TextStyle(fontSize: 32.0, color: Colors.black54), + textAlign: TextAlign.center), + Text(message, + style: const TextStyle(fontSize: 16.0, color: Colors.black54), + textAlign: TextAlign.center), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/utils/receive_share_file.dart b/lib/utils/receive_share_file.dart new file mode 100644 index 0000000..efa46a4 --- /dev/null +++ b/lib/utils/receive_share_file.dart @@ -0,0 +1,90 @@ +import 'dart:async'; + +import 'package:receive_sharing_intent/receive_sharing_intent.dart'; + +import 'MessageMgr.dart'; + +class ReceiveShareFile { + static StreamSubscription _intentDataStreamSubscription; + static List _sharedFiles; + static String tempFilePath; + + + static void init() { +// For sharing images coming from outside the app while the app is in the memory + _intentDataStreamSubscription = ReceiveSharingIntent.getMediaStream() + .listen((List value) { +// setState(() { +// _sharedFiles = value; +// print("Shared:" + (_sharedFiles?.map((f) => f.path)?.join(",") ?? "")); +// }); +// print('#### getfilePath ${value[0].path}'); + + if (currentIndex == 1) { + if (value != null && value.length > 0) { + MessageMgr().emit(MessageMgr.RECEIVE_THIRD_SHARE, value[0].path); + } + } else { +// print("### 记录下来了1"); + if (value != null && value.length > 0) { + tempFilePath = value[0].path; + } + } + }, onError: (err) { + print("getIntentDataStream error: $err"); + }); + + // For sharing images coming from outside the app while the app is closed + ReceiveSharingIntent.getInitialMedia().then((List value) { +// setState(() { +// _sharedFiles = value; +// print("Shared:" + (_sharedFiles?.map((f) => f.path)?.join(",") ?? "")); +// }); + +// print('#### getfilePath ${value[0].path}'); + + if (currentIndex == 1) { + if (value != null && value.length > 0) { + MessageMgr().emit(MessageMgr.RECEIVE_THIRD_SHARE, value[0].path); + } + } else { +// print("### 记录下来了"); + if (value != null && value.length > 0) { + tempFilePath = value[0].path; + } + } + }); + + // For sharing or opening urls/text coming from outside the app while the app is in the memory + _intentDataStreamSubscription = + ReceiveSharingIntent.getTextStream().listen((String value) { + print('#### getfilePath dddd $value '); + + MessageMgr().emit(MessageMgr.RECEIVE_THIRD_SHARE, value); + }, onError: (err) { + print("getLinkStream error: $err"); + }); + + // For sharing or opening urls/text coming from outside the app while the app is closed + ReceiveSharingIntent.getInitialText().then((String value) { + print('#### getfilePath $value '); +// setState(() { +// _sharedText = value; +// print("Shared: $_sharedText"); +// }); + }); + } + + static int currentIndex = 0; + + static void start() { + currentIndex = 1; + if (tempFilePath != null) { + MessageMgr().emit(MessageMgr.RECEIVE_THIRD_SHARE, tempFilePath); + } + } + + static dispose() { + currentIndex = 0; + } +} diff --git a/lib/utils/restart_widget.dart b/lib/utils/restart_widget.dart new file mode 100644 index 0000000..6384582 --- /dev/null +++ b/lib/utils/restart_widget.dart @@ -0,0 +1,59 @@ +import 'package:flutter/widgets.dart'; + +class RestartWidget extends StatefulWidget { + final Widget child; + + const RestartWidget({ + Key key, + this.child, + }) : super(key: key); + + @override + _RestartWidgetState createState() => _RestartWidgetState(); + + static _RestartWidgetState of(BuildContext context) { + assert(context != null); + + return (context + .getElementForInheritedWidgetOfExactType< + _RestartInheritedWidget>() + .widget as _RestartInheritedWidget) + .state; + } +} + +class _RestartWidgetState extends State { + Key _key = UniqueKey(); + + /// Change the key to a new one which will make the widget tree + /// re render. + void restartApp() async { + setState(() { + _key = UniqueKey(); + }); + } + + @override + Widget build(BuildContext context) { + return _RestartInheritedWidget( + key: _key, + state: this, + child: widget.child, + ); + } +} + +class _RestartInheritedWidget extends InheritedWidget { + final _RestartWidgetState state; + + _RestartInheritedWidget({ + Key key, + this.state, + Widget child, + }) : super(key: key, child: child); + + @override + bool updateShouldNotify(InheritedWidget oldWidget) { + return false; + } +} diff --git a/lib/utils/screen.dart b/lib/utils/screen.dart new file mode 100644 index 0000000..fa12891 --- /dev/null +++ b/lib/utils/screen.dart @@ -0,0 +1,98 @@ +import 'package:chat/chat/my_special_text_span_builder.dart'; +import 'package:extended_text/extended_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'dart:ui' as ui show window; + +class Screen { + static double uiFactor = 1.0; + static initFactor() { + uiFactor = width / 640; + } + + static double get width { + MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); + return mediaQuery.size.width; + } + + static double get height { + MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); + return mediaQuery.size.height; + } + + static double get scale { + MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); + return mediaQuery.devicePixelRatio; + } + + static double get textScaleFactor { + MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); + return mediaQuery.textScaleFactor; + } + + static double get navigationBarHeight { + MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); + return mediaQuery.padding.top + kToolbarHeight; + } + + static double get topSafeHeight { + MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); + return mediaQuery.padding.top; + } + + static double get bottomSafeHeight { + MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window); + return mediaQuery.padding.bottom; + } + + static updateStatusBarStyle(SystemUiOverlayStyle style) { + SystemChrome.setSystemUIOverlayStyle(style); + } +} + +fixedFontSize(double fontSize) { + return fontSize / Screen.textScaleFactor; +} + +fixedText(data, {Color color, double fontSize, FontWeight fontWeight}) { + return Text(data, + textScaleFactor: 1.0, + style: TextStyle( + fontSize: fontSize ?? 14.0, color: color, fontWeight: fontWeight)); +} + +extendedText(String text, + {Color color = Colors.blue, + double fontSize = 14, + selectionEnabled = false, + double emojisize = 20.0, + Function hideKeyboard, + fontWeight,int maxLines, + Function onSpecialTextTap + }) { + return ExtendedText( + text, + onSpecialTextTap: onSpecialTextTap, + textAlign: TextAlign.left, + maxLines: maxLines, + specialTextSpanBuilder: MySpecialTextSpanBuilder(emojiSize: emojisize), + textScaleFactor: 1.0, + style: TextStyle(fontSize: fontSize, color: color, fontWeight: fontWeight), + selectionEnabled: selectionEnabled, + ); +} + + +setStatusBar(){ + SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarBrightness: Brightness.light, + statusBarIconBrightness: Brightness.dark, + systemNavigationBarColor: Colors.white, + systemNavigationBarIconBrightness: Brightness.dark)); +} + + +debugPrint(dynamic msg){ + print('###${DateTime.now()}####### '+msg); +} diff --git a/lib/utils/screen_shot.dart b/lib/utils/screen_shot.dart new file mode 100644 index 0000000..3d4a638 --- /dev/null +++ b/lib/utils/screen_shot.dart @@ -0,0 +1,65 @@ +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:chat/map/location_result.dart'; +import 'package:chat/utils/screen.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_image_compress/flutter_image_compress.dart'; + +import 'MessageMgr.dart'; + +class ScreenShot { + static const MethodChannel _channel = + const MethodChannel('make.photo.screen.hibok'); + static const EventChannel eventChannel = + const EventChannel('com.file.hibok'); + + + static Future> takeScreenshotImage() async { + Map args = {}; + Uint8List bytes = await _channel.invokeMethod('makePhotoScreen', args); + + var compressImg = await FlutterImageCompress.compressWithList(bytes, + quality: 20, minWidth: (Screen.width).toInt()); + + print('地图大小${bytes.length}'); + return compressImg; + } + + static Future getOtherMapAppList() async { + Map args = {}; + return _channel.invokeMethod('getListForMap', args); + } + + static void openMapForOth(String mapType, LocationResult result) async { + Map args = { + 'mapType': mapType, + 'address': result.address, + 'latLng': [result.latLng.latitude, result.latLng.longitude] + }; + _channel.invokeMethod('openMapForOth', args); + } + + static Future isSupportGoogle() async { + Map args = {}; + return _channel.invokeMethod('isSupportGoogle', args); + } + + + static getFileStream() { + eventChannel.receiveBroadcastStream().listen((Object agrs){ + print('######## receiveBroadcastStream $agrs'); + + File file = new File(agrs.toString()); + if(file.existsSync()){ + print('接收到的文件--存在'); + MessageMgr().emit(MessageMgr.RECEIVE_THIRD_SHARE, agrs); + }else{ + print('接收到的文件--不存在'); + } + + }, onError: (Object error){ + print('######## error $error'); + }); + } +} diff --git a/lib/utils/sound_util.dart b/lib/utils/sound_util.dart new file mode 100644 index 0000000..64eb049 --- /dev/null +++ b/lib/utils/sound_util.dart @@ -0,0 +1,99 @@ +import 'package:audioplayer/audioplayer.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/utils/sp_utils.dart'; +import 'package:flutter/widgets.dart'; + +class SoundUtils { + // 工厂模式 + factory SoundUtils() => _getInstance(); + + static SoundUtils get instance => _getInstance(); + static SoundUtils _instance; + + String curSoundUrl; + + Map soundStateMap = {}; + + SoundUtils._internal() { + // 初始化 + audioPlugin = new AudioPlayer(); + stateStream = audioPlugin.onPlayerStateChanged; + } + + AudioPlayer audioPlugin; +// AudioCache audioCache = AudioCache(); + Stream stateStream; + bool isPlaying(url) { + return soundStateMap[url] ?? false; + } + + static SoundUtils _getInstance() { + if (_instance == null) { + _instance = new SoundUtils._internal(); + } + return _instance; + } + + + initPlayMode() async { + bool playMode = await SPUtils.getBool(Constants.SOUND_PLAY_MODE); + if (playMode != null && playMode) { + setReceiver(true); + } else { + setReceiver(false); + } + } + + savePlayModeConfig(bool playMode) async { + await SPUtils.saveBool(Constants.SOUND_PLAY_MODE, playMode); + setReceiver(playMode); + } + + ///设置听筒true 设置外放false + setReceiver(bool setReceiver) async { + await audioPlugin.setReceiver(setReceiver); + } + + play(url, + {bool isLocal = true, + VoidCallback onPlayed, + VoidCallback complete}) async { + if (curSoundUrl != null && curSoundUrl != url) { + print('不是同一个音频文件'); + await stop(); + } + print('播放url:$url'); + await audioPlugin.play(url, isLocal: isLocal); + + curSoundUrl = url; + stateStream.listen((state) { + if (state == AudioPlayerState.PLAYING) { + soundStateMap[curSoundUrl] = true; + if (onPlayed != null) { + onPlayed(); + } + } else { + soundStateMap[curSoundUrl] = false; + + if (complete != null) { + complete(); + } + } + }); + } + + pause() async { + print('暂停播放'); + if (curSoundUrl != null) { + soundStateMap[curSoundUrl] = false; + await audioPlugin.pause(); + } + } + + stop() async { + if (curSoundUrl != null) { + soundStateMap[curSoundUrl] = false; + await audioPlugin.stop(); + } + } +} diff --git a/lib/utils/sp_utils.dart b/lib/utils/sp_utils.dart new file mode 100755 index 0000000..515d4f8 --- /dev/null +++ b/lib/utils/sp_utils.dart @@ -0,0 +1,43 @@ + +import 'package:shared_preferences/shared_preferences.dart'; + +class SPUtils { + + + + static saveString(String key, value) async { + SharedPreferences spf = await SharedPreferences.getInstance(); + spf.setString(key, value); + } + + static saveList(String key, List value) async { + SharedPreferences spf = await SharedPreferences.getInstance(); + spf.setStringList(key, value); + } + + + static saveBool(String key, value) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setBool(key, value); + } + + static getBool(String key) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + return prefs.getBool(key); + } + + static save(String key, value) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setString(key, value); + } + + static get(String key) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + return prefs.get(key); + } + + static remove(String key) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.remove(key); + } +} diff --git a/lib/utils/sql_model.dart b/lib/utils/sql_model.dart new file mode 100644 index 0000000..67597c8 --- /dev/null +++ b/lib/utils/sql_model.dart @@ -0,0 +1,130 @@ +import 'dart:async'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/utils/sql_util.dart'; +import 'package:sqflite/sqflite.dart'; + +class BaseModel { + Database db; + final String table = ''; + var query; + + BaseModel(this.db) { + query = db.query; + } +} + +class Sql extends BaseModel { + final String tableName; + + Sql.setTable(String name) + : tableName = name, + super(SqlUtil.getCurrentDatabase()); + + Future get() async { + var myId = UserData().basicInfo.userId; + return await this.query(tableName, where: 'userId = $myId'); + } + + Future getAll() async { + var myId = UserData().basicInfo.userId; + var result = await this.query(tableName, where: 'userId = $myId'); + return result.toList(); + } + + String getTableName() { + return tableName; + } + + Future delete(String value, String key) async { + return await this.db.delete(tableName, + where: '$key = ? and userId = ?', + whereArgs: [value, UserData().basicInfo.userId]); + } + + Future createTable(String tableName, String colums) async { + return await this + .db + .execute('CREATE TABLE IF NOT EXISTS $tableName ($colums)'); + } + + Future clearTable(String tableName) async { + return await this.db.delete(tableName); + } + + Future getByCondition({Map conditions}) async { + if (conditions == null || conditions.isEmpty) { + return this.get(); + } + + String stringConditions = ''; + int index = 0; + conditions.forEach((key, value) { + if (value == null) { + return; + } + if (value.runtimeType == String) { + stringConditions = '$stringConditions $key = "$value"'; + } + if (value.runtimeType == int) { + stringConditions = '$stringConditions $key = $value'; + } + + if (index >= 0 && index < conditions.length - 1) { + stringConditions = '$stringConditions and'; + } + index++; + }); + + var myId = UserData().basicInfo.userId; + if (stringConditions.length > 0) { + stringConditions = '$stringConditions and userId = $myId'; + } + + return await this.query(tableName, where: stringConditions); + } + + Future> insert(Map json) async { + var id = await this.db.insert(tableName, json); + json['id'] = id; + return json; + } + + /// + /// 搜索 + /// @param Object condition + /// @mods [And, Or] default is Or + /// search({'name': "hanxu', 'id': 1}; + /// + Future search( + {Map conditions, String mods = 'Or'}) async { + if (conditions == null || conditions.isEmpty) { + return this.get(); + } + String stringConditions = ''; + int index = 0; + conditions.forEach((key, value) { + if (value == null) { + return; + } + + if (value.runtimeType == String) { + stringConditions = '$stringConditions $key like "%$value%"'; + } + if (value.runtimeType == int) { + stringConditions = '$stringConditions $key = "%$value%"'; + } + + if (index >= 0 && index < conditions.length - 1) { + stringConditions = '$stringConditions $mods'; + } + index++; + }); + + var myId = UserData().basicInfo.userId; + if (stringConditions.length > 0) { + stringConditions = '$stringConditions and userId = $myId'; + } + + return await this.query(tableName, where: stringConditions); + } +} diff --git a/lib/utils/sql_util.dart b/lib/utils/sql_util.dart new file mode 100644 index 0000000..5203c80 --- /dev/null +++ b/lib/utils/sql_util.dart @@ -0,0 +1,194 @@ +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/chat_data_table.dart'; +import 'package:chat/utils/conversation_table.dart'; +import 'package:chat/utils/group_chat_table.dart'; +import 'package:chat/utils/group_info_table.dart'; +import 'package:chat/utils/group_member_table.dart'; +import 'package:chat/utils/user_info_table.dart'; +import 'package:sqflite/sqflite.dart'; +import 'package:path/path.dart'; + +class SqlUtil { + static const _VERSION = 1; + + static const _DbName = "chat.db"; + + static Database _database; + + static FriendTableModel friendTableModel; //好友列表 + static ChatDataTableModel chatDataTableModel; //私聊数据 + static GroupInfoTableModel groupInfoTableModel; //群聊信息 + static GroupChatTableModel groupChatTableModel; //群聊聊天数据 + static GroupMemberTableModel groupMemberTableModel; //群聊成员数据 + static UserInfoTable userInfoTable; + + ///初始化 + static init() async { + print('初始化数据库'); + var databasesPath = await getDatabasesPath(); + + String path = join(databasesPath, _DbName); + print(path); + try { + _database = await openDatabase(path, version: _VERSION); + friendTableModel = FriendTableModel(); + chatDataTableModel = ChatDataTableModel(); + groupChatTableModel = GroupChatTableModel(); + groupInfoTableModel = GroupInfoTableModel(); + groupMemberTableModel = GroupMemberTableModel(); + + userInfoTable = UserInfoTable(); + + await friendTableModel.createTable(); + await chatDataTableModel.createTable(); + await groupChatTableModel.createTable(); + await groupInfoTableModel.createTable(); + await groupMemberTableModel.createTable(); + await userInfoTable.createTable(); + } catch (e) { + print(e); + } + } + + static Future> getFriendList() { + return friendTableModel.getAllConversation(); + } + + ///获取当前数据库对象 + static Database getCurrentDatabase() { + return _database; + } + + //查询未读消息条数 + static Future> getUnreadCount(bool isGroup) async { + if (isGroup) { + return groupChatTableModel.getUnreadCount(); + } else { + return chatDataTableModel.getUnreadCount(); + } + } + + //查询记录 + static Future>> getAllRecord( + {bool isGroup = false}) async { + if (isGroup) { + return groupChatTableModel.getAllRecord(); + } else { + return chatDataTableModel.getAllRecord(); + } + } + + //获取群的数量 + static Future getGroupCount() async { + return groupInfoTableModel.getGroupCount(); + } + + //获取所有群信息 + static Future> getAllGroupInfo() async { + return groupInfoTableModel.getGroupList(); + } + + ///插入到数据库 + static Future insert(MsgModel msgModel) async { + if (msgModel.channelType == ChatChannelType.Group.value) { + groupChatTableModel.insert(msgModel); + } else { + chatDataTableModel.insert(msgModel); + } + } + + //更新机器翻译内容 + updateMachineTranslateContent(int session, int sendTime, + List transContent, List enTransContent, int tranState, + {bool isGroup = false}) async { + if (isGroup) { + groupChatTableModel.updateMachineTranslateContent( + session, sendTime, transContent, enTransContent, tranState); + } else { + chatDataTableModel.updateMachineTranslateContent( + session, sendTime, transContent, enTransContent, tranState); + } + } + + //更新人工翻译内容 + updateUserTranslateContent( + int session, int sendTime, List transContent, int tranState) async { + chatDataTableModel.updateUserTranslateContent( + session, sendTime, transContent, tranState); + } + + //更新人工翻译评价 + updateUserTranslateRate(int session, int sendTime, int tranState) async { + chatDataTableModel.updateUserTranslateRate(session, sendTime, tranState); + } + + //更新消息发送状态 + updateMsgState(int session, int sendTime, int state, + {bool isGroup = false}) async { + if (isGroup) { + groupChatTableModel.updateMsgState(session, sendTime, state); + } else { + chatDataTableModel.updateMsgState(session, sendTime, state); + } + } + + //更新红包状态 + updateWalletState(MsgModel msgModel) async { + chatDataTableModel.updateWalletState(msgModel); + } + + //更新数据是否已被读取 + updateReadState(int session, {bool isGroup = false}) async { + if (isGroup) { + groupChatTableModel.updateReadState(session); + } else { + chatDataTableModel.updateReadState(session); + } + } + + //更新文件本地路径 + updateLocalFile(String extraData, String local, + {bool isGroup = false}) async { + if (isGroup) { + groupChatTableModel.updateLocalFile(extraData, local); + } else { + chatDataTableModel.updateLocalFile(extraData, local); + } + } + + //更新语音已读状态 + updateSoundListened(MsgModel msg) { + bool isGroup = msg.channelType == ChatChannelType.Group.value; + if (isGroup) { + groupChatTableModel.updateSoundListened(msg); + } else { + chatDataTableModel.updateSoundListened(msg); + } + } + + deleteSigleRecordWith(int session, int timeatmp, + {bool isGroup = false}) async { + if (isGroup) { + groupChatTableModel.deleteSigleRecordWith(session, timeatmp); + } else { + chatDataTableModel.deleteSigleRecordWith(session, timeatmp); + } + } + + //删除聊天数据 + delteRecord(int session, {bool isGroup = false}) async { + if (isGroup) { + groupChatTableModel.delteRecord(session); + } else { + chatDataTableModel.delteRecord(session); + } + } + + ///关闭 + static close() { + _database?.close(); + _database = null; + } +} diff --git a/lib/utils/upload_util.dart b/lib/utils/upload_util.dart new file mode 100644 index 0000000..be1beda --- /dev/null +++ b/lib/utils/upload_util.dart @@ -0,0 +1,403 @@ +import 'dart:convert'; +import 'package:chat/data/UserData.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:chat/models/ChatMsg.dart'; +import 'package:chat/models/group_info_model.dart'; +import 'package:chat/models/group_info_server_model.dart'; +import 'package:chat/proto/all.pbserver.dart'; +import 'package:chat/utils/LoadingDialog.dart'; +import 'package:chat/utils/file_cache_mgr.dart'; +import 'package:convert/convert.dart'; +import 'package:dio/dio.dart'; +import 'package:crypto/crypto.dart'; +import 'dart:async'; +import 'package:http_parser/http_parser.dart'; +import 'package:chat/utils/MessageMgr.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:chat/utils/msgHandler.dart'; +import 'package:chat/utils/sql_util.dart'; + +var signKey = 'O@MlSxWaeAlc5CYu'; + +class UploadUtil { + // 工厂模式 + factory UploadUtil() => _getInstance(); + static UploadUtil get instance => _getInstance(); + static UploadUtil _instance; + UploadUtil._internal() { + // 初始化 + } + + static UploadUtil _getInstance() { + if (_instance == null) { + _instance = new UploadUtil._internal(); + } + return _instance; + } + + Dio dio; + + //进度流 + Map> streamMap = {}; + + //缓存进度,方便快速显示 + Map streamLastPercentMap = {}; + + //上传地址 + String uploadUrl; + String rootUrl; + void setUploadUrl(url) { + rootUrl = 'http://' + url; + uploadUrl = 'http://' + url + '/chatresfile/'; + BaseOptions options = BaseOptions( + baseUrl: uploadUrl, + headers: {}, + ); + + print(uploadUrl); + dio = new Dio(options); + } + +// md5 加密 + String generateMd5(String data) { + var content = new Utf8Encoder().convert(data); + var digest = md5.convert(content); + // 这里其实就是 digest.toString() + return hex.encode(digest.bytes); + } + + String getSign(Map parameter) { + String k = ''; + var keyList = []; + for (var key in parameter.keys) { + keyList.add(key); + } + keyList.sort(); + for (var key in keyList) { + k += '$key=${parameter[key]}&'; + } + k += 'key=O@MlSxWaeAlc5CYu'; + return generateMd5(k); + } + + String getFileType(String suffix) { + if (suffix == 'png' || suffix == 'jpg' || suffix == 'jpeg') { + return 'image'; + } else if (suffix == 'wav') { + return 'audio'; + } else { + return 'video'; + } + } + + bool isImage(String suffix) { + suffix = suffix.toLowerCase(); + return suffix == 'png' || suffix == 'jpg' || suffix == 'jpeg'; + } + + StreamController getStream(String fileId) { + if (streamMap[fileId] == null) { + streamMap[fileId] = StreamController.broadcast(); + } + return streamMap[fileId]; + } + + Future uploadFile(MsgModel msg, {CancelToken cancelToken}) async { + Response response; + + var data = { + "upuserid": msg.from, + 'channeltype': msg.channelType, + "targetid": msg.sessionId, + 'fileid': msg.extraFile, + }; + + print('上传参数$data'); + var path = msg.localFile; + var name = path.substring(path.lastIndexOf("/") + 1, path.length); + String suffix = name.substring(name.lastIndexOf(".") + 1, name.length); + + var fileType = getFileType(suffix); + print('文件类型 : $fileType $suffix'); + + data['sign'] = getSign(data); + data['uploadfile'] = await MultipartFile.fromFile(path, + filename: name, contentType: MediaType(fileType, suffix)); + + FormData formData = new FormData.fromMap(data); + + try { + print('开始上传文件${msg.extraFile} url:${uploadUrl + 'uploadchatfile'}'); + + var streamController = getStream(msg.extraFile); + + response = await dio.post(uploadUrl + 'uploadchatfile', data: formData, + onSendProgress: (int progress, int total) { + streamController.sink.add(progress / total); + streamLastPercentMap[msg.extraFile] = progress / total; + }, cancelToken: cancelToken); + + streamController.close(); + streamMap.remove(msg.extraFile); + print('uploadFile response $response'); + + if (response.data['code'] == 0) { + var data = response.data['data']; + print('uploadFile 上传成功'); + msg.state = MsgState.Uploaded; + MsgHandler.sendChatMsg(msg); + MessageMgr().emit('Update LastMsg', msg.sessionId); + return data; + } else { + print('uploadFile 上传失败'); + msg.state = MsgState.UploadFailed; + MessageMgr().emit('Update LastMsg', msg.sessionId); + return null; + } + } on DioError catch (e) { + if (CancelToken.isCancel(e)) { + print('post请求取消! ' + e.message); + } + showToast('上传文件失败'); + msg.state = MsgState.UploadFailed; + print('post请求发生错误:$e'); + } + + MessageMgr().emit('Update LastMsg', msg.sessionId); + return null; + } + + void cancelRequests(CancelToken cancelToken) { + print('取消请求$cancelToken'); + cancelToken.cancel("cancelled"); + } + + String getFullUrl(String imgData, int sessionid, int channelType) { + var data = { + "fileid": imgData, + 'targetid': sessionid, + "userid": UserData().basicInfo.userId, + 'channeltype': channelType + }; + + var sign = getSign(data); + + return uploadUrl + + 'downloadchatfile?targetid=$sessionid&channeltype=$channelType&userid=${UserData().basicInfo.userId}&fileid=$imgData&sign=$sign'; + } + + Future downloadFile(MsgModel msg, {CancelToken cancelToken}) async { + Response response; + + var fullUrl = getFullUrl(msg.extraFile, msg.sessionId, msg.channelType); + + print('下载文件$fullUrl'); + + var path = await FileCacheMgr().genFilePath(msg.extraFile); + if (msg.msgType == ChatType.ShortVoiceChatType.value) { + path = path + '.wav'; + } else if (msg.msgType == ChatType.FileChatType.value) { + var fileMsg = FileChat.fromBuffer(msg.msgContent); + var fileName = fileMsg.name; + path = await FileCacheMgr().genFilePath(fileName); + } + + print('文件保存路径$path'); + + try { + var streamController = getStream(msg.extraFile); + + response = await dio.download(fullUrl, path, + onReceiveProgress: (int progress, int total) { + streamController.sink.add(progress / total); + streamLastPercentMap[msg.extraFile] = progress / total; + }, cancelToken: cancelToken); + + streamController.close(); + streamMap.remove(msg.extraFile); + if (response.statusCode == 200) { + msg.state = MsgState.DownloadSuccess; + msg.localFile = path; + SqlUtil().updateLocalFile(msg.extraFile, path, + isGroup: msg.channelType == ChatChannelType.Group.value); + + return path; + } else { + msg.state = MsgState.DownloadFailed; + showToast(I18n.of(LoadingManage.context).server_error_tips); + return null; + } + } catch (e) { + msg.state = MsgState.DownloadFailed; + showToast(I18n.of(LoadingManage.context).server_error_tips); + print(response.toString()); + } + } + + //机器人翻译,type 1文字,2语音 + Future commitTranslateSource( + int type, int sourceLang, int toLang, dynamic content) async { + Response response; + + var myId = UserData().basicInfo.userId; + + Map data = { + 'userid': myId, + 'cType': type, + 'ulanguage': sourceLang, + 'tlanguage': toLang + }; + + data['sign'] = getSign(data); + data['content'] = content; + + if (type == 2) { + data['content'] = await MultipartFile.fromFile(content); + } + + FormData formData = new FormData.fromMap(data); + + try { + print('开始请求翻译$data ${uploadUrl + 'translate/transqt'}'); + response = await dio.post(rootUrl + '/translate/transqt', data: formData); + Map resData = response.data; + print('翻译结果$resData'); + if (resData['code'] == 0) { + return resData['data']; + } + } catch (e) { + print(e); + } + + return null; + } + + //获取群列表 + Future> getGroupList() async { + Response response; + + var myId = UserData().basicInfo.userId; + + Map data = { + 'userid': myId, + }; + data['sign'] = getSign(data); + + try { + print('开始请求群列表$data}'); + response = await dio.post(rootUrl + '/chat/queryusergroups', data: data); + Map resData = response.data; + + if (resData['code'] == 0) { + List resList = resData['data']; + List groupList = []; + for (var i = 0; i < resList.length; i++) { + var info = GroupInfoServerModel.fromJson(resList[i]); + + groupList.add(GroupInfoModel.fromServerGroupInfo(info)); + } + + return groupList; + } + } catch (e) { + print(e); + } + + return null; + } + + //获取多个群信息 + Future> getMoreGroupInfo(List groupIds) async { + Response response; + + var myId = UserData().basicInfo.userId; + + Map data = { + 'userid': myId, + }; + data['sign'] = getSign(data); + data['groupids'] = groupIds; + + try { + print('开始请求 getMoreGroupInfo $data'); + response = await dio.post(rootUrl + '/chat/querygroups', data: data); + Map resData = response.data; + + if (resData['code'] == 0) { + List data = resData['data']; + print('群信息$data'); + if (data != null && data.length > 0) { + List res = []; + for (var each in data) { + var info = GroupInfoServerModel.fromJson(each); + res.add(GroupInfoModel.fromServerGroupInfo(info)); + } + return res; + } + } + } catch (e) { + print(e); + } + + return null; + } + + //获取群信息 + Future getGroupInfo(int groupId) async { + Response response; + + var myId = UserData().basicInfo.userId; + + Map data = { + 'userid': myId, + }; + data['sign'] = getSign(data); + data['groupids'] = [groupId]; + + try { + print('开始请求群信息$data'); + response = await dio.post(rootUrl + '/chat/querygroups', data: data); + Map resData = response.data; + + if (resData['code'] == 0) { + List data = resData['data']; + print('群信息$data'); + if (data != null && data.length > 0) { + var info = GroupInfoServerModel.fromJson(data.first); + return GroupInfoModel.fromServerGroupInfo(info); + } + } + } catch (e) { + print(e); + } + + return null; + } + + //获取群校验信息 + Future getGroupCheckInfo() async { + Response response; + + var myId = UserData().basicInfo.userId; + + Map data = { + 'userid': myId, + }; + data['sign'] = getSign(data); + + try { + print('请求获取群校验信息$data'); + response = await dio.post(rootUrl + '/chat/checkgroup', data: data); + Map resData = response.data; + + if (resData['code'] == 0) { + print('群校验信息${resData['data']}'); + return resData['data']; + } + } catch (e) { + print(e); + } + + return null; + } +} diff --git a/lib/utils/user_info_table.dart b/lib/utils/user_info_table.dart new file mode 100644 index 0000000..0e443b0 --- /dev/null +++ b/lib/utils/user_info_table.dart @@ -0,0 +1,109 @@ +import 'package:chat/models/UserInfo.dart'; +import 'package:chat/utils/sql_model.dart'; +import 'package:sqflite/sqflite.dart'; + +class UserInfoTable { + final String table = 'user_info'; + Sql sql; + + UserInfoTable() { + sql = Sql.setTable(table); + } + + createTable() async { + print('创建表$table'); + await sql.createTable(table, '''userId INTEGER PRIMARY KEY, + headimgurl TEXT, + nickName TEXT, + meetPlace TEXT, + birthday TEXT, + occupation TEXT, + program TEXT, + hopeObject TEXT, + height INTEGER, + weight INTEGER, + ownMsg TEXT, + isAttestation INTEGER, + isVipAttestation INTEGER, + invisibleStatus INTEGER, + distanceStatus INTEGER, + accountStatus INTEGER, + chatStatus INTEGER, + photoAut INTEGER, + infoAut INTEGER, + loginDate TEXT, + onlineStatus INTEGER, + sex INTEGER, + applyStatus INTEGER, + payStatus INTEGER, + city TEXT, + country TEXT, + constellation INTEGER, + price INTEGER, + burnNum INTEGER, + accessNum INTEGER, + distince INTEGER, + wechat TEXT, + facebook TEXT, + isMember INTEGER, + isAuthority INTEGER, + freeNum INTEGER, + usedNum INTEGER, + publishNum INTEGER, + usedPublishNum INTEGER, + isBlackList INTEGER, + isLike INTEGER, + followNum INTEGER, + fans INTEGER, + dynamicNum INTEGER, + isCanStrangerNews INTEGER, + isBlackened INTEGER, + isAddFriends INTEGER'''); + } + + Future clear() { + return sql.clearTable(table); + } + + //插入新用户 + Future insertUser(UserInfo userInfo) async { + var res = await sql.db.rawQuery( + 'select count(*) as count from $table where userId=${userInfo.userId}'); + var count = Sqflite.firstIntValue(res); + print('用户是否存在$count'); + + if (count == null || count == 0) { + var res = await sql.insert(userInfo.toDbJson()); + + print('插入用户结果$res'); + return res; + } else { + return updateUser(userInfo); + } + } + + //删除用户信息 + deleteUser(int userId) async { + var res = + await sql.db.delete(table, where: 'userId=?', whereArgs: [userId]); + print('删除用户结果$res'); + return res; + } + + //更新用户信息 + updateUser(UserInfo userInfo) async { + var res = await sql.db.update(table, userInfo.toDbJson(), + where: 'userId=?', whereArgs: [userInfo.userId]); + print('更新用户信息$res'); + return res; + } + + //从本地获取用户信息,仅限聊天 + Future getUserInfoFromLocal(int userId) async { + List list = await sql.query(table, where: 'userId=?', whereArgs: [userId]); + if (list != null && list.length > 0) { + return UserInfo.fromLocalDB(list.first); + } + return null; + } +} diff --git a/lib/utils/uuid.dart b/lib/utils/uuid.dart new file mode 100644 index 0000000..5d11f44 --- /dev/null +++ b/lib/utils/uuid.dart @@ -0,0 +1,38 @@ +/// A UUID generator library. +library uuid; + +import 'dart:math' show Random; + +/// A UUID generator. +/// +/// This will generate unique IDs in the format: +/// +/// f47ac10b-58cc-4372-a567-0e02b2c3d479 +/// +/// The generated uuids are 128 bit numbers encoded in a specific string format. +/// For more information, see +/// [en.wikipedia.org/wiki/Universally_unique_identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier). +class Uuid { + final Random _random = new Random(); + + /// Generate a version 4 (random) uuid. This is a uuid scheme that only uses + /// random numbers as the source of the generated uuid. + String generateV4() { + // Generate xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx / 8-4-4-4-12. + int special = 8 + _random.nextInt(4); + + return '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}-' + '${_bitsDigits(16, 4)}-' + '4${_bitsDigits(12, 3)}-' + '${_printDigits(special, 1)}${_bitsDigits(12, 3)}-' + '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}'; + } + + String _bitsDigits(int bitCount, int digitCount) => + _printDigits(_generateBits(bitCount), digitCount); + + int _generateBits(int bitCount) => _random.nextInt(1 << bitCount); + + String _printDigits(int value, int count) => + value.toRadixString(16).padLeft(count, '0'); +} \ No newline at end of file diff --git a/lib/utils/version_update_utils.dart b/lib/utils/version_update_utils.dart new file mode 100644 index 0000000..12c4e8f --- /dev/null +++ b/lib/utils/version_update_utils.dart @@ -0,0 +1,117 @@ +import 'dart:io'; + +import 'package:app_installer/app_installer.dart'; +import 'package:chat/data/constants.dart'; +import 'package:chat/generated/i18n.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'CustomUI.dart'; +import 'HttpUtil.dart'; + +class VersionUtils { + static bool hasShowUpdate=false; + static void versionUpdate(BuildContext context,{bool fromProfileNeedShow=false}) async { + if(hasShowUpdate && !fromProfileNeedShow){ + return; + } + hasShowUpdate=true; + + + Directory tempDir ; + if(Platform.isAndroid){ + tempDir = await getExternalStorageDirectory(); + } + final ValueNotifier updateProgress = ValueNotifier('-1'); + + HttpUtil().appVersionUpdate((bool needNotice, bool forceUpdate, + String versionName, String describe, String downloadUrl,String appId) { + + + + List online = versionName.split('.'); + List current = Constants.versionName.split('.'); + bool isSandbox =false; + bool needUpdate = false; + if(int.parse(current[0]) > int.parse(online[0])){ + isSandbox=true; + } + + if(int.parse(current[0]) == int.parse(online[0]) && int.parse(current[1]) > int.parse(online[1])){ + isSandbox=true; + } + + if(int.parse(current[0]) == int.parse(online[0]) && int.parse(current[1]) == int.parse(online[1]) && int.parse(current[2]) > int.parse(online[2])){ + isSandbox=true; + } + + if(int.parse(online[0]) > int.parse(current[0])){ + needUpdate=true; + } + + if(int.parse(current[0]) == int.parse(online[0]) && int.parse(online[1]) > int.parse(current[1])){ + needUpdate=true; + } + + if(int.parse(current[0]) == int.parse(online[0]) && int.parse(current[1]) == int.parse(online[1]) && int.parse(online[2]) > int.parse(current[2])){ + needUpdate=true; + } + + + print('isSandbox $isSandbox'); + Constants.isSandbox = isSandbox; + + +// needUpdate=true;///test +// needNotice=true;///test + + + String filePath ; + if(Platform.isAndroid){ + filePath = '${tempDir.path}/$versionName.apk'; + } + print( + '当前版本号:${Constants.versionName} --新包版本号 $versionName needNotice:$needNotice forceUpdate"$forceUpdate describe:$describe'); + if (needUpdate) { + if (needNotice) { + ///需要弹窗提示更新 + CustomUI.buildVersionUpdate( + context, versionName, forceUpdate, describe, updateProgress, () { + if (Constants.isStoreVersion) { + String androidAppId = Constants.packageName; + String iOSAppId = appId; + AppInstaller.goStore(androidAppId, iOSAppId); + } else { + if (Platform.isAndroid) { + HttpUtil().downloadApk(context, filePath, downloadUrl, + (int count, int total) { + ///下载进度更新 + double percent = (count / total) * 100; + print('count:$count total:$total percent:$percent'); + updateProgress.value = percent.toStringAsFixed(0); + if (count == total) { + ///下载完成-安装 + AppInstaller.installApk(filePath); + Future.delayed(Duration(seconds: 3), () { + updateProgress.value = '-1'; + + ///重置状态 + }); + } + }); + } else { + launch(downloadUrl); + } + } + }); + } + } else { + if(fromProfileNeedShow){ + showToast(I18n.of(context).already_new); + } + + } + }); + } +} diff --git a/lib/utils/video_anim.dart b/lib/utils/video_anim.dart new file mode 100644 index 0000000..1e1ad25 --- /dev/null +++ b/lib/utils/video_anim.dart @@ -0,0 +1,59 @@ +import 'package:chat/utils/CustomUI.dart'; +import 'package:flutter/material.dart'; + +class VideoAnim extends StatefulWidget { + final double begin; + final int maxTime; + final double end; + final double start; + VideoAnim({ + this.begin, + this.maxTime = 550, + this.end, + this.start = 0, + }); + + @override + _VideoAnimState createState() => _VideoAnimState(); +} + +class _VideoAnimState extends State + with SingleTickerProviderStateMixin { + Animation _animation; + AnimationController _controller; + + @override + void initState() { + super.initState(); + // 启动动画controller + _controller = new AnimationController( + duration: Duration(milliseconds: widget.maxTime), vsync: this); + _controller.addStatusListener((AnimationStatus status) { + if (status == AnimationStatus.completed) { + _controller.reverse(); + } else if (status == AnimationStatus.dismissed) { + _controller.forward(); + } + }); + + _animation = new Tween(begin: widget.begin, end: widget.end) + .animate(_controller) + ..addListener(() { + setState(() {}); + }); + + _controller.forward(from: widget.start); + } + + @override + void dispose() { + _controller.stop(); + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return CustomUI.buildAudioContaniner(_animation.value); + } +} diff --git a/lib/utils/wpop/triangle_painter.dart b/lib/utils/wpop/triangle_painter.dart new file mode 100644 index 0000000..59c3f43 --- /dev/null +++ b/lib/utils/wpop/triangle_painter.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; + +const double _kMenuScreenPadding = 8.0; + +class TrianglePainter extends CustomPainter { + Paint _paint; + final Color color; + final RelativeRect position; + final Size size; + final double radius; + final bool isInverted; + final double screenWidth; + + TrianglePainter( + {@required this.color, + @required this.position, + @required this.size, + this.radius = 20, + this.isInverted = false, + this.screenWidth}) { + _paint = Paint() + ..style = PaintingStyle.fill + ..color = color + ..strokeWidth = 10 + ..isAntiAlias = true; + } + + @override + void paint(Canvas canvas, Size size) { + var path = Path(); + + // 如果 menu 的长度 大于 child 的长度 + if (size.width > this.size.width) { + // 靠右 + if (position.left + this.size.width / 2 > position.right) { + if (screenWidth - (position.left + this.size.width) > size.width / 2 + _kMenuScreenPadding) { + path.moveTo(size.width / 2, isInverted ? 0 : size.height); + path.lineTo(size.width / 2 - radius / 2, isInverted ? size.height : 0); + path.lineTo(size.width / 2 + radius / 2, isInverted ? size.height : 0); + }else { + path.moveTo(size.width - this.size.width + this.size.width / 2, + isInverted ? 0 : size.height); + path.lineTo( + size.width - this.size.width + this.size.width / 2 - radius / 2, + isInverted ? size.height : 0); + path.lineTo( + size.width - this.size.width + this.size.width / 2 + radius / 2, + isInverted ? size.height : 0); + } + }else{ + // 靠左 + if(position.left > size.width / 2 + _kMenuScreenPadding){ + path.moveTo(size.width / 2, isInverted ? 0 : size.height); + path.lineTo(size.width / 2 - radius / 2, isInverted ? size.height : 0); + path.lineTo(size.width / 2 + radius / 2, isInverted ? size.height : 0); + }else { + path.moveTo(this.size.width / 2, isInverted ? 0 : size.height); + path.lineTo( + this.size.width / 2 - radius / 2, isInverted ? size.height : 0); + path.lineTo( + this.size.width / 2 + radius / 2, isInverted ? size.height : 0); + } + } + } else { + path.moveTo(size.width / 2, isInverted ? 0 : size.height); + path.lineTo( + size.width / 2 - radius / 2, isInverted ? size.height : 0); + path.lineTo( + size.width / 2 + radius / 2, isInverted ? size.height : 0); + } + + path.close(); + + canvas.drawPath( + path, + _paint, + ); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return true; + } +} diff --git a/lib/utils/wpop/w_popup_menu.dart b/lib/utils/wpop/w_popup_menu.dart new file mode 100644 index 0000000..62b67eb --- /dev/null +++ b/lib/utils/wpop/w_popup_menu.dart @@ -0,0 +1,545 @@ +import 'package:flutter/material.dart'; +import 'triangle_painter.dart'; + +const double _kMenuScreenPadding = 8.0; + +class WPopupMenu extends StatefulWidget { + WPopupMenu({ + Key key, + @required this.onValueChanged, + @required this.actions, + @required this.child, + this.pressType = PressType.longPress, + this.pageMaxChildCount = 3, + this.backgroundColor = Colors.black, + this.menuWidth = 250, + this.menuHeight = 38, + this.onLongPressStart, + this.onLongPressEnd, + }); + + final ValueChanged onValueChanged; + final List actions; + final Widget child; + final PressType pressType; // 点击方式 长按 还是单击 + final int pageMaxChildCount; + final Color backgroundColor; + final double menuWidth; + final double menuHeight; + final Function onLongPressStart; + final Function onLongPressEnd; + + @override + _WPopupMenuState createState() => _WPopupMenuState(); +} + +class _WPopupMenuState extends State { + double width; + double height; + RenderBox button; + RenderBox overlay; + OverlayEntry entry; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((call) { + if(context!=null && context.size!=null){ + width = context.size.width; + height = context.size.height; + button = context.findRenderObject(); + overlay = Overlay.of(context).context.findRenderObject(); + } + + + }); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + child: widget.child, + onTap: () { + if (widget.pressType == PressType.singleClick) { + onTap(); + } + }, + onLongPress: () { + if (widget.pressType == PressType.longPress) { + onTap(); + } + }, + onLongPressStart: (LongPressStartDetails details) { + print('onLongPressStart'); + if(widget.onLongPressStart!=null) + widget.onLongPressStart(); + }, + onLongPressEnd: (LongPressEndDetails detail) { + print('onLongPressEnd'); + if(widget.onLongPressEnd!=null) + widget.onLongPressEnd(); + }); + } + + void onTap() { + Widget menuWidget = _MenuPopWidget( + context, + height, + width, + widget.actions, + widget.pageMaxChildCount, + widget.backgroundColor, + widget.menuWidth, + widget.menuHeight, + button, + overlay, + (index) { + if (index != -1) widget.onValueChanged(index); + removeOverlay(); + }, + ); + + entry = OverlayEntry(builder: (context) { + return menuWidget; + }); + Overlay.of(context).insert(entry); + } + + void removeOverlay() { + entry.remove(); + entry = null; + } +} + +enum PressType { + // 长按 + longPress, + // 单击 + singleClick, +} + +class _MenuPopWidget extends StatefulWidget { + final BuildContext btnContext; + final List actions; + final int _pageMaxChildCount; + final Color backgroundColor; + final double menuWidth; + final double menuHeight; + final double _height; + final double _width; + final RenderBox button; + final RenderBox overlay; + final ValueChanged onValueChanged; + + _MenuPopWidget( + this.btnContext, + this._height, + this._width, + this.actions, + this._pageMaxChildCount, + this.backgroundColor, + this.menuWidth, + this.menuHeight, + this.button, + this.overlay, + this.onValueChanged, + ); + + @override + _MenuPopWidgetState createState() => _MenuPopWidgetState(); +} + +class _MenuPopWidgetState extends State<_MenuPopWidget> { + int _curPage = 0; + final double _arrowWidth = 40; + final double _separatorWidth = 1; + final double _triangleHeight = 10; + + RelativeRect position; + + @override + void initState() { + super.initState(); + position = RelativeRect.fromRect( + Rect.fromPoints( + widget.button.localToGlobal(Offset.zero, ancestor: widget.overlay), + widget.button.localToGlobal(Offset.zero, ancestor: widget.overlay), + ), + Offset.zero & widget.overlay.size, + ); + } + + @override + Widget build(BuildContext context) { + // 这里计算出来 当前页的 child 一共有多少个 + int _curPageChildCount = + (_curPage + 1) * widget._pageMaxChildCount > widget.actions.length + ? widget.actions.length % widget._pageMaxChildCount + : widget._pageMaxChildCount; + + double _curArrowWidth = 0; + int _curArrowCount = 0; // 一共几个箭头 + + if (widget.actions.length > widget._pageMaxChildCount) { + // 数据长度大于 widget._pageMaxChildCount + if (_curPage == 0) { + // 如果是第一页 + _curArrowWidth = _arrowWidth; + _curArrowCount = 1; + } else { + // 如果不是第一页 则需要也显示左箭头 + _curArrowWidth = _arrowWidth * 2; + _curArrowCount = 2; + } + } + + double _curPageWidth = widget.menuWidth + + (_curPageChildCount - 1 + _curArrowCount) * _separatorWidth + + _curArrowWidth; + + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + widget.onValueChanged(-1); + }, + child: MediaQuery.removePadding( + context: context, + removeTop: true, + removeBottom: true, + removeLeft: true, + removeRight: true, + child: Builder( + builder: (BuildContext context) { + var isInverted = (position.top + + (MediaQuery.of(context).size.height - + position.top - + position.bottom) / + 2.0 - + (widget.menuHeight + _triangleHeight)) < + (widget.menuHeight + _triangleHeight) * 2; + return CustomSingleChildLayout( + // 这里计算偏移量 + delegate: _PopupMenuRouteLayout( + position, + widget.menuHeight + _triangleHeight, + Directionality.of(widget.btnContext), + widget._width, + widget.menuWidth, + widget._height), + child: SizedBox( + height: widget.menuHeight + _triangleHeight, + width: _curPageWidth, + child: Material( + color: Colors.transparent, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + isInverted + ? CustomPaint( + size: Size(_curPageWidth, _triangleHeight), + painter: TrianglePainter( + color: widget.backgroundColor, + position: position, + isInverted: true, + size: widget.button.size, + screenWidth: MediaQuery.of(context).size.width, + ), + ) + : Container(), + Expanded( + child: Stack( + children: [ + ClipRRect( + borderRadius: + BorderRadius.all(Radius.circular(5)), + child: Container( + color: widget.backgroundColor, + height: widget.menuHeight, + ), + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + // 左箭头:判断是否是第一页,如果是第一页则不显示 + _curPage == 0 + ? Container( + height: widget.menuHeight, + ) + : InkWell( + onTap: () { + setState(() { + _curPage--; + }); + }, + child: Container( + alignment: Alignment.centerRight, + width: _arrowWidth + 3, + height: widget.menuHeight - 10, + child: Image.asset( + 'assets/images/left_white.png', + fit: BoxFit.none, + ), + ), + ), + // 左箭头:判断是否是第一页,如果是第一页则不显示 + _curPage == 0 + ? Container( + height: widget.menuHeight, + ) + : Container( + width: 1, + height: widget.menuHeight, + color: Colors.grey, + ), + + // 中间是ListView + _buildList(_curPageChildCount, _curPageWidth, + _curArrowWidth, _curArrowCount), + + // 右箭头:判断是否有箭头,如果有就显示,没有就不显示 + _curArrowCount > 0 + ? Container( + width: 1, + color: Colors.grey, + height: widget.menuHeight, + ) + : Container( + height: widget.menuHeight, + ), + _curArrowCount > 0 + ? InkWell( + onTap: () { + if ((_curPage + 1) * + widget._pageMaxChildCount < + widget.actions.length) + setState(() { + _curPage++; + }); + }, + child: Container( + width: _arrowWidth, + height: widget.menuHeight, + child: Image.asset( + (_curPage + 1) * + widget + ._pageMaxChildCount >= + widget.actions.length + ? 'assets/images/right_gray.png' + : 'assets/images/right_white.png', + fit: BoxFit.none, + ), + ), + ) + : Container( + height: widget.menuHeight, + ), + ], + ), + ], + ), + ), + isInverted + ? Container() + : CustomPaint( + size: Size(_curPageWidth, _triangleHeight), + painter: TrianglePainter( + color: widget.backgroundColor, + position: position, + size: widget.button.size, + screenWidth: MediaQuery.of(context).size.width, + ), + ), + ], + ), + ), + ), + ); + }, + ), + ), + ); + } + + Widget _buildList(int _curPageChildCount, double _curPageWidth, + double _curArrowWidth, int _curArrowCount) { + List list = []; + + int totalTxtLength = 0; + double minPadding = 12; + double width = widget.menuWidth - _curPageChildCount * minPadding; + + for (int k = 0; k < _curPageChildCount; k++) { + totalTxtLength = totalTxtLength + + widget.actions[_curPage * widget._pageMaxChildCount + k].length; + } + + for (int k = 0; k < _curPageChildCount; k++) { + String text = widget.actions[_curPage * widget._pageMaxChildCount + k]; + + list.add(InkWell( + onTap: () { + widget.onValueChanged(_curPage * widget._pageMaxChildCount + k); + }, + child: SizedBox( +// width: (_curPageWidth - +// _curArrowWidth - +// (_curPageChildCount - 1 + _curArrowCount) * +// _separatorWidth) / +// _curPageChildCount, + width: (text.length / (totalTxtLength) * (width)) + minPadding, + height: widget.menuHeight, + child: Center( + child: Text( + text, + maxLines: 1, + textScaleFactor: 1.0, + style: TextStyle(color: Colors.white, fontSize: 13), + ), + ), + ), + )); + + if (k != _curPageChildCount - 1) { + list.add(Container( + width: 1, + height: widget.menuHeight, + color: Colors.grey.withAlpha(70), + )); + } + } + + return Wrap( + children: list, + ); + +// return ListView.separated( +// shrinkWrap: true, +// physics: NeverScrollableScrollPhysics(), +// scrollDirection: Axis.horizontal, +// itemCount: _curPageChildCount, +// itemBuilder: (BuildContext context, int index) { +// return GestureDetector( +// onTap: () { +// widget.onValueChanged(_curPage * widget._pageMaxChildCount + index); +// +// }, +// child: SizedBox( +// width: (_curPageWidth - +// _curArrowWidth - +// (_curPageChildCount - 1 + _curArrowCount) * +// _separatorWidth) / +// _curPageChildCount, +// height: widget.menuHeight, +// child: Center( +// child: Text( +// +// widget.actions[_curPage * widget._pageMaxChildCount + index], +// maxLines: 1, +// style: TextStyle(color: Colors.white, fontSize: 16), +// ), +// ), +// ), +// ); +// }, +// separatorBuilder: (BuildContext context, int index) { +// return Container( +// width: 1, +// height: widget.menuHeight, +// color: Colors.grey, +// ); +// }, +// ); + } +} + +// Positioning of the menu on the screen. +class _PopupMenuRouteLayout extends SingleChildLayoutDelegate { + _PopupMenuRouteLayout(this.position, this.selectedItemOffset, + this.textDirection, this.width, this.menuWidth, this.height); + + // Rectangle of underlying button, relative to the overlay's dimensions. + final RelativeRect position; + + // The distance from the top of the menu to the middle of selected item. + // + // This will be null if there's no item to position in this way. + final double selectedItemOffset; + + // Whether to prefer going to the left or to the right. + final TextDirection textDirection; + + final double width; + final double height; + final double menuWidth; + + // We put the child wherever position specifies, so long as it will fit within + // the specified parent size padded (inset) by 8. If necessary, we adjust the + // child's position so that it fits. + + @override + BoxConstraints getConstraintsForChild(BoxConstraints constraints) { + // The menu can be at most the size of the overlay minus 8.0 pixels in each + // direction. + return BoxConstraints.loose(constraints.biggest - + const Offset(_kMenuScreenPadding * 2.0, _kMenuScreenPadding * 2.0)); + } + + @override + Offset getPositionForChild(Size size, Size childSize) { + // size: The size of the overlay. + // childSize: The size of the menu, when fully open, as determined by + // getConstraintsForChild. + + // Find the ideal vertical position. + double y; + if (selectedItemOffset == null) { + y = position.top; + } else { + y = position.top + + (size.height - position.top - position.bottom) / 2.0 - + selectedItemOffset; + } + + // Find the ideal horizontal position. + double x; + + // 如果menu 的宽度 小于 child 的宽度,则直接把menu 放在 child 中间 + if (childSize.width < width) { + x = position.left + (width - childSize.width) / 2; + } else { + // 如果靠右 + if (position.left > size.width - (position.left + width)) { + if (size.width - (position.left + width) > + childSize.width / 2 + _kMenuScreenPadding) { + x = position.left - (childSize.width - width) / 2; + } else { + print('${position.left + width} --- ${size.width} -- $childSize'); + x = position.left + width - childSize.width; + } + } else if (position.left < size.width - (position.left + width)) { + if (position.left > childSize.width / 2 + _kMenuScreenPadding) { + x = position.left - (childSize.width - width) / 2; + } else + x = position.left; + } else { + x = position.right - width / 2 - childSize.width / 2; + } + } + + if (y < _kMenuScreenPadding) + y = _kMenuScreenPadding; + else if (y + childSize.height > size.height - _kMenuScreenPadding) + y = size.height - childSize.height; + else if (y < childSize.height * 2) { + y = position.top + height; + } +// print(Offset(x, y)); +// print('${size} --- ${childSize}'); + return Offset(x, y); + } + + @override + bool shouldRelayout(_PopupMenuRouteLayout oldDelegate) { + return position != oldDelegate.position; + } +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..db16726 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,1150 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + agora_rtc_engine: + dependency: "direct main" + description: + name: agora_rtc_engine + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.6" + amap_location: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: "252b86e8c4ee6c5613926d05dd4633adb545b3f4" + url: "https://github.com/randomjoho/flutter_amap_location.git" + source: git + version: "0.2.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.36.4" + analyzer_plugin: + dependency: transitive + description: + name: analyzer_plugin + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.1" + android_intent: + dependency: "direct main" + description: + name: android_intent + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.4+7" + app_installer: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: d6db356b38a5648e13aa5b2b31a99c024569daf2 + url: "https://github.com/randomjoho/app_installer.git" + source: git + version: "0.1.0" + apple_sign_in: + dependency: "direct main" + description: + name: apple_sign_in + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.0" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.11" + args: + dependency: transitive + description: + name: args + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.5.2" + async: + dependency: transitive + description: + name: async + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.4.0" + audioplayer: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: a5158bdf4d39186bca8407575fcee06f3a720a95 + url: "https://github.com/randomjoho/audioplayer.git" + source: git + version: "0.5.2" + auto_orientation: + dependency: "direct main" + description: + name: auto_orientation + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.5" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.5" + buffer: + dependency: "direct main" + description: + name: buffer + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.6" + build: + dependency: transitive + description: + name: build + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.6" + build_config: + dependency: transitive + description: + name: build_config + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.4.1+1" + build_daemon: + dependency: transitive + description: + name: build_daemon + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.0" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.1" + build_runner: + dependency: transitive + description: + name: build_runner + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.6.9" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.1" + built_collection: + dependency: transitive + description: + name: built_collection + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.2.2" + built_value: + dependency: transitive + description: + name: built_value + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.8.2" + built_value_generator: + dependency: transitive + description: + name: built_value_generator + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.8.2" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.2" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.2" + city_pickers: + dependency: "direct main" + description: + name: city_pickers + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.29" + code_builder: + dependency: transitive + description: + name: code_builder + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.2.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.14.11" + connectivity: + dependency: "direct main" + description: + name: connectivity + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.4.6" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.1" + crclib: + dependency: "direct main" + description: + name: crclib + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.3" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.16.1" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.3" + dart_style: + dependency: transitive + description: + name: dart_style + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.9" + dio: + dependency: "direct main" + description: + name: dio + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.7" + easy_contact_picker: + dependency: "direct main" + description: + name: easy_contact_picker + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.2" + extended_image: + dependency: "direct main" + description: + name: extended_image + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.7.1" + extended_image_library: + dependency: "direct main" + description: + name: extended_image_library + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.0" + extended_nested_scroll_view: + dependency: "direct main" + description: + name: extended_nested_scroll_view + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.8" + extended_text: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: "8af13caac5385108659b2e0871c28acb335d773c" + url: "https://github.com/randomjoho/extended_text.git" + source: git + version: "0.7.1" + extended_text_field: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: "4431cbb6e2731dc7267ed11285ef741555026900" + url: "https://github.com/randomjoho/extended_text_field.git" + source: git + version: "0.4.9" + extended_text_library: + dependency: transitive + description: + path: "." + ref: HEAD + resolved-ref: b20fa702d9c398d44131fd0704b78239d56052ce + url: "https://github.com/randomjoho/extended_text_library.git" + source: git + version: "0.5.3" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.3" + file: + dependency: transitive + description: + name: file + url: "https://pub.flutter-io.cn" + source: hosted + version: "5.1.0" + file_picker: + dependency: "direct main" + description: + name: file_picker + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.3+2" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.10.11" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_app_badger: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: a81628c28e52fb441c5bd9190ec99891f3da36d6 + url: "https://github.com/randomjoho/flutter_app_badger.git" + source: git + version: "1.1.1" + flutter_audio_recorder: + dependency: "direct main" + description: + name: flutter_audio_recorder + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.5.5" + flutter_bugly: + dependency: "direct main" + description: + name: flutter_bugly + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.8" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.3" + flutter_datetime_picker: + dependency: "direct main" + description: + name: flutter_datetime_picker + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.1" + flutter_facebook_login: + dependency: "direct main" + description: + name: flutter_facebook_login + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.0" + flutter_ijkplayer: + dependency: "direct main" + description: + name: flutter_ijkplayer + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.5+1" + flutter_image_compress: + dependency: "direct main" + description: + name: flutter_image_compress + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.6.3" + flutter_inapp_purchase: + dependency: "direct main" + description: + name: flutter_inapp_purchase + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.6" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.8.4+3" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_page_indicator: + dependency: transitive + description: + name: flutter_page_indicator + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.3" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.6" + flutter_qr_reader: + dependency: "direct main" + description: + name: flutter_qr_reader + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.3" + flutter_screenutil: + dependency: "direct main" + description: + name: flutter_screenutil + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.5.3" + flutter_swiper: + dependency: "direct main" + description: + name: flutter_swiper + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.6" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_webview_plugin: + dependency: "direct main" + description: + name: flutter_webview_plugin + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.10" + fluwx_no_pay: + dependency: "direct main" + description: + name: fluwx_no_pay + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.0" + front_end: + dependency: transitive + description: + name: front_end + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.19" + geolocator: + dependency: "direct main" + description: + name: geolocator + url: "https://pub.flutter-io.cn" + source: hosted + version: "5.1.5" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" + google_api_availability: + dependency: transitive + description: + name: google_api_availability + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.1" + google_maps_flutter: + dependency: "direct main" + description: + name: google_maps_flutter + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.5.21+11" + graphs: + dependency: transitive + description: + name: graphs + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.0" + html: + dependency: transitive + description: + name: html + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.14.0+3" + http: + dependency: transitive + description: + name: http + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.12.0+2" + http_client_helper: + dependency: transitive + description: + name: http_client_helper + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.1" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.0" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.3" + image: + dependency: transitive + description: + name: image + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.4" + image_cropper: + dependency: "direct main" + description: + name: image_cropper + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.2" + image_gallery_saver: + dependency: "direct main" + description: + name: image_gallery_saver + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.6.3+4" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.16.0" + io: + dependency: transitive + description: + name: io + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.3" + jpush_flutter: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: "025640a3ce0a849cde6dd29c4348d884c4e0f876" + url: "https://github.com/randomjoho/jpush-flutter-plugin.git" + source: git + version: "0.5.2" + js: + dependency: transitive + description: + name: js + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.6.1+1" + json_annotation: + dependency: "direct main" + description: + name: json_annotation + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.3.0" + json_model: + dependency: "direct dev" + description: + name: json_model + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.2" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.3.0" + kernel: + dependency: transitive + description: + name: kernel + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.19" + keyboard_utils: + dependency: "direct main" + description: + name: keyboard_utils + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.0" + location: + dependency: "direct main" + description: + name: location + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.3.5" + location_permissions: + dependency: "direct main" + description: + name: location_permissions + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.3" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.11.3+2" + lpinyin: + dependency: "direct main" + description: + name: lpinyin + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.7" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.12.6" + menu: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: "9dfd99810f16db4e3458ae0e18eec3be7df0553f" + url: "https://github.com/randomjoho/flutter_long_tap_menu.git" + source: git + version: "0.1.4" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.8" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.6+3" + node_interop: + dependency: transitive + description: + name: node_interop + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.3" + node_io: + dependency: transitive + description: + name: node_io + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1+2" + oktoast: + dependency: "direct main" + description: + name: oktoast + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.2.1" + open_file: + dependency: "direct main" + description: + name: open_file + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.1" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.0" + package_info: + dependency: "direct main" + description: + name: package_info + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.4.0+12" + package_resolver: + dependency: transitive + description: + name: package_resolver + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.10" + path: + dependency: transitive + description: + name: path + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.6.4" + path_provider: + dependency: "direct main" + description: + name: path_provider + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.5.0" + pedantic: + dependency: transitive + description: + name: pedantic + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.8.0+1" + percent_indicator: + dependency: "direct main" + description: + name: percent_indicator + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.1+1" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.0.0" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.4.0" + photo_manager: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: c3f6591a653851399ab957ed00651cfd86410e37 + url: "https://github.com/CaiJingLong/flutter_photo_manager.git" + source: git + version: "0.5.0-dev.1" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.2.1" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.0" + protobuf: + dependency: "direct main" + description: + name: protobuf + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.13.16+1" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.2.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.2" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.5" + pull_to_refresh: + dependency: "direct main" + description: + name: pull_to_refresh + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.5.8" + qr: + dependency: transitive + description: + name: qr + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" + qr_flutter: + dependency: "direct main" + description: + name: qr_flutter + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.0" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.5" + receive_sharing_intent: + dependency: "direct main" + description: + name: receive_sharing_intent + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.3" + rxdart: + dependency: "direct main" + description: + name: rxdart + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.22.6" + share: + dependency: "direct main" + description: + name: share + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.6.3+4" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.5.6+2" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.1+6" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.2+4" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.7.5" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.3" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.4+4" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.5.5" + sqflite: + dependency: "direct main" + description: + name: sqflite + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.8" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.9.3" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.19" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.5" + synchronized: + dependency: transitive + description: + name: synchronized + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.11" + timing: + dependency: transitive + description: + name: timing + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.1+2" + transformer_page_view: + dependency: transitive + description: + name: transformer_page_view + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.6" + tuple: + dependency: transitive + description: + name: tuple + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.3" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.6" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + url: "https://pub.flutter-io.cn" + source: hosted + version: "5.2.7" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.5" + uuid: + dependency: transitive + description: + name: uuid + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.4" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.8" + video_player: + dependency: "direct main" + description: + name: video_player + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.10.4+1" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.3" + video_thumbnail: + dependency: "direct main" + description: + name: video_thumbnail + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.7" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.7+13" + web_socket_channel: + dependency: "direct main" + description: + name: web_socket_channel + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.0" + wifi_info_plugin: + dependency: "direct main" + description: + name: wifi_info_plugin + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.6" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.5.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.2.0" +sdks: + dart: ">=2.6.0 <3.0.0" + flutter: ">=1.12.13+hotfix.4 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..6986226 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,469 @@ +name: chat +description: A new Flutter project. +#修改版本号后get-clean +version: 1.0.5+6 + +environment: + sdk: ">=2.1.0 <3.0.0" + +dependencies: + flutter_localizations: + sdk: flutter + flutter: + sdk: flutter + + cached_network_image: ^2.0.0 + dio: ^3.0.7 + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^0.1.2 + json_annotation: ^2.0.0 + web_socket_channel: ^1.0.14 + buffer: ^1.0.6 + protobuf: ^0.13.16 + image_picker: ^0.6.3+4 + city_pickers: ^0.1.22 + + #作者git最新版修了闪退bug- + photo_manager: + git: https://github.com/CaiJingLong/flutter_photo_manager.git + + #微信登录 + fluwx_no_pay: ^1.0.0 + flutter_swiper: ^1.1.6 + + #facebook登陆 + flutter_facebook_login: ^3.0.0 + + oktoast: ^2.1.9 + + #压缩 + flutter_image_compress: ^0.6.3 + + #视频封面 + video_thumbnail: ^0.1.6 + + #权限 + permission_handler: ^4.0.0 + + location_permissions: ^2.0.3 + # audioplayer: ^0.5.2 + audioplayer: + git: https://github.com/randomjoho/audioplayer.git + + + flutter_audio_recorder: ^0.5.4 + + image_cropper : '^1.1.0' + + video_player: ^0.10.3+3 + + flutter_ijkplayer: ^0.3.5+1 + + shared_preferences: ^0.5.6+2 + + extended_image: ^0.7.1 + extended_image_library: ^0.2.0 + + url_launcher: '^5.1.3' + + share: ^0.6.2+4 + + #下拉刷新控件 + pull_to_refresh: ^1.5.7 + + #crc32 + crclib: ^1.0.1 + + #数据存 + sqflite: ^1.1.6+5 + provider: ^3.1.0+1 + path_provider: ^1.5.0 + + auto_orientation: ^1.0.5 + + #声网 + agora_rtc_engine: any + + #网络 + connectivity: ^0.4.5+2 + + keyboard_utils: ^1.0.0 + + flutter_screenutil: ^0.5.3 + + flutter_inapp_purchase: ^2.0.4 + + #地图 + android_intent: ^0.3.4+4 + geolocator: ^5.1.5 + + location: ^2.3.5 + + amap_location: + git: https://github.com/randomjoho/flutter_amap_location.git + + google_maps_flutter: 0.5.21+11 + #修改了长按逻辑 + extended_text: + git: https://github.com/randomjoho/extended_text.git + + extended_text_field: + git: https://github.com/randomjoho/extended_text_field.git + + #本地推送 + flutter_local_notifications: 0.8.4+3 + rxdart: ^0.22.6 + #推送-设置桌面角标 + flutter_app_badger: + git: https://github.com/randomjoho/flutter_app_badger.git + + #日期选择 + flutter_datetime_picker: ^1.2.8 + + #获取通讯录 + easy_contact_picker: ^0.0.2 + #聊天长按菜单-修改了弹出位置 + menu: + git: https://github.com/randomjoho/flutter_long_tap_menu.git +# w_popup_menu: ^0.3.0 + + #进度条 + percent_indicator: ^2.1.1+1 + #版本信息 + package_info: ^0.4.0+12 + #APP安装-市场跳转-修改了安卓闪退问题 + app_installer: + git: https://github.com/randomjoho/app_installer.git + #苹果登录 + apple_sign_in: ^0.1.0 + + #二维码 + qr_flutter: ^3.1.0 + flutter_qr_reader: ^1.0.3 + + #wifi信息 + wifi_info_plugin: ^1.0.6 + + #nested_scroll_view 为了ios刷动不回弹 + extended_nested_scroll_view: ^0.3.8 + + #极光推送 -build里面版本升级了才收到厂商推送 + jpush_flutter: + git: https://github.com/randomjoho/jpush-flutter-plugin.git + + #文字转拼音 + lpinyin: ^1.0.7 + + #网页-支付跳转 + flutter_webview_plugin: ^0.3.10 + + #图片保存 + image_gallery_saver: ^1.2.2 + + #文档预览打开 +# flutter_filereader: ^1.0.0 + + #接收分享 + receive_sharing_intent: ^1.3.3 + + flutter_bugly: ^0.2.8 + #文件选择 + file_picker: ^1.4.3+2 + #文件打开 + open_file: ^3.0.1 + + + +dev_dependencies: + flutter_test: + sdk: flutter + json_serializable: ^2.0.0 + json_model: ^0.0.2 + + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + assets: + # assets-generator-begin + # assets/images/* + - assets/images/back.png + - assets/images/bg.png + - assets/images/bofang.png + - assets/images/chat_item_1.png + - assets/images/chat_item_2.png + - assets/images/chat_item_3.png + - assets/images/chat_item_4.png + - assets/images/chat_item_5.png + - assets/images/chat_item_6.png + - assets/images/chat_item_7.png + - assets/images/coin.png + - assets/images/daily_bg_1.png + - assets/images/daily_bg_2.png + - assets/images/daily_btn_1.png + - assets/images/daily_btn_2.png + - assets/images/daily_coin.png + - assets/images/daily_icon.png + - assets/images/default_nor_avatar.png + - assets/images/ext_apk.png + - assets/images/ext_excel.png + - assets/images/ext_pdf.png + - assets/images/ext_ppt.png + - assets/images/ext_sound.png + - assets/images/ext_txt.png + - assets/images/ext_unknown.png + - assets/images/ext_video.png + - assets/images/ext_word.png + - assets/images/ext_zip.png + - assets/images/gift_1.png + - assets/images/gift_2.png + - assets/images/gift_3.png + - assets/images/gift_anim_1.gif + - assets/images/gift_anim_2.gif + - assets/images/gift_anim_3.gif + - assets/images/gift_show_2_1.png + - assets/images/gift_show_2_2.png + - assets/images/gift_show_2_3.png + - assets/images/gift_show_2_4.png + - assets/images/hand.png + - assets/images/ic_album.png + - assets/images/ic_bottle_msg.png + - assets/images/ic_cards_wallet.png + - assets/images/ic_collections.png + - assets/images/ic_emotions.png + - assets/images/ic_feeds.png + - assets/images/ic_fengchao.png + - assets/images/ic_file_transfer.png + - assets/images/ic_game_entry.png + - assets/images/ic_group_chat.png + - assets/images/ic_mini_program.png + - assets/images/ic_new_friend.png + - assets/images/ic_people_nearby.png + - assets/images/ic_public_account.png + - assets/images/ic_qrcode_preview_tiny.png + - assets/images/ic_quick_scan.png + - assets/images/ic_quick_search.png + - assets/images/ic_settings.png + - assets/images/ic_shake_phone.png + - assets/images/ic_shopping.png + - assets/images/ic_social_circle.png + - assets/images/ic_tag.png + - assets/images/ic_tx_news.png + - assets/images/ic_wallet.png + - assets/images/ic_wx_games.png + - assets/images/img_fyj.png + - assets/images/img_long_index.png + - assets/images/img_splash_1.png + - assets/images/img_splash_2.png + - assets/images/img_splash_3.png + - assets/images/img_temp_hy.png + - assets/images/img_temp_qb.png + - assets/images/img_temp_qd.png + - assets/images/img_temp_see.png + - assets/images/img_temp_share.png + - assets/images/img_update_bg.png + - assets/images/left_gray.png + - assets/images/left_white.png + - assets/images/net_error.png + - assets/images/qianbao_bg.png + - assets/images/red_packet_bg.png + - assets/images/right_gray.png + - assets/images/right_white.png + - assets/images/robot.jpg + - assets/images/server_icon.png + - assets/images/service_icon.png + - assets/images/suo.png + - assets/images/svip.png + - assets/images/VIP.png + - assets/images/voucher.png + - assets/images/yqm_bg.png + - assets/images/zhiwen.png + # assets/images/chat/* + - assets/images/chat/emoji.png + - assets/images/chat/icon1.png + - assets/images/chat/icon2.png + - assets/images/chat/icon3.png + - assets/images/chat/icon4.png + - assets/images/chat/icon5.png + - assets/images/chat/icon6.png + - assets/images/chat/onion.png + # assets/images/login/* + - assets/images/login/delete.png + - assets/images/login/dly_icon1.png + - assets/images/login/dly_icon2.png + - assets/images/login/dly_icon3.png + - assets/images/login/dly_icon4.png + - assets/images/login/dly_logo.png + - assets/images/login/lock.png + - assets/images/login/money.png + - assets/images/login/rzzx.png + - assets/images/login/SY_bg.png + - assets/images/login/SY_logo.png + - assets/images/login/vip_logio.png + - assets/images/login/vip_other.png + - assets/images/login/vip_rect1.png + - assets/images/login/vip_rect2.png + - assets/images/login/vip_rect3.png + - assets/images/login/vip_wx.png + - assets/images/login/vip_zfb.png + - assets/images/login/xzxb_female.png + - assets/images/login/xzxb_male.png + # assets/images/park/* + - assets/images/park/qz_icon1.png + - assets/images/park/qz_icon2.png + - assets/images/park/qz_icon3.png + - assets/images/park/qz_icon4.png + - assets/images/park/qz_icon5.png + - assets/images/park/qz_icon6.png + - assets/images/park/qz_icon7.png + - assets/images/park/qz_icon8.png + # assets/images/sticker/* + - assets/images/sticker/sticker_1.gif + - assets/images/sticker/sticker_10.gif + - assets/images/sticker/sticker_11.gif + - assets/images/sticker/sticker_12.gif + - assets/images/sticker/sticker_13.gif + - assets/images/sticker/sticker_14.gif + - assets/images/sticker/sticker_15.gif + - assets/images/sticker/sticker_16.gif + - assets/images/sticker/sticker_17.gif + - assets/images/sticker/sticker_18.gif + - assets/images/sticker/sticker_19.gif + - assets/images/sticker/sticker_2.gif + - assets/images/sticker/sticker_20.gif + - assets/images/sticker/sticker_21.gif + - assets/images/sticker/sticker_22.gif + - assets/images/sticker/sticker_23.gif + - assets/images/sticker/sticker_24.gif + - assets/images/sticker/sticker_25.gif + - assets/images/sticker/sticker_26.gif + - assets/images/sticker/sticker_27.gif + - assets/images/sticker/sticker_28.gif + - assets/images/sticker/sticker_29.gif + - assets/images/sticker/sticker_3.gif + - assets/images/sticker/sticker_30.gif + - assets/images/sticker/sticker_4.gif + - assets/images/sticker/sticker_5.gif + - assets/images/sticker/sticker_6.gif + - assets/images/sticker/sticker_7.gif + - assets/images/sticker/sticker_8.gif + - assets/images/sticker/sticker_9.gif + # assets/images/vip/* + - assets/images/vip/hy_bg.png + - assets/images/vip/hy_cjhy.png + - assets/images/vip/hy_hy.png + - assets/images/vip/hy_tj.png + - assets/images/vip/hy_tq.png + - assets/images/vip/hy_xz.png + # assets/images/emojiface/* + - assets/images/emojiface/1.png + - assets/images/emojiface/10.png + - assets/images/emojiface/11.png + - assets/images/emojiface/12.png + - assets/images/emojiface/13.png + - assets/images/emojiface/14.png + - assets/images/emojiface/15.png + - assets/images/emojiface/16.png + - assets/images/emojiface/17.png + - assets/images/emojiface/18.png + - assets/images/emojiface/19.png + - assets/images/emojiface/2.png + - assets/images/emojiface/20.png + - assets/images/emojiface/21.png + - assets/images/emojiface/22.png + - assets/images/emojiface/23.png + - assets/images/emojiface/24.png + - assets/images/emojiface/25.png + - assets/images/emojiface/26.png + - assets/images/emojiface/27.png + - assets/images/emojiface/28.png + - assets/images/emojiface/29.png + - assets/images/emojiface/3.png + - assets/images/emojiface/30.png + - assets/images/emojiface/31.png + - assets/images/emojiface/32.png + - assets/images/emojiface/33.png + - assets/images/emojiface/34.png + - assets/images/emojiface/35.png + - assets/images/emojiface/36.png + - assets/images/emojiface/37.png + - assets/images/emojiface/38.png + - assets/images/emojiface/39.png + - assets/images/emojiface/4.png + - assets/images/emojiface/40.png + - assets/images/emojiface/41.png + - assets/images/emojiface/42.png + - assets/images/emojiface/43.png + - assets/images/emojiface/44.png + - assets/images/emojiface/45.png + - assets/images/emojiface/46.png + - assets/images/emojiface/47.png + - assets/images/emojiface/48.png + - assets/images/emojiface/49.png + - assets/images/emojiface/5.png + - assets/images/emojiface/50.png + - assets/images/emojiface/51.png + - assets/images/emojiface/52.png + - assets/images/emojiface/53.png + - assets/images/emojiface/54.png + - assets/images/emojiface/55.png + - assets/images/emojiface/56.png + - assets/images/emojiface/57.png + - assets/images/emojiface/58.png + - assets/images/emojiface/59.png + - assets/images/emojiface/6.png + - assets/images/emojiface/60.png + - assets/images/emojiface/61.png + - assets/images/emojiface/62.png + - assets/images/emojiface/63.png + - assets/images/emojiface/64.png + - assets/images/emojiface/65.png + - assets/images/emojiface/66.png + - assets/images/emojiface/67.png + - assets/images/emojiface/68.png + - assets/images/emojiface/69.png + - assets/images/emojiface/7.png + - assets/images/emojiface/70.png + - assets/images/emojiface/71.png + - assets/images/emojiface/72.png + - assets/images/emojiface/73.png + - assets/images/emojiface/74.png + - assets/images/emojiface/75.png + - assets/images/emojiface/76.png + - assets/images/emojiface/77.png + - assets/images/emojiface/78.png + - assets/images/emojiface/79.png + - assets/images/emojiface/8.png + - assets/images/emojiface/80.png + - assets/images/emojiface/81.png + - assets/images/emojiface/82.png + - assets/images/emojiface/83.png + - assets/images/emojiface/84.png + - assets/images/emojiface/85.png + - assets/images/emojiface/86.png + - assets/images/emojiface/87.png + - assets/images/emojiface/88.png + - assets/images/emojiface/89.png + - assets/images/emojiface/9.png + - assets/images/emojiface/90.png + # assets-generator-end + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + + fonts: + - family: iconfont + fonts: + - asset: assets/fonts/iconfont.ttf