From 910a9cc17ea26b0e86b2a9a5241459e5cd3177a2 Mon Sep 17 00:00:00 2001 From: hackycy Date: Tue, 21 Jul 2020 11:16:40 +0800 Subject: [PATCH 01/13] =?UTF-8?q?docs=EF=BC=9Aupdate=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a9b9875..f205212 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,9 @@ Flutter-PicGo: 一个用于快速上传图片并获取图片URL链接的**手机 # 特色功能 - 长按相册列表项可**同步删除远端的文件**,也可配置仅删除本地列表 -- 支持扫描二维码将PicGo(v2.3.0-beta.2以上版本)配置文件转换成Flutter-PicGo的配置,使用请移步[链接](https://github.com/Molunerfinn/PicGo/releases/tag/v2.3.0-beta.2) +- 支持扫描二维码将*PicGo(v2.3.0-beta.2以上版本)*配置文件转换成*Flutter-PicGo*的配置,使用请移步[链接](https://github.com/Molunerfinn/PicGo/releases/tag/v2.3.0-beta.2) - 适配深色模式,可跟随系统或手动设置 -- 支持将flutter-picgo的配置导出至剪切板 +- 支持将*Flutter-PicGo*的配置导出至剪切板 > 基本使用配置与PicGo无异,可参考[配置文档](https://picgo.github.io/PicGo-Doc/zh/guide/config.html#%E5%9B%BE%E5%BA%8A%E5%8C%BA)。 > 腾讯云COS仅支持v5版配置 @@ -51,9 +51,12 @@ Flutter-PicGo: 一个用于快速上传图片并获取图片URL链接的**手机 目前仅支持iOS与Android端,由于部分插件例如[sqflite](https://pub.dev/packages/sqflite),所以并不支持Web端。 +# 相关 + +- [PC端PicGo](https://github.com/Molunerfinn/PicGo) + # 致谢 -- [PicGo](https://github.com/Molunerfinn/PicGo) - [Flutter-Go](https://github.com/alibaba/flutter-go) # License From 4aee5c95c4cb5a114742f45634235e5ae7e82e69 Mon Sep 17 00:00:00 2001 From: hackycy Date: Tue, 21 Jul 2020 14:32:38 +0800 Subject: [PATCH 02/13] =?UTF-8?q?docs=EF=BC=9Aupdate=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f205212..54981f5 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Flutter-PicGo: 一个用于快速上传图片并获取图片URL链接的**手机 # 相关 -- [PC端PicGo](https://github.com/Molunerfinn/PicGo) +- [PicGo](https://github.com/Molunerfinn/PicGo) # 致谢 From b8d74fb0eea6419b511b44afc9922fda40e7a9e5 Mon Sep 17 00:00:00 2001 From: hackycy Date: Tue, 21 Jul 2020 15:25:29 +0800 Subject: [PATCH 03/13] =?UTF-8?q?docs=EF=BC=9Aupdate=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 54981f5..667d5ab 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,10 @@ Flutter-PicGo: 一个用于快速上传图片并获取图片URL链接的**手机 目前仅支持iOS与Android端,由于部分插件例如[sqflite](https://pub.dev/packages/sqflite),所以并不支持Web端。 +# 有问题或者有更好的建议 + +欢迎提 [Issues](https://github.com/PicGo/flutter-picgo/issues) + # 相关 - [PicGo](https://github.com/Molunerfinn/PicGo) From 469fcfdf9dc20fee5fc6f309dc46f69683580708 Mon Sep 17 00:00:00 2001 From: hackycy Date: Wed, 22 Jul 2020 10:46:17 +0800 Subject: [PATCH 04/13] =?UTF-8?q?docs=EF=BC=9Aupdate=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 667d5ab..563e89e 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,13 @@ Flutter-PicGo: 一个用于快速上传图片并获取图片URL链接的**手机 # 应用说明 -目前仅支持iOS与Android端,由于部分插件例如[sqflite](https://pub.dev/packages/sqflite),所以并不支持Web端。 +目前仅支持iOS与Android端,由于部分插件例如[sqflite](https://pub.dev/packages/sqflite)不支持Web端,所以应用也并不支持Web端。 # 有问题或者有更好的建议 -欢迎提 [Issues](https://github.com/PicGo/flutter-picgo/issues) +- 欢迎提 [Issues](https://github.com/PicGo/flutter-picgo/issues) + +> 如果项目有帮助到你或者喜欢这个项目,可以给个Star支持一下鸭 # 相关 @@ -63,7 +65,29 @@ Flutter-PicGo: 一个用于快速上传图片并获取图片URL链接的**手机 - [Flutter-Go](https://github.com/alibaba/flutter-go) -# License +# [License](https://github.com/hackycy/flutter-picgo/blob/master/LICENSE) + +``` txt +MIT License + +Copyright (c) 2020 Mr.Yang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -[MIT](https://github.com/hackycy/flutter-picgo/blob/master/LICENSE) +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` From 48ba971ef4836a639ea56b2c79606c19d86184a9 Mon Sep 17 00:00:00 2001 From: hackycy Date: Wed, 22 Jul 2020 10:53:09 +0800 Subject: [PATCH 05/13] =?UTF-8?q?docs=EF=BC=9Aupdate=20sqlite=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "docs/\350\256\276\350\256\241\346\226\207\346\241\243.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/docs/\350\256\276\350\256\241\346\226\207\346\241\243.md" "b/docs/\350\256\276\350\256\241\346\226\207\346\241\243.md" index a7523ba..a2a4629 100644 --- "a/docs/\350\256\276\350\256\241\346\226\207\346\241\243.md" +++ "b/docs/\350\256\276\350\256\241\346\226\207\346\241\243.md" @@ -30,4 +30,5 @@ | 4 | 新增Qiniu图床记录 | | 5 | 新增阿里云OSS图床记录 | | 6 | 新增腾讯云COS图床记录 | +| 7 | 新增牛图网图床记录 | From dffbda8517ae783e88d14a1555ca5ea7f55e9b2d Mon Sep 17 00:00:00 2001 From: hackycy Date: Wed, 22 Jul 2020 11:00:37 +0800 Subject: [PATCH 06/13] =?UTF-8?q?feature=EF=BC=9Aupgrade=20sqlte=20version?= =?UTF-8?q?=20and=20add=20picBed=20row?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/resources/pb_type_keys.dart | 2 ++ lib/utils/db_provider.dart | 3 +++ 2 files changed, 5 insertions(+) diff --git a/lib/resources/pb_type_keys.dart b/lib/resources/pb_type_keys.dart index 9423e01..b0ee8f3 100644 --- a/lib/resources/pb_type_keys.dart +++ b/lib/resources/pb_type_keys.dart @@ -10,4 +10,6 @@ class PBTypeKeys { static const aliyun = 'aliyun'; static const tcyun = 'tcyun'; + + static const niupic = 'niupic'; } diff --git a/lib/utils/db_provider.dart b/lib/utils/db_provider.dart index 43c6ac2..32393a4 100644 --- a/lib/utils/db_provider.dart +++ b/lib/utils/db_provider.dart @@ -105,6 +105,9 @@ class DbProvider { // 腾讯云COS await db.rawInsert( 'INSERT INTO $TABLE_NAME_PBSETTING(type, path, name, config, visible) VALUES("${PBTypeKeys.tcyun}", "/setting/pb/tcyun", "腾讯云COS图床", NULL, 1)'); + // 牛图网 + await db.rawInsert( + 'INSERT INTO $TABLE_NAME_PBSETTING(type, path, name, config, visible) VALUES("${PBTypeKeys.niupic}", "/setting/pb/niupic", "牛图网图床", NULL, 1)'); // copy data // update authors set dynasty_index=(select id from dynasties where dynasties .name=authors.dynasty) where dynasty in (select name from dynasties ) if (isExists) { From 45ee39b52bc995f4c056bc5ecece1b31cc1df39b Mon Sep 17 00:00:00 2001 From: hackycy Date: Wed, 22 Jul 2020 11:07:52 +0800 Subject: [PATCH 07/13] =?UTF-8?q?docs=EF=BC=9Aupdate=20version.json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/version.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/version.json b/docs/version.json index 4da3336..cd58e8d 100644 --- a/docs/version.json +++ b/docs/version.json @@ -1,10 +1,10 @@ { "iOS": { - "versionName": "1.5.3", - "versionCode": "13" + "versionName": "1.6.0", + "versionCode": "14" }, "Android": { - "versionName": "1.5.3", - "versionCode": "13" + "versionName": "1.6.0", + "versionCode": "14" } } \ No newline at end of file From 9018358d090cdde5c1b958496d9c5f354d35fdc4 Mon Sep 17 00:00:00 2001 From: hackycy Date: Wed, 22 Jul 2020 11:23:19 +0800 Subject: [PATCH 08/13] =?UTF-8?q?feature=EF=BC=9Acomplete=20niupic=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/routers/router_handler.dart | 6 ++++++ lib/routers/routers.dart | 6 +++++- .../niupic_page/niupic_page.dart | 21 +++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 lib/views/pb_setting_page/niupic_page/niupic_page.dart diff --git a/lib/routers/router_handler.dart b/lib/routers/router_handler.dart index 436d5d4..7007fb8 100644 --- a/lib/routers/router_handler.dart +++ b/lib/routers/router_handler.dart @@ -7,6 +7,7 @@ import 'package:flutter_picgo/views/pb_setting_page/aliyun_page/aliyun_page.dart import 'package:flutter_picgo/views/pb_setting_page/gitee_page/gitee_page.dart'; import 'package:flutter_picgo/views/pb_setting_page/gitee_page/gitee_repo_page.dart'; import 'package:flutter_picgo/views/pb_setting_page/github_page/github_repo_page.dart'; +import 'package:flutter_picgo/views/pb_setting_page/niupic_page/niupic_page.dart'; import 'package:flutter_picgo/views/pb_setting_page/pb_setting_page.dart'; import 'package:flutter_picgo/views/pb_setting_page/qiniu_page/qiniu_page.dart'; import 'package:flutter_picgo/views/pb_setting_page/smms_page/smms_page.dart'; @@ -120,6 +121,11 @@ var pbsettingTcyunHandler = new Handler( handlerFunc: (context, parameters) => TcyunPage(), ); +// 牛图网图床设置页面 +var pbsettingNiupicHandler = new Handler( + handlerFunc: (context, parameters) => NiupicPage(), +); + // picgo设置页面 var picgosettingHandler = new Handler( handlerFunc: (BuildContext context, Map> params) => diff --git a/lib/routers/routers.dart b/lib/routers/routers.dart index 91b1068..f63e8f1 100644 --- a/lib/routers/routers.dart +++ b/lib/routers/routers.dart @@ -28,9 +28,12 @@ class Routes { // --------- aliyun ------------------- static const String settingPbAliyun = '/setting/pb/aliyun'; // ----------------------------------- - // --------- aliyun ------------------- + // --------- tcyun ------------------- static const String settingPbTcyun = '/setting/pb/tcyun'; // ----------------------------------- + // --------- niupic ------------------- + static const String settingPbNiupic = '/setting/pb/niupic'; + // ----------------------------------- static void configureRoutes(Router router) { router.notFoundHandler = notfoundHandler; @@ -50,5 +53,6 @@ class Routes { router.define(settingPbQiniu, handler: pbsettingQiniuHandler); router.define(settingPbAliyun, handler: pbsettingAliyunHandler); router.define(settingPbTcyun, handler: pbsettingTcyunHandler); + router.define(settingPbNiupic, handler: pbsettingNiupicHandler); } } diff --git a/lib/views/pb_setting_page/niupic_page/niupic_page.dart b/lib/views/pb_setting_page/niupic_page/niupic_page.dart new file mode 100644 index 0000000..a20ed9a --- /dev/null +++ b/lib/views/pb_setting_page/niupic_page/niupic_page.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_picgo/resources/pb_type_keys.dart'; +import 'package:flutter_picgo/views/pb_setting_page/base_pb_page_state.dart'; + +class NiupicPage extends StatefulWidget { + _NiupicPageState createState() => _NiupicPageState(); +} + +class _NiupicPageState extends BasePBSettingPageState { + @override + AppBar get appbar => AppBar( + title: Text('牛图网图床'), + centerTitle: true, + ); + + @override + onLoadConfig(String config) {} + + @override + String get pbType => PBTypeKeys.niupic; +} From 738b377a7d0c5564cd134c0cb6d569738d1a98ed Mon Sep 17 00:00:00 2001 From: hackycy Date: Wed, 22 Jul 2020 11:24:19 +0800 Subject: [PATCH 09/13] =?UTF-8?q?feature=EF=BC=9Aswitch=20default=20picBed?= =?UTF-8?q?=20to=20niupic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/utils/shared_preferences.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/utils/shared_preferences.dart b/lib/utils/shared_preferences.dart index 62b23eb..fbdfcbe 100644 --- a/lib/utils/shared_preferences.dart +++ b/lib/utils/shared_preferences.dart @@ -43,10 +43,10 @@ class SpUtil { putString(SharedPreferencesKeys.settingDefaultPB, type); } - /// 获取当前默认图床,默认为github + /// 获取当前默认图床,默认为牛图网图床 String getDefaultPB() { return getString(SharedPreferencesKeys.settingDefaultPB) ?? - PBTypeKeys.github; + PBTypeKeys.niupic; } // 判断是否存在数据 From 0f901b08191329f43a6e7de2e69c4b2027a4556d Mon Sep 17 00:00:00 2001 From: hackycy Date: Wed, 22 Jul 2020 11:45:02 +0800 Subject: [PATCH 10/13] =?UTF-8?q?fix=EF=BC=9Ainfo=20colunm=20can=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/utils/db_provider.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/utils/db_provider.dart b/lib/utils/db_provider.dart index 32393a4..9979988 100644 --- a/lib/utils/db_provider.dart +++ b/lib/utils/db_provider.dart @@ -34,7 +34,7 @@ class DbProvider { try { db = await openDatabase( path, - version: 6, + version: 7, onCreate: (db, version) async { // 创建pb_setting表 _initPb(db); @@ -44,7 +44,7 @@ class DbProvider { id INTEGER PRIMARY KEY AUTOINCREMENT, path varchar(255) NOT NULL, type varchar(20) NOT NULL, - info varchar(255) NOT NULL + info varchar(255) )'''); }, onUpgrade: (db, oldVersion, newVersion) { From 6459b87665c0292edcc14d6bfdd676ed25f01d8d Mon Sep 17 00:00:00 2001 From: hackycy Date: Wed, 22 Jul 2020 11:45:23 +0800 Subject: [PATCH 11/13] =?UTF-8?q?feature=EF=BC=9Acomplete=20niupic=20image?= =?UTF-8?q?=20upload?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/api/niupic_api.dart | 12 +++++ .../strategy/impl/niupic_image_upload.dart | 53 +++++++++++++++++++ .../strategy/upload_strategy_factory.dart | 4 ++ 3 files changed, 69 insertions(+) create mode 100644 lib/api/niupic_api.dart create mode 100644 lib/utils/strategy/impl/niupic_image_upload.dart diff --git a/lib/api/niupic_api.dart b/lib/api/niupic_api.dart new file mode 100644 index 0000000..107ac7c --- /dev/null +++ b/lib/api/niupic_api.dart @@ -0,0 +1,12 @@ +import 'package:dio/dio.dart'; +import 'package:flutter_picgo/utils/net.dart'; + +class NiupicApi { + static const BASE_URL = 'https://www.niupic.com/'; + + static Future upload(FormData data) async { + Response res = await NetUtils.getInstance() + .post(BASE_URL + 'index/upload/process', data: data); + return res.data; + } +} diff --git a/lib/utils/strategy/impl/niupic_image_upload.dart b/lib/utils/strategy/impl/niupic_image_upload.dart new file mode 100644 index 0000000..7855174 --- /dev/null +++ b/lib/utils/strategy/impl/niupic_image_upload.dart @@ -0,0 +1,53 @@ +import 'package:dio/dio.dart'; +import 'package:flutter_picgo/api/niupic_api.dart'; +import 'package:flutter_picgo/model/uploaded.dart'; +import 'package:flutter_picgo/resources/pb_type_keys.dart'; +import 'package:flutter_picgo/utils/image_upload.dart'; +import 'dart:io'; + +import 'package:flutter_picgo/utils/strategy/image_upload_strategy.dart'; + +class NiupicImageUpload implements ImageUploadStrategy { + /// 牛图网不支持删除 + @override + Future delete(Uploaded uploaded) async { + return uploaded; + } + + @override + Future upload(File file, String renameImage) async { + FormData formData = FormData.fromMap({ + "image_field": + await MultipartFile.fromFile(file.path, filename: renameImage), + }); + var result = await NiupicApi.upload(formData); + if (result["code"] == 200) { + var uploadedItem = Uploaded( + -1, 'https://${result['data']}', PBTypeKeys.niupic, + info: ''); + await ImageUploadUtils.saveUploadedItem(uploadedItem); + return uploadedItem; + } else { + throw new NiupicError(error: '${result['msg']}'); + } + } +} + +class NiupicError implements Exception { + NiupicError({ + this.error, + }); + + dynamic error; + + String get message => (error?.toString() ?? ''); + + @override + String toString() { + var msg = 'NiupicError $message'; + if (error is Error) { + msg += '\n${error.stackTrace}'; + } + return msg; + } +} diff --git a/lib/utils/strategy/upload_strategy_factory.dart b/lib/utils/strategy/upload_strategy_factory.dart index 69826de..7a9fd0b 100644 --- a/lib/utils/strategy/upload_strategy_factory.dart +++ b/lib/utils/strategy/upload_strategy_factory.dart @@ -3,6 +3,7 @@ import 'package:flutter_picgo/utils/strategy/impl/aliyun_image_upload.dart'; import 'package:flutter_picgo/utils/strategy/impl/gitee_image_upload.dart'; import 'package:flutter_picgo/utils/strategy/impl/github_image_upload.dart'; import 'package:flutter_picgo/utils/strategy/image_upload_strategy.dart'; +import 'package:flutter_picgo/utils/strategy/impl/niupic_image_upload.dart'; import 'package:flutter_picgo/utils/strategy/impl/qiniu_image_upload.dart'; import 'package:flutter_picgo/utils/strategy/impl/smms_image_upload.dart'; import 'package:flutter_picgo/utils/strategy/impl/tcyun_image_upload.dart'; @@ -35,6 +36,9 @@ class UploadStrategyFactory { } else if (type == PBTypeKeys.tcyun) { /// 腾讯云 cache[type] = new TcyunImageUpload(); + } else if (type == PBTypeKeys.niupic) { + /// 牛图网 + cache[type] = new NiupicImageUpload(); } } return cache[type]; From 41f595d8727c4188d755c1d3a6aaa5d3df905f5c Mon Sep 17 00:00:00 2001 From: hackycy Date: Wed, 22 Jul 2020 11:49:43 +0800 Subject: [PATCH 12/13] =?UTF-8?q?feature=EF=BC=9Aset=20default=20picBed=20?= =?UTF-8?q?to=20github?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/utils/shared_preferences.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/utils/shared_preferences.dart b/lib/utils/shared_preferences.dart index fbdfcbe..62b23eb 100644 --- a/lib/utils/shared_preferences.dart +++ b/lib/utils/shared_preferences.dart @@ -43,10 +43,10 @@ class SpUtil { putString(SharedPreferencesKeys.settingDefaultPB, type); } - /// 获取当前默认图床,默认为牛图网图床 + /// 获取当前默认图床,默认为github String getDefaultPB() { return getString(SharedPreferencesKeys.settingDefaultPB) ?? - PBTypeKeys.niupic; + PBTypeKeys.github; } // 判断是否存在数据 From cc98d06d83f69ef166cd9c8c1e984397f89ff800 Mon Sep 17 00:00:00 2001 From: hackycy Date: Wed, 22 Jul 2020 11:54:04 +0800 Subject: [PATCH 13/13] =?UTF-8?q?build=EF=BC=9Arelease=20v1.6.0+14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index e3b9a60..033fa80 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.5.3+13 +version: 1.6.0+14 environment: sdk: ">=2.7.0 <3.0.0"