├── .gitignore
├── .idea
├── codeStyles
│ └── Project.xml
├── libraries
│ ├── Dart_Packages.xml
│ ├── Dart_SDK.xml
│ └── Flutter_Plugins.xml
└── misc.xml
├── .metadata
├── README.md
├── android
├── .gitignore
├── .idea
│ ├── codeStyles
│ │ └── Project.xml
│ ├── gradle.xml
│ ├── misc.xml
│ └── runConfigurations.xml
├── app
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── flutterim
│ │ │ └── example
│ │ │ └── flutterapp
│ │ │ └── MainActivity.java
│ │ └── res
│ │ ├── drawable
│ │ └── launch_background.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ └── values
│ │ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
├── assets
├── audio
│ ├── message.wav
│ └── request.mp3
└── images
│ ├── clear.png
│ ├── favorites.png
│ ├── hachker.jpg
│ ├── head.png
│ ├── icon.png
│ ├── message.png
│ ├── new_trend
│ ├── ai.jpeg
│ └── block_chain.jpeg
│ ├── password.png
│ ├── person.png
│ ├── receiver.png
│ ├── sender.png
│ ├── splash.jpeg
│ ├── user.png
│ └── user_background.jpeg
├── demonstration_picture
├── demo1.gif
├── demo2.gif
├── demo3.gif
├── demo4.gif
└── demo5.gif
├── flutter_app.iml
├── flutter_app_android.iml
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ └── contents.xcworkspacedata
└── Runner
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ └── Icon-App-83.5x83.5@2x.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ └── main.m
├── lib
├── com
│ └── navigation
│ │ ├── component
│ │ ├── chart_message_item.dart
│ │ ├── contacts_list_item.dart
│ │ ├── message_list_item.dart
│ │ ├── new_trend_star.dart
│ │ ├── search_contacts_item.dart
│ │ ├── search_item.dart
│ │ ├── system_propel.dart
│ │ └── user_info_item.dart
│ │ ├── models
│ │ ├── contacts_list_model.dart
│ │ ├── message_list_item_model.dart
│ │ ├── new_trend_model.dart
│ │ └── system_propel_model.dart
│ │ ├── netwok
│ │ └── socket_handler.dart
│ │ ├── page
│ │ ├── login.dart
│ │ ├── register.dart
│ │ ├── subpage
│ │ │ ├── about_program.dart
│ │ │ ├── address_list.dart
│ │ │ ├── application_min.dart
│ │ │ ├── application_setting.dart
│ │ │ ├── chart_dialog.dart
│ │ │ ├── contacts.dart
│ │ │ ├── contacts_search.dart
│ │ │ ├── message.dart
│ │ │ ├── new_trend.dart
│ │ │ ├── new_trend
│ │ │ │ ├── artificial_intelligence.dart
│ │ │ │ └── block_chain.dart
│ │ │ ├── picture_select.dart
│ │ │ ├── search.dart
│ │ │ ├── sweep_code.dart
│ │ │ ├── system_inform.dart
│ │ │ ├── user_info.dart
│ │ │ └── webview.dart
│ │ └── user.dart
│ │ └── utils
│ │ ├── application.dart
│ │ ├── constant.dart
│ │ ├── file_handler.dart
│ │ ├── system_announce.dart
│ │ └── utils.dart
├── main.dart
└── splash_screne.dart
├── pubspec.lock
├── pubspec.yaml
├── res
├── images
│ └── beauty
│ │ ├── 1.jpeg
│ │ ├── 2.jpeg
│ │ └── 3.jpeg
└── values
│ └── strings_en.arb
└── test
└── widget_test.dart
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .dart_tool/
3 |
4 | .packages
5 | .pub/
6 |
7 | build/
8 |
9 | .flutter-plugins
10 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.idea/libraries/Dart_SDK.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/.idea/libraries/Flutter_Plugins.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 66091f969653fd3535b265ddcd87436901858a1d
8 | channel: dev
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 畅聊 v0.2
2 | ## 构建环境:
3 | flutter dart java
4 | ## 功能
5 | 即时通信
6 | ## 服务器
7 | 服务端采用github上开源项目[social-vertx](https://github.com/whitewoodcity/social-vertex),并且严格遵守该项目通讯协议
8 | ## 项目整体架构
9 | 
10 |
11 | ### 视屏图片
12 | #### 图片一
13 | 
14 | #### 图片二
15 | 
16 | #### 图片三
17 | 
18 | #### 图片四
19 | 
20 | #### 图片五
21 | 
22 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | *.class
3 | .gradle
4 | /local.properties
5 | /.idea/workspace.xml
6 | /.idea/libraries
7 | .DS_Store
8 | /build
9 | /captures
10 | GeneratedPluginRegistrant.java
11 |
--------------------------------------------------------------------------------
/android/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/android/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
--------------------------------------------------------------------------------
/android/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/android/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | throw new GradleException("versionCode not found. Define flutter.versionCode in the local.properties file.")
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | throw new GradleException("versionName not found. Define flutter.versionName in the local.properties file.")
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
26 |
27 | android {
28 | compileSdkVersion 27
29 |
30 | lintOptions {
31 | disable 'InvalidPackage'
32 | }
33 |
34 | defaultConfig {
35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
36 | applicationId "flutterim.example.flutterapp"
37 | minSdkVersion 21
38 | targetSdkVersion 27
39 | versionCode flutterVersionCode.toInteger()
40 | versionName flutterVersionName
41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
42 | }
43 |
44 | buildTypes {
45 | release {
46 | // TODO: Add your own signing config for the release build.
47 | // Signing with the debug keys for now, so `flutter run --release` works.
48 | signingConfig signingConfigs.debug
49 | }
50 | }
51 | }
52 |
53 | flutter {
54 | source '../..'
55 | }
56 |
57 | dependencies {
58 | testImplementation 'junit:junit:4.12'
59 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
61 | }
62 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
15 |
19 |
26 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/android/app/src/main/java/flutterim/example/flutterapp/MainActivity.java:
--------------------------------------------------------------------------------
1 | package flutterim.example.flutterapp;
2 |
3 | import android.os.Bundle;
4 | import io.flutter.app.FlutterActivity;
5 | import io.flutter.plugins.GeneratedPluginRegistrant;
6 |
7 | public class MainActivity extends FlutterActivity {
8 | @Override
9 | protected void onCreate(Bundle savedInstanceState) {
10 | super.onCreate(savedInstanceState);
11 | GeneratedPluginRegistrant.registerWith(this);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.1.4'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | google()
15 | jcenter()
16 | }
17 | }
18 |
19 | rootProject.buildDir = '../build'
20 | subprojects {
21 | project.buildDir = "${rootProject.buildDir}/${project.name}"
22 | }
23 | subprojects {
24 | project.evaluationDependsOn(':app')
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/assets/audio/message.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/audio/message.wav
--------------------------------------------------------------------------------
/assets/audio/request.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/audio/request.mp3
--------------------------------------------------------------------------------
/assets/images/clear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/clear.png
--------------------------------------------------------------------------------
/assets/images/favorites.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/favorites.png
--------------------------------------------------------------------------------
/assets/images/hachker.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/hachker.jpg
--------------------------------------------------------------------------------
/assets/images/head.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/head.png
--------------------------------------------------------------------------------
/assets/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/icon.png
--------------------------------------------------------------------------------
/assets/images/message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/message.png
--------------------------------------------------------------------------------
/assets/images/new_trend/ai.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/new_trend/ai.jpeg
--------------------------------------------------------------------------------
/assets/images/new_trend/block_chain.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/new_trend/block_chain.jpeg
--------------------------------------------------------------------------------
/assets/images/password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/password.png
--------------------------------------------------------------------------------
/assets/images/person.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/person.png
--------------------------------------------------------------------------------
/assets/images/receiver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/receiver.png
--------------------------------------------------------------------------------
/assets/images/sender.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/sender.png
--------------------------------------------------------------------------------
/assets/images/splash.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/splash.jpeg
--------------------------------------------------------------------------------
/assets/images/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/user.png
--------------------------------------------------------------------------------
/assets/images/user_background.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/assets/images/user_background.jpeg
--------------------------------------------------------------------------------
/demonstration_picture/demo1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/demonstration_picture/demo1.gif
--------------------------------------------------------------------------------
/demonstration_picture/demo2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/demonstration_picture/demo2.gif
--------------------------------------------------------------------------------
/demonstration_picture/demo3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/demonstration_picture/demo3.gif
--------------------------------------------------------------------------------
/demonstration_picture/demo4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/demonstration_picture/demo4.gif
--------------------------------------------------------------------------------
/demonstration_picture/demo5.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/demonstration_picture/demo5.gif
--------------------------------------------------------------------------------
/flutter_app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/flutter_app_android.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vagrant/
3 | .sconsign.dblite
4 | .svn/
5 |
6 | .DS_Store
7 | *.swp
8 | profile
9 |
10 | DerivedData/
11 | build/
12 | GeneratedPluginRegistrant.h
13 | GeneratedPluginRegistrant.m
14 |
15 | .generated/
16 |
17 | *.pbxuser
18 | *.mode1v3
19 | *.mode2v3
20 | *.perspectivev3
21 |
22 | !default.pbxuser
23 | !default.mode1v3
24 | !default.mode2v3
25 | !default.perspectivev3
26 |
27 | xcuserdata
28 |
29 | *.moved-aside
30 |
31 | *.pyc
32 | *sync/
33 | Icon?
34 | .tags*
35 |
36 | /Flutter/app.flx
37 | /Flutter/app.zip
38 | /Flutter/flutter_assets/
39 | /Flutter/App.framework
40 | /Flutter/Flutter.framework
41 | /Flutter/Generated.xcconfig
42 | /ServiceDefinitions.json
43 |
44 | Pods/
45 | .symlinks/
46 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
56 |
58 |
64 |
65 |
66 |
67 |
68 |
69 |
75 |
77 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : FlutterAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #include "AppDelegate.h"
2 | #include "GeneratedPluginRegistrant.h"
3 |
4 | @implementation AppDelegate
5 |
6 | - (BOOL)application:(UIApplication *)application
7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
8 | [GeneratedPluginRegistrant registerWithRegistry:self];
9 | // Override point for customization after application launch.
10 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
11 | }
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GZYangKui/ChangLiao-Mobile/a74ca543c63048d174b8996de46c9ff2952378c3/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | 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.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | flutter_app
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ios/Runner/main.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char* argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lib/com/navigation/component/chart_message_item.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui' as ui;
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_app/com/navigation/utils/constant.dart' as constants;
6 | import 'package:flutter_app/com/navigation/utils/application.dart'
7 | as application;
8 |
9 | ///
10 | ///
11 | /// @_message代表一条消息判其是否以{[|@#\$%|]}结尾来区分发送者身份
12 | ///
13 |
14 | class ChartMessageItem extends StatefulWidget {
15 | final String _message;
16 |
17 | ChartMessageItem(this._message);
18 |
19 | @override
20 | ChartMessageItemState createState() => ChartMessageItemState();
21 | }
22 |
23 | class ChartMessageItemState extends State {
24 | ChartMessageItemState();
25 |
26 | @override
27 | Widget build(BuildContext context) {
28 | return widget._message.endsWith(constants.messageOwn)
29 | ? _ownSend()
30 | : _friendSend();
31 | }
32 |
33 | Widget _friendSend() {
34 | return Row(
35 | children: [
36 | CircleAvatar(
37 | backgroundColor: Colors.grey,
38 | child: application.images["sender"],
39 | ),
40 | Container(
41 | foregroundDecoration: ShapeDecoration(
42 | shape: RoundedRectangleBorder(
43 | side: BorderSide(color: Colors.lightBlue),
44 | borderRadius: BorderRadius.all(
45 | Radius.circular(10.0),
46 | ),
47 | ),
48 | ),
49 | margin: EdgeInsets.only(top: 15.0),
50 | alignment: Alignment.center,
51 | padding: EdgeInsets.all(10.0),
52 | decoration: BoxDecoration(
53 | color: Color.fromRGBO(250, 250, 210, 1.0),
54 | borderRadius: BorderRadius.all(
55 | Radius.circular(20.00),
56 | ),
57 | ),
58 | width:
59 | (ui.window.physicalSize.width / ui.window.devicePixelRatio) * 0.7,
60 | child: Text(
61 | widget._message,
62 | style: TextStyle(fontSize: 20.0),
63 | ),
64 | ),
65 | ],
66 | );
67 | }
68 |
69 | Widget _ownSend() {
70 | final message = widget._message.split(constants.messageOwn)[0];
71 | return Row(
72 | mainAxisAlignment: MainAxisAlignment.end,
73 | children: [
74 | Container(
75 | foregroundDecoration: ShapeDecoration(
76 | shape: RoundedRectangleBorder(
77 | side: BorderSide(color: Colors.lightBlue),
78 | borderRadius: BorderRadius.all(Radius.circular(10.0))),
79 | ),
80 | margin: EdgeInsets.only(top: 15.0),
81 | alignment: Alignment.center,
82 | padding: EdgeInsets.all(10.0),
83 | decoration: BoxDecoration(
84 | color: Color.fromRGBO(250, 250, 210, 1.0),
85 | borderRadius: BorderRadius.all(
86 | Radius.circular(20.00),
87 | ),
88 | ),
89 | width:
90 | (ui.window.physicalSize.width / ui.window.devicePixelRatio) * 0.7,
91 | child: Text(
92 | message,
93 | style: TextStyle(fontSize: 20.0),
94 | ),
95 | ),
96 | CircleAvatar(
97 | backgroundColor: Colors.grey,
98 | child: application.images["receiver"],
99 | ),
100 | ],
101 | );
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/lib/com/navigation/component/contacts_list_item.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_app/com/navigation/models/contacts_list_model.dart';
4 | import 'package:flutter_app/com/navigation/page/subpage/chart_dialog.dart';
5 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
6 | as handler;
7 |
8 | class ContactItem extends StatefulWidget {
9 | final Entry entry;
10 |
11 | ContactItem(this.entry);
12 |
13 | @override
14 | ContactItemState createState() => ContactItemState();
15 | }
16 |
17 | class ContactItemState extends State
18 | with SingleTickerProviderStateMixin {
19 | AnimationController _controller;
20 | Animation _drawerContentsOpacity;
21 |
22 | @override
23 | void initState() {
24 | super.initState();
25 | _controller = new AnimationController(
26 | vsync: this,
27 | duration: const Duration(milliseconds: 200),
28 | );
29 | _drawerContentsOpacity = new CurvedAnimation(
30 | parent: new ReverseAnimation(_controller),
31 | curve: Curves.fastOutSlowIn,
32 | );
33 | }
34 |
35 | Widget _buildTiles(Entry root) {
36 | if (root.list.isEmpty)
37 | return FadeTransition(
38 | opacity: _drawerContentsOpacity,
39 | child: ListTile(
40 | title: getPerson(root.title),
41 | onTap: () => Navigator.push(
42 | context,
43 | MaterialPageRoute(
44 | builder: (BuildContext context) => ChartDialog(
45 | messages: handler.getChatRecorder(root.title),
46 | name: root.title,
47 | ),
48 | ),
49 | ),
50 | ),
51 | );
52 | return ExpansionTile(
53 | key: PageStorageKey(root),
54 | title: getGroup(root.title),
55 | children: root.list.map(_buildTiles).toList(),
56 | );
57 | }
58 |
59 | @override
60 | Widget build(BuildContext context) {
61 | return _buildTiles(widget.entry);
62 | }
63 |
64 | getGroup(String title) {
65 | return Row(
66 | children: [
67 | Column(
68 | children: [
69 | Text(
70 | title,
71 | style: TextStyle(fontSize: 22.0),
72 | ),
73 | ],
74 | ),
75 | ],
76 | );
77 | }
78 |
79 | getPerson(String name) {
80 | return Row(
81 | children: [
82 | Column(
83 | children: [
84 | CircleAvatar(
85 | radius: 25.0,
86 | backgroundImage: AssetImage("assets/images/icon.png"),
87 | ),
88 | ],
89 | ),
90 | Expanded(
91 | child: Padding(
92 | padding: const EdgeInsets.all(8.0),
93 | child: Column(
94 | crossAxisAlignment: CrossAxisAlignment.start,
95 | children: [
96 | Text(
97 | name,
98 | style: TextStyle(fontSize: 20.0),
99 | )
100 | ],
101 | ),
102 | ),
103 | ),
104 | ],
105 | );
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/lib/com/navigation/component/message_list_item.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_app/com/navigation/models/message_list_item_model.dart';
4 | import 'package:flutter_app/com/navigation/page/subpage/chart_dialog.dart';
5 | import 'package:flutter_app/com/navigation/utils/constant.dart' as constants;
6 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
7 | as handler;
8 |
9 | ///
10 | /// 消息列表itme
11 | ///
12 | class MessageListItem extends StatefulWidget {
13 | final MessageListItemModel model;
14 |
15 | MessageListItem(this.model);
16 |
17 | @override
18 | MessageListItemState createState() => MessageListItemState();
19 | }
20 |
21 | class MessageListItemState extends State {
22 | @override
23 | Widget build(BuildContext context) {
24 | return GestureDetector(
25 | child: Column(
26 | children: [
27 | Row(
28 | children: [
29 | CircleAvatar(
30 | radius: 25.0,
31 | backgroundColor: Colors.green,
32 | backgroundImage: AssetImage("assets/images/icon.png"),
33 | ),
34 | Expanded(
35 | child: Padding(
36 | padding: const EdgeInsets.all(8.0),
37 | child: Column(
38 | children: [
39 | Row(
40 | children: [
41 | Expanded(
42 | child: Text(
43 | widget.model.name,
44 | style: TextStyle(fontSize: 22.0),
45 | overflow: TextOverflow.ellipsis,
46 | ),
47 | ),
48 | Text(_calTime()),
49 | ],
50 | ),
51 | SizedBox(
52 | height: 3.00,
53 | ),
54 | Row(
55 | children: [
56 | Expanded(
57 | child: Text(
58 | widget.model
59 | .messages[widget.model.messages.length - 1]
60 | .split(constants.messageOwn)[0],
61 | overflow: TextOverflow.ellipsis,
62 | ),
63 | ),
64 | widget.model.messages.length !=
65 | handler.obtainMessageNumber(widget.model.name)
66 | ? Container(
67 | width: 30.0,
68 | height: 20.0,
69 | alignment: Alignment.center,
70 | decoration: BoxDecoration(
71 | shape: BoxShape.rectangle,
72 | color: Color.fromRGBO(142, 229, 238, 0.8),
73 | borderRadius: BorderRadius.all(
74 | Radius.circular(7.0),
75 | ),
76 | ),
77 | child: Text((widget.model.messages.length -
78 | handler.obtainMessageNumber(
79 | widget.model.name))
80 | .toString()),
81 | )
82 | : Text(""),
83 | ],
84 | ),
85 | ],
86 | ),
87 | ),
88 | ),
89 | ],
90 | ),
91 | Divider(
92 | height: 3.0,
93 | ),
94 | ],
95 | ),
96 | onTapDown: (event) {
97 | Navigator.of(context).push(
98 | MaterialPageRoute(
99 | builder: (BuildContext context) => ChartDialog(
100 | name: widget.model.name,
101 | messages: widget.model.messages,
102 | ),
103 | ),
104 | );
105 | },
106 | );
107 | }
108 |
109 | ///
110 | /// 计算当前时间
111 | ///
112 | String _calTime() {
113 | final DateTime dateTime = DateTime.now();
114 | final int hour = dateTime.hour;
115 | final int minute = dateTime.minute;
116 | if (minute.toInt() < 10)
117 | return "$hour:0$minute";
118 | else
119 | return "$hour:$minute";
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/lib/com/navigation/component/new_trend_star.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_app/com/navigation/models/new_trend_model.dart';
6 | import 'package:flutter_app/com/navigation/page/subpage/webview.dart';
7 | import 'package:flutter_app/com/navigation/utils/file_handler.dart'
8 | as fileHandler;
9 |
10 | class NewTrendStar extends StatefulWidget {
11 | @override
12 | State createState() => _NewTrendStarState();
13 | }
14 |
15 | class _NewTrendStarState extends State
16 | with TickerProviderStateMixin {
17 | final List menuItems = ["移除"];
18 | List items = [];
19 | AnimationController _controller;
20 | Animation _drawerContentsOpacity;
21 | @override
22 | void initState() {
23 | super.initState();
24 | _controller = new AnimationController(
25 | vsync: this,
26 | duration: const Duration(milliseconds: 200),
27 | );
28 | _drawerContentsOpacity = new CurvedAnimation(
29 | parent: new ReverseAnimation(_controller),
30 | curve: Curves.fastOutSlowIn,
31 | );
32 | _loadData();
33 | }
34 |
35 | @override
36 | Widget build(BuildContext context) {
37 | return RefreshIndicator(
38 | child: ListView.builder(
39 | itemBuilder: (BuildContext context, int index) => FadeTransition(
40 | opacity: _drawerContentsOpacity,
41 | child: Column(
42 | children: [
43 | ListTile(
44 | leading: CircleAvatar(
45 | backgroundImage:
46 | AssetImage("assets/images/favorites.png"),
47 | ),
48 | title: Text(items[index].title),
49 | trailing: PopupMenuButton(
50 | onSelected: (value) {
51 | _removeItem(value);
52 | },
53 | itemBuilder: (BuildContext context) =>
54 | menuItems.map((value) {
55 | return PopupMenuItem(
56 | value: items[index].title,
57 | child: Text(value),
58 | );
59 | }).toList()),
60 | onTap: () {
61 | Navigator.of(context).push(
62 | MaterialPageRoute(
63 | builder: (BuildContext context) =>
64 | WebViewStateful(
65 | url: items[index].url,
66 | ),
67 | ),
68 | );
69 | },
70 | ),
71 | Divider(
72 | height: 3.0,
73 | ),
74 | ],
75 | ),
76 | ),
77 | itemCount: items.length,
78 | ),
79 | onRefresh: () async {
80 | return await _loadData();
81 | },
82 | );
83 | }
84 |
85 | Future _loadData() async {
86 | if (items.length > 0) items.clear();
87 | items = await fileHandler.loadCollects();
88 | this.setState(() {});
89 | return TickerFuture.complete();
90 | }
91 |
92 | void _removeItem(String title) async {
93 | var result = await fileHandler.deleteCollects(title);
94 | if (result > 0) {
95 | int index = 0;
96 | items.forEach((model) {
97 | if (model.title == title) {
98 | return;
99 | }
100 | index++;
101 | });
102 | this.setState(() {
103 | items.removeAt(index);
104 | });
105 | }
106 | }
107 |
108 | @override
109 | void dispose() {
110 | super.dispose();
111 | items.clear();
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/lib/com/navigation/component/search_contacts_item.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
4 | as handler;
5 | import 'package:flutter_app/com/navigation/page/subpage/chart_dialog.dart';
6 |
7 | class SearchContactsItem extends StatefulWidget {
8 | final String _name;
9 |
10 | SearchContactsItem(this._name);
11 |
12 | @override
13 | State createState() => SearchContactsItemState();
14 | }
15 |
16 | class SearchContactsItemState extends State {
17 | @override
18 | Widget build(BuildContext context) {
19 | return GestureDetector(
20 | child: Padding(
21 | padding: EdgeInsets.all(5.0),
22 | child: Column(
23 | children: [
24 | Row(
25 | children: [
26 | CircleAvatar(
27 | radius: 25.0,
28 | backgroundColor: Colors.green,
29 | child: Image.asset(
30 | "assets/images/icon.png",
31 | width: 45.0,
32 | height: 45.0,
33 | ),
34 | ),
35 | Expanded(
36 | child: Column(
37 | children: [
38 | Row(
39 | children: [
40 | Text(
41 | widget._name,
42 | style: TextStyle(fontSize: 20.0),
43 | )
44 | ],
45 | ),
46 | SizedBox(
47 | width: 0.0,
48 | height: 2.0,
49 | ),
50 | Row(
51 | children: [Text("暂无个性签名")],
52 | )
53 | ],
54 | ),
55 | ),
56 | ],
57 | ),
58 | Divider(
59 | height: 3.0,
60 | ),
61 | ],
62 | ),
63 | ),
64 | onTapDown: (e) {
65 | Navigator.push(
66 | context,
67 | MaterialPageRoute(
68 | builder: (BuildContext context) => ChartDialog(
69 | messages: handler.getChatRecorder(widget._name),
70 | name: widget._name,
71 | ),
72 | ),
73 | );
74 | },
75 | );
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/lib/com/navigation/component/search_item.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_app/com/navigation/utils/constant.dart' as constants;
2 | import 'package:flutter/cupertino.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
5 | as handler;
6 |
7 | class UserItem extends StatefulWidget {
8 | final String userId;
9 |
10 | UserItem(this.userId);
11 |
12 | @override
13 | UserItemState createState() => UserItemState();
14 | }
15 |
16 | class UserItemState extends State {
17 | UserItemState();
18 |
19 | @override
20 | Widget build(BuildContext context) {
21 | return Padding(
22 | padding: const EdgeInsets.only(top: 4.0, bottom: 4.0),
23 | child: Column(
24 | children: [
25 | Row(
26 | children: [
27 | Expanded(
28 | child: Row(
29 | children: [
30 | Column(
31 | children: [
32 | Padding(
33 | padding: const EdgeInsets.only(left: 8.0, right: 8.0),
34 | child: CircleAvatar(
35 | radius: 25.0,
36 | backgroundColor: Colors.green,
37 | child: Image.asset(
38 | "assets/images/icon.png",
39 | width: 45.0,
40 | height: 45.0,
41 | ),
42 | ),
43 | ),
44 | ],
45 | ),
46 | Expanded(
47 | child: Column(
48 | children: [
49 | Row(
50 | children: [
51 | Text(
52 | widget.userId,
53 | style: TextStyle(fontSize: 20.0),
54 | ),
55 | ],
56 | ),
57 | ],
58 | ),
59 | ),
60 | ],
61 | ),
62 | ),
63 | Align(
64 | alignment: Alignment.centerRight,
65 | child: IconButton(
66 | icon: InputDecorator(
67 | decoration: InputDecoration(icon: Icon(Icons.add)),
68 | ),
69 | onPressed: () {
70 | var message = {
71 | constants.type: constants.friend,
72 | constants.subtype: constants.request,
73 | constants.to: widget.userId,
74 | constants.message: "${handler.userId}请求添加你为好友!",
75 | constants.version: constants.currentVersion
76 | };
77 | handler.sendRequest(message);
78 | Scaffold
79 | .of(context)
80 | .showSnackBar(SnackBar(content: Text("请求已发送")));
81 | },
82 | ),
83 | ),
84 | ],
85 | ),
86 | Divider(),
87 | ],
88 | ),
89 | );
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/lib/com/navigation/component/system_propel.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter_app/com/navigation/models/system_propel_model.dart';
3 | import 'package:flutter_app/com/navigation/utils/constant.dart' as constants;
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart' as handler;
6 |
7 | ///
8 | ///
9 | ///
10 | /// 系统推送消息
11 | /// @message 推送内容
12 | /// @type 推送类型(目前只有好友请求和好友回复两种类型)
13 | ///
14 | ///
15 |
16 | class SystemPropel extends StatefulWidget {
17 | final SystemPropelModel _model;
18 |
19 | SystemPropel(this._model);
20 |
21 | @override
22 | SystemPropelState createState() => SystemPropelState();
23 | }
24 |
25 | class SystemPropelState extends State {
26 | @override
27 | Widget build(BuildContext context) {
28 | switch (widget._model.type) {
29 | case constants.response:
30 | return _showResponse();
31 | default:
32 | return _showRequest();
33 | }
34 | }
35 |
36 | Widget _showRequest() {
37 | return Container(
38 | margin: EdgeInsets.all(10.0),
39 | decoration: BoxDecoration(
40 | border: Border(
41 | left: BorderSide(style: BorderStyle.solid),
42 | bottom: BorderSide(style: BorderStyle.solid),
43 | right: BorderSide(style: BorderStyle.solid),
44 | ),
45 | ),
46 | child: Column(
47 | children: [
48 | Container(
49 | alignment: Alignment.centerLeft,
50 | decoration: BoxDecoration(color: Colors.lightBlue),
51 | child: Padding(
52 | padding: const EdgeInsets.all(4.0),
53 | child: Text(
54 | "好友请求",
55 | style: TextStyle(fontSize: 23.0),
56 | ),
57 | ),
58 | ),
59 | Container(
60 | margin: EdgeInsets.only(top: 10.0, bottom: 10.0),
61 | child: Text(
62 | widget._model.message,
63 | style: TextStyle(fontSize: 20.0),
64 | ),
65 | ),
66 | Container(
67 | alignment: Alignment.center,
68 | margin: EdgeInsets.all(5.0),
69 | child: widget._model.isDeal
70 | ? (widget._model.isAccept
71 | ? Text(
72 | "你已经同意该好友请求",
73 | style: TextStyle(fontSize: 17.0),
74 | )
75 | : Text(
76 | "你已经拒绝该好友请求",
77 | style: TextStyle(fontSize: 17.0),
78 | ))
79 | : _showHandler(),
80 | ),
81 | ],
82 | ),
83 | );
84 | }
85 |
86 | Widget _showResponse() {
87 | return Container(
88 | margin: EdgeInsets.all(10.0),
89 | decoration: BoxDecoration(
90 | border: Border(
91 | left: BorderSide(style: BorderStyle.solid),
92 | bottom: BorderSide(style: BorderStyle.solid),
93 | right: BorderSide(style: BorderStyle.solid),
94 | ),
95 | ),
96 | child: Column(
97 | children: [
98 | Container(
99 | alignment: Alignment.centerLeft,
100 | decoration: BoxDecoration(color: Colors.lightBlue),
101 | child: Text("好友回复",style: TextStyle(fontSize: 23.0),),
102 | ),
103 | Container(
104 | margin: EdgeInsets.all(10.0),
105 | child: Text(widget._model.message,style: TextStyle(fontSize: 17.0),),
106 | ),
107 | ],
108 | ),
109 | );
110 | }
111 | Widget _showHandler() {
112 | return Row(
113 | mainAxisAlignment: MainAxisAlignment.center,
114 | children: [
115 | GestureDetector(
116 | child: Container(
117 | decoration: BoxDecoration(
118 | border: Border(
119 | top: BorderSide(color: Colors.green),
120 | bottom: BorderSide(color: Colors.green),
121 | left: BorderSide(color: Colors.green),
122 | right: BorderSide(color: Colors.green))),
123 | margin: EdgeInsets.only(right: 10.0),
124 | child: Padding(
125 | padding: const EdgeInsets.all(8.0),
126 | child: Text(
127 | "同意",
128 | style: TextStyle(fontSize: 18.0),
129 | ),
130 | ),
131 | ),
132 | onTapDown: (e) {
133 | _sendResponse(true);
134 | },
135 | ),
136 | GestureDetector(
137 | child: Container(
138 | decoration: BoxDecoration(
139 | border: Border(
140 | top: BorderSide(color: Colors.red),
141 | bottom: BorderSide(color: Colors.red),
142 | left: BorderSide(color: Colors.red),
143 | right: BorderSide(color: Colors.red))),
144 | child: Padding(
145 | padding: const EdgeInsets.all(8.0),
146 | child: Text(
147 | "拒绝",
148 | style: TextStyle(fontSize: 18.0),
149 | ),
150 | ),
151 | ),
152 | onTapDown: (e) {
153 | _sendResponse(false);
154 | },
155 | ),
156 | ],
157 | );
158 | }
159 | void _sendResponse(bool isAccept) {
160 | widget._model.isDeal = true;
161 | widget._model.isAccept = isAccept;
162 | Map message = {
163 | constants.type: constants.friend,
164 | constants.subtype: constants.response,
165 | constants.to: widget._model.to,
166 | constants.accept: isAccept,
167 | constants.version: constants.currentVersion
168 | };
169 | handler.sendRequest(message);
170 | if(isAccept) handler.handlerContacts(widget._model.to);
171 | this.setState(() {
172 | handler.systemPropel=new List.from(handler.systemPropel);
173 | });
174 |
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/lib/com/navigation/component/user_info_item.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
6 | as handler;
7 | import 'package:flutter_app/com/navigation/utils/file_handler.dart'
8 | as fileHandler;
9 |
10 | Map userInfo = {};
11 |
12 | class UserInfoItem extends StatefulWidget {
13 | @override
14 | State createState() => _UserInfoState();
15 | }
16 |
17 | class _UserInfoState extends State {
18 | final List _items = ["账号", "用户名", "个性签名", "个人邮箱", "手机号", "个人网址"];
19 | final List panels = [];
20 | @override
21 | void initState() {
22 | super.initState();
23 | for (var item in _items)
24 | panels.add(InfoItem(title: item, itemValue: _checkData(item)));
25 | _loadInfo();
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | return ExpansionPanelList(
31 | expansionCallback: (int index, bool isExpanded) {
32 | this.setState(() {
33 | panels[index].isExpanded = !isExpanded;
34 | });
35 | },
36 | children: panels.map((panel) {
37 | return panel.buildExpansionPanel;
38 | }).toList(),
39 | );
40 | }
41 |
42 | void _loadInfo() async {
43 | userInfo = await fileHandler.obtainUsers(userId: handler.userId);
44 | this.setState(() {
45 | userInfo = Map.from(userInfo);
46 | });
47 | }
48 |
49 | String _checkData(String title) {
50 | switch (title) {
51 | case "用户名":
52 | return userInfo["userName"] ?? handler.userId;
53 | case "个性签名":
54 | return userInfo["userName"] ?? "";
55 | case "个人邮箱":
56 | return userInfo["mail"] ?? "";
57 | case "手机号":
58 | return userInfo["phone"] ?? "";
59 | case "个人网址":
60 | return userInfo["website"] ?? "";
61 | default:
62 | return handler.userId;
63 | }
64 | }
65 | }
66 |
67 | class InfoItem {
68 | String title;
69 | bool isExpanded = false;
70 | String itemValue;
71 |
72 | InfoItem({@required this.title, @required this.itemValue});
73 | ExpansionPanel get buildExpansionPanel => ExpansionPanel(
74 | headerBuilder: (BuildContext context, bool expanded) => ListTile(
75 | leading: Text(title),
76 | title: Text(itemValue),
77 | ),
78 | body: Column(
79 | mainAxisAlignment: MainAxisAlignment.center,
80 | children: [
81 | Container(
82 | margin: EdgeInsets.only(left: 30.0, right: 30.0),
83 | child: Row(
84 | children: [
85 | Text(
86 | "修改:",
87 | style: TextStyle(
88 | fontSize: 18.0,
89 | color: Colors.red,
90 | ),
91 | ),
92 | Expanded(
93 | child: TextField(),
94 | ),
95 | ],
96 | ),
97 | ),
98 | Row(
99 | mainAxisAlignment: MainAxisAlignment.end,
100 | children: [
101 | FlatButton(
102 | onPressed: () {
103 | onSave();
104 | },
105 | child: Text(
106 | "确定",
107 | style: TextStyle(color: Colors.lightBlue, fontSize: 20.0),
108 | ),
109 | ),
110 | ],
111 | ),
112 | ],
113 | ),
114 | isExpanded: title != "账号" ? isExpanded : false,
115 | );
116 | void onSave() async {}
117 | }
118 |
--------------------------------------------------------------------------------
/lib/com/navigation/models/contacts_list_model.dart:
--------------------------------------------------------------------------------
1 | class Entry {
2 | final String title;
3 | final List list;
4 | Entry(this.title, [this.list = const []]);
5 | }
--------------------------------------------------------------------------------
/lib/com/navigation/models/message_list_item_model.dart:
--------------------------------------------------------------------------------
1 | class MessageListItemModel {
2 | List messages;
3 | String name;
4 |
5 | MessageListItemModel({List messags, String name}) {
6 | this.messages = messags;
7 | this.name = name;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lib/com/navigation/models/new_trend_model.dart:
--------------------------------------------------------------------------------
1 | class NewTrendModel {
2 | String title;
3 | String url;
4 | String cnbrief;
5 | String enbrief;
6 |
7 | NewTrendModel(this.title, this.url, this.cnbrief, this.enbrief);
8 | }
9 |
--------------------------------------------------------------------------------
/lib/com/navigation/models/system_propel_model.dart:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | /// 系统推送数据model
4 | /// @ _message 推送内容
5 | /// @ _type 推送类型
6 | /// @ _to 若需要回复,回复对象
7 | /// @ isDeal 该条消息是否处理
8 | /// @ isAccept 处理结果
9 | ///
10 | ///
11 | class SystemPropelModel{
12 | final String message;
13 | final String type;
14 | final String to;
15 | bool isDeal = false;
16 | bool isAccept = false;
17 | SystemPropelModel(this.message, this.type, this.to);
18 |
19 | }
--------------------------------------------------------------------------------
/lib/com/navigation/netwok/socket_handler.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:convert';
3 | import 'dart:io';
4 | import 'package:flutter/cupertino.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:flutter_app/com/navigation/models/contacts_list_model.dart';
7 | import 'package:flutter_app/com/navigation/models/system_propel_model.dart';
8 | import 'package:flutter_app/com/navigation/page/login.dart';
9 | import 'package:flutter_app/com/navigation/utils/constant.dart' as constants;
10 | import 'package:flutter_app/com/navigation/utils/utils.dart';
11 | import 'package:http/http.dart';
12 | import 'package:flutter_app/com/navigation/utils/file_handler.dart'
13 | as fileHandler;
14 | import 'package:flutter_app/com/navigation/utils/system_announce.dart'
15 | as system;
16 | import 'package:flutter_app/com/navigation/utils/application.dart'
17 | as application;
18 |
19 | ///
20 | /// 整个app向服务器发送请求和接收服务器回复的综合处理类,
21 | /// 此类强烈不建议与ui部分发生直接交互,只负责产生数据,某个页面需要数据直接获取即可.
22 | /// @socket 整个app socket
23 | /// @contactsList 储存联系人列表
24 | /// @systemPropel为系统推送消息
25 | /// @timer 定时器,定时向服务器发送数据以确保,连接正常可用
26 | /// @ messageList 消息列表 key代表好友名称 value代表和该好友聊天的所有消息
27 | ///
28 | ///
29 | ///
30 |
31 | Socket socket;
32 | List contactsList = [];
33 | List systemPropel = [];
34 | Map> messageList = {};
35 | Map lastNum = {};
36 |
37 | LoginState loginState;
38 | String userId;
39 | String password;
40 | State currentState;
41 |
42 | Timer _timer;
43 |
44 | ///
45 | ///
46 | /// 初始化连接
47 | ///
48 |
49 | void initSocket(Map req) async {
50 | if (socket != null) {
51 | socket.destroy();
52 | socket.close();
53 | }
54 | Socket.connect(constants.domain, constants.tcpPort)
55 | ..then((_socket) {
56 | if (_socket != null) {
57 | socket = _socket;
58 | socketHandler();
59 | sendRequest(req);
60 | keepAlive();
61 | }
62 | })
63 | ..catchError((error) {
64 | showToast("连接服务器发生未知错误!");
65 | dispose();
66 | })
67 | ..timeout(Duration(seconds: 5), onTimeout: () {
68 | showToast("连接超时.....");
69 | });
70 | }
71 |
72 | ///
73 | ///
74 | /// 处理服务器返回来的数据id
75 | ///
76 | ///
77 | void socketHandler() {
78 | if (socket != null) {
79 | socket.done.catchError((error) {
80 | showToast("网络异常,请重新登录!");
81 | dispose();
82 | });
83 | socket.transform(utf8.decoder).listen((data) {
84 | var result = json.decode(data);
85 | var type = result[constants.type];
86 | switch (type) {
87 | case constants.user:
88 | handlerUser(result);
89 | break;
90 | case constants.friend:
91 | handlerFriend(result);
92 | break;
93 | case constants.message:
94 | handlerMessage(result);
95 | break;
96 | }
97 | });
98 | }
99 | }
100 |
101 | ///
102 | ///
103 | ///
104 | /// 向服务器发送数据
105 | ///
106 | ///
107 | void sendRequest(Map message) async {
108 | socket.write(json.encode(message) + constants.end);
109 | }
110 |
111 | ///
112 | ///
113 | /// 处理type为user的所有socket事件
114 | ///
115 | ///
116 |
117 | void handlerUser(dynamic data) async {
118 | var subtype = data[constants.subtype];
119 | if (subtype == "login") {
120 | var status = data["login"];
121 | if (status) {
122 | showToast("登录成功");
123 | fileHandler.addUser(userId, password);
124 | password = md5(password);
125 | var friends = data["friends"];
126 | if (friends.length > 0) {
127 | List list = [];
128 | for (var friend in friends) list.add(Entry(friend["id"]));
129 | contactsList.add(Entry("我的好友", list));
130 | }
131 | loginState.toUserCenter();
132 | _offlineMessage();
133 | } else {
134 | dispose();
135 | showToast("用户名/密码错误!");
136 | }
137 | }
138 | }
139 |
140 | ///
141 | ///
142 | ///处理type为friend的所有socket事件
143 | ///
144 | void handlerFriend(dynamic data) {
145 | bool isPlay = true;
146 | if (application.settings["voiceSwitch"] != null &&
147 | application.settings["voiceSwitch"] == "false") isPlay = false;
148 | if (isPlay) system.playFriendMention();
149 | var subtype = data[constants.subtype];
150 | if (subtype == constants.request) {
151 | systemPropel.add(SystemPropelModel(data[constants.message],
152 | data[constants.subtype], data[constants.from]));
153 | }
154 | if (subtype == constants.response) {
155 | if (data[constants.accept]) {
156 | systemPropel.add(SystemPropelModel("${data[constants.from]}同意添加你为好友!",
157 | constants.response, data["from"]));
158 | handlerContacts(data[constants.from]);
159 | } else {
160 | systemPropel.add(SystemPropelModel("${data[constants.from]}拒绝添加你为好友!",
161 | constants.response, data["from"]));
162 | }
163 | }
164 | }
165 |
166 | ///
167 | ///
168 | /// 处理所有type为message的服务器返回数据
169 | /// 目前只有subtype为text的数据,在将来可能添加image voice等
170 | ///
171 | ///
172 | void handlerMessage(dynamic data) {
173 | bool isPlay = true;
174 | var subtype = data["subtype"];
175 | var id = data[constants.from];
176 | var body = data[constants.body];
177 | if (application.settings["voiceSwitch"] != null &&
178 | application.settings["voiceSwitch"] == "false") isPlay = false;
179 | if (subtype == constants.text) {
180 | if (isPlay) system.playMessageMention();
181 | handlerMessageList(id, body);
182 | }
183 | }
184 |
185 | ///
186 | /// 如果存在该用户信息连天记录,更新记录
187 | /// 如果不存存在添加记录
188 | ///
189 | ///
190 | void handlerMessageList(String id, String message) async {
191 | if (messageList.containsKey(id)) {
192 | messageList.update(id, (old) {
193 | old.add(message);
194 | return old;
195 | });
196 | } else {
197 | List list = List();
198 | list.add(message);
199 | messageList.putIfAbsent(id, () => list);
200 | if (!lastNum.containsKey(id)) lastNum.putIfAbsent(id, () => 0);
201 | }
202 | }
203 |
204 | ///
205 | /// 如果好友列表中已经存在该用户,将不做任何处理,如果不存在将其加入到好友列表中去
206 | /// 目前服务端对好友默认是我的好友目录下,暂不支持分组,分组功能将会留在以后实现
207 | /// @ isExist 判断是否已经时好友关系
208 | ///
209 | void handlerContacts(String id) {
210 | var isExist = false;
211 | if (contactsList.length > 0) {
212 | var list = contactsList[0].list;
213 | for (Entry e in list) if (e.title == id) isExist = true;
214 | if (!isExist) {
215 | for (Entry entry in contactsList) {
216 | if (entry.title == "我的好友") entry.list.add(Entry(id));
217 | }
218 | }
219 | } else {
220 | List list = List();
221 | list.add(Entry(id));
222 | contactsList.add(Entry("我的好友", list));
223 | }
224 | }
225 |
226 | ///
227 | /// 通过用户id查找相应的聊天记录
228 | ///
229 | ///
230 | List getChatRecorder(String id) {
231 | List record = [];
232 | if (messageList.containsKey(id)) {
233 | messageList.forEach((key, list) {
234 | if (key == id) {
235 | record = list;
236 | return;
237 | }
238 | });
239 | } else {
240 | messageList.putIfAbsent(id, () => record);
241 | }
242 | if (!lastNum.containsKey(id)) lastNum.putIfAbsent(id, () => 0);
243 | return record;
244 | }
245 |
246 | ///
247 | /// 清除指定用户的聊天记录
248 | ///
249 | ///
250 | void clearMessage(String id) async {
251 | bool isRemove = false;
252 | if (messageList.containsKey(id)) {
253 | messageList.forEach((key, value) {
254 | if (key == id) {
255 | value.clear();
256 | isRemove = true;
257 | return;
258 | }
259 | });
260 | }
261 | if (isRemove) messageList.remove(id);
262 | }
263 |
264 | ///
265 | /// 请求获取离线消息
266 | /// todo 将其加入到handler的Map中去
267 | ///
268 | ///
269 | void _offlineMessage() {
270 | Map requestMes = {
271 | constants.type: constants.user,
272 | constants.subtype: constants.offline,
273 | constants.id: userId,
274 | constants.password: password,
275 | constants.version: constants.currentVersion
276 | };
277 | put("${constants.http}${constants.domain}/${constants.user}/${constants.offline}",
278 | body: "${json.encode(requestMes)}${constants.end}").then((response) {
279 | if (response.statusCode == 200) {
280 | var result = json.decode(utf8.decode(response.bodyBytes));
281 | print("offline:$result");
282 | }
283 | });
284 | }
285 |
286 | ///
287 | /// 通过id获取上一次消息数目
288 | ///
289 | int obtainMessageNumber(String id) {
290 | int number = 0;
291 | if (lastNum.containsKey(id)) {
292 | lastNum.forEach((key, value) {
293 | if (key == id) {
294 | number = value;
295 | return;
296 | }
297 | });
298 | }
299 | return number;
300 | }
301 |
302 | ///
303 | ///
304 | /// 通过id更新消息条数
305 | ///
306 | void updateMessageNumber(String id, int number) async {
307 | if (lastNum.containsKey(id)) {
308 | lastNum.update(id, (old) => number);
309 | }
310 | }
311 |
312 | ///
313 | /// 心跳机制保持连接可用
314 | ///
315 | ///
316 | void keepAlive() async {
317 | if (_timer != null && _timer.isActive) _timer;
318 | _timer = Timer.periodic(Duration(seconds: 5), (event) {
319 | handlerMessage({});
320 | });
321 | }
322 |
323 | ///
324 | ///
325 | ///退出登录时释放掉该用户所有信息
326 | ///
327 | ///
328 |
329 | void dispose() {
330 | socket?.destroy();
331 | socket?.close();
332 | contactsList?.clear();
333 | systemPropel?.clear();
334 | messageList?.clear();
335 | lastNum?.clear();
336 | if (_timer != null && _timer.isActive) _timer.cancel();
337 | }
338 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/login.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter/services.dart';
4 | import 'package:flutter_app/com/navigation/page/register.dart';
5 | import 'package:flutter_app/com/navigation/page/user.dart';
6 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
7 | as handler;
8 | import 'package:flutter_app/com/navigation/utils/constant.dart' as constants;
9 | import 'package:flutter_app/com/navigation/utils/utils.dart';
10 | import 'package:fluttertoast/fluttertoast.dart';
11 | import 'package:flutter_app/com/navigation/utils/application.dart'
12 | as application;
13 |
14 | class Login extends StatefulWidget {
15 | @override
16 | LoginState createState() => LoginState();
17 | }
18 |
19 | class LoginState extends State with TickerProviderStateMixin {
20 | final GlobalKey key = GlobalKey();
21 | final List _counts = [];
22 | String _userId = "";
23 | String _password = "";
24 | bool isSelect = true;
25 | bool isExpanded = true;
26 | AnimationController _controller;
27 | Animation _drawerContentsOpacity;
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | return WillPopScope(
32 | child:
33 | isSelect && _counts.length > 0 ? _selectCounts() : _inputCountLogin(),
34 | onWillPop: () {
35 | SystemNavigator.pop();
36 | },
37 | );
38 | }
39 |
40 | @override
41 | void initState() {
42 | super.initState();
43 | handler.loginState = this;
44 | application.counts.forEach((count) {
45 | count.forEach((key, value) {
46 | if (key == "userId") _counts.add(value);
47 | });
48 | });
49 | _controller = new AnimationController(
50 | vsync: this,
51 | duration: const Duration(milliseconds: 200),
52 | );
53 | _drawerContentsOpacity = new CurvedAnimation(
54 | parent: new ReverseAnimation(_controller),
55 | curve: Curves.fastOutSlowIn,
56 | );
57 | if (_counts.length > 0) {
58 | _userId = _counts[0];
59 | _password = application.findUser(_userId);
60 | }
61 | }
62 |
63 | void _vailUser() async {
64 | if (_userId.trim() == "") {
65 | showToast("用户名不能为空!");
66 | return;
67 | }
68 | if (_password.trim() == "") {
69 | showToast("密码不能为空!");
70 | return;
71 | }
72 | Map requestMes = {
73 | constants.type: constants.user,
74 | constants.subtype: constants.login,
75 | constants.id: _userId,
76 | constants.password: md5(_password),
77 | constants.version: constants.currentVersion,
78 | };
79 | handler.userId = _userId;
80 | handler.password = _password;
81 | handler.initSocket(requestMes);
82 | }
83 |
84 | void toUserCenter() {
85 | Navigator.push(context,
86 | MaterialPageRoute(builder: (BuildContext context) => UserCenter()));
87 | }
88 |
89 | Widget _inputCountLogin() {
90 | return Scaffold(
91 | key: key,
92 | body: Container(
93 | margin: EdgeInsets.only(top: 100.0, left: 20.0, right: 20.0),
94 | child: ListView(
95 | children: [
96 | Row(
97 | children: [
98 | Expanded(
99 | child: Container(
100 | alignment: Alignment.centerLeft,
101 | child: Row(
102 | children: [
103 | Image.asset(
104 | "assets/images/icon.png",
105 | width: 70.0,
106 | height: 70.0,
107 | ),
108 | Expanded(
109 | child: Padding(
110 | padding: const EdgeInsets.only(left: 8.0),
111 | child: Text(
112 | "畅聊",
113 | style: TextStyle(fontSize: 25.0),
114 | ),
115 | ),
116 | ),
117 | ],
118 | ),
119 | ),
120 | ),
121 | ],
122 | ),
123 | Row(
124 | children: [
125 | Expanded(
126 | child: TextField(
127 | decoration: InputDecoration(
128 | labelText: "用户名",
129 | ),
130 | onChanged: (value) => _userId = value,
131 | ),
132 | ),
133 | ],
134 | ),
135 | Row(
136 | children: [
137 | Expanded(
138 | child: TextField(
139 | decoration: InputDecoration(labelText: "密码"),
140 | onChanged: (value) => _password = value,
141 | obscureText: true,
142 | ),
143 | )
144 | ],
145 | ),
146 | Row(
147 | children: [
148 | Expanded(
149 | child: GestureDetector(
150 | child: Container(
151 | height: 50.0,
152 | margin: EdgeInsets.all(10.0),
153 | alignment: Alignment.center,
154 | decoration: BoxDecoration(
155 | color: Color.fromRGBO(0, 245, 255, 0.8),
156 | ),
157 | child: const Text(
158 | "登录",
159 | style: TextStyle(
160 | fontSize: 20.0,
161 | color: Color.fromRGBO(248, 248, 255, 1.0)),
162 | ),
163 | ),
164 | onTapDown: (e) {
165 | _vailUser();
166 | },
167 | ),
168 | ),
169 | ],
170 | ),
171 | Row(
172 | children: [
173 | Expanded(
174 | child: GestureDetector(
175 | child: const Text(
176 | "选择账号",
177 | style: TextStyle(fontSize: 18.0, color: Colors.green),
178 | ),
179 | onTapDown: (e) {
180 | if (_counts.length > 0) {
181 | _userId = _counts[0];
182 | _password = application.findUser(_userId);
183 | this.setState(() {
184 | isSelect = !isSelect;
185 | });
186 | } else {
187 | showToast("暂无账号!");
188 | }
189 | },
190 | ),
191 | ),
192 | Expanded(
193 | child: Align(
194 | alignment: Alignment.centerRight,
195 | child: GestureDetector(
196 | child: const Text("新用户注册",
197 | style:
198 | TextStyle(fontSize: 18.0, color: Colors.green)),
199 | onTapDown: (e) {
200 | Navigator.push(
201 | context,
202 | MaterialPageRoute(
203 | builder: (BuildContext context) => Register()));
204 | },
205 | ),
206 | ),
207 | )
208 | ],
209 | )
210 | ],
211 | ),
212 | ),
213 | );
214 | }
215 |
216 | Widget _selectCounts() {
217 | return Scaffold(
218 | body: Center(
219 | child: Column(
220 | mainAxisAlignment: MainAxisAlignment.center,
221 | children: [
222 | Container(
223 | margin: EdgeInsets.only(left: 10.0, bottom: 10.0, right: 10.0),
224 | alignment: Alignment.centerLeft,
225 | child: Text(
226 | "畅聊",
227 | style: TextStyle(fontSize: 30.0),
228 | ),
229 | ),
230 | ExpansionPanelList(
231 | expansionCallback: (int index, bool isExpanded) {
232 | this.setState(() {
233 | this.isExpanded = !isExpanded;
234 | });
235 | },
236 | children: [
237 | ExpansionPanel(
238 | isExpanded: isExpanded,
239 | headerBuilder: (BuildContext context, bool isExpand) {
240 | return Row(
241 | children: [
242 | CircleAvatar(
243 | backgroundImage: AssetImage("assets/images/head.png"),
244 | radius: 30.0,
245 | ),
246 | Expanded(
247 | child: Padding(
248 | padding: EdgeInsets.only(left: 10.0),
249 | child: Text(
250 | _userId,
251 | style: TextStyle(fontSize: 20.0),
252 | ),
253 | ),
254 | ),
255 | ],
256 | );
257 | },
258 | body: Column(
259 | children: [
260 | Column(
261 | children: _counts.map((countName) {
262 | return FadeTransition(
263 | opacity: _drawerContentsOpacity,
264 | child: ListTile(
265 | leading: CircleAvatar(
266 | backgroundImage:
267 | AssetImage("assets/images/head.png"),
268 | ),
269 | title: Text(countName),
270 | onTap: () {
271 | this.setState(() {
272 | _userId = countName;
273 | _password = application.findUser(_userId);
274 | });
275 | },
276 | ),
277 | );
278 | }).toList(),
279 | ),
280 | Row(
281 | mainAxisAlignment: MainAxisAlignment.end,
282 | children: [
283 | new Container(
284 | margin: const EdgeInsets.only(right: 8.0),
285 | child: new FlatButton(
286 | onPressed: () {
287 | this.setState(() {
288 | isSelect = !isSelect;
289 | _userId = "";
290 | _password = "";
291 | });
292 | },
293 | textTheme: ButtonTextTheme.accent,
294 | child: const Text(
295 | "输入账号",
296 | style: TextStyle(fontSize: 20.0),
297 | ),
298 | ),
299 | ),
300 | new Container(
301 | margin: const EdgeInsets.only(right: 8.0),
302 | child: new FlatButton(
303 | onPressed: () {
304 | _vailUser();
305 | },
306 | textTheme: ButtonTextTheme.accent,
307 | child: const Text(
308 | "登录",
309 | style: TextStyle(fontSize: 20.0),
310 | ),
311 | ),
312 | ),
313 | ],
314 | ),
315 | ],
316 | ),
317 | ),
318 | ],
319 | )
320 | ],
321 | ),
322 | ),
323 | );
324 | }
325 | }
326 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/register.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'dart:convert';
4 | import 'package:flutter_app/com/navigation/utils/constant.dart' as constants;
5 | import 'package:flutter_app/com/navigation/utils/utils.dart';
6 | import 'package:http/http.dart';
7 | import 'package:flutter_app/com/navigation/utils/application.dart'
8 | as application;
9 |
10 | class Register extends StatefulWidget {
11 | @override
12 | RegisterState createState() => RegisterState();
13 | }
14 |
15 | class RegisterState extends State {
16 | String _userName = "";
17 | String _password = "";
18 | String _rePassword = "";
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | return Scaffold(
23 | body: ListView(
24 | children: [
25 | Container(
26 | margin: EdgeInsets.only(top: 20.0),
27 | child: Column(
28 | mainAxisAlignment: MainAxisAlignment.center,
29 | crossAxisAlignment: CrossAxisAlignment.center,
30 | children: [
31 | Padding(
32 | padding: const EdgeInsets.all(8.0),
33 | child: Row(
34 | children: [
35 | Expanded(
36 | child: Image.asset(
37 | "assets/images/icon.png",
38 | width: 100.0,
39 | height: 100.0,
40 | ),
41 | )
42 | ],
43 | ),
44 | ),
45 | Row(
46 | children: [
47 | Expanded(
48 | child: Center(
49 | child: Text(
50 | "加入我们,一起畅聊",
51 | style: TextStyle(fontSize: 25.0),
52 | ),
53 | ),
54 | ),
55 | ],
56 | ),
57 | ],
58 | ),
59 | ),
60 | Padding(
61 | padding: const EdgeInsets.all(8.0),
62 | child: Row(
63 | children: [
64 | application.images["user"],
65 | Expanded(
66 | child: TextField(
67 | decoration: InputDecoration(labelText: "用户名"),
68 | onChanged: (value) {
69 | _userName = value;
70 | },
71 | ),
72 | ),
73 | ],
74 | ),
75 | ),
76 | Padding(
77 | padding: const EdgeInsets.all(8.0),
78 | child: Row(
79 | children: [
80 | application.images["password"],
81 | Expanded(
82 | child: TextField(
83 | obscureText: true,
84 | decoration: InputDecoration(labelText: "密码"),
85 | onChanged: (value) {
86 | _password = value;
87 | },
88 | ),
89 | )
90 | ],
91 | ),
92 | ),
93 | Padding(
94 | padding: const EdgeInsets.all(8.0),
95 | child: Row(
96 | children: [
97 | application.images["password"],
98 | Expanded(
99 | child: TextField(
100 | obscureText: true,
101 | decoration: InputDecoration(labelText: "确认密码"),
102 | onChanged: (value) {
103 | _rePassword = value;
104 | },
105 | ),
106 | )
107 | ],
108 | ),
109 | ),
110 | Padding(
111 | padding: const EdgeInsets.all(8.0),
112 | child: Row(
113 | children: [
114 | Expanded(
115 | child: Builder(
116 | builder: (BuildContext context) => GestureDetector(
117 | child: Builder(
118 | builder: (BuildContext context) => Container(
119 | height: 40.0,
120 | margin: EdgeInsets.only(top: 10.0),
121 | alignment: Alignment.center,
122 | decoration: BoxDecoration(
123 | color: Color.fromRGBO(0, 245, 255, 0.8),
124 | ),
125 | child: Text("注册"),
126 | ),
127 | ),
128 | onTapDown: (event) {
129 | _vailData(context);
130 | },
131 | ),
132 | ),
133 | ),
134 | ],
135 | ),
136 | )
137 | ],
138 | ),
139 | );
140 | }
141 |
142 | void _sendRequest(String message, BuildContext context) {
143 | put("${constants.http}${constants.domain}/${constants.user}/${constants.register}",
144 | body: message).then((response) {
145 | if (response.statusCode == 200) {
146 | var result = json.decode(utf8.decode(response.bodyBytes));
147 | if (result["register"]) {
148 | _showMessage(context, "注册成功!");
149 | } else {
150 | _showMessage(context, result["info"]);
151 | }
152 | } else {
153 | _showMessage(context, "服务器异常,请重试!");
154 | }
155 | });
156 | }
157 |
158 | void _vailData(BuildContext context) {
159 | if (_userName.trim() != "" &&
160 | _password.trim() != "" &&
161 | _rePassword.trim() != "") {
162 | if (_password == _rePassword) {
163 | Map map = {
164 | constants.type: constants.user,
165 | constants.subtype: constants.register,
166 | constants.id: "$_userName",
167 | constants.password: md5("$_password"),
168 | constants.version: constants.currentVersion
169 | };
170 | _sendRequest(json.encode(map) + constants.end, context);
171 | } else {
172 | _showMessage(context, "两次密码不一致!");
173 | }
174 | } else {
175 | _showMessage(context, "尚有必要信息为空!");
176 | }
177 | }
178 |
179 | void _showMessage(BuildContext context, String message) {
180 | Scaffold.of(context).showSnackBar(SnackBar(content: Text(message)));
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/about_program.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_app/com/navigation/page/subpage/webview.dart';
4 | import 'package:flutter_app/com/navigation/utils/application.dart'
5 | as application;
6 |
7 | class About extends StatefulWidget {
8 | @override
9 | AboutState createState() => AboutState();
10 | }
11 |
12 | class AboutState extends State {
13 | final GlobalKey key = GlobalKey();
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return Theme(
18 | data: ThemeData(
19 | primaryColor: application.settings["primaryColor"] == null
20 | ? Colors.lightBlue
21 | : Color(
22 | int.parse(application.settings["primaryColor"]),
23 | ),
24 | ),
25 | child: Scaffold(
26 | key: key,
27 | appBar: AppBar(
28 | title: new Text("关于"),
29 | centerTitle: true,
30 | ),
31 | body: Column(
32 | children: [
33 | Container(
34 | alignment: Alignment.center,
35 | child: Column(
36 | children: [
37 | Row(
38 | mainAxisAlignment: MainAxisAlignment.center,
39 | children: [
40 | Padding(
41 | padding: const EdgeInsets.all(8.0),
42 | child: CircleAvatar(
43 | backgroundColor: Colors.deepPurple,
44 | minRadius: 60.0,
45 | child: Image.asset(
46 | "assets/images/icon.png",
47 | width: 100.0,
48 | height: 100.0,
49 | ),
50 | ),
51 | ),
52 | ],
53 | ),
54 | Row(
55 | mainAxisAlignment: MainAxisAlignment.center,
56 | children: [
57 | Text(
58 | "版本:0.2",
59 | style: TextStyle(fontSize: 20.0),
60 | ),
61 | ],
62 | ),
63 | Padding(
64 | padding: const EdgeInsets.only(top: 8.0, bottom: 8.0),
65 | child: Row(
66 | mainAxisAlignment: MainAxisAlignment.center,
67 | children: [
68 | GestureDetector(
69 | child: Text(
70 | "开源地址:github",
71 | style: TextStyle(
72 | fontSize: 20.0, color: Colors.lightBlue),
73 | ),
74 | onTapDown: (e) {
75 | _openLink(
76 | "https://github.com/GZYangKui/flutter-IM");
77 | },
78 | ),
79 | ],
80 | ),
81 | )
82 | ],
83 | ),
84 | ),
85 | Padding(
86 | padding: const EdgeInsets.all(8.0),
87 | child: Container(
88 | alignment: Alignment.center,
89 | child: Column(
90 | children: [
91 | Row(
92 | children: [
93 | Text(
94 | "版本更新",
95 | style: TextStyle(fontSize: 20.0),
96 | ),
97 | Expanded(
98 | child: Row(
99 | mainAxisAlignment: MainAxisAlignment.end,
100 | children: [
101 | Builder(
102 | builder: (BuildContext context) => IconButton(
103 | icon: Icon(Icons.update),
104 | onPressed: () {
105 | _updateProgram(context);
106 | },
107 | ),
108 | ),
109 | ],
110 | ),
111 | ),
112 | ],
113 | ),
114 | ],
115 | ),
116 | ),
117 | ),
118 | ],
119 | ),
120 | ),
121 | );
122 | }
123 |
124 | void _updateProgram(BuildContext context) {
125 | Scaffold.of(context).showSnackBar(SnackBar(content: Text("检测更新中.....")));
126 | }
127 |
128 | void _openLink(String url) async {
129 | Navigator.of(context).push(
130 | MaterialPageRoute(
131 | builder: (BuildContext context) => WebViewStateful(
132 | url: url,
133 | ),
134 | ),
135 | );
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/address_list.dart:
--------------------------------------------------------------------------------
1 | ///
2 | /// 通讯录好友界面
3 | ///
4 | ///
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/application_min.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_app/com/navigation/page/subpage/new_trend.dart';
4 |
5 | class MinApplication extends StatefulWidget {
6 | @override
7 | MinApplicationState createState() => MinApplicationState();
8 | }
9 |
10 | class MinApplicationState extends State
11 | with TickerProviderStateMixin {
12 | AnimationController _controller;
13 | Animation _drawerContentsOpacity;
14 |
15 | @override
16 | void initState() {
17 | super.initState();
18 | _controller = new AnimationController(
19 | vsync: this,
20 | duration: const Duration(milliseconds: 200),
21 | );
22 | _drawerContentsOpacity = new CurvedAnimation(
23 | parent: new ReverseAnimation(_controller),
24 | curve: Curves.fastOutSlowIn,
25 | );
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | return Tab(
31 | child: ListView(
32 | children: [
33 | FadeTransition(
34 | opacity: _drawerContentsOpacity,
35 | child: Column(
36 | children: [
37 | ListTile(
38 | leading: Icon(Icons.new_releases),
39 | title: Text(
40 | "新趋势",
41 | style: TextStyle(fontSize: 20.0),
42 | ),
43 | onTap: () => Navigator.of(context).push(
44 | MaterialPageRoute(
45 | builder: (BuildContext context) => NewTrend()),
46 | ),
47 | ),
48 | Divider(
49 | height: 3.0,
50 | ),
51 | ],
52 | ),
53 | ),
54 | ],
55 | ),
56 | );
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/application_setting.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_app/com/navigation/utils/application.dart'
4 | as application;
5 | import 'package:flutter_app/com/navigation/utils/file_handler.dart'
6 | as fileHandler;
7 |
8 | ///
9 | /// Application设置界面
10 | ///
11 | ///
12 | ///
13 | class ApplicationSetting extends StatefulWidget {
14 | @override
15 | State createState() => ApplicationSettingState();
16 | }
17 |
18 | class ApplicationSettingState extends State
19 | with TickerProviderStateMixin {
20 | final List colors = [
21 | Colors.lightBlue,
22 | Colors.black,
23 | Colors.black12,
24 | Colors.deepPurpleAccent,
25 | Colors.teal,
26 | Colors.brown,
27 | Colors.red,
28 | Colors.green,
29 | Colors.deepOrange,
30 | Colors.deepPurple,
31 | Colors.yellow,
32 | Colors.purpleAccent,
33 | Colors.black54
34 | ];
35 | AnimationController _controller;
36 | Animation _drawerContentsOpacity;
37 | bool isExpand = false;
38 | bool voiceSwitch = true;
39 | Color primaryColor = Colors.lightBlue;
40 | @override
41 | void initState() {
42 | super.initState();
43 | _controller = new AnimationController(
44 | vsync: this,
45 | duration: const Duration(milliseconds: 200),
46 | );
47 | _drawerContentsOpacity = new CurvedAnimation(
48 | parent: new ReverseAnimation(_controller),
49 | curve: Curves.fastOutSlowIn,
50 | );
51 | if (application.settings["voiceSwitch"] != null &&
52 | application.settings["voiceSwitch"] == "false") voiceSwitch = false;
53 | if (application.settings["primaryColor"] != null &&
54 | Color(int.parse(application.settings["primaryColor"])) != primaryColor)
55 | primaryColor = Color(int.parse(application.settings["primaryColor"]));
56 | }
57 |
58 | @override
59 | Widget build(BuildContext context) {
60 | return Theme(
61 | data: ThemeData(primaryColor: primaryColor),
62 | child: Scaffold(
63 | appBar: AppBar(
64 | title: Text("设置"),
65 | centerTitle: true,
66 | ),
67 | body: ListView(
68 | children: [
69 | FadeTransition(
70 | opacity: _drawerContentsOpacity,
71 | child: ListTile(
72 | leading: Icon(Icons.volume_up),
73 | title: Text(
74 | "新消息提醒",
75 | style: TextStyle(fontSize: 20.0),
76 | ),
77 | trailing: Switch(
78 | value: voiceSwitch,
79 | onChanged: (value) {
80 | this.setState(() {
81 | voiceSwitch = value;
82 | application.settings["voiceSwitch"] = value.toString();
83 | });
84 | }),
85 | ),
86 | ),
87 | Divider(
88 | height: 10.0,
89 | ),
90 | _selectTheme(),
91 | Divider(
92 | height: 10.0,
93 | ),
94 | ],
95 | ),
96 | ),
97 | );
98 | }
99 |
100 | Widget _selectTheme() {
101 | return Row(
102 | children: [
103 | Expanded(
104 | child: ExpansionPanelList(
105 | expansionCallback: (int index, bool isExpanded) {
106 | print(index);
107 | this.setState(() {
108 | this.isExpand = !isExpanded;
109 | });
110 | },
111 | children: [
112 | ExpansionPanel(
113 | headerBuilder: (BuildContext context, bool isExpanded) {
114 | return Row(
115 | children: [
116 | Container(
117 | margin: EdgeInsets.only(left: 10.0, right: 30.0),
118 | child: Icon(Icons.palette),
119 | ),
120 | Expanded(
121 | child: Row(
122 | children: [
123 | Text(
124 | "主题",
125 | style: TextStyle(fontSize: 20.0),
126 | ),
127 | Container(
128 | margin: EdgeInsets.only(left: 10.0),
129 | width: 20.0,
130 | height: 20.0,
131 | color: primaryColor,
132 | ),
133 | ],
134 | ),
135 | ),
136 | ],
137 | );
138 | },
139 | body: Wrap(
140 | children: colors.map((color) {
141 | return GestureDetector(
142 | child: Container(
143 | margin: EdgeInsets.all(3.0),
144 | height: 40.0,
145 | width: 40.0,
146 | color: color,
147 | ),
148 | onTapDown: (event) {
149 | application.settings["primaryColor"] =
150 | color.value.toString();
151 | this.setState(() {
152 | primaryColor = color;
153 | });
154 | },
155 | );
156 | }).toList(),
157 | ),
158 | isExpanded: this.isExpand,
159 | ),
160 | ],
161 | ),
162 | ),
163 | ],
164 | );
165 | }
166 |
167 | @override
168 | void dispose() {
169 | super.dispose();
170 | fileHandler.updateConfig();
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/chart_dialog.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_app/com/navigation/component/chart_message_item.dart';
6 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
7 | as handler;
8 | import 'package:flutter_app/com/navigation/utils/constant.dart' as constants;
9 | import 'package:flutter_app/com/navigation/utils/application.dart'
10 | as application;
11 |
12 | class ChartDialog extends StatefulWidget {
13 | final List _list;
14 | final String _name;
15 |
16 | ChartDialog({
17 | @required List messages,
18 | @required String name,
19 | }) : this._list = messages,
20 | this._name = name;
21 |
22 | @override
23 | ChartDialogState createState() => ChartDialogState();
24 | }
25 |
26 | class ChartDialogState extends State {
27 | String _message = "";
28 | Timer _timer;
29 | bool enable = false;
30 |
31 | @override
32 | void initState() {
33 | super.initState();
34 | handler.currentState = this;
35 | _timer = Timer.periodic(Duration(milliseconds: 30), (event) {
36 | this.setState(() {});
37 | });
38 | }
39 |
40 | @override
41 | Widget build(BuildContext context) {
42 | return Theme(
43 | data: ThemeData(
44 | primaryColor: application.settings["primaryColor"] == null
45 | ? Colors.lightBlue
46 | : Color(
47 | int.parse(application.settings["primaryColor"]),
48 | ),
49 | ),
50 | child: Scaffold(
51 | appBar: AppBar(
52 | title: Text(widget._name),
53 | centerTitle: true,
54 | actions: [
55 | Tooltip(
56 | child: IconButton(
57 | icon: application.images["clear"],
58 | onPressed: () {
59 | _clearMessage();
60 | },
61 | ),
62 | message: "清除聊天记录",
63 | ),
64 | ],
65 | ),
66 | body: Column(
67 | children: [
68 | Expanded(
69 | child: ListView.builder(
70 | itemBuilder: (BuildContext context, int index) =>
71 | ChartMessageItem(widget._list[index]),
72 | itemCount: widget._list.length,
73 | ),
74 | ),
75 | Row(
76 | children: [
77 | Expanded(
78 | child: TextField(
79 | decoration: InputDecoration(
80 | filled: true,
81 | suffixIcon: GestureDetector(
82 | child: Container(
83 | margin: EdgeInsets.all(8.0),
84 | width: 50.0,
85 | height: 20.0,
86 | decoration: BoxDecoration(
87 | color: enable ? Colors.white : Colors.grey,
88 | border: Border.all(color: Colors.red),
89 | borderRadius: BorderRadius.all(
90 | Radius.circular(5.0),
91 | ),
92 | ),
93 | alignment: Alignment.center,
94 | child: Text(
95 | "发送",
96 | style: TextStyle(fontSize: 16.0),
97 | ),
98 | ),
99 | onTapDown: (e) {
100 | _sendMessage(_message);
101 | },
102 | ),
103 | ),
104 | onChanged: (value) {
105 | if (value != "")
106 | enable = true;
107 | else
108 | enable = false;
109 | _message = value;
110 | },
111 | controller: MyController(
112 | text: _message,
113 | textSelection: TextSelection(
114 | baseOffset: _message.length,
115 | extentOffset: _message.length)),
116 | ),
117 | ),
118 | ],
119 | ),
120 | ],
121 | ),
122 | ),
123 | );
124 | }
125 |
126 | void _sendMessage(String value) {
127 | if (enable) {
128 | widget._list.add(value + constants.messageOwn);
129 | var message = {
130 | constants.type: constants.message,
131 | constants.subtype: constants.text,
132 | constants.to: widget._name,
133 | constants.body: value,
134 | constants.version: constants.currentVersion
135 | };
136 | handler.sendRequest(message);
137 | _message = "";
138 | enable = false;
139 | }
140 | }
141 |
142 | void _clearMessage() {
143 | showDialog(
144 | context: context,
145 | builder: (BuildContext context) => SimpleDialog(
146 | title: Text("警告"),
147 | children: [
148 | Column(
149 | children: [
150 | Row(
151 | mainAxisAlignment: MainAxisAlignment.center,
152 | children: [
153 | Expanded(
154 | child: Text(
155 | "确定要清空聊天记录?",
156 | textAlign: TextAlign.center,
157 | style: TextStyle(fontSize: 17.0),
158 | ),
159 | ),
160 | ],
161 | ),
162 | Row(
163 | mainAxisAlignment: MainAxisAlignment.center,
164 | children: [
165 | RaisedButton(
166 | child: Text("取消"),
167 | onPressed: () => Navigator.pop(context),
168 | shape: StadiumBorder(
169 | side: BorderSide(color: Colors.red),
170 | ),
171 | ),
172 | SizedBox(
173 | width: 10.0,
174 | ),
175 | RaisedButton(
176 | child: Text("确定"),
177 | onPressed: () {
178 | handler.clearMessage(widget._name);
179 | Navigator.pop(context);
180 | },
181 | shape: StadiumBorder(
182 | side: BorderSide(color: Colors.red),
183 | ),
184 | ),
185 | ],
186 | )
187 | ],
188 | ),
189 | ],
190 | ),
191 | );
192 | }
193 |
194 | @override
195 | void dispose() {
196 | super.dispose();
197 | if (_timer != null && _timer.isActive) _timer.cancel();
198 | if (widget._list.length != handler.obtainMessageNumber(widget._name))
199 | handler.updateMessageNumber(widget._name, widget._list.length);
200 | if (widget._list.length == 0) handler.clearMessage(widget._name);
201 | }
202 | }
203 |
204 | class MyController extends TextEditingController {
205 | MyController({String text, TextSelection textSelection}) : super(text: text) {
206 | this.text = text;
207 | super.selection = textSelection;
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/contacts.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_app/com/navigation/component/contacts_list_item.dart';
6 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
7 | as handler;
8 | import 'package:flutter_app/com/navigation/page/subpage/contacts_search.dart';
9 |
10 | ///
11 | /// 联系人界面
12 | ///
13 | ///
14 | class Contacts extends StatefulWidget {
15 | @override
16 | ContactsState createState() => ContactsState();
17 | }
18 |
19 | class ContactsState extends State {
20 | Timer _timer;
21 | @override
22 | void initState() {
23 | super.initState();
24 | _timer = Timer.periodic(Duration(seconds: 1), (event) {
25 | this.setState(() {});
26 | });
27 | }
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | return Tab(
32 | child: RefreshIndicator(
33 | child: Column(
34 | children: [
35 | GestureDetector(
36 | child: Container(
37 | margin: EdgeInsets.all(3.0),
38 | decoration: BoxDecoration(color: Colors.grey),
39 | child: Padding(
40 | padding: const EdgeInsets.all(8.0),
41 | child: Row(
42 | mainAxisAlignment: MainAxisAlignment.center,
43 | children: [
44 | Icon(Icons.search),
45 | Text(
46 | "搜索",
47 | style: TextStyle(fontSize: 18.0),
48 | ),
49 | ],
50 | ),
51 | ),
52 | ),
53 | onTapDown: (e) {
54 | Navigator.of(context).push(MaterialPageRoute(
55 | builder: (BuildContext context) => ContactsSearch()));
56 | },
57 | ),
58 | Expanded(
59 | child: ListView.builder(
60 | itemBuilder: (BuildContext context, int index) =>
61 | ContactItem(handler.contactsList[index]),
62 | itemCount: handler.contactsList.length,
63 | ),
64 | ),
65 | ],
66 | ),
67 | onRefresh: () => TickerFuture.complete(),
68 | ));
69 | }
70 |
71 | @override
72 | void dispose() {
73 | super.dispose();
74 | if (_timer != null && _timer.isActive) _timer.cancel();
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/contacts_search.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter/services.dart';
4 | import 'package:flutter_app/com/navigation/component/search_contacts_item.dart';
5 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
6 | as handler;
7 | import 'package:flutter_app/com/navigation/utils/utils.dart';
8 | import 'package:flutter_app/com/navigation/utils/application.dart'
9 | as application;
10 |
11 | ///
12 | /// 联系人及聊天信息搜索
13 | ///
14 | ///
15 | class ContactsSearch extends StatefulWidget {
16 | @override
17 | State createState() => ContactsSearchState();
18 | }
19 |
20 | class ContactsSearchState extends State {
21 | List _list = [];
22 | List _chipItem = [];
23 |
24 | @override
25 | void initState() {
26 | super.initState();
27 | }
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | return Theme(
32 | data: ThemeData(
33 | primaryColor: application.settings["primaryColor"] == null
34 | ? Colors.lightBlue
35 | : Color(
36 | int.parse(application.settings["primaryColor"]),
37 | ),
38 | ),
39 | child: Scaffold(
40 | appBar: AppBar(
41 | automaticallyImplyLeading: false,
42 | title: Container(
43 | child: Row(
44 | children: [
45 | Expanded(
46 | child: TextField(
47 | decoration: InputDecoration(
48 | filled: true,
49 | prefixIcon: const Icon(Icons.search),
50 | hintText: "搜索"),
51 | textInputAction: TextInputAction.search,
52 | onSubmitted: (value) {
53 | if (value != "") {
54 | _search(value);
55 | _addChip(value);
56 | } else {
57 | showToast("搜索关键字不能为空!");
58 | }
59 | },
60 | ),
61 | ),
62 | GestureDetector(
63 | child: Container(
64 | margin: EdgeInsets.only(left: 3.0),
65 | child: Padding(
66 | padding: const EdgeInsets.all(8.0),
67 | child: Text(
68 | "取消",
69 | style: TextStyle(color: Colors.blueAccent),
70 | ),
71 | ),
72 | ),
73 | onTapDown: (e) {
74 | Navigator.pop(context);
75 | },
76 | ),
77 | ],
78 | ),
79 | ),
80 | ),
81 | body: Column(
82 | children: [
83 | Expanded(
84 | child: _list.length == 0 ? _showCard() : _showContactList(),
85 | ),
86 | ],
87 | ),
88 | ),
89 | );
90 | }
91 |
92 | Widget _showCard() {
93 | return new Wrap(
94 | spacing: 10.0, // gap between adjacent chips
95 | runSpacing: 4.0, // gap between lines
96 | children: _chipItem,
97 | );
98 | }
99 |
100 | Widget _showContactList() {
101 | return ListView.builder(
102 | itemBuilder: (BuildContext context, int index) =>
103 | SearchContactsItem(_list[index]),
104 | itemCount: _list.length,
105 | );
106 | }
107 |
108 | void _search(String value) async {
109 | if (_list.length > 0) _list.clear();
110 | bool isExist = false;
111 | handler.contactsList.forEach((entry) {
112 | if (entry.list != null && entry.list.length > 0) {
113 | entry.list.forEach((e) {
114 | if (e.title == value) {
115 | print(e.title);
116 | _list.add(e.title);
117 | isExist = true;
118 | return;
119 | }
120 | });
121 | }
122 | if (isExist) return;
123 | });
124 | if (!isExist) showToast("找不到相关信息!");
125 | this.setState(() {});
126 | }
127 |
128 | void _addChip(String message) {
129 | InputChip clip = InputChip(
130 | label: Text(message),
131 | avatar: CircleAvatar(
132 | backgroundColor: Colors.blue.shade900,
133 | child: const Text("CL"),
134 | ),
135 | onPressed: () {
136 | _search(message);
137 | },
138 | );
139 | _chipItem.add(clip);
140 | }
141 |
142 | @override
143 | void dispose() {
144 | super.dispose();
145 | if (_list.length > 0) _list.clear();
146 | if (_chipItem.length > 0) _chipItem.clear();
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/message.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_app/com/navigation/component/message_list_item.dart';
6 | import 'package:flutter_app/com/navigation/models/message_list_item_model.dart';
7 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
8 | as handler;
9 | import 'package:flutter_app/com/navigation/utils/constant.dart' as constants;
10 |
11 | ///
12 | ///
13 | /// 消息界面
14 | ///
15 | ///
16 | class Message extends StatefulWidget {
17 | @override
18 | MessageState createState() => MessageState();
19 | }
20 |
21 | class MessageState extends State {
22 | List _list = [];
23 | Timer _timer;
24 |
25 | @override
26 | void initState() {
27 | super.initState();
28 |
29 | _timer = Timer.periodic(Duration(seconds: 1), (e) {
30 | this.setState(() {});
31 | });
32 | }
33 |
34 | @override
35 | Widget build(BuildContext context) {
36 | _initData();
37 | return Tab(
38 | child: RefreshIndicator(
39 | child: ListView.builder(
40 | itemBuilder: (BuildContext context, int index) =>
41 | MessageListItem(_list[index]),
42 | itemCount: _list.length,
43 | ),
44 | onRefresh: () {
45 | return TickerFuture.complete();
46 | }),
47 | );
48 | }
49 |
50 | @override
51 | void dispose() {
52 | super.dispose();
53 | if (_timer != null && _timer.isActive) _timer.cancel();
54 | if (_list != null) _list.clear();
55 | }
56 |
57 | ///
58 | ///
59 | /// 初始化数据
60 | ///
61 | ///
62 | void _initData() {
63 | if (_list.length > 0) _list.clear();
64 | handler.messageList.forEach((key, value) {
65 | _list.add(MessageListItemModel(messags: value, name: key));
66 | });
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/new_trend.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_app/com/navigation/page/subpage/new_trend/artificial_intelligence.dart';
4 | import 'package:flutter_app/com/navigation/page/subpage/new_trend/block_chain.dart';
5 | import 'package:flutter_app/com/navigation/utils/application.dart'
6 | as application;
7 |
8 | ///
9 | /// 此页是new_trend的一个精简版界面
10 | ///
11 | ///
12 | class NewTrend extends StatefulWidget {
13 | @override
14 | State createState() => NewTrendState();
15 | }
16 |
17 | class NewTrendState extends State
18 | with SingleTickerProviderStateMixin {
19 | TabController _tabController;
20 | int _currentIndex = 0;
21 | final List _tabs = [
22 | ArtificialIntelligence(),
23 | BlockChain(),
24 | ];
25 | @override
26 | void initState() {
27 | super.initState();
28 | _tabController =
29 | TabController(initialIndex: 0, length: _tabs.length, vsync: this);
30 | _tabController.addListener(() {
31 | this.setState(() {
32 | this._currentIndex = _tabController.index;
33 | });
34 | });
35 | }
36 |
37 | @override
38 | Widget build(BuildContext context) {
39 | return Theme(
40 | data: ThemeData(
41 | primaryColor: application.settings["primaryColor"] == null
42 | ? Colors.lightBlue
43 | : Color(
44 | int.parse(application.settings["primaryColor"]),
45 | ),
46 | ),
47 | child: Scaffold(
48 | appBar: AppBar(
49 | title: Text("新趋势"),
50 | centerTitle: true,
51 | automaticallyImplyLeading: false,
52 | ),
53 | body: TabBarView(
54 | children: _tabs,
55 | controller: _tabController,
56 | ),
57 | bottomNavigationBar: BottomNavigationBar(
58 | items: [
59 | BottomNavigationBarItem(
60 | icon: Icon(Icons.threed_rotation),
61 | title: Text("人工智能"),
62 | ),
63 | BottomNavigationBarItem(
64 | icon: Icon(Icons.attach_money),
65 | title: Text("区块链"),
66 | ),
67 | ],
68 | onTap: (index) {
69 | this.setState(() {
70 | _currentIndex = index;
71 | _tabController.index = _currentIndex;
72 | });
73 | },
74 | currentIndex: _currentIndex,
75 | ),
76 | ),
77 | );
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/new_trend/artificial_intelligence.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:convert';
3 |
4 | import 'package:flutter/cupertino.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:flutter_app/com/navigation/models/new_trend_model.dart';
7 | import 'package:flutter_app/com/navigation/page/subpage/webview.dart';
8 | import 'package:flutter_app/com/navigation/utils/utils.dart';
9 | import 'package:http/http.dart';
10 | import 'package:flutter_app/com/navigation/utils/constant.dart' as constants;
11 | import 'package:flutter_app/com/navigation/utils/application.dart'
12 | as application;
13 | import 'package:flutter_app/com/navigation/utils/file_handler.dart'
14 | as fileHandler;
15 |
16 | ///
17 | /// 此页是new_trend的一个精简版界面
18 | /// 之人工智能
19 | ///
20 |
21 | List _model = [];
22 |
23 | class ArtificialIntelligence extends StatefulWidget {
24 | @override
25 | State createState() => _ArtificialIntelligenceState();
26 | }
27 |
28 | class _ArtificialIntelligenceState extends State
29 | with TickerProviderStateMixin {
30 | AnimationController _controller;
31 | Animation _drawerContentsOpacity;
32 | @override
33 | void initState() {
34 | super.initState();
35 | _loadData(application.aiDate);
36 | _controller = new AnimationController(
37 | vsync: this,
38 | duration: const Duration(milliseconds: 200),
39 | );
40 | _drawerContentsOpacity = new CurvedAnimation(
41 | parent: new ReverseAnimation(_controller),
42 | curve: Curves.fastOutSlowIn,
43 | );
44 | }
45 |
46 | @override
47 | Widget build(BuildContext context) {
48 | return Scaffold(
49 | body: RefreshIndicator(
50 | child: ListView(
51 | children: _model.map((ai) {
52 | return FadeTransition(
53 | opacity: _drawerContentsOpacity,
54 | child: Column(
55 | children: [
56 | ArtificialIntelligenceItem(ai),
57 | Divider(
58 | height: 3.0,
59 | ),
60 | ],
61 | ),
62 | );
63 | }).toList(),
64 | ),
65 | onRefresh: () async {
66 | return await _refreshLoadData();
67 | }),
68 | floatingActionButton: FloatingActionButton(
69 | onPressed: () {
70 | _showSelectDate();
71 | },
72 | child: Icon(Icons.date_range),
73 | ),
74 | );
75 | }
76 |
77 | void _showSelectDate() async {
78 | DateTime date = await showDatePicker(
79 | context: context,
80 | firstDate: DateTime.parse("2018-07-01"),
81 | initialDate: DateTime.tryParse(application.aiDate),
82 | lastDate: DateTime.now());
83 | if (date != null) {
84 | application.aiDate = date.toString().split(" ")[0];
85 | _loadData(date.toString().split(" ")[0]);
86 | }
87 | }
88 |
89 | Future _loadData(String date) async {
90 | _model.clear();
91 | get("http://www.dashixiuxiu.cn/query_aitopics?crawltime=$date")
92 | .then((response) {
93 | if (response.statusCode == 200) {
94 | var result = json.decode(response.body);
95 | if (result[constants.status] == "success") {
96 | var data = result[constants.data];
97 | if (data.length > 0)
98 | for (var item in data) {
99 | NewTrendModel news = NewTrendModel(item["cn_title"], item["url"],
100 | item["cn_brief"], item["en_brief"]);
101 | _model.add(news);
102 | }
103 | else {
104 | showToast("暂无信息!");
105 | }
106 | this.setState(() {});
107 | } else
108 | showToast("获取信息出错!");
109 | } else {
110 | showToast("连接服务器失败!");
111 | }
112 | });
113 | }
114 |
115 | _refreshLoadData() async {
116 | await _loadData(application.aiDate).then((value) {
117 | showToast("刷新成功!");
118 | }).catchError((error) {
119 | showToast("未知错误!");
120 | }).whenComplete(() {});
121 | return TickerFuture.complete();
122 | }
123 |
124 | @override
125 | void dispose() {
126 | super.dispose();
127 | _model?.clear();
128 | }
129 | }
130 |
131 | class ArtificialIntelligenceItem extends StatefulWidget {
132 | final NewTrendModel model;
133 |
134 | ArtificialIntelligenceItem(this.model);
135 |
136 | @override
137 | State createState() => ArtificialIntelligenceItemState();
138 | }
139 |
140 | class ArtificialIntelligenceItemState
141 | extends State {
142 | bool isStar = false;
143 | @override
144 | void initState() {
145 | super.initState();
146 | _checkDate();
147 | }
148 |
149 | @override
150 | Widget build(BuildContext context) {
151 | return ListTile(
152 | leading: CircleAvatar(
153 | backgroundImage: AssetImage("assets/images/new_trend/ai.jpeg"),
154 | ),
155 | title: Text(widget.model.title),
156 | trailing: IconButton(
157 | icon: Icon(!isStar ? Icons.star_border : Icons.star),
158 | onPressed: () {
159 | this.setState(() {
160 | isStar = !isStar;
161 | if (isStar)
162 | fileHandler.insertCollect(widget.model, "AI");
163 | else
164 | fileHandler.deleteCollects(widget.model.title);
165 | });
166 | },
167 | ),
168 | onTap: () {
169 | Navigator.of(context).push(
170 | MaterialPageRoute(
171 | builder: (BuildContext context) => WebViewStateful(
172 | url: widget.model.url,
173 | ),
174 | ),
175 | );
176 | },
177 | );
178 | }
179 |
180 | void _checkDate() async {
181 | bool isExist = await fileHandler.selectCollects(widget.model.title);
182 | if (isExist) {
183 | this.setState(() {
184 | isStar = isExist;
185 | });
186 | }
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/new_trend/block_chain.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:convert';
3 |
4 | import 'package:flutter/cupertino.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:flutter_app/com/navigation/models/new_trend_model.dart';
7 | import 'package:flutter_app/com/navigation/page/subpage/webview.dart';
8 | import 'package:flutter_app/com/navigation/utils/application.dart'
9 | as application;
10 | import 'package:http/http.dart';
11 | import 'package:flutter_app/com/navigation/utils/constant.dart' as constants;
12 | import 'package:flutter_app/com/navigation/utils/utils.dart';
13 | import 'package:flutter_app/com/navigation/utils/file_handler.dart'
14 | as fileHandler;
15 |
16 | ///
17 | /// 此页是new_trend的一个精简版界面
18 | /// 之人区块链
19 | ///
20 | ///
21 | List _model = [];
22 |
23 | class BlockChain extends StatefulWidget {
24 | @override
25 | State createState() => BlockChainState();
26 | }
27 |
28 | class BlockChainState extends State with TickerProviderStateMixin {
29 | AnimationController _controller;
30 | Animation _drawerContentsOpacity;
31 | @override
32 | void initState() {
33 | super.initState();
34 | _loadData(application.blockDate);
35 | _controller = new AnimationController(
36 | vsync: this,
37 | duration: const Duration(milliseconds: 200),
38 | );
39 | _drawerContentsOpacity = new CurvedAnimation(
40 | parent: new ReverseAnimation(_controller),
41 | curve: Curves.fastOutSlowIn,
42 | );
43 | }
44 |
45 | @override
46 | Widget build(BuildContext context) {
47 | return Scaffold(
48 | body: RefreshIndicator(
49 | child: ListView(
50 | children: _model.map((block) {
51 | return FadeTransition(
52 | opacity: _drawerContentsOpacity,
53 | child: Column(
54 | children: [
55 | BlockChainItem(block),
56 | Divider(
57 | height: 3.0,
58 | ),
59 | ],
60 | ),
61 | );
62 | }).toList(),
63 | ),
64 | onRefresh: () async {
65 | return await _refreshLoadData();
66 | }),
67 | floatingActionButton: FloatingActionButton(
68 | onPressed: () {
69 | _showSelectDate();
70 | },
71 | child: Icon(Icons.date_range),
72 | ),
73 | );
74 | }
75 |
76 | void _showSelectDate() async {
77 | DateTime date = await showDatePicker(
78 | context: context,
79 | firstDate: DateTime.parse("2018-07-01"),
80 | initialDate: DateTime.tryParse(application.blockDate),
81 | lastDate: DateTime.now());
82 | if (date != null) {
83 | application.blockDate = date.toString().split(" ")[0];
84 | _loadData(date.toString().split(" ")[0]);
85 | }
86 | }
87 |
88 | Future _loadData(String date) async {
89 | this.setState(() {
90 | _model.clear();
91 | });
92 | print(_model.length);
93 | get("http://www.dashixiuxiu.cn/query_cointelegraph?crawltime=$date")
94 | .then((response) {
95 | if (response.statusCode == 200) {
96 | var result = json.decode(response.body);
97 | if (result[constants.status] == "success") {
98 | var data = result[constants.data];
99 | if (data.length > 0)
100 | for (var item in data) {
101 | _model.add(NewTrendModel(item["cn_title"], item["url"],
102 | item["cn_brief"], item["en_brief"]));
103 | }
104 | else {
105 | showToast("暂无信息!");
106 | }
107 | this.setState(() {});
108 | } else
109 | showToast("获取信息出错!");
110 | } else {
111 | showToast("连接服务器失败!");
112 | }
113 | });
114 | }
115 |
116 | _refreshLoadData() async {
117 | await _loadData(application.blockDate).then((value) {
118 | showToast("刷新成功!");
119 | }).catchError((error) {
120 | showToast("未知错误!");
121 | }).whenComplete(() {});
122 | return TickerFuture.complete();
123 | }
124 |
125 | @override
126 | void dispose() {
127 | super.dispose();
128 | _model.clear();
129 | }
130 | }
131 |
132 | class BlockChainItem extends StatefulWidget {
133 | final NewTrendModel model;
134 |
135 | BlockChainItem(this.model);
136 |
137 | @override
138 | State createState() => BlockChainItemState();
139 | }
140 |
141 | class BlockChainItemState extends State {
142 | bool isStar = false;
143 | @override
144 | void initState() {
145 | super.initState();
146 | _checkDate();
147 | }
148 |
149 | @override
150 | Widget build(BuildContext context) {
151 | return ListTile(
152 | leading: CircleAvatar(
153 | backgroundImage: AssetImage("assets/images/new_trend/block_chain.jpeg"),
154 | ),
155 | title: Text(widget.model.title),
156 | trailing: IconButton(
157 | icon: Icon(!isStar ? Icons.star_border : Icons.star),
158 | onPressed: () {
159 | this.setState(() {
160 | isStar = !isStar;
161 | if (isStar)
162 | fileHandler.insertCollect(widget.model, "BC");
163 | else
164 | fileHandler.deleteCollects(widget.model.title);
165 | });
166 | },
167 | ),
168 | onTap: () {
169 | Navigator.of(context).push(
170 | MaterialPageRoute(
171 | builder: (BuildContext context) => WebViewStateful(
172 | url: widget.model.url,
173 | ),
174 | ),
175 | );
176 | },
177 | );
178 | }
179 |
180 | void _checkDate() async {
181 | bool isExist = await fileHandler.selectCollects(widget.model.title);
182 | if (isExist) {
183 | this.setState(() {
184 | isStar = isExist;
185 | });
186 | }
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/picture_select.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | ///
7 | /// 图片选择器
8 | ///
9 | class SelectPicture extends StatefulWidget {
10 | final String title;
11 |
12 | SelectPicture(this.title);
13 |
14 | @override
15 | State createState() => SelectPictureState();
16 | }
17 |
18 | class SelectPictureState extends State {
19 | final List tabs = ["美女", "帅哥", "风景"];
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | return DefaultTabController(
24 | length: tabs.length,
25 | child: Scaffold(
26 | appBar: AppBar(
27 | title: Text(widget.title),
28 | centerTitle: true,
29 | bottom: TabBar(
30 | tabs: tabs.map((title) {
31 | return Tab(
32 | text: title,
33 | );
34 | }).toList()),
35 | ),
36 | body: TabBarView(children: [
37 | GridView.count(
38 | crossAxisCount: 5,
39 | children: [],
40 | ),
41 | GridView.count(
42 | crossAxisCount: 5,
43 | children: [],
44 | ),
45 | GridView.count(
46 | crossAxisCount: 5,
47 | children: [],
48 | ),
49 | ]),
50 | ),
51 | );
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/search.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_app/com/navigation/component/search_item.dart';
6 | import 'package:flutter_app/com/navigation/page/subpage/sweep_code.dart';
7 | import 'package:flutter_app/com/navigation/utils/constant.dart' as constants;
8 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
9 | as handler;
10 | import 'package:http/http.dart';
11 | import 'package:flutter_app/com/navigation/utils/application.dart'
12 | as application;
13 |
14 | class Search extends StatefulWidget {
15 | @override
16 | State createState() => SearchState();
17 | }
18 |
19 | class SearchState extends State with SingleTickerProviderStateMixin {
20 | GlobalKey key = GlobalKey();
21 |
22 | @override
23 | void initState() {
24 | super.initState();
25 | handler.currentState = this;
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | return Theme(
31 | data: ThemeData(
32 | primaryColor: application.settings["primaryColor"] == null
33 | ? Colors.lightBlue
34 | : Color(
35 | int.parse(application.settings["primaryColor"]),
36 | ),
37 | ),
38 | child: Scaffold(
39 | key: key,
40 | appBar: AppBar(
41 | title: Text("添加"),
42 | centerTitle: true,
43 | ),
44 | body: Column(
45 | children: [
46 | Container(
47 | margin: EdgeInsets.only(
48 | top: 10.0, left: 3.0, right: 3.0, bottom: 10.0),
49 | decoration: BoxDecoration(
50 | color: Color.fromRGBO(211, 211, 211, 0.8),
51 | ),
52 | child: Row(
53 | children: [
54 | Expanded(
55 | child: GestureDetector(
56 | child: Padding(
57 | padding: const EdgeInsets.all(8.0),
58 | child: Container(
59 | child: Row(
60 | children: [
61 | Icon(Icons.search),
62 | Expanded(
63 | child: Text(
64 | "搜索用户名",
65 | style: TextStyle(fontSize: 20.0),
66 | ),
67 | ),
68 | ],
69 | ),
70 | ),
71 | ),
72 | onTapDown: (event) {
73 | Navigator.of(context).push(MaterialPageRoute(
74 | builder: (BuildContext context) => SearchDialog()));
75 | },
76 | ),
77 | ),
78 | ],
79 | ),
80 | ),
81 | Expanded(
82 | child: _showMenu(),
83 | ),
84 | ],
85 | ),
86 | ),
87 | );
88 | }
89 |
90 | Widget _showMenu() {
91 | return ListView(
92 | children: [
93 | Padding(
94 | padding: const EdgeInsets.all(8.0),
95 | child: GestureDetector(
96 | child: Row(
97 | children: [
98 | Icon(Icons.phone_iphone),
99 | Expanded(
100 | child: Column(
101 | mainAxisAlignment: MainAxisAlignment.center,
102 | crossAxisAlignment: CrossAxisAlignment.start,
103 | children: [
104 | Text(
105 | "手机联系人",
106 | style: TextStyle(fontSize: 22.0),
107 | ),
108 | Text("添加或邀请通讯录中的好友"),
109 | ],
110 | ),
111 | ),
112 | ],
113 | ),
114 | onTapDown: (e) {
115 | key.currentState
116 | .showSnackBar(SnackBar(content: Text("该功能将在下一个版本开放!")));
117 | },
118 | ),
119 | ),
120 | Padding(
121 | padding: const EdgeInsets.all(8.0),
122 | child: GestureDetector(
123 | child: Row(
124 | children: [
125 | Icon(Icons.swap_calls),
126 | Expanded(
127 | child: Column(
128 | mainAxisAlignment: MainAxisAlignment.center,
129 | crossAxisAlignment: CrossAxisAlignment.start,
130 | children: [
131 | Text(
132 | "扫码",
133 | style: TextStyle(fontSize: 22.0),
134 | ),
135 | Text("扫描二维码名片"),
136 | ],
137 | ),
138 | ),
139 | ],
140 | ),
141 | onTapDown: (e) {
142 | Navigator.of(context).push(MaterialPageRoute(
143 | builder: (BuildContext context) => SweepCode()));
144 | },
145 | ),
146 | ),
147 | ],
148 | );
149 | }
150 |
151 | @override
152 | void dispose() {
153 | super.dispose();
154 | }
155 | }
156 |
157 | class SearchDialog extends StatefulWidget {
158 | @override
159 | SearchDialogState createState() => SearchDialogState();
160 | }
161 |
162 | class SearchDialogState extends State {
163 | List list = [];
164 | String _keyword = "";
165 | GlobalKey key = GlobalKey();
166 |
167 | @override
168 | Widget build(BuildContext context) {
169 | return Theme(
170 | data: ThemeData(
171 | primaryColor: application.settings["primaryColor"] == null
172 | ? Colors.lightBlue
173 | : Color(int.parse(application.settings["primaryColor"]))),
174 | child: Scaffold(
175 | key: key,
176 | appBar: AppBar(
177 | title: TextField(
178 | style: TextStyle(fontSize: 20.0),
179 | decoration: InputDecoration(hintText: "搜索用户名"),
180 | onSubmitted: (value) {
181 | _keyword = value;
182 | _search();
183 | },
184 | ),
185 | leading: IconButton(
186 | icon: Icon(Icons.chevron_left),
187 | onPressed: () => Navigator.pop(context),
188 | padding: EdgeInsets.all(0.0),
189 | ),
190 | /* backgroundColor: Colors.lightBlue,*/
191 | ),
192 | body: ListView.builder(
193 | itemBuilder: (BuildContext context, int index) =>
194 | UserItem(list[index]),
195 | itemCount: list.length,
196 | ),
197 | ),
198 | );
199 | }
200 |
201 | void _search() {
202 | if (_keyword != null && _keyword.trim() != "") {
203 | list.clear();
204 | var message = {
205 | constants.type: constants.search,
206 | constants.subtype: constants.info,
207 | constants.id: handler.userId,
208 | constants.password: handler.password,
209 | constants.keyword: _keyword,
210 | constants.version: constants.currentVersion
211 | };
212 | put("${constants.http}${constants.domain}/${constants.search}/${constants.info}",
213 | body: json.encode(message) + constants.end).then((response) {
214 | if (response.statusCode == 200) {
215 | var _result = json.decode(utf8.decode(response.bodyBytes));
216 | if (_result["user"] != null) {
217 | list.clear();
218 | list.add(_result["user"]["id"]);
219 | } else {
220 | key.currentState.showSnackBar(SnackBar(content: Text("该用户不存在")));
221 | }
222 | this.setState(() {});
223 | } else {
224 | key.currentState.showSnackBar(SnackBar(content: Text("服务器错误")));
225 | }
226 | });
227 | _keyword = "";
228 | }
229 | }
230 | }
231 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/sweep_code.dart:
--------------------------------------------------------------------------------
1 | ///
2 | /// 扫码添加好友界面
3 | ///
4 | import 'package:flutter/material.dart';
5 | import 'package:camera/camera.dart';
6 |
7 | class SweepCode extends StatefulWidget {
8 | @override
9 | State createState() => _SweepCodeState();
10 | }
11 |
12 | class _SweepCodeState extends State {
13 | CameraController controller;
14 | List cameras;
15 | bool _isInitial = false;
16 |
17 | @override
18 | void initState() {
19 | super.initState();
20 | _initCamera();
21 | }
22 |
23 | @override
24 | void dispose() {
25 | controller?.dispose();
26 | super.dispose();
27 | }
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | if (!_isInitial) {
32 | return Center(
33 | child: Column(
34 | mainAxisAlignment: MainAxisAlignment.center,
35 | children: [CircularProgressIndicator(), Text("相机正在初始化在...")],
36 | ),
37 | );
38 | } else {
39 | if (!controller.value.isInitialized) {
40 | return new Container();
41 | }
42 | return new AspectRatio(
43 | aspectRatio: controller.value.aspectRatio,
44 | child: new CameraPreview(controller));
45 | }
46 | }
47 |
48 | void _initCamera() async {
49 | cameras = await availableCameras();
50 | controller = new CameraController(cameras[0], ResolutionPreset.medium);
51 | controller.initialize().then((_) {
52 | if (!mounted) {
53 | return;
54 | }
55 | setState(() {
56 | _isInitial = true;
57 | });
58 | });
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/system_inform.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui' as ui;
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_app/com/navigation/component/system_propel.dart';
6 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
7 | as handler;
8 | import 'package:flutter_app/com/navigation/utils/application.dart'
9 | as application;
10 |
11 | ///
12 | ///
13 | ///系统推送界面
14 | ///
15 | ///
16 |
17 | class SystemInform extends StatefulWidget {
18 | @override
19 | State createState() => SystemInformState();
20 | }
21 |
22 | class SystemInformState extends State {
23 | @override
24 | void initState() {
25 | super.initState();
26 | handler.currentState = this;
27 | }
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | return Theme(
32 | data: ThemeData(
33 | primaryColor: application.settings["primaryColor"] == null
34 | ? Colors.lightBlue
35 | : Color(int.parse(application.settings["primaryColor"]))),
36 | child: Scaffold(
37 | appBar: AppBar(
38 | title: Text("系统消息"),
39 | centerTitle: true,
40 | ),
41 | body: handler.systemPropel.length > 0 ? _showPropel() : _showEmpty(),
42 | ),
43 | );
44 | }
45 |
46 | Widget _showPropel() {
47 | return ListView.builder(
48 | itemBuilder: (BuildContext context, int index) =>
49 | SystemPropel(handler.systemPropel[index]),
50 | itemCount: handler.systemPropel.length,
51 | );
52 | }
53 |
54 | Widget _showEmpty() {
55 | return Container(
56 | margin: EdgeInsets.only(
57 | top: (ui.window.physicalSize.height / ui.window.devicePixelRatio) *
58 | 0.2),
59 | alignment: Alignment.center,
60 | child: Column(
61 | children: [
62 | Image.asset("assets/images/icon.png"),
63 | Text(
64 | "暂无系统消息",
65 | style: TextStyle(fontSize: 20.0),
66 | ),
67 | ],
68 | ),
69 | );
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/user_info.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_app/com/navigation/component/new_trend_star.dart';
4 | import 'package:flutter_app/com/navigation/component/user_info_item.dart';
5 | import 'package:flutter_app/com/navigation/page/subpage/picture_select.dart';
6 | import 'package:flutter_app/com/navigation/utils/application.dart'
7 | as application;
8 |
9 | class UserInfo extends StatefulWidget {
10 | final String userName;
11 |
12 | UserInfo(this.userName);
13 |
14 | @override
15 | State createState() => UserInfoState();
16 | }
17 |
18 | class TabItem {
19 | String title;
20 | IconData icon;
21 |
22 | TabItem({this.icon, this.title});
23 | }
24 |
25 | class UserInfoState extends State
26 | with SingleTickerProviderStateMixin {
27 | final List menuItem = ["更换背景"];
28 | final List _tabs = [
29 | TabItem(title: "个人信息", icon: Icons.info),
30 | TabItem(title: "收藏", icon: Icons.collections)
31 | ];
32 | TabController _controller;
33 |
34 | Color primaryColor = Colors.lightBlue;
35 |
36 | @override
37 | void initState() {
38 | super.initState();
39 | primaryColor = application.settings["primaryColor"] == null
40 | ? Colors.lightBlue
41 | : Color(
42 | int.parse(application.settings["primaryColor"]),
43 | );
44 | _controller = TabController(length: 2, vsync: this);
45 | }
46 |
47 | @override
48 | Widget build(BuildContext context) {
49 | return Theme(
50 | data: ThemeData(primaryColor: primaryColor),
51 | child: Scaffold(
52 | appBar: AppBar(
53 | flexibleSpace: Stack(
54 | fit: StackFit.expand,
55 | children: [
56 | application.images["user_background"],
57 | ],
58 | ),
59 | bottom: TabBar(
60 | tabs: _tabs.map((tab) {
61 | return Tab(
62 | text: tab.title,
63 | icon: Icon(tab.icon),
64 | );
65 | }).toList(),
66 | controller: _controller,
67 | ),
68 | ),
69 | body: TabBarView(
70 | children: [
71 | ListView(
72 | children: [
73 | UserInfoItem(),
74 | ],
75 | ),
76 | NewTrendStar(),
77 | ],
78 | controller: _controller,
79 | ),
80 | ),
81 | );
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/subpage/webview.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
6 | import 'package:flutter_app/com/navigation/utils/application.dart'
7 | as application;
8 | import 'package:url_launcher/url_launcher.dart';
9 | import 'package:flutter_app/com/navigation/utils/utils.dart';
10 |
11 | class WebViewStateful extends StatefulWidget {
12 | final String _url;
13 |
14 | WebViewStateful({String url}) : this._url = url;
15 |
16 | @override
17 | State createState() => WebViewState();
18 | }
19 |
20 | class WebViewState extends State {
21 | final FlutterWebviewPlugin manager = FlutterWebviewPlugin();
22 | String _title = "loading......";
23 | String _url;
24 | @override
25 | void initState() {
26 | super.initState();
27 | initWebView();
28 | }
29 |
30 | @override
31 | Widget build(BuildContext context) {
32 | return Theme(
33 | data: ThemeData(
34 | primaryColor: application.settings["primaryColor"] == null
35 | ? Colors.lightBlue
36 | : Color(
37 | int.parse(application.settings["primaryColor"]),
38 | ),
39 | ),
40 | child: WebviewScaffold(
41 | url: widget._url,
42 | appBar: AppBar(
43 | title: Container(
44 | alignment: Alignment.center,
45 | width: (window.physicalSize.width / window.devicePixelRatio) * 0.6,
46 | child: Text(
47 | _title,
48 | ),
49 | ),
50 | centerTitle: true,
51 | actions: [
52 | Tooltip(
53 | message: "外部浏览器打开",
54 | child: IconButton(
55 | icon: Icon(Icons.zoom_out_map),
56 | onPressed: () {
57 | _openOutBrowser();
58 | },
59 | ),
60 | )
61 | ],
62 | ),
63 | ),
64 | );
65 | }
66 |
67 | void initWebView() async {
68 | manager.onUrlChanged.listen((url) {
69 | _url = url;
70 | manager.evalJavascript("document.title").then((title) {
71 | title = title.replaceAll("\"", "");
72 | this.setState(() {
73 | _title = title;
74 | });
75 | });
76 | });
77 | }
78 |
79 | void _openOutBrowser() async {
80 | String url = _url ?? widget._url;
81 | if (await canLaunch(url)) {
82 | await launch(url);
83 | } else {
84 | showToast("调起系统浏览器失败!");
85 | }
86 | }
87 |
88 | @override
89 | void dispose() {
90 | super.dispose();
91 | manager.close();
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/lib/com/navigation/page/user.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter/services.dart';
4 | import 'package:flutter_app/com/navigation/page/subpage/about_program.dart';
5 | import 'package:flutter_app/com/navigation/page/subpage/application_min.dart';
6 | import 'package:flutter_app/com/navigation/page/subpage/application_setting.dart';
7 | import 'package:flutter_app/com/navigation/page/subpage/contacts.dart';
8 | import 'package:flutter_app/com/navigation/page/subpage/message.dart';
9 | import 'package:flutter_app/com/navigation/page/subpage/search.dart';
10 | import 'package:flutter_app/com/navigation/page/login.dart';
11 | import 'package:flutter_app/com/navigation/netwok/socket_handler.dart'
12 | as handler;
13 | import 'package:flutter_app/com/navigation/page/subpage/system_inform.dart';
14 | import 'package:flutter_app/com/navigation/page/subpage/user_info.dart';
15 | import 'package:flutter_app/com/navigation/utils/utils.dart';
16 | import 'package:flutter_app/com/navigation/utils/application.dart'
17 | as application;
18 |
19 | class UserCenter extends StatefulWidget {
20 | @override
21 | UserCenterState createState() => UserCenterState();
22 | }
23 |
24 | class UserCenterState extends State
25 | with SingleTickerProviderStateMixin {
26 | static final List _tabs = [
27 | Message(),
28 | Contacts(),
29 | MinApplication()
30 | ];
31 | TabController _tabController;
32 | int _currentIndex = 0;
33 | final List _titles = ["消息", "联系人", "小应用"];
34 |
35 | @override
36 | Widget build(BuildContext context) {
37 | return Theme(
38 | data: ThemeData(
39 | primaryColor: application.settings["primaryColor"] == null
40 | ? Colors.lightBlue
41 | : Color(int.parse(application.settings["primaryColor"]))),
42 | child: WillPopScope(
43 | child: Scaffold(
44 | appBar: AppBar(
45 | centerTitle: true,
46 | title: new Text(_titles[_currentIndex]),
47 | actions: [
48 | IconButton(
49 | icon: Icon(Icons.add),
50 | onPressed: () {
51 | Navigator.push(
52 | context,
53 | MaterialPageRoute(
54 | builder: (BuildContext context) => Search()));
55 | },
56 | ),
57 | IconButton(
58 | icon: Icon(Icons.notifications),
59 | onPressed: () => Navigator.of(context).push(MaterialPageRoute(
60 | builder: (BuildContext context) => SystemInform())),
61 | ),
62 | ],
63 | ),
64 | drawer: Drawer(
65 | child: DrawerItems(),
66 | ),
67 | body: TabBarView(
68 | children: _tabs,
69 | controller: _tabController,
70 | ),
71 | bottomNavigationBar: BottomNavigationBar(
72 | items: [
73 | BottomNavigationBarItem(
74 | icon: Icon(Icons.message), title: Text("消息")),
75 | BottomNavigationBarItem(
76 | icon: Icon(Icons.perm_contact_calendar), title: Text("联系人")),
77 | BottomNavigationBarItem(
78 | icon: Icon(Icons.streetview), title: Text("小应用")),
79 | ],
80 | onTap: (index) {
81 | this.setState(() {
82 | _currentIndex = index;
83 | });
84 | _tabController.animateTo(index);
85 | },
86 | currentIndex: _currentIndex,
87 | ),
88 | ),
89 | onWillPop: () {
90 | SystemNavigator.pop();
91 | },
92 | ),
93 | );
94 | }
95 |
96 | @override
97 | void initState() {
98 | super.initState();
99 | SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.top]);
100 | handler.currentState = this;
101 | _tabController =
102 | TabController(initialIndex: 0, length: _tabs.length, vsync: this);
103 | _tabController.addListener(() {
104 | this.setState(() {
105 | this._currentIndex = _tabController.index;
106 | });
107 | });
108 | }
109 |
110 | @override
111 | void dispose() {
112 | super.dispose();
113 | _tabController.dispose();
114 | }
115 | }
116 |
117 | class DrawerItems extends StatefulWidget {
118 | @override
119 | State createState() => DrawerItemsState();
120 | }
121 |
122 | class DrawerItemsState extends State
123 | with TickerProviderStateMixin {
124 | AnimationController _controller;
125 | Animation _drawerContentsOpacity;
126 | @override
127 | void initState() {
128 | super.initState();
129 | _controller = new AnimationController(
130 | vsync: this,
131 | duration: const Duration(milliseconds: 200),
132 | );
133 | _drawerContentsOpacity = new CurvedAnimation(
134 | parent: new ReverseAnimation(_controller),
135 | curve: Curves.fastOutSlowIn,
136 | );
137 | }
138 |
139 | @override
140 | Widget build(BuildContext context) {
141 | return ListView(
142 | children: [
143 | Row(
144 | children: [
145 | Expanded(
146 | child: Container(
147 | alignment: Alignment.centerLeft,
148 | child: Column(
149 | children: [
150 | Row(
151 | mainAxisAlignment: MainAxisAlignment.start,
152 | crossAxisAlignment: CrossAxisAlignment.center,
153 | children: [
154 | Expanded(
155 | child: UserAccountsDrawerHeader(
156 | accountName: Text(handler.userId),
157 | accountEmail: const Text("752544765@qqcom"),
158 | currentAccountPicture: GestureDetector(
159 | child: const CircleAvatar(
160 | backgroundImage:
161 | AssetImage("assets/images/head.png"),
162 | ),
163 | onTapDown: (e) {
164 | Navigator.of(context).push(
165 | MaterialPageRoute(
166 | builder: (BuildContext context) =>
167 | UserInfo(handler.userId),
168 | ),
169 | );
170 | },
171 | ),
172 | otherAccountsPictures: [],
173 | ),
174 | ),
175 | ],
176 | ),
177 | ],
178 | ),
179 | ),
180 | ),
181 | ],
182 | ),
183 | FadeTransition(
184 | opacity: _drawerContentsOpacity,
185 | child: Column(
186 | children: [
187 | ListTile(
188 | leading: Icon(Icons.settings),
189 | title: Text(
190 | "设置",
191 | style: TextStyle(fontSize: 20.0),
192 | ),
193 | onTap: () => Navigator.of(context).push(
194 | MaterialPageRoute(
195 | builder: (BuildContext context) => ApplicationSetting(),
196 | ),
197 | ),
198 | ),
199 | ListTile(
200 | leading: Icon(Icons.info),
201 | title: Text(
202 | "关于",
203 | style: TextStyle(fontSize: 20.0),
204 | ),
205 | onTap: () => Navigator.of(context).push(
206 | MaterialPageRoute(
207 | builder: (BuildContext context) => About(),
208 | ),
209 | ),
210 | ),
211 | ListTile(
212 | leading: Icon(Icons.share),
213 | title: Text(
214 | "分享",
215 | style: TextStyle(fontSize: 20.0),
216 | ),
217 | onTap: () => showToast("该功能正在开发中,敬请期待!"),
218 | ),
219 | ListTile(
220 | leading: Icon(Icons.exit_to_app),
221 | title: Text(
222 | "注销",
223 | style: TextStyle(fontSize: 20.0),
224 | ),
225 | onTap: () => _logout(),
226 | ),
227 | ],
228 | ),
229 | ),
230 | ],
231 | );
232 | }
233 |
234 | void _logout() {
235 | showDialog(
236 | context: context,
237 | builder: (BuildContext context) => SimpleDialog(
238 | title: Text("消息"),
239 | children: [
240 | Row(
241 | mainAxisAlignment: MainAxisAlignment.center,
242 | children: [Text("你确定要退出当前账号?")],
243 | ),
244 | SizedBox(
245 | height: 10.0,
246 | ),
247 | Row(
248 | mainAxisAlignment: MainAxisAlignment.center,
249 | children: [
250 | RaisedButton(
251 | child: Text("取消"),
252 | shape: StadiumBorder(
253 | side: BorderSide(color: Colors.red),
254 | ),
255 | onPressed: () => Navigator.pop(context),
256 | ),
257 | SizedBox(
258 | width: 10.0,
259 | height: 0.0,
260 | ),
261 | RaisedButton(
262 | child: Text("确定"),
263 | shape: StadiumBorder(
264 | side: BorderSide(color: Colors.red),
265 | ),
266 | onPressed: () {
267 | handler.dispose();
268 | Navigator.of(context).push(MaterialPageRoute(
269 | builder: (BuildContext context) => Login()));
270 | },
271 | ),
272 | ],
273 | ),
274 | ],
275 | ),
276 | );
277 | }
278 | }
279 |
--------------------------------------------------------------------------------
/lib/com/navigation/utils/application.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:sqflite/sqflite.dart';
3 |
4 | ///
5 | /// 存放整个app的全局变量
6 | ///
7 |
8 | /// 整个应用数据存储路径
9 | String dir = "";
10 |
11 | ///数据库文件路径
12 | String dbPath = "";
13 |
14 | ///sqlite数据库操纵实例
15 | Database dataBases;
16 |
17 | ///人工智能时间查询
18 | String aiDate = "2018-07-29";
19 |
20 | ///区块链查询时间
21 | String blockDate = "2018-07-29";
22 |
23 | ///账号集合
24 | List