Merge branch 'master' of gitee.com:starlock-cn/app-starlock
# Conflicts: # star_lock/lib/main/lockDetail/lockDetail/lockDetail_page.dart # star_lock/lib/network/api.dart
7
star_lock/.run/main_dev_dart.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="main_dev.dart" type="FlutterRunConfigurationType" factoryName="Flutter">
|
||||
<option name="buildFlavor" value="dev"/>
|
||||
<option name="filePath" value="$PROJECT_DIR$/lib/main_dev.dart"/>
|
||||
<method v="2"/>
|
||||
</configuration>
|
||||
</component>
|
||||
7
star_lock/.run/main_pre_dart.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="main_pre.dart" type="FlutterRunConfigurationType" factoryName="Flutter">
|
||||
<option name="buildFlavor" value="pre"/>
|
||||
<option name="filePath" value="$PROJECT_DIR$/lib/main_pre.dart"/>
|
||||
<method v="2"/>
|
||||
</configuration>
|
||||
</component>
|
||||
7
star_lock/.run/main_sky_dart.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="main_sky.dart" type="FlutterRunConfigurationType" factoryName="Flutter">
|
||||
<option name="buildFlavor" value="sky"/>
|
||||
<option name="filePath" value="$PROJECT_DIR$/lib/main_sky.dart"/>
|
||||
<method v="2"/>
|
||||
</configuration>
|
||||
</component>
|
||||
7
star_lock/.run/main_xhj_dart.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="main_xhj.dart" type="FlutterRunConfigurationType" factoryName="Flutter">
|
||||
<option name="buildFlavor" value="xhj"/>
|
||||
<option name="filePath" value="$PROJECT_DIR$/lib/main_xhj.dart"/>
|
||||
<method v="2"/>
|
||||
</configuration>
|
||||
</component>
|
||||
@ -1,16 +1,72 @@
|
||||
# star_lock
|
||||
# 星锁APP
|
||||
|
||||
A new Flutter project.
|
||||
星云项目组旗下的智能锁应用,其中锁相关数据接入星云平台,业务数据接入星锁自有后台。
|
||||
|
||||
## Getting Started
|
||||
基于Flutter技术架构,支持Android和iOS平台。
|
||||
|
||||
This project is a starting point for a Flutter application.
|
||||
## 开发步骤
|
||||
|
||||
A few resources to get you started if this is your first Flutter project:
|
||||
### 安装Flutter
|
||||
|
||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
||||
参阅 [安装 - Flutter](https://docs.flutter.dev/get-started/install)
|
||||
|
||||
For help getting started with Flutter development, view the
|
||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
||||
然后 `flutter doctor` 检查环境
|
||||
|
||||
### 禁用不需要的平台
|
||||
|
||||
```bash
|
||||
flutter config --no-enable-macos-desktop --no-enable-windows-desktop --no-enable-linux-desktop --no-enable-web
|
||||
```
|
||||
|
||||
|
||||
### 安装依赖
|
||||
|
||||
```bash
|
||||
flutter pub get
|
||||
```
|
||||
|
||||
### 运行
|
||||
|
||||
```bash
|
||||
|
||||
# 运行sky渠道
|
||||
flutter run --flavor sky -t lib/main_sky.dart
|
||||
|
||||
```
|
||||
|
||||
## 配置签名
|
||||
|
||||
参阅 [构建和发布 Android 应用 - 创建上载密钥库 - Flutter](https://docs.flutter.dev/deployment/android#create-an-upload-keystore)
|
||||
|
||||
为发布渠道创建JAVA密钥储存(密钥库)文件 `.jks`,或者 `.keystore` 文件。
|
||||
|
||||
```bash
|
||||
keytool -genkey -v -keystore android/app/sky.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
|
||||
```
|
||||
|
||||
请记住你输入的主密码和键密码
|
||||
|
||||
因为本项目将会发布2个以上的渠道,所以密钥库也会有2个以上,请注意区分 同一个发布渠道必须使用同一个密钥库,不要生成多个。
|
||||
|
||||
为了编译管理方便,我们将密钥库文件放在了项目代码内。
|
||||
|
||||
`key.properties` 文件用于存放密钥库的相关信息,但是我们不用这个文件,而是直接在 `build.gradle` 中写入密钥库的相关信息。
|
||||
因为我们将密钥库文件本身都已经储存在git中了,也就没必要再单独存放密钥信息了。
|
||||
|
||||
## 编译
|
||||
```bash
|
||||
flutter build apk --split-per-abi --release --flavor sky -t lib/main_sky.dart
|
||||
```
|
||||
|
||||
## 获取编译包的签名
|
||||
用于APP备案,国内商店上架等
|
||||
|
||||
需要使用到`apksigner`工具,对于Windows来说,它在:`C:\Users\myUser\AppData\Local\Android\Sdk\build-tools\34.0.0\lib`
|
||||
|
||||
在 `git bash` 中我需要使用 `apksigner.bat` 来使用它;在其它系统中应该可以直接使用 `apksigner` 命令即可。
|
||||
|
||||
参阅:[How to find signature of apk file?](https://stackoverflow.com/questions/38558623/how-to-find-signature-of-apk-file)
|
||||
|
||||
```bash
|
||||
apksigner verify --print-certs -v build/app/outputs/flutter-apk/app-sky-release.apk
|
||||
```
|
||||
|
||||
8
star_lock/android/.gitignore
vendored
@ -8,6 +8,8 @@ GeneratedPluginRegistrant.java
|
||||
|
||||
# Remember to never publicly share your keystore.
|
||||
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
|
||||
key.properties
|
||||
**/*.keystore
|
||||
**/*.jks
|
||||
# 因为我们要管理多个项目,所以这里不要忽略keystore
|
||||
# 而且我们的代码库是私有的,不存在泄露问题
|
||||
#key.properties
|
||||
#**/*.keystore
|
||||
#**/*.jks
|
||||
|
||||
@ -28,7 +28,59 @@ apply plugin: 'kotlin-android'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
android {
|
||||
compileSdkVersion flutter.compileSdkVersion
|
||||
signingConfigs {
|
||||
pre {
|
||||
storeFile file("starlock.keystore")
|
||||
storePassword '123456'
|
||||
keyAlias = 'starlock'
|
||||
keyPassword '123456'
|
||||
}
|
||||
sky {
|
||||
// CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
|
||||
storeFile file("sky.jks")
|
||||
storePassword 'sky2028'
|
||||
keyAlias = 'upload'
|
||||
keyPassword 'sky2028'
|
||||
}
|
||||
xhj {
|
||||
storeFile file("xhj.jks")
|
||||
storePassword 'xhj8872'
|
||||
keyAlias = 'upload'
|
||||
keyPassword 'xhj8872'
|
||||
}
|
||||
}
|
||||
// ----- BEGIN flavorDimensions (autogenerated by flutter_flavorizr) -----
|
||||
flavorDimensions "flavor-type"
|
||||
|
||||
productFlavors {
|
||||
dev {
|
||||
dimension "flavor-type"
|
||||
applicationId "com.starlock.lock.dev"
|
||||
resValue "string", "app_name", "星锁-dev"
|
||||
}
|
||||
pre {
|
||||
dimension "flavor-type"
|
||||
applicationId "com.starlock.lock.pre"
|
||||
resValue "string", "app_name", "星锁"
|
||||
}
|
||||
sky {
|
||||
dimension "flavor-type"
|
||||
applicationId "com.skychip.lock"
|
||||
signingConfig signingConfigs.sky
|
||||
resValue "string", "app_name", "锁通通"
|
||||
}
|
||||
xhj {
|
||||
dimension "flavor-type"
|
||||
applicationId "com.xhjcn.lock"
|
||||
signingConfig signingConfigs.xhj
|
||||
resValue "string", "app_name", "鑫锁"
|
||||
}
|
||||
}
|
||||
|
||||
// ----- END flavorDimensions (autogenerated by flutter_flavorizr) -----
|
||||
|
||||
|
||||
compileSdkVersion flutter.compileSdkVersion
|
||||
ndkVersion flutter.ndkVersion
|
||||
|
||||
lintOptions{
|
||||
@ -52,7 +104,6 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "cn.starlock.lock"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
||||
@ -63,37 +114,28 @@ android {
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
|
||||
signingConfig signingConfigs.pre
|
||||
// 为减少体积,使用不同架构分包发布编译选项 flutter build apk --split-per-abi
|
||||
// 所以需要禁用ndk在同一个个包中包含多个架构
|
||||
ndk {
|
||||
//设置支持的SO库架构(开发者可以根据需要,选择一个或多个平台的so)
|
||||
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64"
|
||||
}
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
storeFile file("starlock.keystore")
|
||||
storePassword '123456'
|
||||
keyAlias = 'starlock'
|
||||
keyPassword '123456'
|
||||
}
|
||||
debug {
|
||||
storeFile file("starlock.keystore")
|
||||
storePassword '123456'
|
||||
keyAlias = 'starlock'
|
||||
keyPassword '123456'
|
||||
splits {
|
||||
abi {
|
||||
include "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig signingConfigs.release
|
||||
productFlavors.dev.signingConfig signingConfigs.pre
|
||||
productFlavors.pre.signingConfig signingConfigs.pre
|
||||
productFlavors.sky.signingConfig signingConfigs.sky
|
||||
productFlavors.xhj.signingConfig signingConfigs.xhj
|
||||
}
|
||||
debug {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --debug` works.
|
||||
signingConfig signingConfigs.debug
|
||||
signingConfig signingConfigs.pre
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
star_lock/android/app/sky.jks
Normal file
BIN
star_lock/android/app/src/dev/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
star_lock/android/app/src/dev/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
star_lock/android/app/src/dev/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
star_lock/android/app/src/dev/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
star_lock/android/app/src/dev/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
@ -1,110 +1,78 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.star_lock">
|
||||
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />-->
|
||||
<!-- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />-->
|
||||
|
||||
<!--允许访问网络,必选权限-->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!--允许获取精确位置,精准定位必选-->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<!--允许获取粗略位置,粗略定位必选-->
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
|
||||
<!--允许获取设备和运营商信息,用于问题排查和网络定位(无gps情况下的定位),若需网络定位功能则必选-->
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
|
||||
|
||||
<!--允许获取网络状态,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<!--允许获取wifi网络信息,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
|
||||
<!--允许获取wifi状态改变,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
|
||||
<!--后台获取位置信息,若需后台定位则必选-->
|
||||
<!-- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />-->
|
||||
|
||||
<!--用于申请调用A-GPS模块,卫星定位加速-->
|
||||
<!-- <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />-->
|
||||
|
||||
<!--允许写设备缓存,用于问题排查-->
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||
|
||||
<!--允许写入扩展存储,用于写入缓存定位数据-->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<!--允许读设备等信息,用于问题排查-->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<!--允许麦克风权限,用于录音发送-->
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.REORDER_TASKS" />
|
||||
|
||||
<application
|
||||
android:label="星锁"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_logo">
|
||||
<!-- 配置定位Service -->
|
||||
<service android:name="com.amap.api.location.APSService"/>
|
||||
<activity
|
||||
android:name="cn.starlock.lock.MainActivity"
|
||||
android:exported="true"
|
||||
android:screenOrientation="portrait"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.star_lock">
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
|
||||
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />-->
|
||||
<!-- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />-->
|
||||
<!--允许访问网络,必选权限-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<!--允许获取精确位置,精准定位必选-->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<!--允许获取粗略位置,粗略定位必选-->
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||
<!--允许获取设备和运营商信息,用于问题排查和网络定位(无gps情况下的定位),若需网络定位功能则必选-->
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
||||
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
|
||||
<!--允许获取网络状态,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<!--允许获取wifi网络信息,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<!--允许获取wifi状态改变,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||
<!--后台获取位置信息,若需后台定位则必选-->
|
||||
<!-- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />-->
|
||||
<!--用于申请调用A-GPS模块,卫星定位加速-->
|
||||
<!-- <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />-->
|
||||
<!--允许写设备缓存,用于问题排查-->
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
|
||||
<!--允许写入扩展存储,用于写入缓存定位数据-->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<!--允许读设备等信息,用于问题排查-->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<!--允许麦克风权限,用于录音发送-->
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.REORDER_TASKS"/>
|
||||
<application android:label="@string/app_name" android:name="${applicationName}" android:icon="@mipmap/ic_launcher">
|
||||
<!-- 配置定位Service -->
|
||||
<service android:name="com.amap.api.location.APSService"/>
|
||||
<activity android:name="cn.starlock.lock.MainActivity" android:exported="true" android:screenOrientation="portrait" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
<meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme"/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
<meta-data android:name="com.amap.api.v2.apikey" android:value="11d49b3f4fc09c04a02bbb7500925ba2"> </meta-data>
|
||||
<!-- 请填写你自己的- appKey -->
|
||||
<meta-data android:name="com.alibaba.app.appkey" android:value="333904040"/>
|
||||
<!-- 请填写你自己的appSecret -->
|
||||
<meta-data android:name="com.alibaba.app.appsecret" android:value="c316965fe0a74fc9a481a5c44a535dc2"/>
|
||||
<!-- 消息接收监听器 (用户可自主扩展) -->
|
||||
<receiver
|
||||
android:name="cn.starlock.lock.MyMessageReceiver"
|
||||
android:exported="false" > <!-- 为保证receiver安全,建议设置不可导出,如需对其他应用开放可通过android:permission进行限制 -->
|
||||
<intent-filter>
|
||||
<action android:name="com.alibaba.sdk.android.push.intent.MESSAGE" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.alibaba.push2.action.NOTIFICATION_OPENED" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.alibaba.push2.action.NOTIFICATION_REMOVED" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.alibaba.sdk.android.push.RECEIVE" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</application>
|
||||
<meta-data android:name="flutterEmbedding" android:value="2"/>
|
||||
<meta-data android:name="com.amap.api.v2.apikey" android:value="11d49b3f4fc09c04a02bbb7500925ba2"></meta-data>
|
||||
<!-- 请填写你自己的- appKey -->
|
||||
<meta-data android:name="com.alibaba.app.appkey" android:value="333904040"/>
|
||||
<!-- 请填写你自己的appSecret -->
|
||||
<meta-data android:name="com.alibaba.app.appsecret" android:value="c316965fe0a74fc9a481a5c44a535dc2"/>
|
||||
<!-- 消息接收监听器 (用户可自主扩展) -->
|
||||
<receiver android:name="cn.starlock.lock.MyMessageReceiver" android:exported="false">
|
||||
<!-- 为保证receiver安全,建议设置不可导出,如需对其他应用开放可通过android:permission进行限制 -->
|
||||
<intent-filter>
|
||||
<action android:name="com.alibaba.sdk.android.push.intent.MESSAGE"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.alibaba.push2.action.NOTIFICATION_OPENED"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.alibaba.push2.action.NOTIFICATION_REMOVED"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.alibaba.sdk.android.push.RECEIVE"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@ -7,6 +7,6 @@
|
||||
<item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/ic_logo" />
|
||||
android:src="@mipmap/ic_launcher" />
|
||||
</item>
|
||||
</layer-list>
|
||||
|
||||
@ -7,6 +7,6 @@
|
||||
<item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/ic_logo" />
|
||||
android:src="@mipmap/ic_launcher" />
|
||||
</item>
|
||||
</layer-list>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 11 KiB |
BIN
star_lock/android/app/src/pre/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
star_lock/android/app/src/pre/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
star_lock/android/app/src/pre/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
star_lock/android/app/src/pre/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
star_lock/android/app/src/pre/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
star_lock/android/app/src/sky/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
star_lock/android/app/src/sky/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
star_lock/android/app/src/sky/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
star_lock/android/app/src/sky/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
star_lock/android/app/src/sky/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
star_lock/android/app/src/xhj/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
star_lock/android/app/src/xhj/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
star_lock/android/app/src/xhj/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
star_lock/android/app/src/xhj/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
star_lock/android/app/src/xhj/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
star_lock/android/app/starlock.keystore
Normal file
BIN
star_lock/android/app/xhj.jks
Normal file
BIN
star_lock/assets/icon/dev.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
star_lock/assets/icon/pre.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
star_lock/assets/icon/sky.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
star_lock/assets/icon/xhj.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
59
star_lock/flavorizr.yaml
Normal file
@ -0,0 +1,59 @@
|
||||
# 用于编译出不同的APPID
|
||||
|
||||
# 生成:意思是将本文件定义的配置,生成对应的代码,或者原生的配置、构建过程、文件资源等
|
||||
# 风味用法:dart run flutter_flavorizr -p <processor_1>,<processor_2>
|
||||
|
||||
# 以下行为都是覆盖,所以如果不是很清楚自己在做什么,请不要随意运行,以免覆盖有用的文件
|
||||
# 安卓图标:dart run flutter_flavorizr -p android:icons
|
||||
# 安卓构建参数集配置:dart run flutter_flavorizr -p android:androidManifest
|
||||
# 安卓构建目标配置:dart run flutter_flavorizr -p android:buildGradle
|
||||
# iOS图标:dart run flutter_flavorizr -
|
||||
# iOS构建参数集配置:dart run flutter_flavorizr -
|
||||
# iOS构建目标配置:dart run flutter_flavorizr -
|
||||
|
||||
# 项目运行说明:添加不同风味后,不能再使用flutter默认的运行方式`flutter run`,而是需要指定运行的风味
|
||||
# flutter run --flavor <flavor> -t lib/main_<flavor>.dart
|
||||
# 注意,这里有 入口文件(main_<flavor>.dart) 和 口味(<flavor>) 两个参数
|
||||
# 其中入口文件在代码中指定运行时的差异,例如 页面上的名称、颜色、API请求的域名等
|
||||
# 而 口味 指定 构建差异,例如 APPID、Logo、应用名称等
|
||||
# 下面是4个运行示例:
|
||||
# flutter run --flavor dev -t lib/main_dev.dart
|
||||
# flutter run --flavor pre -t lib/main_pre.dart
|
||||
# flutter run --flavor sky -t lib/main_sky.dart
|
||||
# flutter run --flavor xhj -t lib/main_xhj.dart
|
||||
|
||||
app:
|
||||
android:
|
||||
flavorDimensions: "flavor-type"
|
||||
|
||||
flavors:
|
||||
dev:
|
||||
app:
|
||||
name: "星锁-dev"
|
||||
icon: "assets/icon/dev.png"
|
||||
android:
|
||||
applicationId: "com.starlock.lock.dev"
|
||||
|
||||
pre:
|
||||
app:
|
||||
name: "星锁"
|
||||
icon: "assets/icon/pre.png"
|
||||
android:
|
||||
applicationId: "com.starlock.lock.pre"
|
||||
sky:
|
||||
app:
|
||||
name: "锁通通"
|
||||
icon: "assets/icon/sky.png"
|
||||
android:
|
||||
applicationId: "com.skychip.lock"
|
||||
customConfig:
|
||||
signingConfig: signingConfigs.sky
|
||||
xhj:
|
||||
app:
|
||||
name: "鑫锁"
|
||||
icon: "assets/icon/xhj.png"
|
||||
android:
|
||||
applicationId: "com.xhjcn.lock"
|
||||
customConfig:
|
||||
signingConfig: signingConfigs.xhj
|
||||
ide: idea
|
||||
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 3.6 KiB |
177
star_lock/lib/app.dart
Normal file
@ -0,0 +1,177 @@
|
||||
import 'package:aliyun_push/aliyun_push.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:star_lock/tools/app_manager.dart';
|
||||
import 'package:star_lock/tools/bindings/app_binding.dart';
|
||||
|
||||
import 'package:star_lock/tools/storage.dart';
|
||||
import 'package:star_lock/tools/xs_aliyunPush.dart';
|
||||
import 'package:star_lock/translations/app_dept.dart';
|
||||
import 'package:star_lock/translations/trans_lib.dart';
|
||||
|
||||
import 'appRouters.dart';
|
||||
import 'baseWidget.dart';
|
||||
import 'tools/appRouteObserver.dart';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class MyApp extends StatefulWidget {
|
||||
const MyApp({GlobalKey? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<MyApp> createState() => _MyAppState();
|
||||
}
|
||||
|
||||
// 注册 RouteObserver 作为 navigation observer.
|
||||
// final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
|
||||
|
||||
class _MyAppState extends State<MyApp> with WidgetsBindingObserver, BaseWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ScreenUtilInit(
|
||||
designSize: const Size(585, 1265),
|
||||
builder: (w, a) => _initMaterialApp());
|
||||
}
|
||||
|
||||
GetMaterialApp _initMaterialApp() => GetMaterialApp(
|
||||
title: 'Star Lock',
|
||||
navigatorObservers: [AppRouteObserver().routeObserver],
|
||||
translations: TranslationMessage(),
|
||||
supportedLocales: appDept.deptSupportedLocales,
|
||||
localizationsDelegates: const [
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
],
|
||||
localeResolutionCallback: (locale, supportedLocales) {
|
||||
if (!supportedLocales.contains(locale)) {
|
||||
int idx = appSupportedLocales.indexWhere(
|
||||
(element) => element.languageCode == locale!.languageCode);
|
||||
if (idx != -1) {
|
||||
locale = appSupportedLocales[idx];
|
||||
} else {
|
||||
locale = const Locale('zh', 'CN');
|
||||
}
|
||||
}
|
||||
// print("localelocalelocalelocalelocale locale:${locale} locale.languageCode:${locale.languageCode} locale.countryCode:${locale.countryCode} supportedLocales:${supportedLocales}");
|
||||
AppManager()
|
||||
.setLanCode(code: '${locale!.languageCode}_${locale.countryCode}');
|
||||
return locale;
|
||||
},
|
||||
// locale: StoreService.to.getLanguageCode().isNotEmpty ? appDept.deptSupportedLocales.where((element) => element.languageCode == StoreService.to.getLanguageCode()).first : Get.deviceLocale,
|
||||
locale: Get.deviceLocale,
|
||||
fallbackLocale: const Locale('zh', 'CN'),
|
||||
theme: ThemeData(
|
||||
scaffoldBackgroundColor: const Color(0xFFF6F6F6),
|
||||
backgroundColor: const Color(0xFFF6F6F6),
|
||||
primaryColor: const Color(0xFFFFFFFF),
|
||||
textTheme: TextTheme(
|
||||
//用在非Material组件上的文字显示,
|
||||
bodyText1:
|
||||
TextStyle(fontSize: 28.sp, color: const Color(0xff2E2B2B)),
|
||||
//Material组件上的文字显示
|
||||
bodyText2:
|
||||
TextStyle(fontSize: 28.sp, color: const Color(0xff2E2B2B)),
|
||||
button: TextStyle(fontSize: 28.sp)),
|
||||
iconTheme: IconThemeData(size: 28.sp, color: const Color(0xff2E2B2B)),
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: const Color(0xFFFFFFFF),
|
||||
elevation: 0,
|
||||
centerTitle: true,
|
||||
iconTheme: IconThemeData(color: const Color(0xff333333), size: 36.sp),
|
||||
titleTextStyle: TextStyle(
|
||||
color: const Color(0xff333333),
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 36.sp),
|
||||
),
|
||||
splashColor: Colors.transparent, // 点击时的高亮效果设置为透明
|
||||
highlightColor: Colors.transparent,
|
||||
),
|
||||
debugShowCheckedModeBanner: false,
|
||||
getPages: AppRouters.routePages,
|
||||
builder: EasyLoading.init(),
|
||||
initialBinding: AppBindings(),
|
||||
initialRoute: '/');
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
|
||||
openBlueScan();
|
||||
|
||||
initAliyunPush();
|
||||
}
|
||||
|
||||
//初始化阿里云推送
|
||||
void initAliyunPush() {
|
||||
final aliyunPush = AliyunPush();
|
||||
XSAliyunPushProvider().init(aliyunPush);
|
||||
XSAliyunPushProvider().initAliyunPush();
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
XSAliyunPushProvider().initAliyunThirdPush();
|
||||
}
|
||||
|
||||
//暂使用DeviceID推送
|
||||
aliyunPush.getDeviceId().then((deviceId) async {
|
||||
// print('得到的DeviceId$deviceId');
|
||||
final data = await Storage.getString(saveUserLoginData);
|
||||
if (data!.isNotEmpty && deviceId.isNotEmpty) {
|
||||
XSAliyunPushProvider()
|
||||
.pushBindDeviceID(deviceId, Platform.isAndroid ? 10 : 20);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void openBlueScan() {
|
||||
if (Platform.isIOS) {
|
||||
print("有蓝牙权限开始扫描");
|
||||
// startScanAction();
|
||||
} else {
|
||||
getMicrophonePermission().then((value) {
|
||||
if (value) {
|
||||
// 有权限
|
||||
print("有蓝牙权限开始扫描");
|
||||
// startScanAction();
|
||||
} else {
|
||||
//没有权限
|
||||
openAppSettings(); //打开app系统设置
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// void startScanAction() {
|
||||
// BlueManage().startScan();
|
||||
// }
|
||||
|
||||
///请求蓝牙权限
|
||||
Future<bool> getMicrophonePermission() async {
|
||||
// You can request multiple permissions at once.
|
||||
Map<Permission, PermissionStatus> statuses = await [
|
||||
Permission.bluetoothScan,
|
||||
Permission.bluetoothConnect,
|
||||
Permission.location,
|
||||
].request();
|
||||
|
||||
//granted 通过,denied 被拒绝,permanentlyDenied 拒绝且不在提示
|
||||
if (statuses[Permission.bluetoothScan]!.isGranted &&
|
||||
statuses[Permission.bluetoothConnect]!.isGranted &&
|
||||
statuses[Permission.location]!.isGranted) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -130,4 +130,6 @@ class AppColors {
|
||||
|
||||
static Color openPassageModeColor = const Color(0xFFEB2A3B);// 首页开启常开模式颜色(红色)
|
||||
static Color listTimeYellowColor = const Color(0xFFF3BA37);// 首页时间过期颜色(黄色)
|
||||
|
||||
static Color get lockDetailBottomBtnUneable => const Color(0xFF808080);// 首页时间灰色颜色(灰色)
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import 'package:star_lock/network/api.dart';
|
||||
import '../../flavors.dart';
|
||||
|
||||
class XSConstantMacro {
|
||||
// 网页的宏定义网址
|
||||
static String baseWebURL = Api.baseAddress; //base地址
|
||||
static String baseWebURL = F.apiPrefix; //base地址
|
||||
static String introduceURL = '$baseWebURL/app/introduce'; //介绍页
|
||||
static String userAgreementURL = '$baseWebURL/app/userAgreement'; //用户协议
|
||||
static String privacyPolicyURL = '$baseWebURL/app/privacy'; //隐私政策
|
||||
|
||||
43
star_lock/lib/flavors.dart
Normal file
@ -0,0 +1,43 @@
|
||||
enum Flavor {
|
||||
dev,
|
||||
pre,
|
||||
sky,
|
||||
xhj,
|
||||
}
|
||||
|
||||
class F {
|
||||
static Flavor? appFlavor;
|
||||
|
||||
static String get name => appFlavor?.name ?? '';
|
||||
|
||||
static String get title {
|
||||
switch (appFlavor) {
|
||||
case Flavor.dev:
|
||||
return '星锁-dev';
|
||||
case Flavor.pre:
|
||||
return '星锁-pre';
|
||||
case Flavor.sky:
|
||||
return '锁通通';
|
||||
case Flavor.xhj:
|
||||
return '鑫锁';
|
||||
default:
|
||||
throw Exception('flavor[$name] title not found');
|
||||
}
|
||||
}
|
||||
static String get apiPrefix {
|
||||
switch (appFlavor) {
|
||||
case Flavor.dev:
|
||||
return 'https://dev.lock.star-lock.cn';
|
||||
case Flavor.pre:
|
||||
return 'https://pre.lock.star-lock.cn';
|
||||
case Flavor.sky:
|
||||
return 'https://lock.skychip.top';
|
||||
case Flavor.xhj:
|
||||
return 'https://lock.xhjcn.ltd';
|
||||
default:
|
||||
// "http://192.168.1.15:8022"; //谢总本地
|
||||
// "https://ge.lock.star-lock.cn"; //葛工开发环境地址
|
||||
throw Exception('flavor[$name] apiPrefix not found');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +1,16 @@
|
||||
import 'package:aliyun_push/aliyun_push.dart';
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:star_lock/tools/app_manager.dart';
|
||||
import 'package:star_lock/tools/bindings/app_binding.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:star_lock/translations/trans_lib.dart';
|
||||
import 'app.dart';
|
||||
import 'package:star_lock/tools/device_info_service.dart';
|
||||
import 'package:star_lock/tools/platform_info_services.dart';
|
||||
import 'package:star_lock/tools/storage.dart';
|
||||
import 'package:star_lock/tools/xs_aliyunPush.dart';
|
||||
import 'package:star_lock/translations/app_dept.dart';
|
||||
import 'package:star_lock/translations/trans_lib.dart';
|
||||
|
||||
import 'appRouters.dart';
|
||||
import 'baseWidget.dart';
|
||||
import 'blue/blue_manage.dart';
|
||||
import 'tools/appRouteObserver.dart';
|
||||
import 'app_settings/app_settings.dart';
|
||||
import 'tools/store_service.dart';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
void main() async {
|
||||
// 该文件不可作为编译入口,请查看 flavorizr.yaml 中的说明
|
||||
FutureOr<void> main() async {
|
||||
await _setCommonServices();
|
||||
|
||||
// 设置国际化信息
|
||||
@ -30,135 +18,19 @@ void main() async {
|
||||
|
||||
runApp(MyApp());
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
if (AppPlatform.isAndroid) {
|
||||
SystemUiOverlayStyle systemUiOverlayStyle =
|
||||
const SystemUiOverlayStyle(statusBarColor: Colors.transparent);
|
||||
const SystemUiOverlayStyle(statusBarColor: Colors.transparent);
|
||||
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
|
||||
}
|
||||
}
|
||||
|
||||
class MyApp extends StatefulWidget {
|
||||
const MyApp({GlobalKey? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<MyApp> createState() => _MyAppState();
|
||||
}
|
||||
|
||||
// 注册 RouteObserver 作为 navigation observer.
|
||||
// final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
|
||||
|
||||
class _MyAppState extends State<MyApp> with WidgetsBindingObserver, BaseWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ScreenUtilInit(
|
||||
designSize: const Size(585, 1265),
|
||||
builder: (w, a) => _initMaterialApp());
|
||||
}
|
||||
|
||||
GetMaterialApp _initMaterialApp() => GetMaterialApp(
|
||||
title: 'Star Lock',
|
||||
navigatorObservers: [AppRouteObserver().routeObserver],
|
||||
translations: TranslationMessage(),
|
||||
supportedLocales: appDept.deptSupportedLocales,
|
||||
localizationsDelegates: const [
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
],
|
||||
localeResolutionCallback: (locale, supportedLocales) {
|
||||
if (!supportedLocales.contains(locale)) {
|
||||
int idx = appSupportedLocales.indexWhere(
|
||||
(element) => element.languageCode == locale!.languageCode);
|
||||
if (idx != -1) {
|
||||
locale = appSupportedLocales[idx];
|
||||
} else {
|
||||
locale = const Locale('zh', 'CN');
|
||||
}
|
||||
}
|
||||
// print("localelocalelocalelocalelocale locale:${locale} locale.languageCode:${locale.languageCode} locale.countryCode:${locale.countryCode} supportedLocales:${supportedLocales}");
|
||||
AppManager()
|
||||
.setLanCode(code: '${locale!.languageCode}_${locale.countryCode}');
|
||||
return locale;
|
||||
},
|
||||
// locale: StoreService.to.getLanguageCode().isNotEmpty ? appDept.deptSupportedLocales.where((element) => element.languageCode == StoreService.to.getLanguageCode()).first : Get.deviceLocale,
|
||||
locale: Get.deviceLocale,
|
||||
fallbackLocale: const Locale('zh', 'CN'),
|
||||
theme: ThemeData(
|
||||
scaffoldBackgroundColor: const Color(0xFFF6F6F6),
|
||||
backgroundColor: const Color(0xFFF6F6F6),
|
||||
primaryColor: const Color(0xFFFFFFFF),
|
||||
textTheme: TextTheme(
|
||||
//用在非Material组件上的文字显示,
|
||||
bodyText1:
|
||||
TextStyle(fontSize: 28.sp, color: const Color(0xff2E2B2B)),
|
||||
//Material组件上的文字显示
|
||||
bodyText2:
|
||||
TextStyle(fontSize: 28.sp, color: const Color(0xff2E2B2B)),
|
||||
button: TextStyle(fontSize: 28.sp)),
|
||||
iconTheme: IconThemeData(size: 28.sp, color: const Color(0xff2E2B2B)),
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: const Color(0xFFFFFFFF),
|
||||
elevation: 0,
|
||||
centerTitle: true,
|
||||
iconTheme: IconThemeData(color: const Color(0xff333333), size: 36.sp),
|
||||
titleTextStyle: TextStyle(
|
||||
color: const Color(0xff333333),
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 36.sp),
|
||||
),
|
||||
splashColor: Colors.transparent, // 点击时的高亮效果设置为透明
|
||||
highlightColor: Colors.transparent,
|
||||
),
|
||||
debugShowCheckedModeBanner: false,
|
||||
getPages: AppRouters.routePages,
|
||||
builder: EasyLoading.init(),
|
||||
initialBinding: AppBindings(),
|
||||
initialRoute: '/');
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
|
||||
openBlueScan();
|
||||
|
||||
initAliyunPush();
|
||||
}
|
||||
|
||||
//初始化阿里云推送
|
||||
void initAliyunPush() {
|
||||
final aliyunPush = AliyunPush();
|
||||
XSAliyunPushProvider().init(aliyunPush);
|
||||
XSAliyunPushProvider().initAliyunPush();
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
XSAliyunPushProvider().initAliyunThirdPush();
|
||||
}
|
||||
|
||||
//暂使用DeviceID推送
|
||||
aliyunPush.getDeviceId().then((deviceId) async {
|
||||
// print('得到的DeviceId$deviceId');
|
||||
final data = await Storage.getString(saveUserLoginData);
|
||||
if (data!.isNotEmpty && deviceId.isNotEmpty) {
|
||||
XSAliyunPushProvider()
|
||||
.pushBindDeviceID(deviceId, Platform.isAndroid ? 10 : 20);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// 设置国际化信息
|
||||
Future _initTranslation() async => TranslationLoader.loadTranslation(
|
||||
zhSource: "images/lan/lan_zh.json",
|
||||
enSource: "images/lan/lan_en.json",
|
||||
keySource: "images/lan/lan_keys.json",
|
||||
);
|
||||
zhSource: "images/lan/lan_zh.json",
|
||||
enSource: "images/lan/lan_en.json",
|
||||
keySource: "images/lan/lan_keys.json",
|
||||
);
|
||||
|
||||
// 设置包名服务设备信息
|
||||
Future _setCommonServices() async {
|
||||
@ -167,43 +39,3 @@ Future _setCommonServices() async {
|
||||
await Get.putAsync(() => DeviceInfoService().init());
|
||||
// Get.log(PlatformInfoService.to.info.version);
|
||||
}
|
||||
|
||||
void openBlueScan() {
|
||||
if (Platform.isIOS) {
|
||||
print("有蓝牙权限开始扫描");
|
||||
// startScanAction();
|
||||
} else {
|
||||
getMicrophonePermission().then((value) {
|
||||
if (value) {
|
||||
// 有权限
|
||||
print("有蓝牙权限开始扫描");
|
||||
// startScanAction();
|
||||
} else {
|
||||
//没有权限
|
||||
openAppSettings(); //打开app系统设置
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// void startScanAction() {
|
||||
// BlueManage().startScan();
|
||||
// }
|
||||
|
||||
///请求蓝牙权限
|
||||
Future<bool> getMicrophonePermission() async {
|
||||
// You can request multiple permissions at once.
|
||||
Map<Permission, PermissionStatus> statuses = await [
|
||||
Permission.bluetoothScan,
|
||||
Permission.bluetoothConnect,
|
||||
Permission.location,
|
||||
].request();
|
||||
|
||||
//granted 通过,denied 被拒绝,permanentlyDenied 拒绝且不在提示
|
||||
if (statuses[Permission.bluetoothScan]!.isGranted &&
|
||||
statuses[Permission.bluetoothConnect]!.isGranted &&
|
||||
statuses[Permission.location]!.isGranted) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_native_contact_picker/flutter_native_contact_picker.dart';
|
||||
// import 'package:flutter_pickers/pickers.dart';
|
||||
// import 'package:flutter_pickers/time_picker/model/date_mode.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/network/api_repository.dart';
|
||||
@ -340,7 +339,7 @@ class _AuthorizedAdminPageState extends State<AuthorizedAdminPage> {
|
||||
// 接受者信息输入框
|
||||
Widget getTFWidget(bool isHaveBtn, String tfStr, int lineIndex) {
|
||||
return SizedBox(
|
||||
height: 50.h,
|
||||
height: 65.h,
|
||||
width: 300.w,
|
||||
child: Row(
|
||||
children: [
|
||||
@ -348,6 +347,10 @@ class _AuthorizedAdminPageState extends State<AuthorizedAdminPage> {
|
||||
child: TextField(
|
||||
//输入框一行
|
||||
maxLines: 1,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.deny('\n'),
|
||||
LengthLimitingTextInputFormatter(30),
|
||||
],
|
||||
controller: lineIndex == 1
|
||||
? state.emailOrPhoneController
|
||||
: state.keyNameController,
|
||||
@ -355,13 +358,24 @@ class _AuthorizedAdminPageState extends State<AuthorizedAdminPage> {
|
||||
textAlign: TextAlign.end,
|
||||
decoration: InputDecoration(
|
||||
//输入里面输入文字内边距设置
|
||||
contentPadding: const EdgeInsets.only(top: 12.0, bottom: 8.0),
|
||||
// contentPadding: const EdgeInsets.only(top: 12.0, bottom: 8.0),
|
||||
hintText: tfStr,
|
||||
hintStyle: TextStyle(
|
||||
color: AppColors.placeholderTextColor, fontSize: 22.sp),
|
||||
//不需要输入框下划线
|
||||
border: InputBorder.none,
|
||||
hintStyle: TextStyle(fontSize: 22.sp),
|
||||
focusedBorder: const OutlineInputBorder(borderSide: BorderSide(width: 0, color: Colors.transparent)),
|
||||
disabledBorder: const OutlineInputBorder(borderSide: BorderSide(width: 0, color: Colors.transparent)),
|
||||
enabledBorder: const OutlineInputBorder(borderSide: BorderSide(width: 0, color: Colors.transparent)),
|
||||
border: const OutlineInputBorder(borderSide: BorderSide(width: 0, color: Colors.transparent)),
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 0),
|
||||
),
|
||||
// decoration: InputDecoration(
|
||||
// //输入里面输入文字内边距设置
|
||||
// contentPadding: const EdgeInsets.only(top: 12.0, bottom: 8.0),
|
||||
// hintText: tfStr,
|
||||
// hintStyle: TextStyle(
|
||||
// color: AppColors.placeholderTextColor, fontSize: 22.sp),
|
||||
// //不需要输入框下划线
|
||||
// border: InputBorder.none,
|
||||
// ),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
|
||||
@ -9,16 +9,16 @@ class AuthorizedAdminListLogic extends BaseGetXController {
|
||||
//请求电子钥匙列表
|
||||
Future<List<ElectronicKeyListItem>> mockNetworkDataRequest() async {
|
||||
ElectronicKeyListEntity entity = await ApiRepository.to.electronicKeyList(
|
||||
'0',
|
||||
state.keyInfo.value.keyId.toString(),
|
||||
'',
|
||||
state.keyInfo.value.lockId.toString(),
|
||||
'',
|
||||
state.pageNum.toString(),
|
||||
state.pageSize.toString(),
|
||||
'0',
|
||||
'0',
|
||||
state.searchStr.value);
|
||||
endDate: '0',
|
||||
keyId: state.keyInfo.value.keyId.toString(),
|
||||
keyStatus: '',
|
||||
lockId: state.keyInfo.value.lockId.toString(),
|
||||
operatorUid: '',
|
||||
pageNo: pageNo.toString(),
|
||||
pageSize: pageSize.toString(),
|
||||
startDate: '0',
|
||||
keyRight: '0',
|
||||
searchStr:state.searchStr.value);
|
||||
List<ElectronicKeyListItem> dataList = [];
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
print("电子钥匙列表成功:${entity.data?.itemList}");
|
||||
|
||||
@ -36,6 +36,7 @@ class _CheckingInListPageState extends State<CheckingInListPage> {
|
||||
haveBack: true,
|
||||
backgroundColor: AppColors.mainColor,
|
||||
actionsList: [
|
||||
(state.getKeyInfosData.value.isLockOwner == 1 && state.getKeyInfosData.value.keyRight == 1) ?
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot);
|
||||
@ -48,7 +49,7 @@ class _CheckingInListPageState extends State<CheckingInListPage> {
|
||||
logic.showToast("演示模式");
|
||||
}
|
||||
},
|
||||
child: Image.asset('images/main/icon_lockDetail_checkIn_set.png', width: 36.w, height: 36.w,)),
|
||||
child: Image.asset('images/main/icon_lockDetail_checkIn_set.png', width: 36.w, height: 36.w,)) : Container(),
|
||||
SizedBox(width: 30.w),
|
||||
],
|
||||
),
|
||||
|
||||
@ -115,17 +115,20 @@ class _CheckingInSetPageState extends State<CheckingInSetPage> {
|
||||
SizedBox(
|
||||
height: 30.h,
|
||||
),
|
||||
SubmitBtn(
|
||||
btnName:
|
||||
"${TranslationLoader.lanKeys!.delete!.tr}${TranslationLoader.lanKeys!.company!.tr}",
|
||||
borderRadius: 20.w,
|
||||
fontSize: 32.sp,
|
||||
isDelete: true,
|
||||
margin: EdgeInsets.only(left: 30.w, right: 30.w, top: 20.w),
|
||||
padding: EdgeInsets.only(top: 20.w, bottom: 20.w),
|
||||
onClick: () {
|
||||
showDeletCompanyAlertDialog(context);
|
||||
}),
|
||||
Visibility(
|
||||
visible: state.getKeyInfosData.value.isLockOwner == 1,
|
||||
child: SubmitBtn(
|
||||
btnName:
|
||||
"${TranslationLoader.lanKeys!.delete!.tr}${TranslationLoader.lanKeys!.company!.tr}",
|
||||
borderRadius: 20.w,
|
||||
fontSize: 32.sp,
|
||||
isDelete: true,
|
||||
margin: EdgeInsets.only(left: 30.w, right: 30.w, top: 20.w),
|
||||
padding: EdgeInsets.only(top: 20.w, bottom: 20.w),
|
||||
onClick: () {
|
||||
showDeletCompanyAlertDialog(context);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@ -5,6 +5,8 @@ import 'package:star_lock/main/lockDetail/electronicKey/electronicKeyList/entity
|
||||
import 'package:star_lock/network/api_repository.dart';
|
||||
import 'package:star_lock/tools/baseGetXController.dart';
|
||||
|
||||
import '../../../../../tools/eventBusEventManage.dart';
|
||||
|
||||
class ElectronicKeyDetailLogic extends BaseGetXController {
|
||||
final ElectronicKeyDetailState state = ElectronicKeyDetailState();
|
||||
|
||||
@ -15,8 +17,10 @@ class ElectronicKeyDetailLogic extends BaseGetXController {
|
||||
state.changeNameController.text, '');
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
print("修改要是名称成功啦啦啦啦啦");
|
||||
showToast("修改成功");
|
||||
Get.back();
|
||||
showToast("修改成功", something: (){
|
||||
eventBus.fire(ElectronicKeyListRefreshUI());
|
||||
Get.back();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,8 +30,10 @@ class ElectronicKeyDetailLogic extends BaseGetXController {
|
||||
.deleteElectronicKey(state.itemData.value.keyId.toString());
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
print("删除电子钥匙成功");
|
||||
showToast("删除成功");
|
||||
Get.back();
|
||||
showToast("删除成功", something: (){
|
||||
eventBus.fire(ElectronicKeyListRefreshUI());
|
||||
Get.back();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@ import 'package:star_lock/main/lockDetail/passwordKey/passwordKey_perpetual/pass
|
||||
import 'package:star_lock/network/api_repository.dart';
|
||||
import 'package:star_lock/tools/baseGetXController.dart';
|
||||
|
||||
import '../../../../../tools/eventBusEventManage.dart';
|
||||
|
||||
class ElectronicKeyDetailChangeDateLogic extends BaseGetXController {
|
||||
final ElectronicKeyDetailChangeDateState state =
|
||||
ElectronicKeyDetailChangeDateState();
|
||||
@ -23,8 +25,10 @@ class ElectronicKeyDetailChangeDateLogic extends BaseGetXController {
|
||||
hoursEnd: state.hoursEnd.value,
|
||||
isCoerced: state.isCoerced.value);
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
showToast("修改成功");
|
||||
Get.back();
|
||||
showToast("修改成功", something: (){
|
||||
eventBus.fire(ElectronicKeyListRefreshUI());
|
||||
Get.back();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,8 +44,10 @@ class ElectronicKeyDetailChangeDateLogic extends BaseGetXController {
|
||||
state.startDay.value,
|
||||
state.weekDays.value);
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
showToast("修改成功");
|
||||
Get.back();
|
||||
showToast("修改成功", something: (){
|
||||
eventBus.fire(ElectronicKeyListRefreshUI());
|
||||
Get.back();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,24 +1,28 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:star_lock/main/lockDetail/electronicKey/electronicKeyList/electronicKeyList_state.dart';
|
||||
import 'package:star_lock/main/lockDetail/electronicKey/electronicKeyList/entity/ElectronicKeyListEntity.dart';
|
||||
import 'package:star_lock/network/api_repository.dart';
|
||||
import 'package:star_lock/tools/baseGetXController.dart';
|
||||
|
||||
import '../../../../tools/eventBusEventManage.dart';
|
||||
|
||||
class ElectronicKeyListLogic extends BaseGetXController {
|
||||
final ElectronicKeyListState state = ElectronicKeyListState();
|
||||
|
||||
//请求电子钥匙列表
|
||||
Future<ElectronicKeyListEntity> mockNetworkDataRequest() async {
|
||||
ElectronicKeyListEntity entity = await ApiRepository.to.electronicKeyList(
|
||||
'0',
|
||||
state.keyInfo.value.keyId.toString(),
|
||||
'',
|
||||
state.keyInfo.value.lockId.toString(),
|
||||
'',
|
||||
pageNo.toString(),
|
||||
pageSize.toString(),
|
||||
'0',
|
||||
'0',
|
||||
state.searchController.text);
|
||||
endDate: '0',
|
||||
keyId: state.keyInfo.value.keyId.toString(),
|
||||
keyStatus: '',
|
||||
lockId: state.keyInfo.value.lockId.toString(),
|
||||
operatorUid: '',
|
||||
pageNo: pageNo.toString(),
|
||||
pageSize: pageSize.toString(),
|
||||
startDate: '0',
|
||||
keyRight: '0',
|
||||
searchStr: state.searchController.text);
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
if (pageNo == 1) {
|
||||
state.itemDataList.value = entity.data!.itemList!;
|
||||
@ -40,6 +44,7 @@ class ElectronicKeyListLogic extends BaseGetXController {
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
print("重置电子钥匙成功啦啦啦啦啦");
|
||||
showToast("重置成功");
|
||||
pageNo = 1;
|
||||
mockNetworkDataRequest();
|
||||
}
|
||||
}
|
||||
@ -51,14 +56,27 @@ class ElectronicKeyListLogic extends BaseGetXController {
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
print("删除电子钥匙成功");
|
||||
showToast("删除成功");
|
||||
pageNo = 1;
|
||||
mockNetworkDataRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/// 刷新电子钥匙列表
|
||||
StreamSubscription? _getElectronicKeyListRefreshUIEvent;
|
||||
void _getElectronicKeyListRefreshUIAction() {
|
||||
// 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus
|
||||
_getElectronicKeyListRefreshUIEvent = eventBus.on<ElectronicKeyListRefreshUI>().listen((event) {
|
||||
pageNo = 1;
|
||||
mockNetworkDataRequest();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
// TODO: implement onReady
|
||||
super.onReady();
|
||||
|
||||
_getElectronicKeyListRefreshUIAction();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -70,5 +88,8 @@ class ElectronicKeyListLogic extends BaseGetXController {
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
|
||||
_getElectronicKeyListRefreshUIEvent?.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,63 +121,64 @@ class _ElectronicKeyListPageState extends State<ElectronicKeyListPage> {
|
||||
Widget _buildMainUI() {
|
||||
return Obx(() => state.itemDataList.value.isEmpty
|
||||
? NoData(noDataHeight: 1.sh - ScreenUtil().statusBarHeight - ScreenUtil().bottomBarHeight - 190.h - 64.h)
|
||||
: ListView.separated(
|
||||
: SlidableAutoCloseBehavior(
|
||||
child: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
itemCount: state.itemDataList.value.length,
|
||||
itemBuilder: (c, index) {
|
||||
ElectronicKeyListItem indexEntity = state.itemDataList.value[index];
|
||||
String useDateStr = ''; //使用期限
|
||||
String keyStatus = ''; //钥匙状态
|
||||
ElectronicKeyListItem indexEntity = state.itemDataList.value[index];
|
||||
String useDateStr = ''; //使用期限
|
||||
String keyStatus = ''; //钥匙状态
|
||||
|
||||
//使用期限
|
||||
useDateStr = getUseDateStr(indexEntity);
|
||||
//使用期限
|
||||
useDateStr = getUseDateStr(indexEntity);
|
||||
|
||||
//钥匙状态
|
||||
keyStatus = getKeyStatus(indexEntity.keyStatus);
|
||||
//钥匙状态
|
||||
keyStatus = getKeyStatus(indexEntity.keyStatus);
|
||||
|
||||
//是否为管理钥匙
|
||||
bool isAdminKey = false;
|
||||
if (indexEntity.keyRight == 1) {
|
||||
isAdminKey = true;
|
||||
} else {
|
||||
isAdminKey = false;
|
||||
}
|
||||
//是否为管理钥匙
|
||||
bool isAdminKey = false;
|
||||
if (indexEntity.keyRight == 1) {
|
||||
isAdminKey = true;
|
||||
} else {
|
||||
isAdminKey = false;
|
||||
}
|
||||
|
||||
return Slidable(
|
||||
key:ValueKey(indexEntity.keyId),
|
||||
endActionPane: ActionPane(
|
||||
extentRatio: 0.2,
|
||||
motion: const ScrollMotion(),
|
||||
children: [
|
||||
SlidableAction(
|
||||
onPressed: (BuildContext context){
|
||||
showIosTipViewDialog(context, indexEntity.keyId!.toString());
|
||||
},
|
||||
backgroundColor: Colors.red,
|
||||
foregroundColor: Colors.white,
|
||||
label: '删除',
|
||||
),
|
||||
],
|
||||
),
|
||||
child: _electronicKeyItem('images/controls_user.png',
|
||||
indexEntity.keyName!, useDateStr, keyStatus, isAdminKey, () {
|
||||
Navigator.pushNamed(context, Routers.electronicKeyDetailPage,
|
||||
arguments: {"itemData": indexEntity}).then((val) {
|
||||
if (val != null) {
|
||||
logic.mockNetworkDataRequest();
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
}),
|
||||
);
|
||||
return Slidable(
|
||||
key:ValueKey(indexEntity.keyId),
|
||||
endActionPane: ActionPane(
|
||||
extentRatio: 0.2,
|
||||
motion: const ScrollMotion(),
|
||||
children: [
|
||||
SlidableAction(
|
||||
onPressed: (BuildContext context){
|
||||
showIosTipViewDialog(context, indexEntity.keyId!.toString());
|
||||
},
|
||||
backgroundColor: Colors.red,
|
||||
foregroundColor: Colors.white,
|
||||
label: '删除',
|
||||
),
|
||||
],
|
||||
),
|
||||
child: _electronicKeyItem('images/controls_user.png', indexEntity.keyName!, useDateStr, keyStatus, isAdminKey, () {
|
||||
Navigator.pushNamed(context, Routers.electronicKeyDetailPage,
|
||||
arguments: {"itemData": indexEntity}).then((val) {
|
||||
if (val != null) {
|
||||
logic.mockNetworkDataRequest();
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
}),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return const Divider(
|
||||
height: 1,
|
||||
color: AppColors.greyLineColor,
|
||||
);
|
||||
return const Divider(
|
||||
height: 1,
|
||||
color: AppColors.greyLineColor,
|
||||
);
|
||||
},
|
||||
));
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
Widget _buildDeleteBtn(String keyId) {
|
||||
@ -269,6 +270,9 @@ class _ElectronicKeyListPageState extends State<ElectronicKeyListPage> {
|
||||
} else if (keyStatusFlag == 110410) {
|
||||
//已重置
|
||||
keyStatus = '已重置';
|
||||
} else if (keyStatusFlag == 110412) {
|
||||
//已过期
|
||||
keyStatus = '已过期';
|
||||
}
|
||||
|
||||
return keyStatus;
|
||||
|
||||
@ -6,6 +6,7 @@ import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart';
|
||||
import 'package:star_lock/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/sendElectronicKey_state.dart';
|
||||
import 'package:star_lock/network/api_repository.dart';
|
||||
import 'package:star_lock/tools/baseGetXController.dart';
|
||||
import 'package:star_lock/tools/eventBusEventManage.dart';
|
||||
import 'package:star_lock/translations/trans_lib.dart';
|
||||
|
||||
class SendElectronicKeyLogic extends BaseGetXController {
|
||||
@ -62,6 +63,9 @@ class SendElectronicKeyLogic extends BaseGetXController {
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
print('发送电子钥匙成功');
|
||||
state.isSendSuccess.value = true;
|
||||
state.sendSucceedType.value = int.parse(state.type.value);
|
||||
resetData();
|
||||
eventBus.fire(ElectronicKeyListRefreshUI());
|
||||
} else {
|
||||
if (entity.errorCode == 425) {
|
||||
//用户未注册
|
||||
@ -162,4 +166,11 @@ class SendElectronicKeyLogic extends BaseGetXController {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void resetData(){
|
||||
state.emailOrPhoneController.text = "";
|
||||
state.keyNameController.text = "";
|
||||
state.selectEffectiveDate = '${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day} ${DateTime.now().hour}:${DateTime.now().minute}'.obs; //默认为当前时间
|
||||
state.selectFailureDate = '${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day} ${DateTime.now().hour}:${DateTime.now().minute}'.obs; //默认为当前时间
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ class _SendElectronicKeyPageState extends State<SendElectronicKeyPage> {
|
||||
}
|
||||
|
||||
Widget indexChangeWidget() {
|
||||
if (state.isSendSuccess.value == true) {
|
||||
if (state.isSendSuccess.value == true && state.sendSucceedType.value.toString() == widget.type) {
|
||||
return sendElectronicKeySucceed();
|
||||
} else {
|
||||
switch (int.parse(widget.type)) {
|
||||
@ -281,8 +281,7 @@ class _SendElectronicKeyPageState extends State<SendElectronicKeyPage> {
|
||||
state.failureDateTime.value.hour,
|
||||
state.failureDateTime.value.minute);
|
||||
//发送钥匙请求
|
||||
if (state.emailOrPhoneController.text.isNotEmpty &&
|
||||
state.keyNameController.text.isNotEmpty) {
|
||||
if (state.emailOrPhoneController.text.isNotEmpty && state.keyNameController.text.isNotEmpty) {
|
||||
if (int.parse(widget.type) == 0) {
|
||||
if (!startDateTime.isBefore(endDateTime) ||
|
||||
startDateTime.isAtSameMomentAs(endDateTime)) {
|
||||
@ -372,7 +371,7 @@ class _SendElectronicKeyPageState extends State<SendElectronicKeyPage> {
|
||||
btnName: '完成',
|
||||
onClick: () {
|
||||
state.isSendSuccess.value = false;
|
||||
Navigator.pop(context, true);
|
||||
logic.resetData();
|
||||
}),
|
||||
SizedBox(
|
||||
height: 10.h,
|
||||
@ -443,7 +442,7 @@ class _SendElectronicKeyPageState extends State<SendElectronicKeyPage> {
|
||||
maxLines: 1,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.deny('\n'),
|
||||
LengthLimitingTextInputFormatter(18),
|
||||
LengthLimitingTextInputFormatter(30),
|
||||
],
|
||||
// controller: _controller,
|
||||
autofocus: false,
|
||||
@ -508,17 +507,20 @@ class _SendElectronicKeyPageState extends State<SendElectronicKeyPage> {
|
||||
|
||||
// 远程开锁
|
||||
Widget remoteUnlockingWidget() {
|
||||
return Column(
|
||||
children: [
|
||||
CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.remoteUnlockingAllowed!.tr,
|
||||
rightTitle: "",
|
||||
isHaveRightWidget: true,
|
||||
rightWidget:
|
||||
SizedBox(width: 60.w, height: 50.h, child: _remoteSwitch(true)),
|
||||
action: () {}),
|
||||
Container(height: 10.h),
|
||||
],
|
||||
return Visibility(
|
||||
visible: state.keyInfo.value.lockSetting!.remoteUnlock == 1 ? true : false,
|
||||
child: Column(
|
||||
children: [
|
||||
CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.remoteUnlockingAllowed!.tr,
|
||||
rightTitle: "",
|
||||
isHaveRightWidget: true,
|
||||
rightWidget:
|
||||
SizedBox(width: 60.w, height: 50.h, child: _remoteSwitch(true)),
|
||||
action: () {}),
|
||||
Container(height: 10.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -35,6 +35,8 @@ class SendElectronicKeyState {
|
||||
var weekdaysList = [].obs;
|
||||
var isCreateUser = false.obs; //用户未注册时传1 已注册传0
|
||||
|
||||
final sendSucceedType = 0.obs;
|
||||
|
||||
SendElectronicKeyState() {
|
||||
Map map = Get.arguments;
|
||||
keyInfo.value = map["keyInfo"];
|
||||
|
||||
@ -38,6 +38,13 @@ class _SendElectronicKeyManageTabbarState
|
||||
vsync: this,
|
||||
length: _itemTabs.length,
|
||||
initialIndex: widget.initialIndex);
|
||||
|
||||
_tabController.addListener(() {
|
||||
// print("_tabController.animation!.value:${_tabController.animation!.value} _tabController.index:${_tabController.index}");
|
||||
if (_tabController.animation!.value==_tabController.index){
|
||||
FocusScope.of(context).requestFocus(FocusNode());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@ -54,6 +61,9 @@ class _SendElectronicKeyManageTabbarState
|
||||
TabBar _tabBar() {
|
||||
return TabBar(
|
||||
controller: _tabController,
|
||||
onTap: (index){
|
||||
FocusScope.of(context).requestFocus(FocusNode());
|
||||
},
|
||||
tabs: _itemTabs.map((ItemView item) => _tab(item)).toList(),
|
||||
isScrollable: true,
|
||||
indicatorColor: Colors.red,
|
||||
|
||||
@ -137,7 +137,10 @@ class LockDetailLogic extends BaseGetXController {
|
||||
case 0x16:
|
||||
// 正在开锁中...
|
||||
print("${reply.commandType}正在开锁中...");
|
||||
showToast("正在开锁中...");
|
||||
state.openLockBtnState.value = 0;
|
||||
showToast("正在开锁中...", something: (){
|
||||
cancelBlueConnetctToastTimer();
|
||||
});
|
||||
break;
|
||||
default:
|
||||
//失败
|
||||
@ -317,7 +320,7 @@ class LockDetailLogic extends BaseGetXController {
|
||||
} else {
|
||||
getLockNetToken();
|
||||
}
|
||||
|
||||
// clickPushBtnAction();
|
||||
break;
|
||||
case 0x06:
|
||||
//无权限
|
||||
@ -598,38 +601,45 @@ class LockDetailLogic extends BaseGetXController {
|
||||
}
|
||||
}
|
||||
|
||||
// 0开锁 1长按闭锁 2密码 3卡 4指纹 5遥控 6人脸 7监控 8操作记录 9消息提醒 10设置
|
||||
clickItemBtnAction(int type){
|
||||
state.clickNextType = type;
|
||||
if (state.lockUserNo == 0) {
|
||||
// 电子钥匙lockUserNo为0 要先添加用户
|
||||
addUserConnectBlue();
|
||||
} else {
|
||||
clickPushBtnAction();
|
||||
}
|
||||
}
|
||||
|
||||
clickPushBtnAction(){
|
||||
// 0开锁 1长按闭锁 2密码 3卡 4指纹 5遥控 6人脸 7监控 8操作记录 9消息提醒 10设置
|
||||
switch(state.clickNextType){
|
||||
case 0:
|
||||
// 开锁
|
||||
startOpenLock();
|
||||
break;
|
||||
case 1:
|
||||
// 长按闭锁
|
||||
startUnLock();
|
||||
break;
|
||||
case 2:
|
||||
// 密码
|
||||
Get.toNamed(Routers.passwordKeyListPage, arguments: {"keyInfo": state.keyInfos.value});
|
||||
break;
|
||||
case 3:
|
||||
// 卡
|
||||
Get.toNamed(Routers.passwordKeyListPage, arguments: {"keyInfo": state.keyInfos.value});
|
||||
break;
|
||||
}
|
||||
}
|
||||
// // 0开锁 1长按闭锁 2密码 3卡 4指纹 5遥控 6人脸 7监控 8操作记录 9消息提醒 10设置
|
||||
// clickItemBtnAction(int type){
|
||||
// state.clickNextType = type;
|
||||
// if (state.lockUserNo == 0) {
|
||||
// // 电子钥匙lockUserNo为0 要先添加用户
|
||||
// addUserConnectBlue();
|
||||
// } else {
|
||||
// clickPushBtnAction();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// clickPushBtnAction(){
|
||||
// // 0开锁 1长按闭锁 2密码 3卡 4指纹 5遥控 6人脸 7监控 8操作记录 9消息提醒 10设置
|
||||
// switch(state.clickNextType){
|
||||
// case 0:
|
||||
// // 开锁
|
||||
// startOpenLock();
|
||||
// break;
|
||||
// case 1:
|
||||
// // 长按闭锁
|
||||
// startUnLock();
|
||||
// break;
|
||||
// case 2:
|
||||
// // 密码
|
||||
// Get.toNamed(Routers.passwordKeyListPage, arguments: {"keyInfo": state.keyInfos.value});
|
||||
// break;
|
||||
// case 3:
|
||||
// // 卡
|
||||
// Get.toNamed(Routers.passwordKeyListPage, arguments: {"keyInfo": state.keyInfos.value});
|
||||
// break;
|
||||
// case 10:
|
||||
// // 设置
|
||||
// Get.toNamed(Routers.lockSetPage, arguments: {
|
||||
// "lockId": state.keyInfos.value.lockId,
|
||||
// "isOnlyOneData": state.isOnlyOneData,
|
||||
// });
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// 获取手机联网token,根据锁设置里面获取的开锁时是否联网来判断是否调用这个接口
|
||||
void getLockNetToken() async {
|
||||
@ -648,6 +658,8 @@ class LockDetailLogic extends BaseGetXController {
|
||||
lockUserNo: state.lockUserNo.toString());
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
if (state.isOpenLockNeedOnline.value == 0) {
|
||||
state.bottomBtnisUneable.value = false;
|
||||
eventBus.fire(RefreshLockListInfoDataEvent());
|
||||
openDoorAction(1);
|
||||
} else {
|
||||
getLockNetToken();
|
||||
|
||||
@ -38,12 +38,15 @@ class _LockDetailPageState extends State<LockDetailPage>
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
Get.log("LockDetailPage initState1111");
|
||||
// Get.log("LockDetailPage initState1111");
|
||||
|
||||
print("LockDetailPage isOnlyOneData==${widget.isOnlyOneData}");
|
||||
state.keyInfos.value = widget.lockListInfoItemEntity;
|
||||
state.lockUserNo = state.keyInfos.value.lockUserNo!;
|
||||
print("state.lockUserNo==${state.lockUserNo}");
|
||||
if (state.lockUserNo == 0) {
|
||||
state.bottomBtnisUneable.value = true;
|
||||
}
|
||||
state.isOnlyOneData = widget.isOnlyOneData;
|
||||
// print("state.lockUserNo==${state.lockUserNo}");
|
||||
state.senderUserId = state.keyInfos.value.senderUserId!;
|
||||
state.isAttendance.value = state.keyInfos.value.lockSetting!.attendance!;
|
||||
state.isOpenLockNeedOnline.value =
|
||||
@ -153,7 +156,6 @@ class _LockDetailPageState extends State<LockDetailPage>
|
||||
}
|
||||
|
||||
Widget topWidget() {
|
||||
// KeyInfos keyInfo = widget.lockMainEntity.data!.keyInfos![0];
|
||||
return Column(
|
||||
children: [
|
||||
SizedBox(height: 50.h),
|
||||
@ -439,24 +441,35 @@ class _LockDetailPageState extends State<LockDetailPage>
|
||||
|
||||
// 普通用户
|
||||
List<Widget> getNormalWidget() {
|
||||
var showWidgetArr = [
|
||||
// 操作记录
|
||||
bottomItem('images/main/icon_main_operatingRecord.png',
|
||||
TranslationLoader.lanKeys!.operatingRecord!.tr, () {
|
||||
Get.toNamed(Routers.lockOperatingRecordPage,
|
||||
arguments: {"keyInfo": state.keyInfos.value});
|
||||
}),
|
||||
var showWidgetArr = <Widget>[];
|
||||
// 考勤
|
||||
if (state.isAttendance.value == 1) {
|
||||
showWidgetArr.add(bottomItem(
|
||||
'images/main/icon_main_clockingIn.png',
|
||||
TranslationLoader.lanKeys!.checkingIn!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
Get.toNamed(Routers.checkingInListPage,
|
||||
arguments: state.keyInfos.value);
|
||||
}));
|
||||
}
|
||||
// 操作记录
|
||||
showWidgetArr.add(bottomItem(
|
||||
'images/main/icon_main_operatingRecord.png',
|
||||
TranslationLoader.lanKeys!.operatingRecord!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
Get.toNamed(Routers.lockOperatingRecordPage,
|
||||
arguments: {"keyInfo": state.keyInfos.value});
|
||||
}));
|
||||
|
||||
// 设置
|
||||
showWidgetArr.add(bottomItem('images/main/icon_main_set.png',
|
||||
TranslationLoader.lanKeys!.set!.tr, state.bottomBtnisUneable.value, () {
|
||||
Get.toNamed(Routers.lockSetPage, arguments: {
|
||||
"lockId": state.keyInfos.value.lockId,
|
||||
"isOnlyOneData": state.isOnlyOneData
|
||||
});
|
||||
}));
|
||||
|
||||
// 设置
|
||||
bottomItem(
|
||||
'images/main/icon_main_set.png', TranslationLoader.lanKeys!.set!.tr,
|
||||
() {
|
||||
Get.toNamed(Routers.lockSetPage, arguments: {
|
||||
"lockId": state.keyInfos.value.lockId,
|
||||
"isOnlyOneData": widget.isOnlyOneData,
|
||||
});
|
||||
}),
|
||||
];
|
||||
return showWidgetArr;
|
||||
}
|
||||
|
||||
@ -465,31 +478,39 @@ class _LockDetailPageState extends State<LockDetailPage>
|
||||
var showWidgetArr = <Widget>[];
|
||||
// 考勤
|
||||
if (state.isAttendance.value == 1) {
|
||||
showWidgetArr.add(bottomItem('images/main/icon_main_clockingIn.png',
|
||||
TranslationLoader.lanKeys!.checkingIn!.tr, () {
|
||||
showWidgetArr.add(bottomItem(
|
||||
'images/main/icon_main_clockingIn.png',
|
||||
TranslationLoader.lanKeys!.checkingIn!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
Get.toNamed(Routers.checkingInListPage,
|
||||
arguments: state.keyInfos.value);
|
||||
}));
|
||||
}
|
||||
|
||||
// 电子钥匙
|
||||
showWidgetArr.add(bottomItem('images/main/icon_main_electronicKey.png',
|
||||
TranslationLoader.lanKeys!.electronicKey!.tr, () {
|
||||
showWidgetArr.add(bottomItem(
|
||||
'images/main/icon_main_electronicKey.png',
|
||||
TranslationLoader.lanKeys!.electronicKey!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
Get.toNamed(Routers.electronicKeyListPage,
|
||||
arguments: {"keyInfo": state.keyInfos.value});
|
||||
}));
|
||||
|
||||
// 密码
|
||||
showWidgetArr.add(bottomItem('images/main/icon_main_password.png',
|
||||
TranslationLoader.lanKeys!.password!.tr, () {
|
||||
showWidgetArr.add(bottomItem(
|
||||
'images/main/icon_main_password.png',
|
||||
TranslationLoader.lanKeys!.password!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
Get.toNamed(Routers.passwordKeyListPage,
|
||||
arguments: {"keyInfo": state.keyInfos.value});
|
||||
}));
|
||||
|
||||
// ic卡
|
||||
if (state.keyInfos.value.lockFeature!.icCard == 1) {
|
||||
showWidgetArr.add(bottomItem('images/main/icon_main_icCard.png',
|
||||
TranslationLoader.lanKeys!.card!.tr, () {
|
||||
showWidgetArr.add(bottomItem(
|
||||
'images/main/icon_main_icCard.png',
|
||||
TranslationLoader.lanKeys!.card!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
// logic.showToast("普通用户第一次需要在锁旁边操作哦。", something: () {
|
||||
// logic.showEasyLoading();
|
||||
// });
|
||||
@ -501,8 +522,10 @@ class _LockDetailPageState extends State<LockDetailPage>
|
||||
|
||||
// 指纹
|
||||
if (state.keyInfos.value.lockFeature!.fingerprint == 1) {
|
||||
showWidgetArr.add(bottomItem('images/main/icon_main_fingerprint.png',
|
||||
TranslationLoader.lanKeys!.fingerprint!.tr, () {
|
||||
showWidgetArr.add(bottomItem(
|
||||
'images/main/icon_main_fingerprint.png',
|
||||
TranslationLoader.lanKeys!.fingerprint!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
Get.toNamed(Routers.fingerprintListPage, arguments: {
|
||||
"lockId": state.keyInfos.value.lockId,
|
||||
});
|
||||
@ -511,8 +534,10 @@ class _LockDetailPageState extends State<LockDetailPage>
|
||||
|
||||
// 遥控
|
||||
if (state.keyInfos.value.lockFeature!.bluetoothRemoteControl == 1) {
|
||||
showWidgetArr.add(bottomItem('images/main/icon_main_remoteControl.png',
|
||||
TranslationLoader.lanKeys!.remoteControl!.tr, () {
|
||||
showWidgetArr.add(bottomItem(
|
||||
'images/main/icon_main_remoteControl.png',
|
||||
TranslationLoader.lanKeys!.remoteControl!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
Get.toNamed(Routers.remoteControlListPage);
|
||||
}));
|
||||
}
|
||||
@ -520,8 +545,10 @@ class _LockDetailPageState extends State<LockDetailPage>
|
||||
//可视对讲门锁新增->人脸
|
||||
if (state.keyInfos.value.lockFeature!.d3Face == 1) {
|
||||
showWidgetArr.add(
|
||||
bottomItem('images/main/icon_face.png',
|
||||
TranslationLoader.lanKeys!.humanFace!.tr, () {
|
||||
bottomItem(
|
||||
'images/main/icon_face.png',
|
||||
TranslationLoader.lanKeys!.humanFace!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
Get.toNamed(Routers.faceList, arguments: {
|
||||
"lockId": state.keyInfos.value.lockId,
|
||||
}); // Toast.show(msg: "功能暂未开放");
|
||||
@ -532,8 +559,10 @@ class _LockDetailPageState extends State<LockDetailPage>
|
||||
//可视对讲门锁新增->监控
|
||||
if (state.keyInfos.value.lockFeature!.videoIntercom == 1) {
|
||||
showWidgetArr.add(
|
||||
bottomItem('images/main/icon_catEyes.png',
|
||||
TranslationLoader.lanKeys!.monitoring!.tr, () {
|
||||
bottomItem(
|
||||
'images/main/icon_catEyes.png',
|
||||
TranslationLoader.lanKeys!.monitoring!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
Get.toNamed(Routers.realTimePicturePage, arguments: {
|
||||
"lockName": state.keyInfos.value.lockName,
|
||||
"isMonitoring": true
|
||||
@ -542,40 +571,56 @@ class _LockDetailPageState extends State<LockDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
var endWiddget = [
|
||||
// 授权管理员
|
||||
bottomItem('images/main/icon_main_authorizedAdmin.png',
|
||||
TranslationLoader.lanKeys!.authorizedAdmin!.tr, () {
|
||||
// 授权管理员
|
||||
if (state.keyInfos.value.isLockOwner == 1) {
|
||||
showWidgetArr.add(bottomItem(
|
||||
'images/main/icon_main_authorizedAdmin.png',
|
||||
TranslationLoader.lanKeys!.authorizedAdmin!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
Get.toNamed(Routers.authorizedAdminListPage,
|
||||
arguments: {"keyInfo": state.keyInfos.value});
|
||||
}),
|
||||
}));
|
||||
}
|
||||
// bottomItem('images/main/icon_main_authorizedAdmin.png', TranslationLoader.lanKeys!.authorizedAdmin!.tr, state.bottomBtnisUneable.value, () {
|
||||
// Get.toNamed(Routers.authorizedAdminListPage,
|
||||
// arguments: {"keyInfo": state.keyInfos.value});
|
||||
// })
|
||||
|
||||
var endWiddget = [
|
||||
// 操作记录
|
||||
bottomItem('images/main/icon_main_operatingRecord.png',
|
||||
TranslationLoader.lanKeys!.operatingRecord!.tr, () {
|
||||
bottomItem(
|
||||
'images/main/icon_main_operatingRecord.png',
|
||||
TranslationLoader.lanKeys!.operatingRecord!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
// Get.toNamed(Routers.lockOperatingRecordPage,
|
||||
// arguments: {"keyInfo": state.keyInfos.value});
|
||||
Get.toNamed(Routers.doorLockLogPage,
|
||||
arguments: {"keyInfo": state.keyInfos.value});
|
||||
}),
|
||||
// 视频日志
|
||||
bottomItem('images/main/icon_lockDetail_videoLog.png',
|
||||
TranslationLoader.lanKeys!.videoLog!.tr, () {
|
||||
bottomItem(
|
||||
'images/main/icon_lockDetail_videoLog.png',
|
||||
TranslationLoader.lanKeys!.videoLog!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
//视频日志
|
||||
Get.toNamed(Routers.videoLogPage);
|
||||
}),
|
||||
// 消息提醒
|
||||
bottomItem('images/main/icon_lockDetail_messageReminding.png',
|
||||
TranslationLoader.lanKeys!.messageReminding!.tr, () {
|
||||
bottomItem(
|
||||
'images/main/icon_lockDetail_messageReminding.png',
|
||||
TranslationLoader.lanKeys!.messageReminding!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
Get.toNamed(Routers.msgNotificationPage);
|
||||
}),
|
||||
// 设置
|
||||
bottomItem(
|
||||
'images/main/icon_main_set.png', TranslationLoader.lanKeys!.set!.tr,
|
||||
() {
|
||||
// BlueManage().stopScan();
|
||||
'images/main/icon_main_set.png',
|
||||
TranslationLoader.lanKeys!.set!.tr,
|
||||
state.bottomBtnisUneable.value, () {
|
||||
// logic.clickItemBtnAction(10);
|
||||
Get.toNamed(Routers.lockSetPage, arguments: {
|
||||
"lockId": state.keyInfos.value.lockId,
|
||||
"isOnlyOneData": widget.isOnlyOneData,
|
||||
"isOnlyOneData": state.isOnlyOneData,
|
||||
});
|
||||
}),
|
||||
];
|
||||
@ -583,11 +628,17 @@ class _LockDetailPageState extends State<LockDetailPage>
|
||||
return showWidgetArr;
|
||||
}
|
||||
|
||||
Widget bottomItem(String iconUrl, String name, Function() onClick) {
|
||||
//
|
||||
Widget bottomItem(
|
||||
String iconUrl, String name, bool isForbidden, Function() onClick) {
|
||||
var width = 42.w;
|
||||
var height = 42.h;
|
||||
return GestureDetector(
|
||||
onTap: onClick,
|
||||
onTap: isForbidden
|
||||
? () {
|
||||
logic.showToast("请在锁旁边完成第一次开锁");
|
||||
}
|
||||
: onClick,
|
||||
child: Container(
|
||||
// height: 300.h,
|
||||
color: Colors.white,
|
||||
@ -596,15 +647,24 @@ class _LockDetailPageState extends State<LockDetailPage>
|
||||
children: [
|
||||
SizedBox(
|
||||
width: width,
|
||||
height: height,
|
||||
height:
|
||||
height, // isForbidden ? "${iconUrl}_uneable.png" :"${iconUrl}.png"
|
||||
child: Image.asset(iconUrl,
|
||||
width: width, height: height, fit: BoxFit.fitWidth),
|
||||
width: width,
|
||||
height: height,
|
||||
color: isForbidden
|
||||
? AppColors.lockDetailBottomBtnUneable
|
||||
: AppColors.mainColor,
|
||||
fit: BoxFit.fitWidth),
|
||||
),
|
||||
SizedBox(height: 10.w),
|
||||
Expanded(
|
||||
child: Text(name,
|
||||
style: TextStyle(
|
||||
fontSize: 20.sp, color: AppColors.blackColor),
|
||||
fontSize: 20.sp,
|
||||
color: isForbidden
|
||||
? AppColors.lockDetailBottomBtnUneable
|
||||
: AppColors.blackColor),
|
||||
textAlign: TextAlign.center))
|
||||
],
|
||||
)),
|
||||
@ -685,7 +745,7 @@ class _LockDetailPageState extends State<LockDetailPage>
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
widget.lockListInfoItemEntity.lockAlias!,
|
||||
state.keyInfos.value.lockAlias!,
|
||||
style: TextStyle(
|
||||
color: AppColors.placeholderTextColor, fontSize: 24.sp),
|
||||
),
|
||||
|
||||
@ -21,6 +21,7 @@ class LockDetailState {
|
||||
String lockNetToken = "";
|
||||
var lockUserNo = 0;
|
||||
var senderUserId = 0;
|
||||
var isOnlyOneData = false;
|
||||
|
||||
var isAttendance = 0.obs;// 是否开启考勤
|
||||
var isOpenLockNeedOnline = 0.obs; // APP开锁时是否需联网
|
||||
@ -35,8 +36,7 @@ class LockDetailState {
|
||||
var iSOpenLock = true.obs; // 是开锁还是关锁
|
||||
Timer? closedUnlockSuccessfulTimer;
|
||||
|
||||
// 0开锁 1长按闭锁 2密码 3卡 4指纹 5遥控 6人脸 7监控 8操作记录 9消息提醒 10设置
|
||||
var clickNextType = 0;
|
||||
var bottomBtnisUneable = false.obs; // 是否不可用
|
||||
|
||||
//过渡动画控制器
|
||||
late AnimationController animationController;
|
||||
|
||||
@ -34,7 +34,8 @@ class _LockOperatingRecordPageState extends State<LockOperatingRecordPage> {
|
||||
haveBack: true,
|
||||
backgroundColor: AppColors.mainColor,
|
||||
actionsList: [
|
||||
IconButton(
|
||||
(state.keyInfos.value.isLockOwner == 1 || state.keyInfos.value.keyRight == 1)
|
||||
? IconButton(
|
||||
icon: Image.asset(
|
||||
'images/icon_bar_more.png',
|
||||
height: 30.h,
|
||||
@ -63,7 +64,8 @@ class _LockOperatingRecordPageState extends State<LockOperatingRecordPage> {
|
||||
logic.showToast("演示模式");
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
],
|
||||
),
|
||||
body: Column(
|
||||
|
||||
@ -91,6 +91,7 @@ class _BasicInformationPageState extends State<BasicInformationPage> {
|
||||
if (data != null) {
|
||||
setState(() {
|
||||
state.lockBasicInfo.value = data["lockBasicInfo"];
|
||||
print("state.lockBasicInfo.value.lockAlias:${state.lockBasicInfo.value.lockAlias}");
|
||||
});
|
||||
}
|
||||
})),
|
||||
@ -111,8 +112,7 @@ class _BasicInformationPageState extends State<BasicInformationPage> {
|
||||
});
|
||||
})),
|
||||
Visibility(
|
||||
visible: (state.lockBasicInfo.value.isLockOwner == 1 ||
|
||||
state.lockBasicInfo.value.keyRight == 1)
|
||||
visible: state.lockBasicInfo.value.isLockOwner == 1
|
||||
? true
|
||||
: false,
|
||||
child: CommonItem(
|
||||
|
||||
@ -16,8 +16,8 @@ class EditLockNameLogic extends BaseGetXController{
|
||||
lockId: state.lockSetInfoData.value.lockId.toString(),
|
||||
lockName:state.changeLockNameController.text);
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
state.lockBasicInfo.value.lockAlias = state.changeLockNameController.text;
|
||||
showToast("修改成功", something: (){
|
||||
state.lockBasicInfo.value.lockAlias = state.changeLockNameController.text;
|
||||
eventBus.fire(LockSetChangeSetRefreshLockDetailWithType(3, state.lockBasicInfo.value.lockAlias!));
|
||||
eventBus.fire(RefreshLockListInfoDataEvent());
|
||||
});
|
||||
|
||||
@ -330,7 +330,7 @@ class _LockSetPageState extends State<LockSetPage> with RouteAware {
|
||||
}))),
|
||||
// 重置键
|
||||
Obx(() => Visibility(
|
||||
visible: state.lockFeature.value.resetSwitch == 1 ? true : false,
|
||||
visible: (state.lockBasicInfo.value.isLockOwner == 1 && state.lockFeature.value.resetSwitch == 1) ? true : false,
|
||||
child: CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.resetButton!.tr,
|
||||
rightTitle: (state.lockSettingInfo.value.resetSwitch ?? 0) == 1
|
||||
@ -470,7 +470,7 @@ class _LockSetPageState extends State<LockSetPage> with RouteAware {
|
||||
// 考勤
|
||||
Obx(
|
||||
() => Visibility(
|
||||
visible: state.lockFeature.value.attendance == 1 ? true : false,
|
||||
visible: (state.lockBasicInfo.value.isLockOwner == 1 && state.lockFeature.value.attendance == 1) ? true : false,
|
||||
child: CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.checkingIn!.tr,
|
||||
rightTitle: "",
|
||||
@ -481,7 +481,7 @@ class _LockSetPageState extends State<LockSetPage> with RouteAware {
|
||||
// 开锁提醒
|
||||
Obx(
|
||||
() => Visibility(
|
||||
visible: state.lockFeature.value.unlockReminder == 1 ? true : false,
|
||||
visible: state.lockBasicInfo.value.isLockOwner == 1 && state.lockFeature.value.unlockReminder == 1 ? true : false,
|
||||
child: CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.unlockReminder!.tr,
|
||||
rightTitle: "",
|
||||
@ -492,7 +492,7 @@ class _LockSetPageState extends State<LockSetPage> with RouteAware {
|
||||
// APP开锁时是否需联网
|
||||
Obx(
|
||||
() => Visibility(
|
||||
visible: state.lockFeature.value.appUnlockOnline == 1 ? true : false,
|
||||
visible: state.lockBasicInfo.value.isLockOwner == 1 && state.lockFeature.value.appUnlockOnline == 1 ? true : false,
|
||||
child: CommonItem(
|
||||
leftTitel: TranslationLoader
|
||||
.lanKeys!.whetherInternetRequiredWhenUnlocking!.tr,
|
||||
|
||||
@ -23,13 +23,13 @@ class RemoteUnlockingLogic extends BaseGetXController{
|
||||
remoteUnlock:state.remoteEnable.value == 1 ? 0 : 1
|
||||
);
|
||||
if(entity.errorCode!.codeIsSuccessful){
|
||||
eventBus.fire(RefreshLockListInfoDataEvent());
|
||||
|
||||
state.remoteEnable.value = state.remoteEnable.value == 1 ? 0 : 1;
|
||||
state.lockSetInfoData.value.lockSettingInfo!.remoteUnlock = state.remoteEnable.value;
|
||||
print("state.remoteEnable.value:${state.remoteEnable.value} state.getKeyInfosData.value.remoteEnable:${state.lockSetInfoData.value.lockSettingInfo!.remoteUnlock}");
|
||||
eventBus.fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value));
|
||||
showToast("操作成功");
|
||||
showToast("操作成功", something: (){
|
||||
eventBus.fire(RefreshLockListInfoDataEvent());
|
||||
state.remoteEnable.value = state.remoteEnable.value == 1 ? 0 : 1;
|
||||
state.lockSetInfoData.value.lockSettingInfo!.remoteUnlock = state.remoteEnable.value;
|
||||
print("state.remoteEnable.value:${state.remoteEnable.value} state.getKeyInfosData.value.remoteEnable:${state.lockSetInfoData.value.lockSettingInfo!.remoteUnlock}");
|
||||
eventBus.fire(PassCurrentLockInformationEvent(state.lockSetInfoData.value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -41,6 +41,7 @@ class PasswordKeyListLogic extends BaseGetXController {
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
print("重置电子钥匙成功啦啦啦啦啦");
|
||||
showToast("重置成功");
|
||||
pageNo = 1;
|
||||
mockNetworkDataRequest();
|
||||
}
|
||||
}
|
||||
@ -52,6 +53,7 @@ class PasswordKeyListLogic extends BaseGetXController {
|
||||
.deleteKeyboardPwd(lockId, keyboardPwdId, deleteType);
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
showToast("删除成功");
|
||||
pageNo = 1;
|
||||
mockNetworkDataRequest();
|
||||
}
|
||||
}
|
||||
@ -146,6 +148,7 @@ class PasswordKeyListLogic extends BaseGetXController {
|
||||
void _getPasswordListRefreshUIAction() {
|
||||
// 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus
|
||||
_getPasswordListRefreshUIEvent = eventBus.on<GetPasswordListRefreshUI>().listen((event) {
|
||||
pageNo = 1;
|
||||
mockNetworkDataRequest();
|
||||
});
|
||||
}
|
||||
|
||||
8
star_lock/lib/main_dev.dart
Normal file
@ -0,0 +1,8 @@
|
||||
import 'flavors.dart';
|
||||
|
||||
import 'main.dart' as runner;
|
||||
|
||||
Future<void> main() async {
|
||||
F.appFlavor = Flavor.dev;
|
||||
await runner.main();
|
||||
}
|
||||
8
star_lock/lib/main_pre.dart
Normal file
@ -0,0 +1,8 @@
|
||||
import 'flavors.dart';
|
||||
|
||||
import 'main.dart' as runner;
|
||||
|
||||
Future<void> main() async {
|
||||
F.appFlavor = Flavor.pre;
|
||||
await runner.main();
|
||||
}
|
||||
8
star_lock/lib/main_sky.dart
Normal file
@ -0,0 +1,8 @@
|
||||
import 'flavors.dart';
|
||||
|
||||
import 'main.dart' as runner;
|
||||
|
||||
Future<void> main() async {
|
||||
F.appFlavor = Flavor.sky;
|
||||
await runner.main();
|
||||
}
|
||||
8
star_lock/lib/main_xhj.dart
Normal file
@ -0,0 +1,8 @@
|
||||
import 'flavors.dart';
|
||||
|
||||
import 'main.dart' as runner;
|
||||
|
||||
Future<void> main() async {
|
||||
F.appFlavor = Flavor.xhj;
|
||||
await runner.main();
|
||||
}
|
||||
@ -5,6 +5,7 @@ import 'package:star_lock/appRouters.dart';
|
||||
import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart';
|
||||
|
||||
import '../../app_settings/app_colors.dart';
|
||||
import '../../flavors.dart';
|
||||
import '../../tools/commonItem.dart';
|
||||
import '../../tools/titleAppBar.dart';
|
||||
import '../../translations/trans_lib.dart';
|
||||
@ -38,12 +39,12 @@ class _AboutPageState extends State<AboutPage> {
|
||||
),
|
||||
SizedBox(height: 20.h),
|
||||
Text(
|
||||
"星锁 1.0.0.09(preRelease-20240126-1)",
|
||||
"${F.title} 1.0.0.09(preRelease-20240126-1)",
|
||||
style: TextStyle(fontSize: 24.sp, color: AppColors.blackColor),
|
||||
),
|
||||
SizedBox(height: 20.h),
|
||||
Text(
|
||||
Api.baseAddress,
|
||||
F.apiPrefix,
|
||||
style: TextStyle(fontSize: 24.sp, color: AppColors.blackColor),
|
||||
),
|
||||
SizedBox(
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import 'package:easy_refresh/easy_refresh.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
@ -6,7 +5,6 @@ import 'package:star_lock/tools/noData.dart';
|
||||
|
||||
import '../../../appRouters.dart';
|
||||
import '../../../app_settings/app_colors.dart';
|
||||
import '../../../network/api_repository.dart';
|
||||
import '../../../tools/EasyRefreshTool.dart';
|
||||
import '../../../tools/dateTool.dart';
|
||||
import '../../../tools/titleAppBar.dart';
|
||||
@ -79,7 +77,7 @@ class _MessageListPageState extends State<MessageListPage> with TickerProviderSt
|
||||
),
|
||||
],
|
||||
),
|
||||
child: _selectGatewayListListItem(messageItemEntity, () {
|
||||
child: _messageListItem(messageItemEntity, () {
|
||||
Get.toNamed(Routers.messageDetailPage, arguments: {"messageItemEntity": messageItemEntity});
|
||||
}),
|
||||
);
|
||||
@ -90,51 +88,51 @@ class _MessageListPageState extends State<MessageListPage> with TickerProviderSt
|
||||
);
|
||||
}
|
||||
|
||||
Widget _selectGatewayListListItem(MessageItemEntity messageItemEntity, Function() action) {
|
||||
Widget _messageListItem(MessageItemEntity messageItemEntity, Function() action) {
|
||||
return GestureDetector(
|
||||
onTap: action,
|
||||
child: Container(
|
||||
height: 90.h,
|
||||
width: 1.sw,
|
||||
margin: EdgeInsets.only(bottom: 2.h),
|
||||
// padding:
|
||||
// EdgeInsets.only(left: 10.w, right: 20.w, top: 20.h, bottom: 20.h),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10.w),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 20.w,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
child: Container(
|
||||
width: 1.sw,
|
||||
margin: EdgeInsets.only(left: 20.w, right: 20.w),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
SizedBox(
|
||||
width: 1.sw - 20.w*2,
|
||||
child: Flexible(
|
||||
child: Text(
|
||||
messageItemEntity.data!,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 22.sp, color: messageItemEntity.readAt! == 0 ? AppColors.blackColor : AppColors.placeholderTextColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
// Image.asset('images/mine/icon_mine_gatewaySignal_strong.png', width: 40.w, height: 40.w,),
|
||||
// SizedBox(width: 10.w,),
|
||||
Text(DateTool().dateToYMDHNString(messageItemEntity.createdAt!.toString()), style: TextStyle(fontSize: 18.sp, color: messageItemEntity.readAt! == 0 ? AppColors.blackColor : AppColors.placeholderTextColor)),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 20.h),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
SizedBox(height: 10.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
// Image.asset('images/mine/icon_mine_gatewaySignal_strong.png', width: 40.w, height: 40.w,),
|
||||
// SizedBox(width: 10.w,),
|
||||
Text(DateTool().dateToYMDHNString(messageItemEntity.createdAt!.toString()), style: TextStyle(fontSize: 18.sp, color: messageItemEntity.readAt! == 0 ? AppColors.blackColor : AppColors.placeholderTextColor)),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 20.h),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -1,11 +1,4 @@
|
||||
abstract class Api {
|
||||
// static String baseAddress = "https://pre.lock.star-lock.cn"; //预发布环境
|
||||
static String baseAddress = "https://dev.lock.star-lock.cn"; //联调环境
|
||||
// static String baseAddress = "http://192.168.1.15:8022"; //谢总本地
|
||||
// static String baseAddress = "https://ge.lock.star-lock.cn"; //葛工开发环境地址
|
||||
|
||||
final String baseUrl = "$baseAddress/api";
|
||||
|
||||
// 登录注册
|
||||
final String getVerificationCodeUrl = '/user/sendValidationCode';
|
||||
final String registerUrl = '/user/register';
|
||||
|
||||
@ -2,6 +2,7 @@ import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
|
||||
import 'package:get/get.dart';
|
||||
import '../appRouters.dart';
|
||||
import '../flavors.dart';
|
||||
import 'api.dart';
|
||||
import 'request_interceptor.dart';
|
||||
import 'request_interceptor_log.dart';
|
||||
@ -11,7 +12,7 @@ import 'response_interceptor_log.dart';
|
||||
class BaseProvider extends GetConnect with Api {
|
||||
@override
|
||||
void onInit() {
|
||||
httpClient.baseUrl = baseUrl;
|
||||
httpClient.baseUrl = '${F.apiPrefix}/api';
|
||||
httpClient.addRequestModifier(requestInterceptor);
|
||||
httpClient.addResponseModifier(responseInterceptor);
|
||||
httpClient.addRequestModifier(requestLogInterceptor);
|
||||
@ -32,7 +33,7 @@ class BaseProvider extends GetConnect with Api {
|
||||
// print("post: url:${url} body:${body} contentType:${contentType} headers:${headers} query:${query}");
|
||||
if (isUnShowLoading == false) EasyLoading.show();
|
||||
// print('请求url======>$url');
|
||||
// print('请求body体======>$body');
|
||||
print('请求body体======>$body');
|
||||
var res = await super.post(url, body,
|
||||
contentType: contentType,
|
||||
headers: headers,
|
||||
|
||||
@ -125,16 +125,18 @@ class ApiRepository {
|
||||
|
||||
//电子钥匙列表
|
||||
Future<ElectronicKeyListEntity> electronicKeyList(
|
||||
String endDate,
|
||||
String keyId,
|
||||
String keyStatus,
|
||||
String lockId,
|
||||
String operatorUid,
|
||||
String pageNo,
|
||||
String pageSize,
|
||||
String startDate,
|
||||
String keyRight,
|
||||
String searchStr) async {
|
||||
{
|
||||
required String endDate,
|
||||
required String keyId,
|
||||
required String keyStatus,
|
||||
required String lockId,
|
||||
required String operatorUid,
|
||||
required String pageNo,
|
||||
required String pageSize,
|
||||
required String startDate,
|
||||
required String keyRight,
|
||||
required String searchStr
|
||||
}) async {
|
||||
final res = await apiProvider.electronicKeyList(endDate, keyId, keyStatus,
|
||||
lockId, operatorUid, pageNo, pageSize, startDate, keyRight, searchStr);
|
||||
return ElectronicKeyListEntity.fromJson(res.body);
|
||||
|
||||
@ -89,3 +89,8 @@ class GetPasswordListRefreshUI {
|
||||
class ReadMessageRefreshUI {
|
||||
ReadMessageRefreshUI();
|
||||
}
|
||||
|
||||
/// 刷新电子钥匙列表
|
||||
class ElectronicKeyListRefreshUI {
|
||||
ElectronicKeyListRefreshUI();
|
||||
}
|
||||
|
||||
1
star_lock/linux/.gitignore
vendored
@ -1 +0,0 @@
|
||||
flutter/ephemeral
|
||||
@ -1,138 +0,0 @@
|
||||
# Project-level configuration.
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(runner LANGUAGES CXX)
|
||||
|
||||
# The name of the executable created for the application. Change this to change
|
||||
# the on-disk name of your application.
|
||||
set(BINARY_NAME "star_lock")
|
||||
# The unique GTK application identifier for this application. See:
|
||||
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
||||
set(APPLICATION_ID "com.example.star_lock")
|
||||
|
||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||
# versions of CMake.
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
|
||||
# Load bundled libraries from the lib/ directory relative to the binary.
|
||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
|
||||
|
||||
# Root filesystem for cross-building.
|
||||
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
|
||||
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
|
||||
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
endif()
|
||||
|
||||
# Define build configuration options.
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
||||
STRING "Flutter build mode" FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"Debug" "Profile" "Release")
|
||||
endif()
|
||||
|
||||
# Compilation settings that should be applied to most targets.
|
||||
#
|
||||
# Be cautious about adding new options here, as plugins use this function by
|
||||
# default. In most cases, you should add new options to specific targets instead
|
||||
# of modifying this function.
|
||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||
target_compile_features(${TARGET} PUBLIC cxx_std_14)
|
||||
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
|
||||
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
||||
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
||||
endfunction()
|
||||
|
||||
# Flutter library and tool build rules.
|
||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||
|
||||
# System-level dependencies.
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||
|
||||
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
|
||||
|
||||
# Define the application target. To change its name, change BINARY_NAME above,
|
||||
# not the value here, or `flutter run` will no longer work.
|
||||
#
|
||||
# Any new source files that you add to the application should be added here.
|
||||
add_executable(${BINARY_NAME}
|
||||
"main.cc"
|
||||
"my_application.cc"
|
||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||
)
|
||||
|
||||
# Apply the standard set of build settings. This can be removed for applications
|
||||
# that need different build settings.
|
||||
apply_standard_settings(${BINARY_NAME})
|
||||
|
||||
# Add dependency libraries. Add any application-specific dependencies here.
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
||||
|
||||
# Run the Flutter tool portions of the build. This must not be removed.
|
||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||
|
||||
# Only the install-generated bundle's copy of the executable will launch
|
||||
# correctly, since the resources must in the right relative locations. To avoid
|
||||
# people trying to run the unbundled copy, put it in a subdirectory instead of
|
||||
# the default top-level location.
|
||||
set_target_properties(${BINARY_NAME}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
|
||||
)
|
||||
|
||||
# Generated plugin build rules, which manage building the plugins and adding
|
||||
# them to the application.
|
||||
include(flutter/generated_plugins.cmake)
|
||||
|
||||
|
||||
# === Installation ===
|
||||
# By default, "installing" just makes a relocatable bundle in the build
|
||||
# directory.
|
||||
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
||||
endif()
|
||||
|
||||
# Start with a clean build bundle directory every time.
|
||||
install(CODE "
|
||||
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
|
||||
" COMPONENT Runtime)
|
||||
|
||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
|
||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
|
||||
install(FILES "${bundled_library}"
|
||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
endforeach(bundled_library)
|
||||
|
||||
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||
# from a previous install.
|
||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
||||
install(CODE "
|
||||
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
||||
" COMPONENT Runtime)
|
||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
||||
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
||||
|
||||
# Install the AOT library on non-Debug builds only.
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
endif()
|
||||
@ -1,88 +0,0 @@
|
||||
# This file controls Flutter-level build steps. It should not be edited.
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
||||
|
||||
# Configuration provided via flutter tool.
|
||||
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
||||
|
||||
# TODO: Move the rest of this into files in ephemeral. See
|
||||
# https://github.com/flutter/flutter/issues/57146.
|
||||
|
||||
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
|
||||
# which isn't available in 3.10.
|
||||
function(list_prepend LIST_NAME PREFIX)
|
||||
set(NEW_LIST "")
|
||||
foreach(element ${${LIST_NAME}})
|
||||
list(APPEND NEW_LIST "${PREFIX}${element}")
|
||||
endforeach(element)
|
||||
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# === Flutter Library ===
|
||||
# System-level dependencies.
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
|
||||
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
|
||||
|
||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
|
||||
|
||||
# Published to parent scope for install step.
|
||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
|
||||
|
||||
list(APPEND FLUTTER_LIBRARY_HEADERS
|
||||
"fl_basic_message_channel.h"
|
||||
"fl_binary_codec.h"
|
||||
"fl_binary_messenger.h"
|
||||
"fl_dart_project.h"
|
||||
"fl_engine.h"
|
||||
"fl_json_message_codec.h"
|
||||
"fl_json_method_codec.h"
|
||||
"fl_message_codec.h"
|
||||
"fl_method_call.h"
|
||||
"fl_method_channel.h"
|
||||
"fl_method_codec.h"
|
||||
"fl_method_response.h"
|
||||
"fl_plugin_registrar.h"
|
||||
"fl_plugin_registry.h"
|
||||
"fl_standard_message_codec.h"
|
||||
"fl_standard_method_codec.h"
|
||||
"fl_string_codec.h"
|
||||
"fl_value.h"
|
||||
"fl_view.h"
|
||||
"flutter_linux.h"
|
||||
)
|
||||
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
|
||||
add_library(flutter INTERFACE)
|
||||
target_include_directories(flutter INTERFACE
|
||||
"${EPHEMERAL_DIR}"
|
||||
)
|
||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
|
||||
target_link_libraries(flutter INTERFACE
|
||||
PkgConfig::GTK
|
||||
PkgConfig::GLIB
|
||||
PkgConfig::GIO
|
||||
)
|
||||
add_dependencies(flutter flutter_assemble)
|
||||
|
||||
# === Flutter tool backend ===
|
||||
# _phony_ is a non-existent file to force this command to run every time,
|
||||
# since currently there's no way to get a full input/output list from the
|
||||
# flutter tool.
|
||||
add_custom_command(
|
||||
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/_phony_
|
||||
COMMAND ${CMAKE_COMMAND} -E env
|
||||
${FLUTTER_TOOL_ENVIRONMENT}
|
||||
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
|
||||
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(flutter_assemble DEPENDS
|
||||
"${FLUTTER_LIBRARY}"
|
||||
${FLUTTER_LIBRARY_HEADERS}
|
||||
)
|
||||
@ -1,27 +0,0 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <aj_captcha_flutter/aj_captcha_flutter_plugin.h>
|
||||
#include <audioplayers_linux/audioplayers_linux_plugin.h>
|
||||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) aj_captcha_flutter_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "AjCaptchaFlutterPlugin");
|
||||
aj_captcha_flutter_plugin_register_with_registrar(aj_captcha_flutter_registrar);
|
||||
g_autoptr(FlPluginRegistrar) audioplayers_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "AudioplayersLinuxPlugin");
|
||||
audioplayers_linux_plugin_register_with_registrar(audioplayers_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
|
||||
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||
#define GENERATED_PLUGIN_REGISTRANT_
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
|
||||
// Registers Flutter plugins.
|
||||
void fl_register_plugins(FlPluginRegistry* registry);
|
||||
|
||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
||||
@ -1,27 +0,0 @@
|
||||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
aj_captcha_flutter
|
||||
audioplayers_linux
|
||||
file_selector_linux
|
||||
url_launcher_linux
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||
endforeach(plugin)
|
||||
|
||||
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
||||
endforeach(ffi_plugin)
|
||||
@ -1,6 +0,0 @@
|
||||
#include "my_application.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
g_autoptr(MyApplication) app = my_application_new();
|
||||
return g_application_run(G_APPLICATION(app), argc, argv);
|
||||
}
|
||||
@ -1,104 +0,0 @@
|
||||
#include "my_application.h"
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
#include <gdk/gdkx.h>
|
||||
#endif
|
||||
|
||||
#include "flutter/generated_plugin_registrant.h"
|
||||
|
||||
struct _MyApplication {
|
||||
GtkApplication parent_instance;
|
||||
char** dart_entrypoint_arguments;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
|
||||
|
||||
// Implements GApplication::activate.
|
||||
static void my_application_activate(GApplication* application) {
|
||||
MyApplication* self = MY_APPLICATION(application);
|
||||
GtkWindow* window =
|
||||
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
|
||||
|
||||
// Use a header bar when running in GNOME as this is the common style used
|
||||
// by applications and is the setup most users will be using (e.g. Ubuntu
|
||||
// desktop).
|
||||
// If running on X and not using GNOME then just use a traditional title bar
|
||||
// in case the window manager does more exotic layout, e.g. tiling.
|
||||
// If running on Wayland assume the header bar will work (may need changing
|
||||
// if future cases occur).
|
||||
gboolean use_header_bar = TRUE;
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
GdkScreen* screen = gtk_window_get_screen(window);
|
||||
if (GDK_IS_X11_SCREEN(screen)) {
|
||||
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
|
||||
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
|
||||
use_header_bar = FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (use_header_bar) {
|
||||
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
||||
gtk_widget_show(GTK_WIDGET(header_bar));
|
||||
gtk_header_bar_set_title(header_bar, "star_lock");
|
||||
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
||||
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
||||
} else {
|
||||
gtk_window_set_title(window, "star_lock");
|
||||
}
|
||||
|
||||
gtk_window_set_default_size(window, 1280, 720);
|
||||
gtk_widget_show(GTK_WIDGET(window));
|
||||
|
||||
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
|
||||
|
||||
FlView* view = fl_view_new(project);
|
||||
gtk_widget_show(GTK_WIDGET(view));
|
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
||||
|
||||
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
|
||||
|
||||
gtk_widget_grab_focus(GTK_WIDGET(view));
|
||||
}
|
||||
|
||||
// Implements GApplication::local_command_line.
|
||||
static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
|
||||
MyApplication* self = MY_APPLICATION(application);
|
||||
// Strip out the first argument as it is the binary name.
|
||||
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
|
||||
|
||||
g_autoptr(GError) error = nullptr;
|
||||
if (!g_application_register(application, nullptr, &error)) {
|
||||
g_warning("Failed to register: %s", error->message);
|
||||
*exit_status = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_application_activate(application);
|
||||
*exit_status = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Implements GObject::dispose.
|
||||
static void my_application_dispose(GObject* object) {
|
||||
MyApplication* self = MY_APPLICATION(object);
|
||||
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
|
||||
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void my_application_class_init(MyApplicationClass* klass) {
|
||||
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
|
||||
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
|
||||
G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
|
||||
}
|
||||
|
||||
static void my_application_init(MyApplication* self) {}
|
||||
|
||||
MyApplication* my_application_new() {
|
||||
return MY_APPLICATION(g_object_new(my_application_get_type(),
|
||||
"application-id", APPLICATION_ID,
|
||||
"flags", G_APPLICATION_NON_UNIQUE,
|
||||
nullptr));
|
||||
}
|
||||