diff --git a/README.md b/README.md
index e47f17e..a4e1a83 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
## 部分功能
-- SDK源码100%开源,[下载](https://pub.dev/packages/bytedesk_kefu/versions)
+- SDK源码100%开源
- 支持安卓、iOS、Web
- 机器人对话
- 技能组客服
diff --git a/bytedesk_kefu/.gitignore b/bytedesk_kefu/.gitignore
new file mode 100644
index 0000000..e9dc58d
--- /dev/null
+++ b/bytedesk_kefu/.gitignore
@@ -0,0 +1,7 @@
+.DS_Store
+.dart_tool/
+
+.packages
+.pub/
+
+build/
diff --git a/bytedesk_kefu/.metadata b/bytedesk_kefu/.metadata
new file mode 100644
index 0000000..0d35783
--- /dev/null
+++ b/bytedesk_kefu/.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: 1d9032c7e1d867f071f2277eb1673e8f9b0274e3
+ channel: stable
+
+project_type: plugin
diff --git a/bytedesk_kefu/CHANGELOG.md b/bytedesk_kefu/CHANGELOG.md
new file mode 100644
index 0000000..35fba8e
--- /dev/null
+++ b/bytedesk_kefu/CHANGELOG.md
@@ -0,0 +1,211 @@
+# Upgrade Log
+
+## 1.2.4
+
+* optimize user experience
+
+## 1.2.3
+
+* optimize user experience
+
+## 1.2.2
+
+* add unreadcount api
+
+## 1.2.1
+
+* optimize user experience
+
+## 1.2.0
+
+* add setDescription interface
+
+## 1.1.9
+
+* optimize user experience
+
+## 1.1.8
+
+* optimize user experience
+
+## 1.1.7
+
+* optimize user experience
+
+## 1.1.6
+
+* optimize user experience
+
+## 1.1.5
+
+* optimize user experience
+
+## 1.1.4
+
+* optimize user experience
+
+## 1.1.3
+
+* optimize user experience
+
+## 1.1.2
+
+* optimize user experience
+
+## 1.1.1
+
+* optimize user experience
+
+## 1.1.0
+
+* optimize user experience
+
+## 1.0.6
+
+* optimize user experience
+
+## 1.0.5
+
+* optimize user experience
+
+## 1.0.4
+
+* optimize user experience
+
+## 1.0.3
+
+* optimize user experience
+
+## 1.0.2
+
+* bug fix
+
+## 1.0.1
+
+* begion to update to null-safty
+* add web support
+
+## 1.0.0
+
+* update to flutter2.0
+
+## 0.6.2
+
+* optimize message send and receive
+
+## 0.6.1
+
+* optimize message send and receive
+
+## 0.5.8
+
+* optimize user experience
+
+## 0.5.6
+
+* compress image and video to upload
+
+## 0.5.5
+
+* compress image and video to upload
+
+## 0.5.4
+
+* optimize user experience
+
+## 0.5.3
+
+* optimize user experience
+
+## 0.5.2
+
+* change upload domain
+
+## 0.5.1
+
+* switch to websocket channel && support cdn
+
+## 0.5.0
+
+* switch to websocket channel && support cdn
+
+## 0.4.0
+
+* optimize user experience
+
+## 0.3.8
+
+* optimize user experience
+
+## 0.3.6
+
+* optimize user experience
+
+## 0.3.5
+
+* optimize user experience
+
+## 0.3.2
+
+* optimize user experience
+
+## 0.3.1
+
+* open chat by click notification
+
+## 0.3.0
+
+* send and play video message
+
+## 0.2.6
+
+* optimize robot and notice
+
+## 0.2.5
+
+* optimize robot
+
+## 0.1.5
+
+* optimize user experience
+
+## 0.1.2
+
+* optimize long connection
+
+## 0.1.1
+
+* optimize user experience
+
+## 0.1.0
+
+* add more functions
+* optimize long connection
+
+## 0.0.8
+
+* update to flutter 1.22.0
+* support show big image
+* support camera + album send image
+* support delete message
+
+## 0.0.5
+
+* optimize user experience
+
+## 0.0.4
+
+* optimize user experience
+
+## 0.0.3
+
+* optimize user experience
+
+## 0.0.2
+
+* optimize long connection
+
+## 0.0.1
+
+* support login
+* support agent chat
diff --git a/bytedesk_kefu/LICENSE b/bytedesk_kefu/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/bytedesk_kefu/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/bytedesk_kefu/README.md b/bytedesk_kefu/README.md
new file mode 100644
index 0000000..4990fcf
--- /dev/null
+++ b/bytedesk_kefu/README.md
@@ -0,0 +1,88 @@
+# bytedesk helpdesk system
+
+- [萝卜丝-智能客服-中文文档](https://git.oschina.net/270580156/bytedesk-flutter)
+- [Push](https://pub.dev/packages/bytedesk_push)
+
+bytedesk flutter helpdesk sdk
+
+- [Website](https://www.bytedesk.com)
+- [Download Gitee Demo](https://git.oschina.net/270580156/bytedesk-flutter)
+- [Download Github Demo](https://github.com/Bytedesk/bytedesk-flutter)
+- [Download ApkDemo](https://bytedesk.oss-cn-shenzhen.aliyuncs.com/apk/bytedesk-android-sdk-demo.apk)
+
+## Features
+
+- support andorid/ios/web
+- chat with agent
+- shopping chat, send commodity info
+- send post script message
+- check online status
+- get history thread
+- message voice && vibrate setting
+- chat with robot
+- send and play video message
+- chat notification
+
+
+
+## Getting Started
+
+### First Step: Register Account
+
+- [Register](https://www.bytedesk.com/admin)
+- [Docs](https://github.com/pengjinning/bytedesk-android)
+
+### Second Step:Login
+
+```dart
+// appkey和subDomain请替换为真实值
+// 获取appkey,登录后台->渠道管理->Flutter->添加应用->获取appkey
+String _appKey = '81f427ea-4467-4c7c-b0cd-5c0e4b51456f';
+// 获取subDomain,也即企业号:登录后台->客服管理->客服账号->企业号
+String _subDomain = "vip";
+BytedeskKefu.init(_appKey, _subDomain);
+```
+
+### Third Step:Contact
+
+```dart
+BytedeskKefu.startWorkGroupChat(context, workGroupWid, "title");
+```
+
+### Completed
+
+| image1 | image2 | image3 |
+| :---------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------: |
+| | | |
+| | | |
+| | | |
+
+### Change UI
+
+- create new folder: vendors
+- [Download](https://pub.dev/packages/bytedesk_kefu/versions) latest source code, put into vendors folder
+- integrate source in pubspect.yaml
+
+```dart
+bytedesk_kefu:
+ path: ./vendors/bytedesk
+```
+
+### Support
+
+- [官网](https://www.bytedesk.com/)
+- QQ 3Group: 825257535
+- Follow Us:
+-
+
+### Other
+
+- [Flutter Push SDK](https://pub.dev/packages/bytedesk_push)
+- [Flutter SDK](https://github.com/bytedesk/bytedesk-flutter)
+- [UniApp SDK](https://github.com/bytedesk/bytedesk-uniapp)
+- [iOS SDK](https://github.com/bytedesk/bytedesk-ios)
+- [Android SDK](https://github.com/bytedesk/bytedesk-android)
+- [Web](https://github.com/bytedesk/bytedesk-web)
+- [微信公众号/小程序接口](https://github.com/bytedesk/bytedesk-wechat)
+- [服务器端接口](https://github.com/bytedesk/bytedesk-server)
+- [机器人](https://github.com/bytedesk/bytedesk-chatbot)
diff --git a/bytedesk_kefu/android/.gitignore b/bytedesk_kefu/android/.gitignore
new file mode 100644
index 0000000..c6cbe56
--- /dev/null
+++ b/bytedesk_kefu/android/.gitignore
@@ -0,0 +1,8 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/bytedesk_kefu/android/.settings/org.eclipse.buildship.core.prefs b/bytedesk_kefu/android/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 0000000..99fd5b0
--- /dev/null
+++ b/bytedesk_kefu/android/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,13 @@
+arguments=
+auto.sync=false
+build.scans.enabled=false
+connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
+connection.project.dir=
+eclipse.preferences.version=1
+gradle.user.home=
+java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home
+jvm.arguments=
+offline.mode=false
+override.workspace.settings=true
+show.console.view=true
+show.executions.view=true
diff --git a/bytedesk_kefu/android/build.gradle b/bytedesk_kefu/android/build.gradle
new file mode 100644
index 0000000..16de8ed
--- /dev/null
+++ b/bytedesk_kefu/android/build.gradle
@@ -0,0 +1,38 @@
+group 'com.bytedesk.bytedesk_kefu'
+version '1.0'
+
+buildscript {
+ repositories {
+ maven { url 'https://maven.aliyun.com/repository/public/' }
+ maven { url 'https://maven.aliyun.com/repository/google/'}
+ maven { url 'https://maven.aliyun.com/repository/jcenter/'}
+ // maven { url "https://maven.google.com" }
+ google()
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.1.0'
+ }
+}
+
+rootProject.allprojects {
+ repositories {
+ maven { url 'https://maven.aliyun.com/repository/public/' }
+ maven { url 'https://maven.aliyun.com/repository/google/'}
+ maven { url 'https://maven.aliyun.com/repository/jcenter/'}
+ // maven { url "https://maven.google.com" }
+ google()
+ jcenter()
+ }
+}
+
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 30
+
+ defaultConfig {
+ minSdkVersion 16
+ }
+}
diff --git a/bytedesk_kefu/android/gradle.properties b/bytedesk_kefu/android/gradle.properties
new file mode 100644
index 0000000..cfa9ec1
--- /dev/null
+++ b/bytedesk_kefu/android/gradle.properties
@@ -0,0 +1,8 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
+#
+# systemProp.http.proxyHost=127.0.0.1
+# systemProp.http.proxyPort=10818
+# systemProp.https.proxyHost=127.0.0.1
+# systemProp.https.proxyPort=10818
\ No newline at end of file
diff --git a/bytedesk_kefu/android/gradle/wrapper/gradle-wrapper.jar b/bytedesk_kefu/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100755
index 0000000..13372ae
Binary files /dev/null and b/bytedesk_kefu/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/bytedesk_kefu/android/gradle/wrapper/gradle-wrapper.properties b/bytedesk_kefu/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..3c9d085
--- /dev/null
+++ b/bytedesk_kefu/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
diff --git a/bytedesk_kefu/android/gradlew b/bytedesk_kefu/android/gradlew
new file mode 100755
index 0000000..9d82f78
--- /dev/null
+++ b/bytedesk_kefu/android/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/bytedesk_kefu/android/gradlew.bat b/bytedesk_kefu/android/gradlew.bat
new file mode 100755
index 0000000..aec9973
--- /dev/null
+++ b/bytedesk_kefu/android/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/bytedesk_kefu/android/settings.gradle b/bytedesk_kefu/android/settings.gradle
new file mode 100644
index 0000000..f447531
--- /dev/null
+++ b/bytedesk_kefu/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'bytedesk_kefu'
diff --git a/bytedesk_kefu/android/src/main/AndroidManifest.xml b/bytedesk_kefu/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..90222fe
--- /dev/null
+++ b/bytedesk_kefu/android/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+
+
diff --git a/bytedesk_kefu/android/src/main/java/com/bytedesk/bytedesk_kefu/BytedeskKefuPlugin.java b/bytedesk_kefu/android/src/main/java/com/bytedesk/bytedesk_kefu/BytedeskKefuPlugin.java
new file mode 100644
index 0000000..1a0bdca
--- /dev/null
+++ b/bytedesk_kefu/android/src/main/java/com/bytedesk/bytedesk_kefu/BytedeskKefuPlugin.java
@@ -0,0 +1,39 @@
+package com.bytedesk.bytedesk_kefu;
+
+import androidx.annotation.NonNull;
+
+import io.flutter.embedding.engine.plugins.FlutterPlugin;
+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;
+
+/** BytedeskKefuPlugin */
+public class BytedeskKefuPlugin implements FlutterPlugin, MethodCallHandler {
+ /// The MethodChannel that will the communication between Flutter and native Android
+ ///
+ /// This local reference serves to register the plugin with the Flutter Engine and unregister it
+ /// when the Flutter Engine is detached from the Activity
+ private MethodChannel channel;
+
+ @Override
+ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
+ channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "bytedesk_kefu");
+ channel.setMethodCallHandler(this);
+ }
+
+ @Override
+ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
+ if (call.method.equals("getPlatformVersion")) {
+ result.success("Android " + android.os.Build.VERSION.RELEASE);
+ } else {
+ result.notImplemented();
+ }
+ }
+
+ @Override
+ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
+ channel.setMethodCallHandler(null);
+ }
+}
diff --git a/bytedesk_kefu/assets/audio/appkefu_alarm.wav b/bytedesk_kefu/assets/audio/appkefu_alarm.wav
new file mode 100755
index 0000000..61894f4
Binary files /dev/null and b/bytedesk_kefu/assets/audio/appkefu_alarm.wav differ
diff --git a/bytedesk_kefu/assets/audio/appkefu_dingdong.wav b/bytedesk_kefu/assets/audio/appkefu_dingdong.wav
new file mode 100755
index 0000000..4ca952e
Binary files /dev/null and b/bytedesk_kefu/assets/audio/appkefu_dingdong.wav differ
diff --git a/bytedesk_kefu/assets/audio/appkefu_newmsg.wav b/bytedesk_kefu/assets/audio/appkefu_newmsg.wav
new file mode 100755
index 0000000..1657d35
Binary files /dev/null and b/bytedesk_kefu/assets/audio/appkefu_newmsg.wav differ
diff --git a/bytedesk_kefu/assets/audio/appkefu_waiting.wav b/bytedesk_kefu/assets/audio/appkefu_waiting.wav
new file mode 100755
index 0000000..3e24674
Binary files /dev/null and b/bytedesk_kefu/assets/audio/appkefu_waiting.wav differ
diff --git a/bytedesk_kefu/assets/images/feedback/mine_feedback_add_image.png b/bytedesk_kefu/assets/images/feedback/mine_feedback_add_image.png
new file mode 100755
index 0000000..3e7c5d2
Binary files /dev/null and b/bytedesk_kefu/assets/images/feedback/mine_feedback_add_image.png differ
diff --git a/bytedesk_kefu/assets/images/feedback/mine_feedback_ic_del.png b/bytedesk_kefu/assets/images/feedback/mine_feedback_ic_del.png
new file mode 100755
index 0000000..3d5e595
Binary files /dev/null and b/bytedesk_kefu/assets/images/feedback/mine_feedback_ic_del.png differ
diff --git a/bytedesk_kefu/chat.jpeg b/bytedesk_kefu/chat.jpeg
new file mode 100755
index 0000000..0a70f8a
Binary files /dev/null and b/bytedesk_kefu/chat.jpeg differ
diff --git a/bytedesk_kefu/chat.png b/bytedesk_kefu/chat.png
new file mode 100755
index 0000000..e69189c
Binary files /dev/null and b/bytedesk_kefu/chat.png differ
diff --git a/bytedesk_kefu/chat_type.jpeg b/bytedesk_kefu/chat_type.jpeg
new file mode 100755
index 0000000..748df87
Binary files /dev/null and b/bytedesk_kefu/chat_type.jpeg differ
diff --git a/bytedesk_kefu/example/.gitignore b/bytedesk_kefu/example/.gitignore
new file mode 100644
index 0000000..0fa6b67
--- /dev/null
+++ b/bytedesk_kefu/example/.gitignore
@@ -0,0 +1,46 @@
+# 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/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/bytedesk_kefu/example/.metadata b/bytedesk_kefu/example/.metadata
new file mode 100644
index 0000000..c1ee81b
--- /dev/null
+++ b/bytedesk_kefu/example/.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: 1d9032c7e1d867f071f2277eb1673e8f9b0274e3
+ channel: stable
+
+project_type: app
diff --git a/bytedesk_kefu/example/README.md b/bytedesk_kefu/example/README.md
new file mode 100644
index 0000000..cd4b64f
--- /dev/null
+++ b/bytedesk_kefu/example/README.md
@@ -0,0 +1,16 @@
+# bytedesk_kefu_example
+
+Demonstrates how to use the bytedesk_kefu plugin.
+
+## 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/bytedesk_kefu/example/android/.gitignore b/bytedesk_kefu/example/android/.gitignore
new file mode 100644
index 0000000..0a741cb
--- /dev/null
+++ b/bytedesk_kefu/example/android/.gitignore
@@ -0,0 +1,11 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
diff --git a/bytedesk_kefu/example/android/.settings/org.eclipse.buildship.core.prefs b/bytedesk_kefu/example/android/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 0000000..5fc6763
--- /dev/null
+++ b/bytedesk_kefu/example/android/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,13 @@
+arguments=
+auto.sync=false
+build.scans.enabled=false
+connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(7.1.1))
+connection.project.dir=
+eclipse.preferences.version=1
+gradle.user.home=
+java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home
+jvm.arguments=
+offline.mode=false
+override.workspace.settings=true
+show.console.view=true
+show.executions.view=true
diff --git a/bytedesk_kefu/example/android/app/build.gradle b/bytedesk_kefu/example/android/app/build.gradle
new file mode 100644
index 0000000..8f5d910
--- /dev/null
+++ b/bytedesk_kefu/example/android/app/build.gradle
@@ -0,0 +1,50 @@
+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 from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion 30
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "com.bytedesk.bytedesk_kefu_example"
+ minSdkVersion 19
+ targetSdkVersion 30
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
diff --git a/bytedesk_kefu/example/android/app/src/debug/AndroidManifest.xml b/bytedesk_kefu/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..096a44f
--- /dev/null
+++ b/bytedesk_kefu/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/bytedesk_kefu/example/android/app/src/main/AndroidManifest.xml b/bytedesk_kefu/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..3815747
--- /dev/null
+++ b/bytedesk_kefu/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bytedesk_kefu/example/android/app/src/main/java/com/bytedesk/bytedesk_kefu_example/MainActivity.java b/bytedesk_kefu/example/android/app/src/main/java/com/bytedesk/bytedesk_kefu_example/MainActivity.java
new file mode 100644
index 0000000..9fe0283
--- /dev/null
+++ b/bytedesk_kefu/example/android/app/src/main/java/com/bytedesk/bytedesk_kefu_example/MainActivity.java
@@ -0,0 +1,6 @@
+package com.bytedesk.bytedesk_kefu_example;
+
+import io.flutter.embedding.android.FlutterActivity;
+
+public class MainActivity extends FlutterActivity {
+}
diff --git a/bytedesk_kefu/example/android/app/src/main/res/drawable-v21/launch_background.xml b/bytedesk_kefu/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/bytedesk_kefu/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/bytedesk_kefu/example/android/app/src/main/res/drawable/launch_background.xml b/bytedesk_kefu/example/android/app/src/main/res/drawable/launch_background.xml
new file mode 100755
index 0000000..304732f
--- /dev/null
+++ b/bytedesk_kefu/example/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100755
index 0000000..d2f7c74
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100755
index 0000000..d2f7c74
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100755
index 0000000..6fd8bf4
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100755
index 0000000..6fd8bf4
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/ic_arrow_back_white_24dp.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/ic_arrow_back_white_24dp.png
new file mode 100755
index 0000000..8214d9d
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/ic_arrow_back_white_24dp.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100755
index 0000000..ce9321e
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100755
index 0000000..ce9321e
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_component.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_component.png
new file mode 100755
index 0000000..4e69b4c
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_component.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_component_selected.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_component_selected.png
new file mode 100755
index 0000000..4da085e
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_component_selected.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_lab.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_lab.png
new file mode 100755
index 0000000..8c211a3
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_lab.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_lab_selected.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_lab_selected.png
new file mode 100755
index 0000000..19be002
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_lab_selected.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_util.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_util.png
new file mode 100755
index 0000000..2e80b79
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_util.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_util_selected.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_util_selected.png
new file mode 100755
index 0000000..567f543
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_tabbar_util_selected.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_topbar_about.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_topbar_about.png
new file mode 100755
index 0000000..02773b9
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_topbar_about.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_topbar_overflow.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_topbar_overflow.png
new file mode 100755
index 0000000..f92d3a1
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xhdpi/icon_topbar_overflow.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/ic_arrow_back_white_24dp.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/ic_arrow_back_white_24dp.png
new file mode 100755
index 0000000..0e43ff9
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/ic_arrow_back_white_24dp.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100755
index 0000000..29e12d5
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100755
index 0000000..29e12d5
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_component.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_component.png
new file mode 100755
index 0000000..5cc1315
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_component.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_component_selected.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_component_selected.png
new file mode 100755
index 0000000..6eb0b0c
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_component_selected.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_lab.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_lab.png
new file mode 100755
index 0000000..5c8e923
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_lab.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_lab_selected.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_lab_selected.png
new file mode 100755
index 0000000..30a59df
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_lab_selected.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_util.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_util.png
new file mode 100755
index 0000000..fc251e3
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_util.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_util_selected.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_util_selected.png
new file mode 100755
index 0000000..712a213
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_tabbar_util_selected.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_topbar_about.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_topbar_about.png
new file mode 100755
index 0000000..4313791
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_topbar_about.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_topbar_overflow.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_topbar_overflow.png
new file mode 100755
index 0000000..1b6d918
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxhdpi/icon_topbar_overflow.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100755
index 0000000..663f287
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100755
index 0000000..663f287
Binary files /dev/null and b/bytedesk_kefu/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/bytedesk_kefu/example/android/app/src/main/res/values-night/styles.xml b/bytedesk_kefu/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..449a9f9
--- /dev/null
+++ b/bytedesk_kefu/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/bytedesk_kefu/example/android/app/src/main/res/values/styles.xml b/bytedesk_kefu/example/android/app/src/main/res/values/styles.xml
new file mode 100755
index 0000000..1f83a33
--- /dev/null
+++ b/bytedesk_kefu/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/bytedesk_kefu/example/android/app/src/main/res/xml/file_paths.xml b/bytedesk_kefu/example/android/app/src/main/res/xml/file_paths.xml
new file mode 100755
index 0000000..fb3af1e
--- /dev/null
+++ b/bytedesk_kefu/example/android/app/src/main/res/xml/file_paths.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bytedesk_kefu/example/android/app/src/main/res/xml/network_security_config.xml b/bytedesk_kefu/example/android/app/src/main/res/xml/network_security_config.xml
new file mode 100755
index 0000000..dca93c0
--- /dev/null
+++ b/bytedesk_kefu/example/android/app/src/main/res/xml/network_security_config.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/bytedesk_kefu/example/android/app/src/profile/AndroidManifest.xml b/bytedesk_kefu/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..096a44f
--- /dev/null
+++ b/bytedesk_kefu/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/bytedesk_kefu/example/android/build.gradle b/bytedesk_kefu/example/android/build.gradle
new file mode 100644
index 0000000..2993024
--- /dev/null
+++ b/bytedesk_kefu/example/android/build.gradle
@@ -0,0 +1,38 @@
+buildscript {
+ repositories {
+ maven { url 'https://maven.aliyun.com/repository/public/' }
+ maven { url 'https://maven.aliyun.com/repository/google/'}
+ maven { url 'https://maven.aliyun.com/repository/jcenter/'}
+ // maven { url "https://maven.google.com" }
+ // google()
+ // jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.1.0'
+ // classpath 'com.android.tools.build:gradle:3.5.4'
+ }
+}
+
+allprojects {
+ repositories {
+ maven { url 'https://maven.aliyun.com/repository/public/' }
+ maven { url 'https://maven.aliyun.com/repository/google/'}
+ maven { url 'https://maven.aliyun.com/repository/jcenter/'}
+ // maven { url "https://maven.google.com" }
+ // google()
+ // jcenter()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/bytedesk_kefu/example/android/gradle.properties b/bytedesk_kefu/example/android/gradle.properties
new file mode 100644
index 0000000..5911b3e
--- /dev/null
+++ b/bytedesk_kefu/example/android/gradle.properties
@@ -0,0 +1,8 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
+#
+# systemProp.http.proxyHost=127.0.0.1
+# systemProp.http.proxyPort=10818
+# systemProp.https.proxyHost=127.0.0.1
+# systemProp.https.proxyPort=10818
diff --git a/bytedesk_kefu/example/android/gradle/wrapper/gradle-wrapper.properties b/bytedesk_kefu/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..014fd12
--- /dev/null
+++ b/bytedesk_kefu/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
+# distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
diff --git a/bytedesk_kefu/example/android/settings.gradle b/bytedesk_kefu/example/android/settings.gradle
new file mode 100644
index 0000000..44e62bc
--- /dev/null
+++ b/bytedesk_kefu/example/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/bytedesk_kefu/example/android/settings_aar.gradle b/bytedesk_kefu/example/android/settings_aar.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/bytedesk_kefu/example/android/settings_aar.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/bytedesk_kefu/example/assets/audio/bytedesk_alarm.wav b/bytedesk_kefu/example/assets/audio/bytedesk_alarm.wav
new file mode 100755
index 0000000..61894f4
Binary files /dev/null and b/bytedesk_kefu/example/assets/audio/bytedesk_alarm.wav differ
diff --git a/bytedesk_kefu/example/assets/audio/bytedesk_dingdong.wav b/bytedesk_kefu/example/assets/audio/bytedesk_dingdong.wav
new file mode 100755
index 0000000..4ca952e
Binary files /dev/null and b/bytedesk_kefu/example/assets/audio/bytedesk_dingdong.wav differ
diff --git a/bytedesk_kefu/example/assets/audio/bytedesk_newmsg.wav b/bytedesk_kefu/example/assets/audio/bytedesk_newmsg.wav
new file mode 100755
index 0000000..1657d35
Binary files /dev/null and b/bytedesk_kefu/example/assets/audio/bytedesk_newmsg.wav differ
diff --git a/bytedesk_kefu/example/assets/audio/bytedesk_waiting.wav b/bytedesk_kefu/example/assets/audio/bytedesk_waiting.wav
new file mode 100755
index 0000000..3e24674
Binary files /dev/null and b/bytedesk_kefu/example/assets/audio/bytedesk_waiting.wav differ
diff --git a/bytedesk_kefu/example/assets/images/feedback/mine_feedback_add_image.png b/bytedesk_kefu/example/assets/images/feedback/mine_feedback_add_image.png
new file mode 100755
index 0000000..3e7c5d2
Binary files /dev/null and b/bytedesk_kefu/example/assets/images/feedback/mine_feedback_add_image.png differ
diff --git a/bytedesk_kefu/example/assets/images/feedback/mine_feedback_ic_del.png b/bytedesk_kefu/example/assets/images/feedback/mine_feedback_ic_del.png
new file mode 100755
index 0000000..3d5e595
Binary files /dev/null and b/bytedesk_kefu/example/assets/images/feedback/mine_feedback_ic_del.png differ
diff --git a/bytedesk_kefu/example/ios/.gitignore b/bytedesk_kefu/example/ios/.gitignore
new file mode 100644
index 0000000..e96ef60
--- /dev/null
+++ b/bytedesk_kefu/example/ios/.gitignore
@@ -0,0 +1,32 @@
+*.mode1v3
+*.mode2v3
+*.moved-aside
+*.pbxuser
+*.perspectivev3
+**/*sync/
+.sconsign.dblite
+.tags*
+**/.vagrant/
+**/DerivedData/
+Icon?
+**/Pods/
+**/.symlinks/
+profile
+xcuserdata
+**/.generated/
+Flutter/App.framework
+Flutter/Flutter.framework
+Flutter/Flutter.podspec
+Flutter/Generated.xcconfig
+Flutter/app.flx
+Flutter/app.zip
+Flutter/flutter_assets/
+Flutter/flutter_export_environment.sh
+ServiceDefinitions.json
+Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!default.mode1v3
+!default.mode2v3
+!default.pbxuser
+!default.perspectivev3
diff --git a/bytedesk_kefu/example/ios/Flutter/AppFrameworkInfo.plist b/bytedesk_kefu/example/ios/Flutter/AppFrameworkInfo.plist
new file mode 100644
index 0000000..8d4492f
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Flutter/AppFrameworkInfo.plist
@@ -0,0 +1,26 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ App
+ CFBundleIdentifier
+ io.flutter.flutter.app
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ App
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ MinimumOSVersion
+ 9.0
+
+
diff --git a/bytedesk_kefu/example/ios/Flutter/Debug.xcconfig b/bytedesk_kefu/example/ios/Flutter/Debug.xcconfig
new file mode 100644
index 0000000..ec97fc6
--- /dev/null
+++ b/bytedesk_kefu/example/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/bytedesk_kefu/example/ios/Flutter/Release.xcconfig b/bytedesk_kefu/example/ios/Flutter/Release.xcconfig
new file mode 100644
index 0000000..c4855bf
--- /dev/null
+++ b/bytedesk_kefu/example/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/bytedesk_kefu/example/ios/Podfile b/bytedesk_kefu/example/ios/Podfile
new file mode 100644
index 0000000..e93971e
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Podfile
@@ -0,0 +1,39 @@
+# Uncomment this line to define a global platform for your project
+platform :ios, '10.0'
+# added by jackning, 20200929
+use_frameworks!
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+ 'Debug' => :debug,
+ 'Profile' => :release,
+ 'Release' => :release,
+}
+
+def flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
+ end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
+ end
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_ios_podfile_setup
+
+target 'Runner' do
+ flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ flutter_additional_ios_build_settings(target)
+ end
+end
diff --git a/bytedesk_kefu/example/ios/Podfile.lock b/bytedesk_kefu/example/ios/Podfile.lock
new file mode 100644
index 0000000..274b3c0
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Podfile.lock
@@ -0,0 +1,157 @@
+PODS:
+ - bytedesk_kefu (0.0.1):
+ - Flutter
+ - device_info (0.0.1):
+ - Flutter
+ - devicelocale (0.0.1):
+ - Flutter
+ - DKImagePickerController/Core (4.3.2):
+ - DKImagePickerController/ImageDataManager
+ - DKImagePickerController/Resource
+ - DKImagePickerController/ImageDataManager (4.3.2)
+ - DKImagePickerController/PhotoGallery (4.3.2):
+ - DKImagePickerController/Core
+ - DKPhotoGallery
+ - DKImagePickerController/Resource (4.3.2)
+ - DKPhotoGallery (0.0.17):
+ - DKPhotoGallery/Core (= 0.0.17)
+ - DKPhotoGallery/Model (= 0.0.17)
+ - DKPhotoGallery/Preview (= 0.0.17)
+ - DKPhotoGallery/Resource (= 0.0.17)
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Core (0.0.17):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Preview
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Model (0.0.17):
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Preview (0.0.17):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Resource
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Resource (0.0.17):
+ - SDWebImage
+ - SwiftyGif
+ - file_picker (0.0.1):
+ - DKImagePickerController/PhotoGallery
+ - Flutter
+ - Flutter (1.0.0)
+ - fluttertoast (0.0.2):
+ - Flutter
+ - Toast
+ - FMDB (2.7.5):
+ - FMDB/standard (= 2.7.5)
+ - FMDB/standard (2.7.5)
+ - image_gallery_saver (1.5.0):
+ - Flutter
+ - image_picker_ios (0.0.1):
+ - Flutter
+ - package_info (0.0.1):
+ - Flutter
+ - path_provider_ios (0.0.1):
+ - Flutter
+ - SDWebImage (5.12.5):
+ - SDWebImage/Core (= 5.12.5)
+ - SDWebImage/Core (5.12.5)
+ - shared_preferences_ios (0.0.1):
+ - Flutter
+ - sqflite (0.0.2):
+ - Flutter
+ - FMDB (>= 2.7.5)
+ - SwiftyGif (5.4.3)
+ - Toast (4.0.0)
+ - video_player_avfoundation (0.0.1):
+ - Flutter
+ - wakelock (0.0.1):
+ - Flutter
+ - webview_flutter_wkwebview (0.0.1):
+ - Flutter
+
+DEPENDENCIES:
+ - bytedesk_kefu (from `.symlinks/plugins/bytedesk_kefu/ios`)
+ - device_info (from `.symlinks/plugins/device_info/ios`)
+ - devicelocale (from `.symlinks/plugins/devicelocale/ios`)
+ - file_picker (from `.symlinks/plugins/file_picker/ios`)
+ - Flutter (from `Flutter`)
+ - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
+ - image_gallery_saver (from `.symlinks/plugins/image_gallery_saver/ios`)
+ - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
+ - package_info (from `.symlinks/plugins/package_info/ios`)
+ - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
+ - shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
+ - sqflite (from `.symlinks/plugins/sqflite/ios`)
+ - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
+ - wakelock (from `.symlinks/plugins/wakelock/ios`)
+ - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
+
+SPEC REPOS:
+ trunk:
+ - DKImagePickerController
+ - DKPhotoGallery
+ - FMDB
+ - SDWebImage
+ - SwiftyGif
+ - Toast
+
+EXTERNAL SOURCES:
+ bytedesk_kefu:
+ :path: ".symlinks/plugins/bytedesk_kefu/ios"
+ device_info:
+ :path: ".symlinks/plugins/device_info/ios"
+ devicelocale:
+ :path: ".symlinks/plugins/devicelocale/ios"
+ file_picker:
+ :path: ".symlinks/plugins/file_picker/ios"
+ Flutter:
+ :path: Flutter
+ fluttertoast:
+ :path: ".symlinks/plugins/fluttertoast/ios"
+ image_gallery_saver:
+ :path: ".symlinks/plugins/image_gallery_saver/ios"
+ image_picker_ios:
+ :path: ".symlinks/plugins/image_picker_ios/ios"
+ package_info:
+ :path: ".symlinks/plugins/package_info/ios"
+ path_provider_ios:
+ :path: ".symlinks/plugins/path_provider_ios/ios"
+ shared_preferences_ios:
+ :path: ".symlinks/plugins/shared_preferences_ios/ios"
+ sqflite:
+ :path: ".symlinks/plugins/sqflite/ios"
+ video_player_avfoundation:
+ :path: ".symlinks/plugins/video_player_avfoundation/ios"
+ wakelock:
+ :path: ".symlinks/plugins/wakelock/ios"
+ webview_flutter_wkwebview:
+ :path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
+
+SPEC CHECKSUMS:
+ bytedesk_kefu: ca69f7b243932a665dc7001be5a8e04fe7f30c57
+ device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
+ devicelocale: b22617f40038496deffba44747101255cee005b0
+ DKImagePickerController: b5eb7f7a388e4643264105d648d01f727110fc3d
+ DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
+ file_picker: 3e6c3790de664ccf9b882732d9db5eaf6b8d4eb1
+ Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
+ fluttertoast: 16fbe6039d06a763f3533670197d01fc73459037
+ FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
+ image_gallery_saver: 259eab68fb271cfd57d599904f7acdc7832e7ef2
+ image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb
+ package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
+ path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
+ SDWebImage: 0905f1b7760fc8ac4198cae0036600d67478751e
+ shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
+ sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
+ SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780
+ Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
+ video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
+ wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
+ webview_flutter_wkwebview: 005fbd90c888a42c5690919a1527ecc6649e1162
+
+PODFILE CHECKSUM: 3992017b8e295cef2daf25d4508056e8c5de3123
+
+COCOAPODS: 1.11.3
diff --git a/bytedesk_kefu/example/ios/Runner.xcodeproj/project.pbxproj b/bytedesk_kefu/example/ios/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..b4052dc
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,550 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 51;
+ 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 */; };
+ 6A722177A8132FF40F6CF720 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ACD77D260F2F57A568414FB9 /* Pods_Runner.framework */; };
+ 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 */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ );
+ 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 = ""; };
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
+ 483DAFF376EA336E70A1AF95 /* 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 = ""; };
+ 72FBC4611027C1F583CD56F7 /* 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 = ""; };
+ 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 = ""; };
+ 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 = ""; };
+ 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 = ""; };
+ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ ACD77D260F2F57A568414FB9 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ DB686996A5E8B0AF86E5C84F /* 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 = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 97C146EB1CF9000F007C117D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 6A722177A8132FF40F6CF720 /* Pods_Runner.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 2A6E5A3D8C1F9F80E2BD0282 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ ACD77D260F2F57A568414FB9 /* Pods_Runner.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 614C55E38B713AD40D4F5ECD /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ 483DAFF376EA336E70A1AF95 /* Pods-Runner.debug.xcconfig */,
+ DB686996A5E8B0AF86E5C84F /* Pods-Runner.release.xcconfig */,
+ 72FBC4611027C1F583CD56F7 /* Pods-Runner.profile.xcconfig */,
+ );
+ path = Pods;
+ sourceTree = "";
+ };
+ 9740EEB11CF90186004384FC /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */,
+ );
+ name = Flutter;
+ sourceTree = "";
+ };
+ 97C146E51CF9000F007C117D = {
+ isa = PBXGroup;
+ children = (
+ 9740EEB11CF90186004384FC /* Flutter */,
+ 97C146F01CF9000F007C117D /* Runner */,
+ 97C146EF1CF9000F007C117D /* Products */,
+ 614C55E38B713AD40D4F5ECD /* Pods */,
+ 2A6E5A3D8C1F9F80E2BD0282 /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ 97C146EF1CF9000F007C117D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146EE1CF9000F007C117D /* Runner.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 97C146F01CF9000F007C117D /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
+ 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
+ 97C146FA1CF9000F007C117D /* Main.storyboard */,
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */,
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
+ 97C147021CF9000F007C117D /* Info.plist */,
+ 97C146F11CF9000F007C117D /* Supporting Files */,
+ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
+ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+ 97C146F11CF9000F007C117D /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146F21CF9000F007C117D /* main.m */,
+ );
+ name = "Supporting Files";
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 97C146ED1CF9000F007C117D /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ 119C728BDA8833CEAEEB1252 /* [CP] Check Pods Manifest.lock */,
+ 9740EEB61CF901F6004384FC /* Run Script */,
+ 97C146EA1CF9000F007C117D /* Sources */,
+ 97C146EB1CF9000F007C117D /* Frameworks */,
+ 97C146EC1CF9000F007C117D /* Resources */,
+ 9705A1C41CF9048500538489 /* Embed Frameworks */,
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+ 5F993E3220C72A9F6B99ABE4 /* [CP] Embed Pods Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ 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 = {
+ LastUpgradeCheck = 1300;
+ ORGANIZATIONNAME = "";
+ TargetAttributes = {
+ 97C146ED1CF9000F007C117D = {
+ CreatedOnToolsVersion = 7.3.1;
+ };
+ };
+ };
+ buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 97C146E51CF9000F007C117D;
+ productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 97C146ED1CF9000F007C117D /* Runner */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 97C146EC1CF9000F007C117D /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
+ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
+ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 119C728BDA8833CEAEEB1252 /* [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\" embed_and_thin";
+ };
+ 5F993E3220C72A9F6B99ABE4 /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ 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 */
+ 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 PBXVariantGroup section */
+ 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;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ 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 = 9.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Profile;
+ };
+ 249021D4217E4FDB00AE95B9 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = L5F47963M2;
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.bytedesk.bytedeskKefuExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Profile;
+ };
+ 97C147031CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ 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 = 9.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 97C147041CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ 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 = 9.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 97C147061CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = L5F47963M2;
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.bytedesk.bytedeskKefuExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 97C147071CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = L5F47963M2;
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.bytedesk.bytedeskKefuExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 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/bytedesk_kefu/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/bytedesk_kefu/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..919434a
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/bytedesk_kefu/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/bytedesk_kefu/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/bytedesk_kefu/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/bytedesk_kefu/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..f9b0d7c
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/bytedesk_kefu/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/bytedesk_kefu/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 0000000..3db53b6
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bytedesk_kefu/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/bytedesk_kefu/example/ios/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..21a3cc1
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/bytedesk_kefu/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/bytedesk_kefu/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/bytedesk_kefu/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/bytedesk_kefu/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..f9b0d7c
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/bytedesk_kefu/example/ios/Runner/AppDelegate.h b/bytedesk_kefu/example/ios/Runner/AppDelegate.h
new file mode 100644
index 0000000..36e21bb
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner/AppDelegate.h
@@ -0,0 +1,6 @@
+#import
+#import
+
+@interface AppDelegate : FlutterAppDelegate
+
+@end
diff --git a/bytedesk_kefu/example/ios/Runner/AppDelegate.m b/bytedesk_kefu/example/ios/Runner/AppDelegate.m
new file mode 100644
index 0000000..70e8393
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner/AppDelegate.m
@@ -0,0 +1,13 @@
+#import "AppDelegate.h"
+#import "GeneratedPluginRegistrant.h"
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ [GeneratedPluginRegistrant registerWithRegistry:self];
+ // Override point for customization after application launch.
+ return [super application:application didFinishLaunchingWithOptions:launchOptions];
+}
+
+@end
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100755
index 0000000..193d0dc
--- /dev/null
+++ b/bytedesk_kefu/example/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/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png
new file mode 100755
index 0000000..6b9c5d0
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png
new file mode 100755
index 0000000..684fee1
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png
new file mode 100755
index 0000000..66908ba
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png
new file mode 100755
index 0000000..c85d39b
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png
new file mode 100755
index 0000000..6d072eb
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png
new file mode 100755
index 0000000..50dc4c7
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png
new file mode 100755
index 0000000..335469c
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png
new file mode 100755
index 0000000..e585977
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
new file mode 100755
index 0000000..5dfbe16
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
new file mode 100755
index 0000000..bd2376d
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png
new file mode 100755
index 0000000..66908ba
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
new file mode 100755
index 0000000..5672877
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png
new file mode 100755
index 0000000..e22345e
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-50.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-50.png
new file mode 100755
index 0000000..870c163
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-50.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png
new file mode 100755
index 0000000..8c6ff14
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-57.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-57.png
new file mode 100755
index 0000000..bd97d1a
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-57.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png
new file mode 100755
index 0000000..b8a20f7
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-57@2x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
new file mode 100755
index 0000000..e22345e
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
new file mode 100755
index 0000000..50e31f4
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-72.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-72.png
new file mode 100755
index 0000000..62997ee
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-72.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png
new file mode 100755
index 0000000..2bf71ff
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png
new file mode 100755
index 0000000..b6fd014
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png
new file mode 100755
index 0000000..949426c
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
new file mode 100755
index 0000000..b445a7f
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
new file mode 100755
index 0000000..0bedcf2
--- /dev/null
+++ b/bytedesk_kefu/example/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/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
new file mode 100755
index 0000000..9da19ea
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
new file mode 100755
index 0000000..9da19ea
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
new file mode 100755
index 0000000..9da19ea
Binary files /dev/null and b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ
diff --git a/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/bytedesk_kefu/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
new file mode 100755
index 0000000..89c2725
--- /dev/null
+++ b/bytedesk_kefu/example/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/bytedesk_kefu/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/bytedesk_kefu/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..f2e259c
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bytedesk_kefu/example/ios/Runner/Base.lproj/Main.storyboard b/bytedesk_kefu/example/ios/Runner/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..f3c2851
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner/Base.lproj/Main.storyboard
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bytedesk_kefu/example/ios/Runner/Info.plist b/bytedesk_kefu/example/ios/Runner/Info.plist
new file mode 100644
index 0000000..935ec6f
--- /dev/null
+++ b/bytedesk_kefu/example/ios/Runner/Info.plist
@@ -0,0 +1,74 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ 萝卜丝Demo
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSRequiresIPhoneOS
+
+ NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+
+ NSAppleMusicUsageDescription
+ $(PRODUCT_NAME) 需要读取音乐
+ NSCalendarsUsageDescription
+ $(PRODUCT_NAME) 需要读取日历
+ NSCameraUsageDescription
+ $(PRODUCT_NAME) 拍照并发送图片
+ NSContactsUsageDescription
+ $(PRODUCT_NAME) 需要读取联系人推荐好友
+ NSLocationAlwaysAndWhenInUseUsageDescription
+ 地图功能需要您的定位服务,否则无法使用,如果您需要使用后台定位功能请选择“始终允许”。
+ NSLocationAlwaysUsageDescription
+ 地图功能需要您的定位服务,否则无法使用。
+ NSLocationWhenInUseUsageDescription
+ 地图功能需要您的定位服务,否则无法使用。
+ NSMicrophoneUsageDescription
+ $(PRODUCT_NAME) 发送语音
+ NSMotionUsageDescription
+ $(PRODUCT_NAME) 需要读取运动健身
+ NSPhotoLibraryAddUsageDescription
+ $(PRODUCT_NAME) 发送图片
+ NSPhotoLibraryUsageDescription
+ $(PRODUCT_NAME) 发送图片
+ NSSpeechRecognitionUsageDescription
+ $(PRODUCT_NAME) 需要读取语音识别
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIViewControllerBasedStatusBarAppearance
+
+
+
diff --git a/bytedesk_kefu/example/ios/Runner/main.m b/bytedesk_kefu/example/ios/Runner/main.m
new file mode 100644
index 0000000..dff6597
--- /dev/null
+++ b/bytedesk_kefu/example/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/bytedesk_kefu/example/lib/main.dart b/bytedesk_kefu/example/lib/main.dart
new file mode 100644
index 0000000..34cc0c1
--- /dev/null
+++ b/bytedesk_kefu/example/lib/main.dart
@@ -0,0 +1,270 @@
+import 'package:bytedesk_kefu/bytedesk_kefu.dart';
+import 'package:bytedesk_kefu/util/bytedesk_constants.dart';
+import 'package:bytedesk_kefu/util/bytedesk_events.dart';
+import 'package:bytedesk_kefu/util/bytedesk_utils.dart';
+import 'package:bytedesk_kefu_example/notification/custom_notification.dart';
+import 'package:bytedesk_kefu_example/page/chat_type_page.dart';
+import 'package:bytedesk_kefu_example/page/history_thread_page.dart';
+import 'package:bytedesk_kefu_example/page/online_status_page.dart';
+import 'package:bytedesk_kefu_example/page/setting_page.dart';
+import 'package:bytedesk_kefu_example/page/user_info_page.dart';
+import 'package:overlay_support/overlay_support.dart';
+import 'package:flutter/material.dart';
+// import 'package:vibration/vibration.dart';
+// import 'package:audioplayers/audioplayers.dart';
+
+void main() {
+ // runApp(MyApp());
+ runApp(OverlaySupport(
+ child: MaterialApp(
+ debugShowCheckedModeBanner: false, // 去除右上角debug的标签
+ home: MyApp(),
+ )));
+
+ // 参考文档:https://github.com/Bytedesk/bytedesk-flutter
+ // 管理后台:https://www.bytedesk.com/admin
+ // appkey和subDomain请替换为真实值
+ // 获取appkey,登录后台->渠道管理->Flutter->添加应用->获取appkey
+ String _appKey = '81f427ea-4467-4c7c-b0cd-5c0e4b51456f';
+ // 获取subDomain,也即企业号:登录后台->客服管理->客服账号->企业号
+ String _subDomain = "vip";
+ // 第一步:初始化
+ BytedeskKefu.init(_appKey, _subDomain);
+ // 注:如果需要多平台统一用户(用于同步聊天记录等),可使用:
+ // BytedeskKefu.initWithUsernameAndNicknameAndAvatar('myuniappusername', '我是美女', 'https://bytedesk.oss-cn-shenzhen.aliyuncs.com/avatars/girl.png', subDomain, appKey);
+ // BytedeskKefu.initWithUsername('myuniappusername',subDomain, appKey); // 其中:username为自定义用户名,可与开发者所在用户系统对接
+ // 如果还需要自定义昵称/头像,可以使用 initWithUsernameAndNickname或initWithUsernameAndNicknameAndAvatar,
+ // 具体参数可以参考 bytedesk_kefu/bytedesk_kefu.dart 文件
+}
+
+class MyApp extends StatefulWidget {
+ @override
+ _MyAppState createState() => _MyAppState();
+}
+
+class _MyAppState extends State with WidgetsBindingObserver {
+ //
+ String _title = '萝卜丝客服Demo(连接中...)';
+ // AudioCache audioCache = AudioCache();
+ // bool _isConnected = false;
+ //
+ @override
+ void initState() {
+ WidgetsBinding.instance?.addObserver(this);
+ super.initState();
+ _listener();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(_title),
+ elevation: 0,
+ ),
+ body: ListView(
+ children: ListTile.divideTiles(
+ context: context,
+ tiles: [
+ ListTile(
+ title: Text('联系客服'),
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ // 第二步:联系客服,完毕
+ Navigator.of(context)
+ .push(new MaterialPageRoute(builder: (context) {
+ return new ChatTypePage();
+ }));
+ },
+ ),
+ ListTile(
+ title: Text('用户信息'), // 自定义用户资料,设置
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ // 需要首先调用anonymousLogin之后,再调用设置用户信息接口
+ Navigator.of(context)
+ .push(new MaterialPageRoute(builder: (context) {
+ return new UserInfoPage();
+ }));
+ },
+ ),
+ ListTile(
+ title: Text('在线状态'), // 技能组或客服账号 在线状态
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ Navigator.of(context)
+ .push(new MaterialPageRoute(builder: (context) {
+ return new OnlineStatusPage();
+ }));
+ },
+ ),
+ ListTile(
+ title: Text('历史会话'), // 会话记录
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ Navigator.of(context)
+ .push(new MaterialPageRoute(builder: (context) {
+ return new HistoryThreadPage();
+ }));
+ },
+ ),
+ // ListTile(
+ // title: Text('TODO:提交工单'),
+ // trailing: Icon(Icons.keyboard_arrow_right),
+ // onTap: () {
+ // print('ticket');
+ // // TODO: 提交工单
+ // },
+ // ),
+ // ListTile(
+ // title: Text('TODO:意见反馈'),
+ // trailing: Icon(Icons.keyboard_arrow_right),
+ // onTap: () {
+ // print('feedback');
+ // // TODO: 意见反馈
+ // },
+ // ),
+ ListTile(
+ title: Text('消息提示'),
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ Navigator.of(context)
+ .push(new MaterialPageRoute(builder: (context) {
+ return new SettingPage();
+ }));
+ },
+ ),
+ ListTile(
+ title: Text('技术支持: QQ-3群: 825257535'),
+ )
+ ],
+ ).toList()),
+ // floatingActionButton: FloatingActionButton(
+ // onPressed: () {
+ // // 第二步:到 客服管理->技能组-有一列 ‘唯一ID(wId)’, 默认设置工作组wid
+ // // 说明:一个技能组可以分配多个客服,访客会按照一定的规则分配给组内的各个客服账号
+ // String _workGroupWid = "201807171659201"; // 默认人工
+ // BytedeskKefu.startWorkGroupChat(context, _workGroupWid, "技能组客服-默认人工");
+ // },
+ // tooltip: '客服',
+ // child: Icon(Icons.message),
+ // ), // Th
+ );
+ }
+
+ // 监听状态
+ _listener() {
+ // 监听连接状态
+ bytedeskEventBus.on().listen((event) {
+ print('长连接状态:' + event.content);
+ if (event.content == BytedeskConstants.USER_STATUS_CONNECTING) {
+ setState(() {
+ _title = "萝卜丝客服Demo(连接中...)";
+ });
+ } else if (event.content == BytedeskConstants.USER_STATUS_CONNECTED) {
+ setState(() {
+ _title = "萝卜丝客服Demo(连接成功)";
+ });
+ } else if (event.content == BytedeskConstants.USER_STATUS_DISCONNECTED) {
+ setState(() {
+ _title = "萝卜丝客服Demo(连接断开)";
+ });
+ }
+ });
+ // 监听消息,开发者可在此决定是否振动或播放提示音声音
+ bytedeskEventBus.on().listen((event) {
+ // print('receive message:' + event.message.content);
+ // 1. 首先将example/assets/audio文件夹中文件拷贝到自己项目;2.在自己项目pubspec.yaml中添加assets
+ // 播放发送消息提示音
+ if (BytedeskKefu.getPlayAudioOnSendMessage()! &&
+ event.message.isSend == 1) {
+ print('play send audio');
+ // 修改为自己项目中语音文件路径
+ // audioCache.play('audio/bytedesk_dingdong.wav');
+ }
+ if (event.message.isSend == 1) {
+ // 自己发送的消息,直接返回
+ return;
+ }
+ // 接收消息播放提示音
+ if (BytedeskKefu.getPlayAudioOnReceiveMessage()! &&
+ event.message.isSend == 0) {
+ print('play receive audio');
+ // audioCache.play('audio/bytedesk_dingdong.wav');
+ }
+ // 振动
+ if (BytedeskKefu.getVibrateOnReceiveMessage()! &&
+ event.message.isSend == 0) {
+ print('should vibrate');
+ vibrate();
+ }
+ if (event.message.type == BytedeskConstants.MESSAGE_TYPE_TEXT) {
+ print('文字消息: ' + event.message.content!);
+ // 判断当前是否客服页面,如否,则显示顶部通知栏
+ if (!BytedeskUtils.isCurrentChatKfPage()!) {
+ // https://github.com/boyan01/overlay_support
+ showOverlayNotification((context) {
+ return MessageNotification(
+ avatar: event.message.user!.avatar!,
+ nickname: event.message.user!.nickname!,
+ content: event.message.content!,
+ onReply: () {
+ //
+ OverlaySupportEntry.of(context)!.dismiss();
+ // 进入客服页面,支持自定义页面标题
+ BytedeskKefu.startChatThread(context, event.message.thread!,
+ title: '客服会话');
+ },
+ );
+ }, duration: Duration(milliseconds: 4000));
+ }
+ } else if (event.message.type == BytedeskConstants.MESSAGE_TYPE_IMAGE) {
+ print('图片消息:' + event.message.imageUrl!);
+ } else if (event.message.type == BytedeskConstants.MESSAGE_TYPE_VOICE) {
+ print('语音消息:' + event.message.voiceUrl!);
+ } else if (event.message.type == BytedeskConstants.MESSAGE_TYPE_VIDEO) {
+ print('视频消息:' + event.message.videoUrl!);
+ } else if (event.message.type == BytedeskConstants.MESSAGE_TYPE_FILE) {
+ print('文件消息:' + event.message.fileUrl!);
+ } else {
+ print('其他类型消息');
+ }
+ });
+ // token过期
+ // bytedeskEventBus.on().listen((event) {
+ // // 执行重新初始化
+ // print('InvalidTokenEventBus, token过期');
+ // });
+ }
+
+ // @override
+ // void didChangeAppLifecycleState(AppLifecycleState state) {
+ // print("main didChangeAppLifecycleState:" + state.toString());
+ // switch (state) {
+ // case AppLifecycleState.inactive: // 处于这种状态的应用程序应该假设它们可能在任何时候暂停。
+ // break;
+ // case AppLifecycleState.paused: // 应用程序不可见,后台
+ // break;
+ // case AppLifecycleState.resumed: // 应用程序可见,前台
+ // // APP切换到前台之后,重连
+ // // BytedeskUtils.mqttReConnect();
+ // break;
+ // case AppLifecycleState.detached: // 申请将暂时暂停
+ // break;
+ // }
+ // }
+
+ // 振动
+ void vibrate() async {
+ // if (await Vibration.hasVibrator()) {
+ // Vibration.vibrate();
+ // }
+ }
+
+ @override
+ void dispose() {
+ WidgetsBinding.instance?.removeObserver(this);
+ super.dispose();
+ // audioCache?
+ }
+}
diff --git a/bytedesk_kefu/example/lib/notification/custom_animation.dart b/bytedesk_kefu/example/lib/notification/custom_animation.dart
new file mode 100755
index 0000000..ca83cba
--- /dev/null
+++ b/bytedesk_kefu/example/lib/notification/custom_animation.dart
@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+import 'ios_toast.dart';
+
+/// Example to show how to popup overlay with custom animation.
+class CustomAnimationToast extends StatelessWidget {
+ final double? value;
+
+ static final Tween tweenOffset =
+ Tween(begin: Offset(0, 40), end: Offset(0, 0));
+
+ static final Tween tweenOpacity = Tween(begin: 0, end: 1);
+
+ const CustomAnimationToast({Key? key, @required this.value})
+ : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Transform.translate(
+ offset: tweenOffset.transform(value!),
+ child: Opacity(
+ child: IosStyleToast(),
+ opacity: tweenOpacity.transform(value!),
+ ),
+ );
+ }
+}
diff --git a/bytedesk_kefu/example/lib/notification/custom_notification.dart b/bytedesk_kefu/example/lib/notification/custom_notification.dart
new file mode 100755
index 0000000..8a0dede
--- /dev/null
+++ b/bytedesk_kefu/example/lib/notification/custom_notification.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+
+class MessageNotification extends StatelessWidget {
+ //
+ final VoidCallback? onReply;
+ final String? avatar;
+ final String? nickname;
+ final String? content;
+
+ const MessageNotification({
+ Key? key,
+ @required this.onReply,
+ @required this.avatar,
+ @required this.nickname,
+ @required this.content,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Card(
+ margin: const EdgeInsets.symmetric(horizontal: 4),
+ child: SafeArea(
+ child: ListTile(
+ leading: SizedBox.fromSize(
+ size: const Size(40, 40),
+ child: ClipOval(child: Image.network(avatar!))),
+ title: Text(nickname!),
+ subtitle: Text(content!),
+ trailing: IconButton(
+ icon: Icon(Icons.reply),
+ onPressed: () {
+ if (onReply != null) onReply!();
+ }),
+ ),
+ ),
+ );
+ }
+}
diff --git a/bytedesk_kefu/example/lib/notification/ios_toast.dart b/bytedesk_kefu/example/lib/notification/ios_toast.dart
new file mode 100755
index 0000000..0cb13cd
--- /dev/null
+++ b/bytedesk_kefu/example/lib/notification/ios_toast.dart
@@ -0,0 +1,40 @@
+import 'package:flutter/material.dart';
+
+class IosStyleToast extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return SafeArea(
+ child: DefaultTextStyle(
+ style: Theme.of(context)
+ .textTheme
+ .bodyText2!
+ .copyWith(color: Colors.white),
+ child: Padding(
+ padding: const EdgeInsets.all(16),
+ child: Center(
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(10),
+ child: Container(
+ color: Colors.black87,
+ padding: const EdgeInsets.symmetric(
+ vertical: 8,
+ horizontal: 16,
+ ),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Icon(
+ Icons.check,
+ color: Colors.white,
+ ),
+ Text('Succeed')
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/bytedesk_kefu/example/lib/page/chat_type_page.dart b/bytedesk_kefu/example/lib/page/chat_type_page.dart
new file mode 100755
index 0000000..6d85b05
--- /dev/null
+++ b/bytedesk_kefu/example/lib/page/chat_type_page.dart
@@ -0,0 +1,229 @@
+import 'dart:convert';
+
+import 'package:bytedesk_kefu/bytedesk_kefu.dart';
+import 'package:bytedesk_kefu/util/bytedesk_constants.dart';
+import 'package:flutter/material.dart';
+
+// 多种客服对话类型列表页面
+class ChatTypePage extends StatefulWidget {
+ ChatTypePage({Key? key}) : super(key: key);
+
+ @override
+ _ChatTypePageState createState() => _ChatTypePageState();
+}
+
+class _ChatTypePageState extends State {
+ // 第二步:到 客服管理->技能组-有一列 ‘唯一ID(wId)’, 默认设置工作组wid
+ // 说明:一个技能组可以分配多个客服,访客会按照一定的规则分配给组内的各个客服账号
+ String _workGroupWid = "201807171659201"; // 默认人工
+ String _workGroupWidRobot = "201809061716221"; // 默认机器人, 在管理后台开启或关闭机器人
+ // 说明:直接发送给此一个客服账号,一对一会话
+ String _agentUid = "201808221551193";
+ // 未读消息数目
+ String _unreadMessageCount = "0";
+ //
+ @override
+ void initState() {
+ // 加载未读消息数目
+ _getUnreadCountVisitor();
+ //
+ super.initState();
+ }
+
+ //
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text('对话类型'),
+ elevation: 0,
+ ),
+ body: ListView(
+ children: ListTile.divideTiles(context: context, tiles: [
+ ListTile(
+ title: Text('未读消息数目:' + _unreadMessageCount),
+ // trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ // 加载未读消息数目
+ _getUnreadCountVisitor();
+ },
+ ),
+ Container(
+ height: 20,
+ ),
+ ListTile(
+ title: Text('技能组客服'),
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ BytedeskKefu.startWorkGroupChat(
+ context, _workGroupWid, "技能组客服-默认人工");
+ },
+ ),
+ ListTile(
+ title: Text('技能组客服-机器人'),
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ BytedeskKefu.startWorkGroupChat(
+ context, _workGroupWidRobot, "技能组客服-默认机器人");
+ },
+ ),
+ ListTile(
+ title: Text('技能组客服-电商'),
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ // 商品信息,type/title/content/price/url/imageUrl/id/categoryCode
+ // 注意:长度不能大于500字符
+ var custom = json.encode({
+ "type": BytedeskConstants.MESSAGE_TYPE_COMMODITY, // 不能修改
+ "title": "商品标题", // 可自定义, 类型为字符串
+ "content": "商品详情", // 可自定义, 类型为字符串
+ "price": "9.99", // 可自定义, 类型为字符串
+ "url":
+ "https://item.m.jd.com/product/12172344.html", // 必须为url网址, 类型为字符串
+ "imageUrl":
+ "https://bytedesk.oss-cn-shenzhen.aliyuncs.com/images/123.webp", //必须为图片网址, 类型为字符串
+ "id": 123, // 可自定义
+ "categoryCode": "100010003", // 可自定义, 类型为字符串
+ "client": "flutter" // 可自定义, 类型为字符串
+ });
+ BytedeskKefu.startWorkGroupChatShop(
+ context, _workGroupWid, "技能组客服-电商", custom);
+ },
+ ),
+ ListTile(
+ title: Text('技能组客服-电商-回调'),
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ // 商品信息,type/title/content/price/url/imageUrl/id/categoryCode
+ // 注意:长度不能大于500字符
+ var custom = json.encode({
+ "type": BytedeskConstants.MESSAGE_TYPE_COMMODITY, // 不能修改
+ "title": "商品标题", // 可自定义, 类型为字符串
+ "content": "商品详情", // 可自定义, 类型为字符串
+ "price": "9.99", // 可自定义, 类型为字符串
+ "url":
+ "https://item.m.jd.com/product/12172344.html", // 必须为url网址, 类型为字符串
+ "imageUrl":
+ "https://bytedesk.oss-cn-shenzhen.aliyuncs.com/images/123.webp", //必须为图片网址, 类型为字符串
+ "id": 123, // 可自定义
+ "categoryCode": "100010003", // 可自定义, 类型为字符串
+ "client": "flutter", // 可自定义, 类型为字符串
+ // 可自定义添加key:value, 客服端不可见,可用于回调原样返回
+ "other1": "", // 可另外添加自定义字段,客服端不可见,可用于回调原样返回
+ "other2": "", // 可另外添加自定义字段,客服端不可见,可用于回调原样返回
+ "other3": "", // 可另外添加自定义字段,客服端不可见,可用于回调原样返回
+ });
+ BytedeskKefu.startWorkGroupChatShopCallback(
+ context, _workGroupWid, "技能组客服-电商-回调", custom, (value) {
+ print('value为custom参数原样返回 $value');
+ // 主要用途:用户在聊天页面点击商品消息,回调此接口,开发者可在此打开进入商品详情页
+ });
+ },
+ ),
+ ListTile(
+ title: Text('技能组客服-附言'),
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ BytedeskKefu.startWorkGroupChatPostscript(
+ context, _workGroupWid, "技能组客服-附言", "随便说点什么吧,我会自动发送给客服");
+ },
+ ),
+ Container(
+ height: 20,
+ ),
+ ListTile(
+ title: Text('指定一对一客服'),
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ BytedeskKefu.startAppointedChat(context, _agentUid, "指定一对一客服");
+ },
+ ),
+ ListTile(
+ title: Text('指定一对一客服-电商'),
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ // 商品信息,type/title/content/price/url/imageUrl/id/categoryCode
+ // 注意:长度不能大于500字符
+ var custom = json.encode({
+ "type": BytedeskConstants.MESSAGE_TYPE_COMMODITY,
+ "title": "商品标题",
+ "content": "商品详情",
+ "price": "9.99",
+ "url": "https://item.m.jd.com/product/12172344.html",
+ "imageUrl":
+ "https://bytedesk.oss-cn-shenzhen.aliyuncs.com/images/123.webp",
+ "id": 123,
+ "categoryCode": "100010003",
+ "client": "flutter"
+ });
+ BytedeskKefu.startAppointedChatShop(
+ context, _agentUid, "指定一对一客服-电商", custom);
+ },
+ ),
+ ListTile(
+ title: Text('指定一对一客服-电商-回调'),
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ // 商品信息,type/title/content/price/url/imageUrl/id/categoryCode
+ // 注意:长度不能大于500字符
+ var custom = json.encode({
+ "type": BytedeskConstants.MESSAGE_TYPE_COMMODITY,
+ "title": "商品标题",
+ "content": "商品详情",
+ "price": "9.99",
+ "url": "https://item.m.jd.com/product/12172344.html",
+ "imageUrl":
+ "https://bytedesk.oss-cn-shenzhen.aliyuncs.com/images/123.webp",
+ "id": 123,
+ "categoryCode": "100010003",
+ "client": "flutter",
+ // 可自定义添加key:value, 客服端不可见,可用于回调原样返回
+ "other1": "", // 可另外添加自定义字段,客服端不可见,可用于回调原样返回
+ "other2": "", // 可另外添加自定义字段,客服端不可见,可用于回调原样返回
+ "other3": "", // 可另外添加自定义字段,客服端不可见,可用于回调原样返回
+ });
+ BytedeskKefu.startAppointedChatShopCallback(
+ context, _agentUid, "指定一对一客服-电商-回调", custom, (value) {
+ print('value为custom参数原样返回 $value');
+ // 主要用途:用户在聊天页面点击商品消息,回调此接口,开发者可在此打开进入商品详情页
+ });
+ },
+ ),
+ ListTile(
+ title: Text('指定一对一客服-附言'),
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ BytedeskKefu.startAppointedChatPostscript(
+ context, _agentUid, "指定一对一客服-附言", "随便说点什么吧,我会自动发送给客服");
+ },
+ ),
+ Container(
+ height: 20,
+ ),
+ ListTile(
+ title: Text('H5网页会话'),
+ trailing: Icon(Icons.keyboard_arrow_right),
+ onTap: () {
+ print('h5 chat');
+ // 注意: 登录后台->客服管理->技能组(或客服账号)->获取客服代码 获取相应URL
+ String url =
+ "https://h1.kefux.cn/chat/h5/index.html?sub=vip&uid=201808221551193&wid=201807171659201&type=workGroup&aid=&hidenav=1&ph=ph";
+ String title = 'H5在线客服演示';
+ BytedeskKefu.startH5Chat(context, url, title);
+ },
+ ),
+ ]).toList(),
+ ),
+ );
+ }
+
+ void _getUnreadCountVisitor() {
+ // 获取指定客服在线状态
+ BytedeskKefu.getUnreadCountVisitor().then((count) => {
+ print('unreadcount:' + count),
+ setState(() {
+ _unreadMessageCount = count;
+ })
+ });
+ }
+}
diff --git a/bytedesk_kefu/example/lib/page/history_thread_page.dart b/bytedesk_kefu/example/lib/page/history_thread_page.dart
new file mode 100755
index 0000000..339e099
--- /dev/null
+++ b/bytedesk_kefu/example/lib/page/history_thread_page.dart
@@ -0,0 +1,66 @@
+import 'package:bytedesk_kefu/bytedesk_kefu.dart';
+import 'package:bytedesk_kefu/model/thread.dart';
+import 'package:flutter/material.dart';
+
+// 历史会话列表
+class HistoryThreadPage extends StatefulWidget {
+ HistoryThreadPage({Key? key}) : super(key: key);
+
+ @override
+ _HistoryThreadPageState createState() => _HistoryThreadPageState();
+}
+
+// TODO: 点击thread会话直接进入对话页面
+class _HistoryThreadPageState extends State {
+ //
+ int _page = 0;
+ int _size = 20;
+ List _historyThreadList = [];
+ //
+ @override
+ void initState() {
+ _getVisitorThreads();
+ super.initState();
+ }
+
+ //
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text('历史会话'),
+ elevation: 0,
+ ),
+ body: RefreshIndicator(
+ child: ListView.builder(
+ padding: EdgeInsets.all(8.0),
+ itemBuilder: (_, int index) => ListTile(
+ leading: Image.network(_historyThreadList[index].avatar!),
+ title: Text(
+ '${_historyThreadList[index].nickname}, ${_historyThreadList[index].timestamp}'),
+ subtitle: Text('${_historyThreadList[index].content}'),
+ onTap: () {
+ // 进入客服页面
+ BytedeskKefu.startChatThread(
+ context, _historyThreadList[index]);
+ },
+ ),
+ itemCount: _historyThreadList.length,
+ ),
+ onRefresh: _onRefresh,
+ ));
+ }
+
+ void _getVisitorThreads() {
+ BytedeskKefu.getVisitorThreads(_page, _size).then((value) => {
+ setState(() {
+ _historyThreadList = value;
+ })
+ });
+ }
+
+ Future _onRefresh() async {
+ _getVisitorThreads();
+ _page++;
+ }
+}
diff --git a/bytedesk_kefu/example/lib/page/online_status_page.dart b/bytedesk_kefu/example/lib/page/online_status_page.dart
new file mode 100755
index 0000000..59f7c61
--- /dev/null
+++ b/bytedesk_kefu/example/lib/page/online_status_page.dart
@@ -0,0 +1,80 @@
+import 'package:bytedesk_kefu/bytedesk_kefu.dart';
+import 'package:flutter/material.dart';
+
+// 查询技能组和指定客服账号的在线状态
+class OnlineStatusPage extends StatefulWidget {
+ OnlineStatusPage({Key? key}) : super(key: key);
+
+ @override
+ _OnlineStatusPageState createState() => _OnlineStatusPageState();
+}
+
+class _OnlineStatusPageState extends State {
+ // 到 客服管理->技能组-有一列 ‘唯一ID(wId)’
+ String _workGroupWid = "201807171659201";
+ // 到 客服管理->客服账号-有一列 ‘唯一ID(uId)’
+ String _agentUid = "201808221551193";
+ //
+ String _workGroupStatus = ''; // 注:online 代表在线,offline 代表离线
+ String _agentStatus = ''; // 注:online 代表在线,offline 代表离线
+ //
+ @override
+ void initState() {
+ // 获取技能组在线状态
+ _getWorkGroupStatus();
+ // 获取指定客服在线状态
+ _getAgentStatus();
+ super.initState();
+ }
+
+ //
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text('在线状态'),
+ elevation: 0,
+ ),
+ body: ListView(
+ children: ListTile.divideTiles(
+ context: context,
+ tiles: [
+ ListTile(
+ title: Text('技能组在线状态'),
+ subtitle: Text(_workGroupStatus),
+ onTap: () {
+ _getWorkGroupStatus();
+ },
+ ),
+ ListTile(
+ title: Text('客服在线状态'),
+ subtitle: Text(_agentStatus),
+ onTap: () {
+ _getAgentStatus();
+ },
+ ),
+ ],
+ ).toList()),
+ );
+ }
+
+ void _getWorkGroupStatus() {
+ // 获取技能组在线状态:当技能组中至少有一个客服在线时,显示在线
+ BytedeskKefu.getWorkGroupStatus(_workGroupWid).then((status) => {
+ print(status),
+ setState(() {
+ _workGroupStatus = status;
+ })
+ });
+ }
+
+ void _getAgentStatus() {
+ // 获取指定客服在线状态
+ BytedeskKefu.getAgentStatus(_agentUid).then((status) => {
+ print(status),
+ setState(() {
+ _agentStatus = status;
+ })
+ });
+ }
+}
diff --git a/bytedesk_kefu/example/lib/page/setting_page.dart b/bytedesk_kefu/example/lib/page/setting_page.dart
new file mode 100755
index 0000000..d189717
--- /dev/null
+++ b/bytedesk_kefu/example/lib/page/setting_page.dart
@@ -0,0 +1,72 @@
+import 'package:bytedesk_kefu/bytedesk_kefu.dart';
+import 'package:flutter/material.dart';
+import 'package:list_tile_switch/list_tile_switch.dart';
+
+// 消息声音、振动设置页面
+class SettingPage extends StatefulWidget {
+ SettingPage({Key? key}) : super(key: key);
+
+ @override
+ _SettingPageState createState() => _SettingPageState();
+}
+
+class _SettingPageState extends State {
+ bool _playAudioOnSendMessage = false;
+ bool _playAudioOnReceiveMessage = false;
+ bool _vibrateOnReceiveMessage = false;
+ //
+ @override
+ void initState() {
+ _playAudioOnSendMessage = BytedeskKefu.getPlayAudioOnSendMessage()!;
+ _playAudioOnReceiveMessage = BytedeskKefu.getPlayAudioOnReceiveMessage()!;
+ _vibrateOnReceiveMessage = BytedeskKefu.getVibrateOnReceiveMessage()!;
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text('消息设置'),
+ elevation: 0,
+ ),
+ body: ListView(
+ children: ListTile.divideTiles(
+ context: context,
+ tiles: [
+ ListTileSwitch(
+ value: _playAudioOnSendMessage,
+ onChanged: (value) {
+ setState(() {
+ _playAudioOnSendMessage = value;
+ });
+ BytedeskKefu.setPlayAudioOnSendMessage(value);
+ },
+ title: Text('发送消息时播放声音'),
+ ),
+ ListTileSwitch(
+ value: _playAudioOnReceiveMessage,
+ onChanged: (value) {
+ setState(() {
+ _playAudioOnReceiveMessage = value;
+ });
+ BytedeskKefu.setPlayAudioOnReceiveMessage(value);
+ },
+ title: Text('收到消息时播放声音'),
+ ),
+ ListTileSwitch(
+ value: _vibrateOnReceiveMessage,
+ onChanged: (value) {
+ setState(() {
+ _vibrateOnReceiveMessage = value;
+ });
+ // 注意:需要在安卓AndroidManifest.xml添加权限
+ BytedeskKefu.setVibrateOnReceiveMessage(value);
+ },
+ title: Text('收到消息时振动'),
+ ),
+ ],
+ ).toList()),
+ );
+ }
+}
diff --git a/bytedesk_kefu/example/lib/page/user_info_page.dart b/bytedesk_kefu/example/lib/page/user_info_page.dart
new file mode 100755
index 0000000..a8739c8
--- /dev/null
+++ b/bytedesk_kefu/example/lib/page/user_info_page.dart
@@ -0,0 +1,125 @@
+import 'package:bytedesk_kefu/bytedesk_kefu.dart';
+import 'package:bytedesk_kefu/util/bytedesk_constants.dart';
+import 'package:flutter/material.dart';
+import 'package:fluttertoast/fluttertoast.dart';
+
+// 需要首先调用anonymousLogin之后,再调用此接口
+// 自定义用户信息接口-对接APP用户信息
+class UserInfoPage extends StatefulWidget {
+ UserInfoPage({Key? key}) : super(key: key);
+
+ @override
+ _UserInfoPageState createState() => _UserInfoPageState();
+}
+
+class _UserInfoPageState extends State {
+ String _uid = ''; // 用户唯一uid
+ String _username = ''; // 用户唯一用户名
+ String _nickname = ''; // 用户昵称
+ String _avatar = BytedeskConstants.DEFAULT_AVATA; // 用户头像
+ String _description = ''; // 用户备注
+ @override
+ void initState() {
+ _getProfile();
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text('用户信息'),
+ elevation: 0,
+ ),
+ body: ListView(
+ children: ListTile.divideTiles(
+ context: context,
+ tiles: [
+ ListTile(
+ title: Text('唯一uid'),
+ subtitle: Text(_uid),
+ ),
+ ListTile(
+ title: Text('用户名'),
+ subtitle: Text(_username),
+ ),
+ ListTile(
+ title: Text('设置昵称(见代码)'),
+ subtitle: Text(_nickname),
+ onTap: () {
+ //
+ _setNickname();
+ },
+ ),
+ ListTile(
+ leading: Image.network(
+ _avatar,
+ height: 30,
+ width: 30,
+ ),
+ title: Text('设置头像(见代码)'),
+ onTap: () {
+ //
+ _setAvatar();
+ },
+ ),
+ ListTile(
+ title: Text('设置备注(见代码)'),
+ subtitle: Text(_description),
+ onTap: () {
+ //
+ _setDescription();
+ },
+ ),
+ ],
+ ).toList()),
+ );
+ }
+
+ void _getProfile() {
+ // 查询当前用户信息:昵称、头像
+ BytedeskKefu.getProfile().then((user) => {
+ setState(() {
+ _uid = user.uid!;
+ _username = user.username!;
+ _nickname = user.nickname!;
+ _avatar = user.avatar!;
+ _description = user.description!;
+ })
+ });
+ }
+
+ void _setNickname() {
+ // 可自定义用户昵称-客服端可见
+ String mynickname = '自定义APP昵称flutter';
+ BytedeskKefu.updateNickname(mynickname).then((user) => {
+ setState(() {
+ _nickname = mynickname;
+ }),
+ Fluttertoast.showToast(msg: "设置昵称成功")
+ });
+ }
+
+ void _setAvatar() {
+ // 可自定义用户头像url-客服端可见,注意:是头像网址,非本地图片路径
+ String myavatarurl =
+ 'https://chainsnow.oss-cn-shenzhen.aliyuncs.com/avatars/visitor_default_avatar.png'; // 头像网址url
+ BytedeskKefu.updateAvatar(myavatarurl).then((user) => {
+ setState(() {
+ _avatar = myavatarurl;
+ }),
+ Fluttertoast.showToast(msg: "设置头像成功")
+ });
+ }
+
+ void _setDescription() {
+ // 可自定义用户昵称-客服端可见
+ String description = '自定义用户备注';
+ BytedeskKefu.updateDescription(description).then((user) => {
+ setState(() {
+ _description = description;
+ }),
+ Fluttertoast.showToast(msg: "设置备注成功")
+ });
+ }
+}
diff --git a/bytedesk_kefu/example/macos/.gitignore b/bytedesk_kefu/example/macos/.gitignore
new file mode 100644
index 0000000..d2fd377
--- /dev/null
+++ b/bytedesk_kefu/example/macos/.gitignore
@@ -0,0 +1,6 @@
+# Flutter-related
+**/Flutter/ephemeral/
+**/Pods/
+
+# Xcode-related
+**/xcuserdata/
diff --git a/bytedesk_kefu/example/macos/Flutter/Flutter-Debug.xcconfig b/bytedesk_kefu/example/macos/Flutter/Flutter-Debug.xcconfig
new file mode 100644
index 0000000..4b81f9b
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Flutter/Flutter-Debug.xcconfig
@@ -0,0 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/bytedesk_kefu/example/macos/Flutter/Flutter-Release.xcconfig b/bytedesk_kefu/example/macos/Flutter/Flutter-Release.xcconfig
new file mode 100644
index 0000000..5caa9d1
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Flutter/Flutter-Release.xcconfig
@@ -0,0 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/bytedesk_kefu/example/macos/Flutter/GeneratedPluginRegistrant.swift b/bytedesk_kefu/example/macos/Flutter/GeneratedPluginRegistrant.swift
new file mode 100644
index 0000000..b7296b3
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -0,0 +1,24 @@
+//
+// Generated file. Do not edit.
+//
+
+import FlutterMacOS
+import Foundation
+
+import audioplayers
+import bytedesk_kefu
+import package_info
+import path_provider_macos
+import shared_preferences_macos
+import sqflite
+import wakelock_macos
+
+func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+ AudioplayersPlugin.register(with: registry.registrar(forPlugin: "AudioplayersPlugin"))
+ BytedeskKefuPlugin.register(with: registry.registrar(forPlugin: "BytedeskKefuPlugin"))
+ FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin"))
+ PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
+ SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
+ SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
+ WakelockMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockMacosPlugin"))
+}
diff --git a/bytedesk_kefu/example/macos/Podfile b/bytedesk_kefu/example/macos/Podfile
new file mode 100644
index 0000000..dade8df
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Podfile
@@ -0,0 +1,40 @@
+platform :osx, '10.11'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+ 'Debug' => :debug,
+ 'Profile' => :release,
+ 'Release' => :release,
+}
+
+def flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
+ end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
+ end
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_macos_podfile_setup
+
+target 'Runner' do
+ use_frameworks!
+ use_modular_headers!
+
+ flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ flutter_additional_macos_build_settings(target)
+ end
+end
diff --git a/bytedesk_kefu/example/macos/Runner.xcodeproj/project.pbxproj b/bytedesk_kefu/example/macos/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..de45192
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,632 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 51;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
+ buildPhases = (
+ 33CC111E2044C6BF0003C045 /* ShellScript */,
+ );
+ dependencies = (
+ );
+ name = "Flutter Assemble";
+ productName = FLX;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
+ B116FB6D6F7C17AD14838202 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92112FB12B6A4D12E1F8251F /* Pods_Runner.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 33CC111A2044C6BA0003C045;
+ remoteInfo = FLX;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 33CC110E2044A8840003C045 /* Bundle Framework */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ );
+ name = "Bundle Framework";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 2922F96554178579FF237F02 /* 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 = ""; };
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; };
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; };
+ 33CC10ED2044A3C60003C045 /* bytedesk_kefu_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = bytedesk_kefu_example.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; };
+ 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
+ 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; };
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; };
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; };
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; };
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; };
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; };
+ 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; };
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; };
+ 5C2970447709BFF43B13A2DC /* 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 = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; };
+ 92112FB12B6A4D12E1F8251F /* 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; path = Debug.xcconfig; sourceTree = ""; };
+ DD709F0552D4479886D058C8 /* 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 = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 33CC10EA2044A3C60003C045 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B116FB6D6F7C17AD14838202 /* Pods_Runner.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 33BA886A226E78AF003329D5 /* Configs */ = {
+ isa = PBXGroup;
+ children = (
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
+ );
+ path = Configs;
+ sourceTree = "";
+ };
+ 33CC10E42044A3C60003C045 = {
+ isa = PBXGroup;
+ children = (
+ 33FAB671232836740065AC1E /* Runner */,
+ 33CEB47122A05771004F2AC0 /* Flutter */,
+ 33CC10EE2044A3C60003C045 /* Products */,
+ D73912EC22F37F3D000D13A0 /* Frameworks */,
+ 7C73FB1E0B9D9A366BA37E4C /* Pods */,
+ );
+ sourceTree = "";
+ };
+ 33CC10EE2044A3C60003C045 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10ED2044A3C60003C045 /* bytedesk_kefu_example.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 33CC11242044D66E0003C045 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */,
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */,
+ 33CC10F72044A3C60003C045 /* Info.plist */,
+ );
+ name = Resources;
+ path = ..;
+ sourceTree = "";
+ };
+ 33CEB47122A05771004F2AC0 /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
+ );
+ path = Flutter;
+ sourceTree = "";
+ };
+ 33FAB671232836740065AC1E /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */,
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */,
+ 33E51914231749380026EE4D /* Release.entitlements */,
+ 33CC11242044D66E0003C045 /* Resources */,
+ 33BA886A226E78AF003329D5 /* Configs */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+ 7C73FB1E0B9D9A366BA37E4C /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ DD709F0552D4479886D058C8 /* Pods-Runner.debug.xcconfig */,
+ 2922F96554178579FF237F02 /* Pods-Runner.release.xcconfig */,
+ 5C2970447709BFF43B13A2DC /* Pods-Runner.profile.xcconfig */,
+ );
+ name = Pods;
+ path = Pods;
+ sourceTree = "";
+ };
+ D73912EC22F37F3D000D13A0 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 92112FB12B6A4D12E1F8251F /* Pods_Runner.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 33CC10EC2044A3C60003C045 /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ 88DE65861EE7BB7782A96423 /* [CP] Check Pods Manifest.lock */,
+ 33CC10E92044A3C60003C045 /* Sources */,
+ 33CC10EA2044A3C60003C045 /* Frameworks */,
+ 33CC10EB2044A3C60003C045 /* Resources */,
+ 33CC110E2044A8840003C045 /* Bundle Framework */,
+ 3399D490228B24CF009A79C7 /* ShellScript */,
+ 929100175D5BE2BD14AA7CC6 /* [CP] Embed Pods Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */,
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 33CC10ED2044A3C60003C045 /* bytedesk_kefu_example.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 33CC10E52044A3C60003C045 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0920;
+ LastUpgradeCheck = 0930;
+ ORGANIZATIONNAME = "";
+ TargetAttributes = {
+ 33CC10EC2044A3C60003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ LastSwiftMigration = 1100;
+ ProvisioningStyle = Automatic;
+ SystemCapabilities = {
+ com.apple.Sandbox = {
+ enabled = 1;
+ };
+ };
+ };
+ 33CC111A2044C6BA0003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Manual;
+ };
+ };
+ };
+ buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 33CC10E42044A3C60003C045;
+ productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 33CC10EC2044A3C60003C045 /* Runner */,
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 33CC10EB2044A3C60003C045 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 3399D490228B24CF009A79C7 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
+ };
+ 33CC111E2044C6BF0003C045 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ Flutter/ephemeral/FlutterInputs.xcfilelist,
+ );
+ inputPaths = (
+ Flutter/ephemeral/tripwire,
+ );
+ outputFileListPaths = (
+ Flutter/ephemeral/FlutterOutputs.xcfilelist,
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
+ };
+ 88DE65861EE7BB7782A96423 /* [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;
+ };
+ 929100175D5BE2BD14AA7CC6 /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 33CC10E92044A3C60003C045 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
+ targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 33CC10F52044A3C60003C045 /* Base */,
+ );
+ name = MainMenu.xib;
+ path = Runner;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 338D0CE9231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ 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_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ 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_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Profile;
+ };
+ 338D0CEA231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Profile;
+ };
+ 338D0CEB231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Profile;
+ };
+ 33CC10F92044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ 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_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ 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_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ 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_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 33CC10FA2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ 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_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ 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_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Release;
+ };
+ 33CC10FC2044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ 33CC10FD2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
+ 33CC111C2044C6BA0003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 33CC111D2044C6BA0003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10F92044A3C60003C045 /* Debug */,
+ 33CC10FA2044A3C60003C045 /* Release */,
+ 338D0CE9231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10FC2044A3C60003C045 /* Debug */,
+ 33CC10FD2044A3C60003C045 /* Release */,
+ 338D0CEA231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC111C2044C6BA0003C045 /* Debug */,
+ 33CC111D2044C6BA0003C045 /* Release */,
+ 338D0CEB231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 33CC10E52044A3C60003C045 /* Project object */;
+}
diff --git a/bytedesk_kefu/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/bytedesk_kefu/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/bytedesk_kefu/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/bytedesk_kefu/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 0000000..2da6296
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bytedesk_kefu/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/bytedesk_kefu/example/macos/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..21a3cc1
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/bytedesk_kefu/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/bytedesk_kefu/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/bytedesk_kefu/example/macos/Runner/AppDelegate.swift b/bytedesk_kefu/example/macos/Runner/AppDelegate.swift
new file mode 100644
index 0000000..d53ef64
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner/AppDelegate.swift
@@ -0,0 +1,9 @@
+import Cocoa
+import FlutterMacOS
+
+@NSApplicationMain
+class AppDelegate: FlutterAppDelegate {
+ override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
+ return true
+ }
+}
diff --git a/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..a2ec33f
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,68 @@
+{
+ "images" : [
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "app_icon_16.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "app_icon_32.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "app_icon_32.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "app_icon_64.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "app_icon_128.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "app_icon_256.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "app_icon_256.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "app_icon_512.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "app_icon_512.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "app_icon_1024.png",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
new file mode 100644
index 0000000..3c4935a
Binary files /dev/null and b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ
diff --git a/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
new file mode 100644
index 0000000..ed4cc16
Binary files /dev/null and b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ
diff --git a/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
new file mode 100644
index 0000000..483be61
Binary files /dev/null and b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ
diff --git a/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
new file mode 100644
index 0000000..bcbf36d
Binary files /dev/null and b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ
diff --git a/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
new file mode 100644
index 0000000..9c0a652
Binary files /dev/null and b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ
diff --git a/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
new file mode 100644
index 0000000..e71a726
Binary files /dev/null and b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ
diff --git a/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
new file mode 100644
index 0000000..8a31fe2
Binary files /dev/null and b/bytedesk_kefu/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ
diff --git a/bytedesk_kefu/example/macos/Runner/Base.lproj/MainMenu.xib b/bytedesk_kefu/example/macos/Runner/Base.lproj/MainMenu.xib
new file mode 100644
index 0000000..537341a
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner/Base.lproj/MainMenu.xib
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bytedesk_kefu/example/macos/Runner/Configs/AppInfo.xcconfig b/bytedesk_kefu/example/macos/Runner/Configs/AppInfo.xcconfig
new file mode 100644
index 0000000..ffa6e69
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner/Configs/AppInfo.xcconfig
@@ -0,0 +1,14 @@
+// Application-level settings for the Runner target.
+//
+// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
+// future. If not, the values below would default to using the project name when this becomes a
+// 'flutter create' template.
+
+// The application's name. By default this is also the title of the Flutter window.
+PRODUCT_NAME = bytedesk_kefu_example
+
+// The application's bundle identifier
+PRODUCT_BUNDLE_IDENTIFIER = com.bytedesk.bytedeskKefuExample
+
+// The copyright displayed in application information
+PRODUCT_COPYRIGHT = Copyright © 2021 com.bytedesk. All rights reserved.
diff --git a/bytedesk_kefu/example/macos/Runner/Configs/Debug.xcconfig b/bytedesk_kefu/example/macos/Runner/Configs/Debug.xcconfig
new file mode 100644
index 0000000..36b0fd9
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner/Configs/Debug.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Debug.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/bytedesk_kefu/example/macos/Runner/Configs/Release.xcconfig b/bytedesk_kefu/example/macos/Runner/Configs/Release.xcconfig
new file mode 100644
index 0000000..dff4f49
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner/Configs/Release.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Release.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/bytedesk_kefu/example/macos/Runner/Configs/Warnings.xcconfig b/bytedesk_kefu/example/macos/Runner/Configs/Warnings.xcconfig
new file mode 100644
index 0000000..42bcbf4
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner/Configs/Warnings.xcconfig
@@ -0,0 +1,13 @@
+WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
+GCC_WARN_UNDECLARED_SELECTOR = YES
+CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
+CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
+CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
+CLANG_WARN_PRAGMA_PACK = YES
+CLANG_WARN_STRICT_PROTOTYPES = YES
+CLANG_WARN_COMMA = YES
+GCC_WARN_STRICT_SELECTOR_MATCH = YES
+CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
+CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
+GCC_WARN_SHADOW = YES
+CLANG_WARN_UNREACHABLE_CODE = YES
diff --git a/bytedesk_kefu/example/macos/Runner/DebugProfile.entitlements b/bytedesk_kefu/example/macos/Runner/DebugProfile.entitlements
new file mode 100644
index 0000000..dddb8a3
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner/DebugProfile.entitlements
@@ -0,0 +1,12 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+ com.apple.security.cs.allow-jit
+
+ com.apple.security.network.server
+
+
+
diff --git a/bytedesk_kefu/example/macos/Runner/Info.plist b/bytedesk_kefu/example/macos/Runner/Info.plist
new file mode 100644
index 0000000..4789daa
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIconFile
+
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSMinimumSystemVersion
+ $(MACOSX_DEPLOYMENT_TARGET)
+ NSHumanReadableCopyright
+ $(PRODUCT_COPYRIGHT)
+ NSMainNibFile
+ MainMenu
+ NSPrincipalClass
+ NSApplication
+
+
diff --git a/bytedesk_kefu/example/macos/Runner/MainFlutterWindow.swift b/bytedesk_kefu/example/macos/Runner/MainFlutterWindow.swift
new file mode 100644
index 0000000..2722837
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner/MainFlutterWindow.swift
@@ -0,0 +1,15 @@
+import Cocoa
+import FlutterMacOS
+
+class MainFlutterWindow: NSWindow {
+ override func awakeFromNib() {
+ let flutterViewController = FlutterViewController.init()
+ let windowFrame = self.frame
+ self.contentViewController = flutterViewController
+ self.setFrame(windowFrame, display: true)
+
+ RegisterGeneratedPlugins(registry: flutterViewController)
+
+ super.awakeFromNib()
+ }
+}
diff --git a/bytedesk_kefu/example/macos/Runner/Release.entitlements b/bytedesk_kefu/example/macos/Runner/Release.entitlements
new file mode 100644
index 0000000..852fa1a
--- /dev/null
+++ b/bytedesk_kefu/example/macos/Runner/Release.entitlements
@@ -0,0 +1,8 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+
+
diff --git a/bytedesk_kefu/example/pubspec.yaml b/bytedesk_kefu/example/pubspec.yaml
new file mode 100644
index 0000000..fcd0f95
--- /dev/null
+++ b/bytedesk_kefu/example/pubspec.yaml
@@ -0,0 +1,87 @@
+name: bytedesk_kefu_example
+description: Demonstrates how to use the bytedesk_kefu plugin.
+
+# The following line prevents the package from being accidentally published to
+# pub.dev using `pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+environment:
+ sdk: ">=2.12.0 <3.0.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+ # 事件通知总线
+ # https://pub.dev/packages/event_bus
+ event_bus: ^2.0.0
+ # toast https://pub.dev/packages/fluttertoast
+ fluttertoast: ^8.0.9
+ # 消息设置switch https://pub.dev/packages/list_tile_switch
+ list_tile_switch: ^1.0.0
+ # 应用内-顶部通知栏 https://pub.dev/packages/overlay_support/
+ overlay_support: ^1.2.1
+ # 播放提示音 https://pub.dev/packages/audioplayers
+ # audioplayers: ^0.20.1
+ # 振动 https://pub.dev/packages/vibration
+ # 针对报错fatal error: 'vibration/vibration-Swift.h' file not found #import , ld: library not found for -lvibration
+ # 请在ios/Podfile中添加:use_frameworks!
+ # vibration: ^1.7.3
+
+ bytedesk_kefu:
+ # When depending on this package from a real application you should use:
+ # bytedesk_kefu: ^x.y.z
+ # See https://dart.dev/tools/pub/dependencies#version-constraints
+ # The example app is bundled with the plugin so we use a path dependency on
+ # the parent directory to use the current plugin's version.
+ path: ../
+
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+ cupertino_icons: ^1.0.2
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+# 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/audio/
+ - assets/images/feedback/
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware.
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/assets-and-images/#from-packages
+
+ # 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
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/bytedesk_kefu/example/test/widget_test.dart b/bytedesk_kefu/example/test/widget_test.dart
new file mode 100644
index 0000000..eec833e
--- /dev/null
+++ b/bytedesk_kefu/example/test/widget_test.dart
@@ -0,0 +1,27 @@
+// This is a basic Flutter widget test.
+//
+// To perform an interaction with a widget in your test, use the WidgetTester
+// utility that Flutter provides. For example, you can send tap and scroll
+// gestures. You can also use WidgetTester to find child widgets in the widget
+// tree, read text, and verify that the values of widget properties are correct.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:bytedesk_kefu_example/main.dart';
+
+void main() {
+ testWidgets('Verify Platform version', (WidgetTester tester) async {
+ // Build our app and trigger a frame.
+ await tester.pumpWidget(MyApp());
+
+ // Verify that platform version is retrieved.
+ expect(
+ find.byWidgetPredicate(
+ (Widget widget) =>
+ widget is Text && widget.data!.startsWith('Running on:'),
+ ),
+ findsOneWidget,
+ );
+ });
+}
diff --git a/bytedesk_kefu/example/web/favicon.png b/bytedesk_kefu/example/web/favicon.png
new file mode 100644
index 0000000..8aaa46a
Binary files /dev/null and b/bytedesk_kefu/example/web/favicon.png differ
diff --git a/bytedesk_kefu/example/web/icons/Icon-192.png b/bytedesk_kefu/example/web/icons/Icon-192.png
new file mode 100644
index 0000000..b749bfe
Binary files /dev/null and b/bytedesk_kefu/example/web/icons/Icon-192.png differ
diff --git a/bytedesk_kefu/example/web/icons/Icon-512.png b/bytedesk_kefu/example/web/icons/Icon-512.png
new file mode 100644
index 0000000..88cfd48
Binary files /dev/null and b/bytedesk_kefu/example/web/icons/Icon-512.png differ
diff --git a/bytedesk_kefu/example/web/index.html b/bytedesk_kefu/example/web/index.html
new file mode 100644
index 0000000..c919473
--- /dev/null
+++ b/bytedesk_kefu/example/web/index.html
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bytedesk_kefu_example
+
+
+
+
+
+
+
+
diff --git a/bytedesk_kefu/example/web/manifest.json b/bytedesk_kefu/example/web/manifest.json
new file mode 100644
index 0000000..0dba733
--- /dev/null
+++ b/bytedesk_kefu/example/web/manifest.json
@@ -0,0 +1,23 @@
+{
+ "name": "bytedesk_kefu_example",
+ "short_name": "bytedesk_kefu_example",
+ "start_url": ".",
+ "display": "standalone",
+ "background_color": "#0175C2",
+ "theme_color": "#0175C2",
+ "description": "Demonstrates how to use the bytedesk_kefu plugin.",
+ "orientation": "portrait-primary",
+ "prefer_related_applications": false,
+ "icons": [
+ {
+ "src": "icons/Icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ]
+}
diff --git a/bytedesk_kefu/home.jpeg b/bytedesk_kefu/home.jpeg
new file mode 100755
index 0000000..94c81f2
Binary files /dev/null and b/bytedesk_kefu/home.jpeg differ
diff --git a/bytedesk_kefu/ios/.gitignore b/bytedesk_kefu/ios/.gitignore
new file mode 100644
index 0000000..aa479fd
--- /dev/null
+++ b/bytedesk_kefu/ios/.gitignore
@@ -0,0 +1,37 @@
+.idea/
+.vagrant/
+.sconsign.dblite
+.svn/
+
+.DS_Store
+*.swp
+profile
+
+DerivedData/
+build/
+GeneratedPluginRegistrant.h
+GeneratedPluginRegistrant.m
+
+.generated/
+
+*.pbxuser
+*.mode1v3
+*.mode2v3
+*.perspectivev3
+
+!default.pbxuser
+!default.mode1v3
+!default.mode2v3
+!default.perspectivev3
+
+xcuserdata
+
+*.moved-aside
+
+*.pyc
+*sync/
+Icon?
+.tags*
+
+/Flutter/Generated.xcconfig
+/Flutter/flutter_export_environment.sh
\ No newline at end of file
diff --git a/bytedesk_kefu/ios/Assets/.gitkeep b/bytedesk_kefu/ios/Assets/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/bytedesk_kefu/ios/Classes/BytedeskKefuPlugin.h b/bytedesk_kefu/ios/Classes/BytedeskKefuPlugin.h
new file mode 100644
index 0000000..6c50d5c
--- /dev/null
+++ b/bytedesk_kefu/ios/Classes/BytedeskKefuPlugin.h
@@ -0,0 +1,4 @@
+#import
+
+@interface BytedeskKefuPlugin : NSObject
+@end
diff --git a/bytedesk_kefu/ios/Classes/BytedeskKefuPlugin.m b/bytedesk_kefu/ios/Classes/BytedeskKefuPlugin.m
new file mode 100644
index 0000000..268a740
--- /dev/null
+++ b/bytedesk_kefu/ios/Classes/BytedeskKefuPlugin.m
@@ -0,0 +1,20 @@
+#import "BytedeskKefuPlugin.h"
+
+@implementation BytedeskKefuPlugin
++ (void)registerWithRegistrar:(NSObject*)registrar {
+ FlutterMethodChannel* channel = [FlutterMethodChannel
+ methodChannelWithName:@"bytedesk_kefu"
+ binaryMessenger:[registrar messenger]];
+ BytedeskKefuPlugin* instance = [[BytedeskKefuPlugin alloc] init];
+ [registrar addMethodCallDelegate:instance channel:channel];
+}
+
+- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
+ if ([@"getPlatformVersion" isEqualToString:call.method]) {
+ result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
+ } else {
+ result(FlutterMethodNotImplemented);
+ }
+}
+
+@end
diff --git a/bytedesk_kefu/ios/bytedesk_kefu.podspec b/bytedesk_kefu/ios/bytedesk_kefu.podspec
new file mode 100644
index 0000000..346efda
--- /dev/null
+++ b/bytedesk_kefu/ios/bytedesk_kefu.podspec
@@ -0,0 +1,23 @@
+#
+# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
+# Run `pod lib lint bytedesk_kefu.podspec` to validate before publishing.
+#
+Pod::Spec.new do |s|
+ s.name = 'bytedesk_kefu'
+ s.version = '0.0.1'
+ s.summary = 'A new flutter plugin project.'
+ s.description = <<-DESC
+A new flutter plugin project.
+ DESC
+ s.homepage = 'http://example.com'
+ s.license = { :file => '../LICENSE' }
+ s.author = { 'Your Company' => 'email@example.com' }
+ s.source = { :path => '.' }
+ s.source_files = 'Classes/**/*'
+ s.public_header_files = 'Classes/**/*.h'
+ s.dependency 'Flutter'
+ s.platform = :ios, '8.0'
+
+ # Flutter.framework does not contain a i386 slice.
+ s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
+end
diff --git a/bytedesk_kefu/lib/blocs/contact_bloc/bloc.dart b/bytedesk_kefu/lib/blocs/contact_bloc/bloc.dart
new file mode 100755
index 0000000..54d62d3
--- /dev/null
+++ b/bytedesk_kefu/lib/blocs/contact_bloc/bloc.dart
@@ -0,0 +1,3 @@
+export 'contact_bloc.dart';
+export 'contact_event.dart';
+export 'contact_state.dart';
diff --git a/bytedesk_kefu/lib/blocs/contact_bloc/contact_bloc.dart b/bytedesk_kefu/lib/blocs/contact_bloc/contact_bloc.dart
new file mode 100755
index 0000000..8ad73ee
--- /dev/null
+++ b/bytedesk_kefu/lib/blocs/contact_bloc/contact_bloc.dart
@@ -0,0 +1,36 @@
+import 'dart:async';
+import 'package:bloc/bloc.dart';
+import 'package:bytedesk_kefu/blocs/contact_bloc/bloc.dart';
+import 'package:bytedesk_kefu/repositories/contact_repository.dart';
+
+class ContactBloc extends Bloc {
+ final ContactRepository contactRepository = new ContactRepository();
+
+ // ContactBloc({@required this.contactRepository});
+ ContactBloc() : super(ContactUninitialized());
+
+ // @override
+ // ContactState get initialState => ContactUninitialized();
+
+ @override
+ Stream mapEventToState(ContactEvent event) async* {
+ //
+ if (event is RefreshContactEvent) {
+ yield* _mapRefreshContactToState(event);
+ } else {
+ //
+ }
+ }
+
+ Stream _mapRefreshContactToState(
+ RefreshContactEvent event) async* {
+ yield ContactLoading();
+ try {
+ // final List contactList = await contactRepository.getContacts();
+ // yield ContactLoadSuccess(contactList);
+ } catch (error) {
+ print(error);
+ yield ContactLoadError();
+ }
+ }
+}
diff --git a/bytedesk_kefu/lib/blocs/contact_bloc/contact_event.dart b/bytedesk_kefu/lib/blocs/contact_bloc/contact_event.dart
new file mode 100755
index 0000000..c41be0f
--- /dev/null
+++ b/bytedesk_kefu/lib/blocs/contact_bloc/contact_event.dart
@@ -0,0 +1,29 @@
+import 'package:equatable/equatable.dart';
+import 'package:meta/meta.dart';
+
+@immutable
+abstract class ContactEvent extends Equatable {
+ // ContactEvent([List props = const []]) : super(props);
+ const ContactEvent();
+
+ @override
+ List