forked from lxm_tools/flutter-picgo
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03dbf3ad93 | ||
|
|
b01bf49a0f | ||
|
|
fbb877e12f | ||
|
|
a9b70bc259 | ||
|
|
9680e1660f | ||
|
|
04b41548fe | ||
|
|
5c3eecf284 | ||
|
|
be70cc70e1 | ||
|
|
479fa4700c | ||
|
|
105ff1d806 | ||
|
|
8795c60503 | ||
|
|
48e5fcf6bb | ||
|
|
dca39be03d | ||
|
|
54eeb0b7ed | ||
|
|
1779b5c8c4 | ||
|
|
3706673dec | ||
|
|
12d72517bc | ||
|
|
e04ad042c3 | ||
|
|
2a7684fc13 | ||
|
|
13df6e311c | ||
|
|
1e758b65ca | ||
|
|
64ecde9bf9 | ||
|
|
4566c5215b | ||
|
|
0425de675c | ||
|
|
f8515c1c4e | ||
|
|
2c3d7cae05 |
@@ -4,8 +4,8 @@
|
||||
<blockquote>图片上传+管理新体验 </blockquote>
|
||||
<img src="https://img.shields.io/github/license/hackycy/flutter-picgo" alt="">
|
||||
<img src="https://img.shields.io/github/workflow/status/hackycy/flutter-picgo/Build and Release apk" alt="">
|
||||
<img src="https://img.shields.io/github/repo-size/hackycy/flutter-picgo" alt="">
|
||||
<img src="https://img.shields.io/github/v/release/hackycy/flutter-picgo" alt="">
|
||||
<img src="https://img.shields.io/github/issues-closed/hackycy/flutter-picgo" alt="">
|
||||
<img src="https://img.shields.io/github/v/release/hackycy/flutter-picgo?include_prereleases" alt="">
|
||||
<img src="https://img.shields.io/github/downloads/hackycy/flutter-picgo/total" alt="">
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,7 @@ Flutter-PicGo: 一个用于快速上传图片并获取图片URL链接的**手机
|
||||
- 七牛云 [v1.3+]
|
||||
- 阿里云OSS [v1.4+]
|
||||
- 腾讯云COS [v1.5+]
|
||||
- 牛图网 [v1.6+]
|
||||
- ~~牛图网(已无法使用)~~ [v1.6+]
|
||||
- 兰空 [v1.7+]
|
||||
- 又拍云 [v1.8+]
|
||||
|
||||
|
||||
@@ -50,6 +50,9 @@ android {
|
||||
targetSdkVersion 28
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
|
||||
// support multidex
|
||||
multiDexEnabled true
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"versionCode": "22"
|
||||
},
|
||||
"Android": {
|
||||
"versionName": "1.9.1",
|
||||
"versionCode": "22"
|
||||
"versionName": "1.9.2",
|
||||
"versionCode": "23"
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,6 @@ PODS:
|
||||
- FMDB (2.7.5):
|
||||
- FMDB/standard (= 2.7.5)
|
||||
- FMDB/standard (2.7.5)
|
||||
- image_picker (0.0.1):
|
||||
- Flutter
|
||||
- MTBBarcodeScanner (5.0.11)
|
||||
- package_info (0.0.1):
|
||||
- Flutter
|
||||
@@ -18,6 +16,8 @@ PODS:
|
||||
- Flutter
|
||||
- "permission_handler (5.0.1+1)":
|
||||
- Flutter
|
||||
- photo_manager (0.0.1):
|
||||
- Flutter
|
||||
- shared_preferences (0.0.1):
|
||||
- Flutter
|
||||
- sqflite (0.0.2):
|
||||
@@ -26,18 +26,21 @@ PODS:
|
||||
- SwiftProtobuf (1.9.0)
|
||||
- url_launcher (0.0.1):
|
||||
- Flutter
|
||||
- video_player (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- barcode_scan (from `.symlinks/plugins/barcode_scan/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||
- image_picker (from `.symlinks/plugins/image_picker/ios`)
|
||||
- package_info (from `.symlinks/plugins/package_info/ios`)
|
||||
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
||||
- permission_handler (from `.symlinks/plugins/permission_handler/ios`)
|
||||
- photo_manager (from `.symlinks/plugins/photo_manager/ios`)
|
||||
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
|
||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
||||
- video_player (from `.symlinks/plugins/video_player/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
@@ -52,35 +55,38 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter
|
||||
flutter_local_notifications:
|
||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||
image_picker:
|
||||
:path: ".symlinks/plugins/image_picker/ios"
|
||||
package_info:
|
||||
:path: ".symlinks/plugins/package_info/ios"
|
||||
path_provider:
|
||||
:path: ".symlinks/plugins/path_provider/ios"
|
||||
permission_handler:
|
||||
:path: ".symlinks/plugins/permission_handler/ios"
|
||||
photo_manager:
|
||||
:path: ".symlinks/plugins/photo_manager/ios"
|
||||
shared_preferences:
|
||||
:path: ".symlinks/plugins/shared_preferences/ios"
|
||||
sqflite:
|
||||
:path: ".symlinks/plugins/sqflite/ios"
|
||||
url_launcher:
|
||||
:path: ".symlinks/plugins/url_launcher/ios"
|
||||
video_player:
|
||||
:path: ".symlinks/plugins/video_player/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
barcode_scan: a5c27959edfafaa0c771905bad0b29d6d39e4479
|
||||
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
|
||||
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
image_picker: 9c3312491f862b28d21ecd8fdf0ee14e601b3f09
|
||||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
||||
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
||||
permission_handler: eac8e15b4a1a3fba55b761d19f3f4e6b005d15b6
|
||||
photo_manager: f7c619c2cc8c2adb8d85c63363babac477de9c67
|
||||
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
|
||||
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
||||
SwiftProtobuf: ecbec1be9036d15655f6b3443a1c4ea693c97932
|
||||
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
||||
video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e
|
||||
|
||||
PODFILE CHECKSUM: 08e41981fcdc78ff11c898bc59c6c49635c114b3
|
||||
|
||||
|
||||
@@ -11,15 +11,14 @@ class TcyunApi {
|
||||
static const String secretKey = 'secretKey';
|
||||
static const String secretId = 'secretId';
|
||||
|
||||
static Future postObject(String secretId, String secretKey, String bucket, String area, String ext, FormData formData) async {
|
||||
static Future postObject(String secretId, String secretKey, String bucket,
|
||||
String area, String ext, FormData formData) async {
|
||||
Response res = await NetUtils.getInstance().post(
|
||||
'https://$bucket.cos.$area.$BASE_URL/',
|
||||
data: formData,
|
||||
options: Options(
|
||||
extra: {TcyunApi.secretId: secretId, TcyunApi.secretKey: secretKey},
|
||||
contentType: 'image/$ext'
|
||||
)
|
||||
);
|
||||
'https://$bucket.cos.$area.$BASE_URL/',
|
||||
data: formData,
|
||||
options: Options(
|
||||
extra: {TcyunApi.secretId: secretId, TcyunApi.secretKey: secretKey},
|
||||
contentType: 'image/$ext'));
|
||||
return res.headers;
|
||||
}
|
||||
|
||||
@@ -56,7 +55,7 @@ class TcyunApi {
|
||||
/// signkey
|
||||
var hmacsha1Signkey = Hmac(sha1, utf8.encode(secretKey));
|
||||
var signKey = hmacsha1Signkey.convert(utf8.encode(keyTime));
|
||||
// string to sign
|
||||
// string to sign
|
||||
var stringToSign = sha1.convert(utf8.encode(policy));
|
||||
// signature
|
||||
var hmacsha1Signature = Hmac(sha1, utf8.encode('$signKey'));
|
||||
@@ -131,7 +130,6 @@ class TcyunInterceptor extends InterceptorsWrapper {
|
||||
}
|
||||
if (headers != null) {
|
||||
headers.forEach((key, value) {
|
||||
print('key = $key, value = $value');
|
||||
headerList += '${Uri.encodeComponent(key).toLowerCase()};';
|
||||
httpHeaders +=
|
||||
'${Uri.encodeComponent(key).toLowerCase()}=${Uri.encodeComponent(value)}&';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_picgo/utils/extended.dart';
|
||||
import 'package:path/path.dart';
|
||||
|
||||
typedef GestureTapCallback = void Function();
|
||||
@@ -77,48 +78,23 @@ class ManageItem extends StatelessWidget {
|
||||
var imageSuffixs = ['png', 'bmp', 'jpeg', 'gif', 'jpg'];
|
||||
if (imageSuffixs.contains(suffix)) {
|
||||
return SizedBox(
|
||||
height: 50,
|
||||
width: 50,
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadiusDirectional.circular(2)),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: this.url,
|
||||
fit: BoxFit.cover,
|
||||
placeholder: (context, url) => Center(
|
||||
child: Container(
|
||||
width: 10,
|
||||
height: 10,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 3,
|
||||
),
|
||||
),
|
||||
height: 50,
|
||||
width: 50,
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadiusDirectional.circular(2)),
|
||||
child: ExtendedImage.network(
|
||||
this.url,
|
||||
width: 50,
|
||||
height: 50,
|
||||
fit: BoxFit.cover,
|
||||
cache: true,
|
||||
border: Border.all(color: Colors.grey, width: 1.0),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
loadStateChanged: (state) => defaultLoadStateChanged(state),
|
||||
),
|
||||
errorWidget: (context, url, error) {
|
||||
return Container(
|
||||
color: Colors.grey,
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
Icons.error,
|
||||
size: 12,
|
||||
),
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
'加载失败',
|
||||
style: TextStyle(fontSize: 8),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
));
|
||||
} else {
|
||||
return buildCenterIcon(Icon(IconData(0xe654, fontFamily: 'iconfont')));
|
||||
}
|
||||
|
||||
193
lib/components/upload_item/upload_item.dart
Normal file
193
lib/components/upload_item/upload_item.dart
Normal file
@@ -0,0 +1,193 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_picgo/components/upload_item/upload_item_presenter.dart';
|
||||
import 'package:flutter_picgo/utils/extended.dart';
|
||||
import 'package:flutter_picgo/utils/local_notification.dart';
|
||||
import 'package:toast/toast.dart';
|
||||
|
||||
enum UploadState {
|
||||
/// 上传中
|
||||
Uploading,
|
||||
|
||||
/// 保存中
|
||||
Saving,
|
||||
|
||||
/// 已完成
|
||||
Complete,
|
||||
|
||||
/// 上传失败
|
||||
UploadFail,
|
||||
|
||||
/// 保存失败
|
||||
SaveFail
|
||||
}
|
||||
|
||||
class UploadItem extends StatefulWidget {
|
||||
final File file;
|
||||
final String rename;
|
||||
final bool needNotify;
|
||||
|
||||
UploadItem(this.file, this.rename, {this.needNotify = false});
|
||||
|
||||
@override
|
||||
_UploadItemState createState() => _UploadItemState();
|
||||
}
|
||||
|
||||
class _UploadItemState extends State<UploadItem> implements UploadItemContract {
|
||||
UploadState _state;
|
||||
UploadItemPresenter _presenter;
|
||||
String _uploadedImageUrl = '';
|
||||
|
||||
/// construct
|
||||
_UploadItemState() {
|
||||
_state = UploadState.Uploading;
|
||||
_presenter = new UploadItemPresenter(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_startUpload();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: SizedBox(
|
||||
height: 50,
|
||||
width: 50,
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadiusDirectional.circular(2)),
|
||||
child: ExtendedImage.file(
|
||||
File(widget.file.path),
|
||||
width: 50,
|
||||
height: 50,
|
||||
fit: BoxFit.cover,
|
||||
border: Border.all(color: Colors.grey, width: 1.0),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
loadStateChanged: (state) => defaultLoadStateChanged(state),
|
||||
),
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
widget.rename,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textWidthBasis: TextWidthBasis.parent,
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w400),
|
||||
),
|
||||
subtitle: Text(
|
||||
'上传状态:${_parseStateText()}',
|
||||
maxLines: 1,
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
trailing: buildStateTip(),
|
||||
onTap: () {
|
||||
_handleTap();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildStateTip() {
|
||||
switch (_state) {
|
||||
case UploadState.Uploading:
|
||||
case UploadState.Saving:
|
||||
return SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: CupertinoActivityIndicator(),
|
||||
);
|
||||
case UploadState.Complete:
|
||||
return Icon(
|
||||
Icons.done,
|
||||
size: 16,
|
||||
color: Colors.green,
|
||||
);
|
||||
case UploadState.UploadFail:
|
||||
case UploadState.SaveFail:
|
||||
default:
|
||||
return GestureDetector(
|
||||
child: Icon(
|
||||
Icons.error,
|
||||
color: Colors.red,
|
||||
size: 16,
|
||||
),
|
||||
onTap: () {
|
||||
_startUpload();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 状态转文字
|
||||
String _parseStateText() {
|
||||
switch (_state) {
|
||||
case UploadState.Uploading:
|
||||
return '上传中';
|
||||
case UploadState.Saving:
|
||||
return '保存中';
|
||||
case UploadState.Complete:
|
||||
return '已完成';
|
||||
case UploadState.UploadFail:
|
||||
return '上传失败';
|
||||
case UploadState.SaveFail:
|
||||
return '保存失败';
|
||||
default:
|
||||
return '未知';
|
||||
}
|
||||
}
|
||||
|
||||
/// 开始上传
|
||||
_startUpload() {
|
||||
setState(() {
|
||||
_state = UploadState.Uploading;
|
||||
});
|
||||
_presenter.doUploadImage(widget.file, widget.rename);
|
||||
}
|
||||
|
||||
/// 处理点击事件
|
||||
_handleTap() {
|
||||
if (_state == UploadState.Complete) {
|
||||
Clipboard.setData(ClipboardData(text: _uploadedImageUrl));
|
||||
Toast.show('已复制到剪切板', context);
|
||||
} else {
|
||||
Toast.show('当前状态无法操作', context);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
uploadFaild(String errorMsg) {
|
||||
setState(() {
|
||||
_state = UploadState.UploadFail;
|
||||
});
|
||||
|
||||
_showNotification(0, '${widget.rename}上传失败:$errorMsg');
|
||||
}
|
||||
|
||||
@override
|
||||
uploadSuccess(String url) async {
|
||||
_uploadedImageUrl = url;
|
||||
setState(() {
|
||||
_state = UploadState.Complete;
|
||||
});
|
||||
|
||||
_showNotification(0, '${widget.rename}上传成功:$url');
|
||||
}
|
||||
|
||||
Future<void> _showNotification(int id, String body) async {
|
||||
LocalNotificationUtil.getInstance().show(
|
||||
id,
|
||||
'上传提示',
|
||||
body,
|
||||
LocalNotificationUtil.createNotificationDetails(
|
||||
LocalNotificationUtil.uploadAndroidChannel(),
|
||||
LocalNotificationUtil.normalIOSNotificationDetails(),
|
||||
LocalNotificationUtil.normalMacOSNotificationDetails()));
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,16 @@
|
||||
import 'dart:io';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_picgo/utils/image_upload.dart';
|
||||
import 'package:flutter_picgo/utils/strategy/upload_strategy_factory.dart';
|
||||
|
||||
abstract class UploadPageContract {
|
||||
loadCurrentPB(String pbname);
|
||||
abstract class UploadItemContract {
|
||||
uploadSuccess(String url);
|
||||
uploadFaild(String errorMsg);
|
||||
}
|
||||
|
||||
class UploadPagePresenter {
|
||||
UploadPageContract _view;
|
||||
UploadPagePresenter(this._view);
|
||||
|
||||
/// 读取当前默认图床
|
||||
doLoadCurrentPB() async {
|
||||
try {
|
||||
String pbType = await ImageUploadUtils.getDefaultPB();
|
||||
String name = await ImageUploadUtils.getPBName(pbType);
|
||||
if (name != null) {
|
||||
_view.loadCurrentPB(name);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
class UploadItemPresenter {
|
||||
UploadItemContract _view;
|
||||
UploadItemPresenter(this._view);
|
||||
|
||||
/// 根据配置上传图片
|
||||
doUploadImage(File file, String renameImage) async {
|
||||
@@ -39,10 +26,8 @@ class UploadPagePresenter {
|
||||
_view.uploadFaild('上传失败!请重试');
|
||||
}
|
||||
} on DioError catch (e) {
|
||||
debugPrint(e.toString());
|
||||
_view.uploadFaild('${e.message}');
|
||||
} catch (e) {
|
||||
debugPrint(e.toString());
|
||||
_view.uploadFaild('$e');
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class UploadedItem extends StatelessWidget {
|
||||
|
||||
final String path;
|
||||
|
||||
UploadedItem(this.path);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 150.0,
|
||||
child: Image.network(path),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import 'package:event_bus/event_bus.dart';
|
||||
|
||||
class ApplicationEvent {
|
||||
|
||||
static EventBus eventBus;
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
class DemoEvent {
|
||||
|
||||
final String name;
|
||||
|
||||
DemoEvent(this.name);
|
||||
|
||||
}
|
||||
@@ -18,11 +18,12 @@ import 'package:flutter_picgo/views/pb_setting_page/smms_page/smms_page.dart';
|
||||
import 'package:flutter_picgo/views/pb_setting_page/tcyun_page/tcyun_page.dart';
|
||||
import 'package:flutter_picgo/views/pb_setting_page/upyun_page/upyun_page.dart';
|
||||
import 'package:flutter_picgo/views/picgo_setting_page/theme_setting_page.dart';
|
||||
import 'package:flutter_picgo/views/upload_page/upload_page.dart';
|
||||
import 'package:flutter_picgo/views/upload_page/handle_upload_page.dart';
|
||||
import 'package:flutter_picgo/views/pb_setting_page/github_page/github_page.dart';
|
||||
import 'package:flutter_picgo/views/picgo_setting_page/picgo_setting_page.dart';
|
||||
import 'package:flutter_picgo/views/setting_page/setting_page.dart';
|
||||
import 'package:flutter_picgo/views/404.dart';
|
||||
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
|
||||
|
||||
var appHandler = new Handler(
|
||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||
@@ -54,9 +55,12 @@ var settingHandler = new Handler(
|
||||
);
|
||||
|
||||
// 上传页面
|
||||
var uploadHandler = new Handler(
|
||||
handlerFunc: (BuildContext context, Map<String, List<String>> params) =>
|
||||
UploadPage(),
|
||||
var preUploadHandler = new Handler(
|
||||
handlerFunc: (context, parameters) {
|
||||
final assets = context.settings.arguments as List<AssetEntity>;
|
||||
|
||||
return HandleUploadPage(assets);
|
||||
},
|
||||
);
|
||||
|
||||
// 图床设置页面
|
||||
|
||||
@@ -8,6 +8,7 @@ class Routes {
|
||||
static const String notfound = '/404';
|
||||
static const String setting = '/setting';
|
||||
static const String upload = '/upload';
|
||||
static const String handleUpload = '/handle/upload';
|
||||
static const String settingPb = '/setting/pb';
|
||||
static const String settingPicgo = '/setting/picgo';
|
||||
static const String settingPicgoTheme = '/setting/picgo/theme';
|
||||
@@ -49,7 +50,7 @@ class Routes {
|
||||
router.define(root, handler: appHandler);
|
||||
router.define(notfound, handler: notfoundHandler);
|
||||
router.define(album, handler: albumHandler);
|
||||
router.define(upload, handler: uploadHandler);
|
||||
router.define(handleUpload, handler: preUploadHandler);
|
||||
router.define(setting, handler: settingHandler);
|
||||
router.define(settingPb, handler: pbsettingHandler);
|
||||
router.define(settingPbGithub, handler: pbsettingGithubHandler);
|
||||
|
||||
@@ -57,7 +57,6 @@ class DbProvider {
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
print('DataBase init Error >>>>>> $e');
|
||||
var file = File(path);
|
||||
file.deleteSync();
|
||||
}
|
||||
|
||||
42
lib/utils/extended.dart
Normal file
42
lib/utils/extended.dart
Normal file
@@ -0,0 +1,42 @@
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget defaultLoadStateChanged(ExtendedImageState state,
|
||||
{double iconSize = 16}) {
|
||||
switch (state.extendedImageLoadState) {
|
||||
case LoadState.loading:
|
||||
return Center(
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
child: CupertinoActivityIndicator(),
|
||||
),
|
||||
),
|
||||
);
|
||||
break;
|
||||
case LoadState.failed:
|
||||
return GestureDetector(
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
alignment: AlignmentDirectional.center,
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
Icons.error,
|
||||
size: iconSize,
|
||||
color: Colors.grey[600],
|
||||
)
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
state.reLoadImage();
|
||||
},
|
||||
);
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class MiniActivityIndicator {}
|
||||
223
lib/utils/image_preview.dart
Normal file
223
lib/utils/image_preview.dart
Normal file
@@ -0,0 +1,223 @@
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_picgo/model/uploaded.dart';
|
||||
import 'package:flutter_picgo/utils/extended.dart';
|
||||
import 'package:toast/toast.dart';
|
||||
|
||||
class ImagePreviewUtils {
|
||||
/// 打开图片预览页面
|
||||
static void open(BuildContext context, Uploaded content) {
|
||||
var page = GalleryPhotoViewWrapper(
|
||||
galleryItems: [content],
|
||||
);
|
||||
Navigator.push(
|
||||
context,
|
||||
Platform.isAndroid
|
||||
? TransparentMaterialPageRoute(builder: (_) => page)
|
||||
: TransparentCupertinoPageRoute(builder: (_) => page),
|
||||
);
|
||||
}
|
||||
|
||||
static void openMulti(BuildContext context, int index, List<Uploaded> items) {
|
||||
var page = GalleryPhotoViewWrapper(
|
||||
galleryItems: items,
|
||||
initialIndex: index,
|
||||
);
|
||||
Navigator.push(
|
||||
context,
|
||||
Platform.isAndroid
|
||||
? TransparentMaterialPageRoute(builder: (_) => page)
|
||||
: TransparentCupertinoPageRoute(builder: (_) => page));
|
||||
}
|
||||
}
|
||||
|
||||
class GalleryPhotoViewWrapper extends StatefulWidget {
|
||||
final int initialIndex;
|
||||
final List<Uploaded> galleryItems;
|
||||
|
||||
GalleryPhotoViewWrapper({
|
||||
this.initialIndex = 0,
|
||||
@required this.galleryItems,
|
||||
});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _GalleryPhotoViewWrapperState();
|
||||
}
|
||||
}
|
||||
|
||||
class _GalleryPhotoViewWrapperState extends State<GalleryPhotoViewWrapper> {
|
||||
int currentIndex;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
currentIndex = widget.initialIndex;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void onPageChanged(int index) {
|
||||
setState(() {
|
||||
currentIndex = index;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ExtendedImageSlidePage(
|
||||
slideAxis: SlideAxis.both,
|
||||
slideType: SlideType.onlyImage,
|
||||
slidePageBackgroundHandler: (offset, pageSize) =>
|
||||
defaultSlidePageBackgroundHandler(
|
||||
offset: offset,
|
||||
pageSize: pageSize,
|
||||
color: Colors.black,
|
||||
pageGestureAxis: SlideAxis.both),
|
||||
child: GestureDetector(
|
||||
child: Stack(
|
||||
// fit: StackFit.expand,
|
||||
alignment: Alignment.bottomRight,
|
||||
children: [
|
||||
ExtendedImageGesturePageView.builder(
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
var item = widget.galleryItems[index];
|
||||
Widget image = item.path.startsWith('http')
|
||||
? ExtendedImage.network(
|
||||
item.path,
|
||||
fit: BoxFit.contain,
|
||||
cache: true,
|
||||
mode: ExtendedImageMode.gesture,
|
||||
enableSlideOutPage: true,
|
||||
loadStateChanged: (state) =>
|
||||
defaultLoadStateChanged(state, iconSize: 50),
|
||||
)
|
||||
: ExtendedImage.file(
|
||||
File(item.path),
|
||||
fit: BoxFit.contain,
|
||||
mode: ExtendedImageMode.gesture,
|
||||
enableSlideOutPage: true,
|
||||
loadStateChanged: (state) =>
|
||||
defaultLoadStateChanged(state, iconSize: 50),
|
||||
);
|
||||
image = Container(
|
||||
child: image,
|
||||
);
|
||||
if (index == currentIndex) {
|
||||
return Hero(
|
||||
tag: index,
|
||||
child: image,
|
||||
);
|
||||
} else {
|
||||
return image;
|
||||
}
|
||||
},
|
||||
itemCount: widget.galleryItems.length,
|
||||
controller: PageController(
|
||||
initialPage: currentIndex,
|
||||
),
|
||||
onPageChanged: onPageChanged,
|
||||
scrollDirection: Axis.horizontal,
|
||||
),
|
||||
SafeArea(
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(right: 10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(4)),
|
||||
color: Colors.grey),
|
||||
padding: EdgeInsets.fromLTRB(5, 2, 5, 2),
|
||||
child: Text(
|
||||
'${currentIndex + 1} / ${widget.galleryItems.length}',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
decoration: TextDecoration.none,
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: 10),
|
||||
),
|
||||
))
|
||||
],
|
||||
),
|
||||
onLongPress: () {
|
||||
_showBottomPane();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 底部弹窗
|
||||
_showBottomPane() {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return SafeArea(
|
||||
child: Container(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(
|
||||
'图床类型',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
subtitle: Text(widget.galleryItems[currentIndex].type),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
'图片链接',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
subtitle: Text(widget.galleryItems[currentIndex].path),
|
||||
onTap: () {
|
||||
_handleCopy(
|
||||
widget.galleryItems[currentIndex].path, context);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
'图片信息',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
subtitle: Text(widget.galleryItems[currentIndex].info),
|
||||
onTap: () {
|
||||
_handleCopy(
|
||||
widget.galleryItems[currentIndex].info, context);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
'取消',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/// 复制链接
|
||||
_handleCopy(String content, BuildContext context) {
|
||||
Clipboard.setData(ClipboardData(text: content));
|
||||
Toast.show('已复制到剪切板', context);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
||||
Color defaultSlidePageBackgroundHandler(
|
||||
{Offset offset, Size pageSize, Color color, SlideAxis pageGestureAxis}) {
|
||||
double opacity = 0.0;
|
||||
if (pageGestureAxis == SlideAxis.both) {
|
||||
opacity = offset.distance /
|
||||
(Offset(pageSize.width, pageSize.height).distance / 2.0);
|
||||
} else if (pageGestureAxis == SlideAxis.horizontal) {
|
||||
opacity = offset.dx.abs() / (pageSize.width / 2.0);
|
||||
} else if (pageGestureAxis == SlideAxis.vertical) {
|
||||
opacity = offset.dy.abs() / (pageSize.height / 2.0);
|
||||
}
|
||||
return color.withOpacity(min(1.0, max(1.0 - opacity, 0.0)));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
|
||||
class LocalNotificationUtil {
|
||||
@@ -34,12 +33,12 @@ class LocalNotificationUtil {
|
||||
requestSoundPermission: false,
|
||||
onDidReceiveLocalNotification: null);
|
||||
var initializationSettings = InitializationSettings(
|
||||
android: initializationSettingsAndroid, iOS: initializationSettingsIOS, macOS: new MacOSInitializationSettings());
|
||||
android: initializationSettingsAndroid,
|
||||
iOS: initializationSettingsIOS,
|
||||
macOS: new MacOSInitializationSettings());
|
||||
await _flutterLocalNotificationsPlugin.initialize(initializationSettings,
|
||||
onSelectNotification: (String payload) async {
|
||||
if (payload != null) {
|
||||
debugPrint('notification payload: ' + payload);
|
||||
}
|
||||
if (payload != null) {}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -98,7 +97,9 @@ class LocalNotificationUtil {
|
||||
}
|
||||
|
||||
static NotificationDetails createNotificationDetails(
|
||||
AndroidNotificationDetails android, IOSNotificationDetails iOS, MacOSNotificationDetails macOS) {
|
||||
AndroidNotificationDetails android,
|
||||
IOSNotificationDetails iOS,
|
||||
MacOSNotificationDetails macOS) {
|
||||
return NotificationDetails(android: android, iOS: iOS, macOS: macOS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ class TcyunImageUpload implements ImageUploadStrategy {
|
||||
"q-sign-time": keyTime,
|
||||
"q-signature": TcyunApi.buildSignature(config.secretKey, keyTime, policy)
|
||||
});
|
||||
print(TcyunApi.buildSignature(config.secretKey, keyTime, policy));
|
||||
await TcyunApi.postObject(
|
||||
config.secretId,
|
||||
config.secretKey,
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:fluro/fluro.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_picgo/components/loading.dart';
|
||||
import 'package:flutter_picgo/model/uploaded.dart';
|
||||
import 'package:flutter_picgo/routers/application.dart';
|
||||
import 'package:flutter_picgo/routers/routers.dart';
|
||||
import 'package:flutter_picgo/utils/extended.dart';
|
||||
import 'package:flutter_picgo/utils/image_preview.dart';
|
||||
import 'package:flutter_picgo/utils/permission.dart';
|
||||
import 'package:flutter_picgo/views/album_page/album_page_presenter.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:toast/toast.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
|
||||
|
||||
class AlbumPage extends StatefulWidget {
|
||||
@override
|
||||
@@ -45,13 +48,8 @@ class _AlbumPageState extends State<AlbumPage> implements AlbumPageContract {
|
||||
floatingActionButton: FloatingActionButton(
|
||||
child: Icon(IconData(0xe639, fontFamily: 'iconfont')),
|
||||
onPressed: () async {
|
||||
var status = await PermissionUtils.requestPhotos();
|
||||
if (status == PermissionStatus.denied) {
|
||||
PermissionUtils.showPermissionDialog(context);
|
||||
return;
|
||||
}
|
||||
Application.router.navigateTo(context, Routes.upload,
|
||||
transition: TransitionType.cupertino);
|
||||
/// assets select
|
||||
handleSelect();
|
||||
},
|
||||
),
|
||||
body: SmartRefresher(
|
||||
@@ -112,70 +110,47 @@ class _AlbumPageState extends State<AlbumPage> implements AlbumPageContract {
|
||||
handleTap(index);
|
||||
},
|
||||
onLongPress: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('确定删除吗'),
|
||||
content: Text('删除后无法恢复'),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return NetLoadingDialog(
|
||||
outsideDismiss: false,
|
||||
loading: true,
|
||||
loadingText: "删除中...",
|
||||
requestCallBack: _presenter
|
||||
.doDeleteImage(_uploadeds[index]),
|
||||
);
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
handleLongPress(index);
|
||||
},
|
||||
child: Container(
|
||||
height: 150,
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadiusDirectional.circular(8)),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: _uploadeds[index].path,
|
||||
fit: BoxFit.cover,
|
||||
placeholder: (context, url) => Center(
|
||||
child: Container(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(),
|
||||
onDoubleTap: () {
|
||||
handleDoubleTap(index);
|
||||
},
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Container(
|
||||
height: 150,
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadiusDirectional.circular(8)),
|
||||
child: ExtendedImage.network(
|
||||
_uploadeds[index].path,
|
||||
height: 150,
|
||||
fit: BoxFit.cover,
|
||||
cache: true,
|
||||
border: Border.all(color: Colors.grey, width: 1.0),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
loadStateChanged: (state) =>
|
||||
defaultLoadStateChanged(state, iconSize: 30),
|
||||
),
|
||||
),
|
||||
errorWidget: (context, url, error) {
|
||||
return Container(
|
||||
color: Colors.grey,
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Icon(Icons.error),
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
'加载失败',
|
||||
style: TextStyle(fontSize: 12),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(4)),
|
||||
color: Colors.grey),
|
||||
padding: EdgeInsets.fromLTRB(5, 2, 5, 2),
|
||||
child: Text(
|
||||
_uploadeds[index].type,
|
||||
style: TextStyle(color: Colors.white, fontSize: 10),
|
||||
),
|
||||
),
|
||||
right: 10,
|
||||
top: 10,
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -220,12 +195,65 @@ class _AlbumPageState extends State<AlbumPage> implements AlbumPageContract {
|
||||
_presenter.doLoadUploadedImages(_perPageItemSize, _currentPage += 1);
|
||||
}
|
||||
|
||||
/// 处理图片点击
|
||||
/// 处理图片点击事件
|
||||
handleTap(int index) {
|
||||
ImagePreviewUtils.openMulti(context, index, _uploadeds);
|
||||
}
|
||||
|
||||
/// 处理图片双击
|
||||
handleDoubleTap(int index) {
|
||||
Clipboard.setData(ClipboardData(text: _uploadeds[index].path));
|
||||
Toast.show('已复制到剪切板', context);
|
||||
}
|
||||
|
||||
/// 处理图片长按事件
|
||||
handleLongPress(int index) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('确定删除吗'),
|
||||
content: Text('删除后无法恢复'),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return NetLoadingDialog(
|
||||
outsideDismiss: false,
|
||||
loading: true,
|
||||
loadingText: "删除中...",
|
||||
requestCallBack:
|
||||
_presenter.doDeleteImage(_uploadeds[index]),
|
||||
);
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// 处理选择图片
|
||||
handleSelect() async {
|
||||
var status = await PermissionUtils.requestPhotos();
|
||||
if (status == PermissionStatus.denied) {
|
||||
PermissionUtils.showPermissionDialog(context);
|
||||
return;
|
||||
}
|
||||
final List<AssetEntity> assets = await AssetPicker.pickAssets(context);
|
||||
if (assets != null && assets.length > 0) {
|
||||
Application.router.navigateTo(context, Routes.handleUpload,
|
||||
transition: TransitionType.cupertino,
|
||||
routeSettings: RouteSettings(arguments: assets));
|
||||
} else {
|
||||
Toast.show('您已取消选择', context);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void loadUploadedImages(List<Uploaded> uploadeds) {
|
||||
setState(() {
|
||||
|
||||
@@ -27,7 +27,6 @@ class AlbumPagePresenter {
|
||||
}).toList();
|
||||
_view.loadUploadedImages(uploadeds);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
_view.loadError();
|
||||
}
|
||||
}
|
||||
@@ -43,7 +42,6 @@ class AlbumPagePresenter {
|
||||
_view.deleteError('删除出错,请重试');
|
||||
}
|
||||
} catch (e) {
|
||||
print(e);
|
||||
_view.deleteError('删除出错,请重试 Error >>> $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ class QiniuRepoPagePresenter {
|
||||
'delimiter': Uri.decodeComponent('/'),
|
||||
}, config.accessKey, config.secretKey);
|
||||
List data = (result['items'] as List<dynamic>).map((e) {
|
||||
print(e);
|
||||
QiniuContent c = QiniuContent.fromJson(e);
|
||||
c.type = FileContentType.FILE;
|
||||
c.url = pathlib.joinAll([
|
||||
@@ -49,16 +48,15 @@ class QiniuRepoPagePresenter {
|
||||
QiniuContent c = QiniuContent();
|
||||
c.type = FileContentType.DIR;
|
||||
c.url = element;
|
||||
|
||||
/// 例如 xin/ax 去除 xin/ 只显示最后一个 ax
|
||||
List<String> keys = '$element'.split('/');
|
||||
print(keys);
|
||||
c.key = keys[keys.length -2];
|
||||
c.key = keys[keys.length - 2];
|
||||
data.add(c);
|
||||
});
|
||||
}
|
||||
_view.loadSuccess(data);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
_view.loadError('$e');
|
||||
}
|
||||
}
|
||||
@@ -71,19 +69,19 @@ class QiniuRepoPagePresenter {
|
||||
_view.loadError('读取配置文件错误');
|
||||
return false;
|
||||
}
|
||||
String encodedEntryURI = QiniuApi.urlSafeBase64Encode(
|
||||
utf8.encode('${config.bucket}:$key'));
|
||||
String url = '${QiniuApi.BASE_URL}/delete/$encodedEntryURI';
|
||||
var result = await QiniuApi.delete(url, config.accessKey, config.secretKey);
|
||||
if (isBlank(result.toString())) {
|
||||
return true;
|
||||
} else {
|
||||
_view.loadError('${result['error']}');
|
||||
return false;
|
||||
}
|
||||
String encodedEntryURI =
|
||||
QiniuApi.urlSafeBase64Encode(utf8.encode('${config.bucket}:$key'));
|
||||
String url = '${QiniuApi.BASE_URL}/delete/$encodedEntryURI';
|
||||
var result =
|
||||
await QiniuApi.delete(url, config.accessKey, config.secretKey);
|
||||
if (isBlank(result.toString())) {
|
||||
return true;
|
||||
} else {
|
||||
_view.loadError('${result['error']}');
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_picgo/model/pb_setting.dart';
|
||||
import 'package:flutter_picgo/resources/table_name_keys.dart';
|
||||
import 'package:flutter_picgo/utils/image_upload.dart';
|
||||
@@ -35,7 +34,6 @@ class PBSettingPagePresenter {
|
||||
}).toList();
|
||||
_view.loadPb(realList);
|
||||
} catch (e) {
|
||||
debugPrint('Error >>>> $e');
|
||||
_view.loadError('${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:fluro/fluro.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
@@ -120,10 +121,6 @@ class _PicGoSettingPageState extends State<PicGoSettingPage> {
|
||||
transition: TransitionType.cupertino);
|
||||
},
|
||||
),
|
||||
// ListTile(
|
||||
// title: Text('设置显示图床'),
|
||||
// onTap: () {},
|
||||
// ),
|
||||
ListTile(
|
||||
title: Text('版本更新'),
|
||||
onTap: () {
|
||||
@@ -141,6 +138,12 @@ class _PicGoSettingPageState extends State<PicGoSettingPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
title: Text('清除缓存'),
|
||||
onTap: () {
|
||||
_handleClearCache();
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
@@ -159,7 +162,6 @@ class _PicGoSettingPageState extends State<PicGoSettingPage> {
|
||||
Response res = await PicgoApi.getLatestVersion();
|
||||
PackageInfo info = await PackageInfo.fromPlatform();
|
||||
int version = int.parse(info.buildNumber);
|
||||
debugPrint('$version');
|
||||
int remoteVersion = 0;
|
||||
if (Platform.isAndroid) {
|
||||
remoteVersion = int.parse('${res.data["Android"]["versionCode"]}');
|
||||
@@ -182,4 +184,19 @@ class _PicGoSettingPageState extends State<PicGoSettingPage> {
|
||||
launch('https://apps.apple.com/cn/app/flutter-picgo/id1519714305');
|
||||
}
|
||||
}
|
||||
|
||||
/// 清空缓存
|
||||
_handleClearCache() async {
|
||||
/// extended_image
|
||||
try {
|
||||
bool clear = await clearDiskCachedImages();
|
||||
if (clear) {
|
||||
Toast.show('清除成功', context);
|
||||
} else {
|
||||
throw ('clear fail');
|
||||
}
|
||||
} catch (e) {
|
||||
Toast.show('清除失败', context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
194
lib/views/upload_page/handle_upload_page.dart
Normal file
194
lib/views/upload_page/handle_upload_page.dart
Normal file
@@ -0,0 +1,194 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter_picgo/components/upload_item/upload_item.dart';
|
||||
import 'package:flutter_picgo/utils/strings.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_picgo/resources/shared_preferences_keys.dart';
|
||||
import 'package:flutter_picgo/utils/image_upload.dart';
|
||||
import 'package:flutter_picgo/utils/shared_preferences.dart';
|
||||
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
|
||||
|
||||
class HandleUploadPage extends StatefulWidget {
|
||||
final List<AssetEntity> assets;
|
||||
|
||||
HandleUploadPage(this.assets, {Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_HandleUploadPageState createState() => _HandleUploadPageState();
|
||||
}
|
||||
|
||||
class _HandleUploadPageState extends State<HandleUploadPage> {
|
||||
String _title = '';
|
||||
bool isParse = false;
|
||||
List<File> files;
|
||||
List<String> filesName;
|
||||
|
||||
TextEditingController _controller = new TextEditingController();
|
||||
|
||||
/// 通知提示
|
||||
bool needNotify = false;
|
||||
|
||||
_HandleUploadPageState() {
|
||||
SpUtil.getInstance().then((sp) {
|
||||
this.needNotify =
|
||||
sp.getBool(SharedPreferencesKeys.settingIsUploadedTip) ?? false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_getCurrentPb();
|
||||
_parseAsset();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(this._title),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: isParse ? buildList() : buildParseTip(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildList() {
|
||||
return Column(
|
||||
children: buildUploadItem(),
|
||||
);
|
||||
}
|
||||
|
||||
List<UploadItem> buildUploadItem() {
|
||||
if (files == null || files.length <= 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
List<UploadItem> items = [];
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
items.add(new UploadItem(
|
||||
files[i],
|
||||
filesName[i],
|
||||
needNotify: needNotify,
|
||||
));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
Widget buildParseTip() {
|
||||
return Center(
|
||||
child: SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
backgroundColor: Colors.transparent,
|
||||
valueColor: AlwaysStoppedAnimation(Colors.blue),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_getCurrentPb() async {
|
||||
String pbType = await ImageUploadUtils.getDefaultPB();
|
||||
String name = await ImageUploadUtils.getPBName(pbType);
|
||||
setState(() {
|
||||
this._title = '图片上传 - $name';
|
||||
});
|
||||
}
|
||||
|
||||
_parseAsset() async {
|
||||
if (widget.assets != null && widget.assets.length > 0) {
|
||||
files = [];
|
||||
filesName = [];
|
||||
File tmp;
|
||||
|
||||
/// 将Assets文件转换成File
|
||||
for (int i = 0; i < widget.assets.length; i++) {
|
||||
tmp = await widget.assets[i].originFile;
|
||||
files.add(tmp);
|
||||
filesName.add(path.basename(tmp.path));
|
||||
}
|
||||
|
||||
var sp = await SpUtil.getInstance();
|
||||
|
||||
var settingIsTimestampRename =
|
||||
sp.getBool(SharedPreferencesKeys.settingIsTimestampRename) ?? false;
|
||||
|
||||
if (settingIsTimestampRename) {
|
||||
int timestamp = new DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
/// 处理时间戳命名
|
||||
for (int i = 0; i < widget.assets.length; i++) {
|
||||
/// 获取图片名
|
||||
String suffix = path.extension(tmp.path);
|
||||
|
||||
/// replace
|
||||
filesName[i] = '${timestamp + i}$suffix';
|
||||
}
|
||||
}
|
||||
var settingIsUploadedRename =
|
||||
sp.getBool(SharedPreferencesKeys.settingIsUploadedRename) ?? false;
|
||||
|
||||
if (settingIsUploadedRename) {
|
||||
String content = filesName.join('\n');
|
||||
|
||||
/// 处理默认文本内容
|
||||
_controller.text = content;
|
||||
|
||||
/// 处理重命名
|
||||
await showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Center(
|
||||
child: Text('重命名图片,多张图片时以换行符分隔'),
|
||||
),
|
||||
content: Container(
|
||||
padding: EdgeInsets.only(left: 4, right: 4),
|
||||
child: TextField(
|
||||
textInputAction: TextInputAction.newline,
|
||||
controller: _controller,
|
||||
scrollPadding: EdgeInsets.zero,
|
||||
maxLines: null,
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
_handleTextFieldContent(_controller.text.trim());
|
||||
}),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
_parseAssetsSuccess();
|
||||
}
|
||||
} else {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
|
||||
_handleTextFieldContent(String content) {
|
||||
List<String> splits = content.split('\n');
|
||||
if (splits != null && splits.length >= widget.assets.length) {
|
||||
/// 处理内容是否正确
|
||||
for (int i = 0; i < widget.assets.length; i++) {
|
||||
if (!isBlank(splits[i])) {
|
||||
/// 不为空,则再覆盖
|
||||
filesName[i] = splits[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
_parseAssetsSuccess();
|
||||
}
|
||||
|
||||
_parseAssetsSuccess() {
|
||||
setState(() {
|
||||
isParse = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,350 +0,0 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_picgo/components/loading.dart';
|
||||
import 'package:flutter_picgo/utils/local_notification.dart';
|
||||
import 'package:flutter_picgo/utils/permission.dart';
|
||||
import 'package:flutter_picgo/utils/shared_preferences.dart';
|
||||
import 'package:flutter_picgo/utils/strings.dart';
|
||||
import 'package:flutter_picgo/views/upload_page/upload_page_presenter.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:toast/toast.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class UploadPage extends StatefulWidget {
|
||||
_UploadPageState createState() => _UploadPageState();
|
||||
}
|
||||
|
||||
class _UploadPageState extends State<UploadPage>
|
||||
with WidgetsBindingObserver
|
||||
implements UploadPageContract {
|
||||
String _title = '';
|
||||
String _previewPath = '';
|
||||
String _renameImage = '';
|
||||
String _clipUrl = '';
|
||||
TextEditingController _controller;
|
||||
// 默认不选中则不复制
|
||||
int _selectButton = 0;
|
||||
|
||||
// 通知提示
|
||||
bool needNotify = false;
|
||||
|
||||
// 按钮id
|
||||
static const MARKDOWN = 1;
|
||||
static const HTML = 2;
|
||||
static const URL = 3;
|
||||
|
||||
UploadPagePresenter _presenter;
|
||||
final picker = ImagePicker();
|
||||
|
||||
_UploadPageState() {
|
||||
_presenter = UploadPagePresenter(this);
|
||||
SpUtil.getInstance().then((sp) {
|
||||
this.needNotify =
|
||||
sp.getBool(SharedPreferencesKeys.settingIsUploadedTip) ?? false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// 加载当前图床的名称
|
||||
_presenter.doLoadCurrentPB();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(this._title),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: uploadView(context),
|
||||
);
|
||||
}
|
||||
|
||||
Widget uploadView(BuildContext context) {
|
||||
return ListView(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
margin: EdgeInsets.all(10.0),
|
||||
height: 250.0,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Theme.of(context).accentColor,
|
||||
),
|
||||
),
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
SizedBox.expand(
|
||||
child: this._previewPath == ''
|
||||
? Center()
|
||||
: Image.file(new File(this._previewPath),
|
||||
fit: BoxFit.cover),
|
||||
),
|
||||
SizedBox.expand(
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
IconData(0xe639, fontFamily: 'iconfont'),
|
||||
size: 50,
|
||||
color: Theme.of(context).accentColor,
|
||||
),
|
||||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
tooltip: "上传",
|
||||
onPressed: () {
|
||||
_getImage();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'图片预览 - ${isBlank(this._previewPath) ? "暂未选择图片" : this._renameImage}',
|
||||
maxLines: 1,
|
||||
textWidthBasis: TextWidthBasis.parent,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: RaisedButton(
|
||||
color: this._selectButton == MARKDOWN
|
||||
? Theme.of(context).accentColor
|
||||
: Colors.white,
|
||||
textColor: this._selectButton == MARKDOWN
|
||||
? Colors.white
|
||||
: Colors.black,
|
||||
child: Text('Markdown'),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
this._selectButton = MARKDOWN;
|
||||
setClipData();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: RaisedButton(
|
||||
color: this._selectButton == HTML
|
||||
? Theme.of(context).accentColor
|
||||
: Colors.white,
|
||||
textColor:
|
||||
this._selectButton == HTML ? Colors.white : Colors.black,
|
||||
child: Text('HTML'),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
this._selectButton = HTML;
|
||||
setClipData();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: RaisedButton(
|
||||
color: this._selectButton == URL
|
||||
? Theme.of(context).accentColor
|
||||
: Colors.white,
|
||||
textColor:
|
||||
this._selectButton == URL ? Colors.white : Colors.black,
|
||||
child: Text('URL'),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
this._selectButton = URL;
|
||||
setClipData();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Container(
|
||||
child: Center(
|
||||
child: Text('点击上传后可获取的对应选中的链接格式到剪切板,可点击切换', maxLines: 2),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Container(
|
||||
height: 40,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 10, right: 10),
|
||||
child: RaisedButton(
|
||||
color: Theme.of(context).accentColor,
|
||||
textColor: Colors.white,
|
||||
child: Text('上传'),
|
||||
onPressed: () {
|
||||
if (this._previewPath == null || this._previewPath == '') {
|
||||
_getImage();
|
||||
return;
|
||||
}
|
||||
_uploadImage();
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// 获取图片
|
||||
_getImage() async {
|
||||
var status = await PermissionUtils.requestPhotos();
|
||||
if (status == PermissionStatus.denied) {
|
||||
PermissionUtils.showPermissionDialog(context);
|
||||
return;
|
||||
}
|
||||
// 获取图片
|
||||
try {
|
||||
final pickedFile = await picker.getImage(source: ImageSource.gallery);
|
||||
if (pickedFile != null) {
|
||||
var sp = await SpUtil.getInstance();
|
||||
var settingIsTimestampRename =
|
||||
sp.getBool(SharedPreferencesKeys.settingIsTimestampRename) ?? false;
|
||||
var settingIsUploadedRename =
|
||||
sp.getBool(SharedPreferencesKeys.settingIsUploadedRename) ?? false;
|
||||
|
||||
/// 获取文件后缀
|
||||
String suffix = path.extension(pickedFile.path);
|
||||
String filename = path.basenameWithoutExtension(pickedFile.path);
|
||||
_renameImage = settingIsTimestampRename
|
||||
? '${new DateTime.now().millisecondsSinceEpoch.toString()}$suffix'
|
||||
: '$filename$suffix';
|
||||
if (settingIsUploadedRename) {
|
||||
_controller = TextEditingController(text: _renameImage);
|
||||
await showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Center(
|
||||
child: Text('重命名图片'),
|
||||
),
|
||||
content: Padding(
|
||||
padding: EdgeInsets.only(left: 4, right: 4),
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
this._renameImage = _controller.text;
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
setState(() {
|
||||
this._previewPath = pickedFile.path;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// 上传图片
|
||||
_uploadImage() {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return NetLoadingDialog(
|
||||
loading: true,
|
||||
loadingText: "上传中",
|
||||
requestCallBack: _presenter.doUploadImage(
|
||||
new File(this._previewPath), _renameImage),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
loadCurrentPB(String pbname) {
|
||||
setState(() {
|
||||
this._title = '图片上传 - $pbname';
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
uploadFaild(String errorMsg) async {
|
||||
if (needNotify) {
|
||||
await _showNotification(0, '上传失败:$errorMsg');
|
||||
}
|
||||
Toast.show(errorMsg ?? '', context);
|
||||
}
|
||||
|
||||
/// 设置剪切板
|
||||
setClipData([bool needShowTip = true]) {
|
||||
if (isBlank(_clipUrl)) {
|
||||
Toast.show('暂无可获取图片', context);
|
||||
return;
|
||||
}
|
||||
String cliptext;
|
||||
switch (_selectButton) {
|
||||
case MARKDOWN:
|
||||
{
|
||||
cliptext = '';
|
||||
}
|
||||
break;
|
||||
case HTML:
|
||||
{
|
||||
cliptext = '<img src="$_clipUrl">';
|
||||
}
|
||||
break;
|
||||
case URL:
|
||||
{
|
||||
cliptext = _clipUrl;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
//statements;
|
||||
cliptext = '';
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!isBlank(cliptext)) {
|
||||
Clipboard.setData(ClipboardData(text: cliptext));
|
||||
}
|
||||
if (needShowTip) {
|
||||
Toast.show('已复制到剪切板', context);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
uploadSuccess(String imageUrl) async {
|
||||
if (needNotify) {
|
||||
await _showNotification(1, '上传成功, 图片链接:$imageUrl');
|
||||
}
|
||||
this._clipUrl = imageUrl;
|
||||
setClipData(false);
|
||||
Toast.show('上传成功,图片链接为:$imageUrl', context);
|
||||
}
|
||||
|
||||
Future<void> _showNotification(int id, String body) async {
|
||||
LocalNotificationUtil.getInstance().show(
|
||||
id,
|
||||
'上传提示',
|
||||
body,
|
||||
LocalNotificationUtil.createNotificationDetails(
|
||||
LocalNotificationUtil.uploadAndroidChannel(),
|
||||
LocalNotificationUtil.normalIOSNotificationDetails(),
|
||||
LocalNotificationUtil.normalMacOSNotificationDetails()
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -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.9.1+22
|
||||
version: 1.9.2+24
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
@@ -28,11 +28,8 @@ dependencies:
|
||||
package_info: ^0.4.1
|
||||
sqflite: ^1.3.2+1
|
||||
fluro: ^1.7.7
|
||||
event_bus: ^1.1.1
|
||||
toast: ^0.1.5
|
||||
image_picker: ^0.6.7+2
|
||||
json_serializable: ^3.3.0
|
||||
cached_network_image: ^2.2.0+1
|
||||
url_launcher: ^5.7.10
|
||||
permission_handler: ^5.0.1
|
||||
barcode_scan: ^3.0.1
|
||||
@@ -41,6 +38,8 @@ dependencies:
|
||||
flutter_local_notifications: ^3.0.1+4
|
||||
pull_to_refresh: ^1.6.2
|
||||
characters: ^1.0.0
|
||||
wechat_assets_picker: ^4.2.2
|
||||
extended_image: ^1.5.0
|
||||
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
|
||||
@@ -24,11 +24,7 @@ main() {
|
||||
'Date': HttpDate.format(new DateTime.now()),
|
||||
}, contentType: 'application/x-www-form-urlencoded'),
|
||||
);
|
||||
|
||||
print(res.data);
|
||||
} on DioError catch (e) {
|
||||
print(e.response.data);
|
||||
}
|
||||
} on DioError catch (e) {}
|
||||
});
|
||||
|
||||
test('测试FormData提交图片', () async {
|
||||
@@ -57,10 +53,6 @@ main() {
|
||||
'file': await MultipartFile.fromFile(pathname, filename: 'logo.png')
|
||||
}),
|
||||
options: Options(contentType: Headers.formUrlEncodedContentType));
|
||||
|
||||
print(res.data);
|
||||
} on DioError catch (e) {
|
||||
print(e.response.data);
|
||||
}
|
||||
} on DioError catch (e) {}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,12 +4,10 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
main() {
|
||||
test('测试UpToken生成', () {
|
||||
String policy = QiniuApi.generatePutPolicy('image', 'test.png');
|
||||
print(policy);
|
||||
var token = QiniuApi.generateUpToken(
|
||||
'CRd7Wa4PuSGvs4ArToPTLBMCigGGUY3sk3F8oc8W',
|
||||
'f2Jkrlyea5s8h8gLEToa9-k895GNM-BlmQ2RfxwU',
|
||||
policy);
|
||||
print('UpToken : $token');
|
||||
});
|
||||
|
||||
test('测试AuthToken生成', () {
|
||||
@@ -22,7 +20,6 @@ main() {
|
||||
null,
|
||||
'MY_ACCESS_KEY',
|
||||
'MY_SECRET_KEY');
|
||||
print('Access Token : $token');
|
||||
expect(token, 'MY_ACCESS_KEY:1uLvuZM6l6oCzZFqkJ6oI4oFMVQ=');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,13 +5,9 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
main() {
|
||||
test('测试生成 KeyTime', () {
|
||||
print(TcyunApi.buildKeyTime());
|
||||
});
|
||||
test('测试生成 KeyTime', () {});
|
||||
|
||||
test('测试生成 SignKey', () {
|
||||
print(TcyunApi.buildSignKey('adsadaads', TcyunApi.buildKeyTime()));
|
||||
});
|
||||
test('测试生成 SignKey', () {});
|
||||
|
||||
test('测试Api 签名', () async {
|
||||
try {
|
||||
@@ -21,20 +17,16 @@ main() {
|
||||
'test-1253954259',
|
||||
'ap-nanjing',
|
||||
'wallhaven-2e9j79.jpg');
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
} catch (e) {}
|
||||
});
|
||||
|
||||
test('PostObjecy 提交', () async {
|
||||
try {
|
||||
String pathname = path.joinAll(
|
||||
[Directory.current.path, '..\\assets\\' 'images', 'logo.png']);
|
||||
print(pathname);
|
||||
String keyTime = TcyunApi.buildKeyTime();
|
||||
String policy = TcyunApi.buildPolicy('ap-nanjing', 'logo.png',
|
||||
'AKIDvb0B9rqfeOr44kt2ar46rO2cwzl6JwUk', keyTime);
|
||||
print(policy);
|
||||
// TcyunApi.postObject(
|
||||
// 'test-1253954259',
|
||||
// 'ap-nanjing',
|
||||
@@ -51,8 +43,6 @@ main() {
|
||||
// "q-signature": TcyunApi.buildSignature(
|
||||
// 'KOEoR1LL5apX1lFRN4VgZB0nJgmdEbie', keyTime, policy)
|
||||
// }));
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
} catch (e) {}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user