forked from lxm_tools/flutter-picgo
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
184e97d826 | ||
|
|
a8293a72bd | ||
|
|
34d098bc5d | ||
|
|
2f115368cb | ||
|
|
e63d57c9d1 | ||
|
|
d06a09f2d1 | ||
|
|
3827337427 | ||
|
|
9fbcb09bb4 | ||
|
|
134020d37d | ||
|
|
64bfc9915f | ||
|
|
1f7bda48b2 | ||
|
|
43f0da9af9 | ||
|
|
b01bf49a0f | ||
|
|
fbb877e12f | ||
|
|
a9b70bc259 | ||
|
|
9680e1660f | ||
|
|
04b41548fe | ||
|
|
5c3eecf284 | ||
|
|
be70cc70e1 | ||
|
|
479fa4700c | ||
|
|
105ff1d806 |
57
README.md
57
README.md
@@ -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>
|
||||
|
||||
@@ -39,9 +39,9 @@ Flutter-PicGo: 一个用于快速上传图片并获取图片URL链接的**手机
|
||||
|
||||
# 应用截图
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
<img src="https://github.static.si-yee.com/picgo/repo_use.gif" width="300px" />
|
||||
|
||||
# 下载安装
|
||||
|
||||
@@ -56,9 +56,51 @@ Flutter-PicGo: 一个用于快速上传图片并获取图片URL链接的**手机
|
||||
|
||||
目前仅支持iOS与Android端,由于部分插件例如[sqflite](https://pub.dev/packages/sqflite)不支持Web端,所以应用也并不支持Web端。
|
||||
|
||||
# 注意事项
|
||||
# F & Q
|
||||
|
||||
- [注意事项](https://github.com/PicGo/flutter-picgo/blob/dev/docs/注意事项.md)
|
||||
## 简单使用说明
|
||||
|
||||
**上传前需要先去`设置` -> `图床设置`下设置图床的配置信息并设置默认上传图床,以及给予App所申请的权限(相册),否则无法进行上传。**
|
||||
|
||||
## 已不可用图床
|
||||
|
||||
- 牛图网(官网也无法使用)
|
||||
|
||||
## 关于Github图片上传问题
|
||||
|
||||
由于国内访问Github访问速度慢的原因,API访问也会经常出错,建议切换别的图床进行使用。
|
||||
|
||||
或者配置host提升访问速度,这里提供一种方式:
|
||||
|
||||
<img src="https://raw.githubusercontent.com/hackycy/flutter-picgo/dev/docs/hostconfig.jpeg" width="200px" />
|
||||
|
||||
在路由器(图中为小米的路由器)里面配置hosts,具体配置可以查看[Github520](https://github.com/521xueweihan/GitHub520)。
|
||||
|
||||
路由器配置hosts后连接Wi-Fi可以显著提升API的访问能力。
|
||||
|
||||
## 将配置信息转二维码供App扫码
|
||||
|
||||
这里拿Github举例:
|
||||
|
||||
GitHub的配置JSON(与桌面版Picgo配置信息一致)如下
|
||||
|
||||
``` json
|
||||
{
|
||||
"github": {
|
||||
"branch": "",
|
||||
"customUrl": "",
|
||||
"path": "",
|
||||
"repo": "",
|
||||
"token": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
想要获取其它的配置信息可以在App随便填一下然后再导出配置,复制粘贴出来填写好配置信息,将这整段json去转换成二维码保存,例如[草料](https://cli.im)。在App扫码就能直接转换好配置了,不用再一项一项的填写。
|
||||
|
||||
> 已经使用过桌面版[PicGo](https://github.com/Molunerfinn/PicGo)则更加方便,直接使用桌面版导出二维码即可。
|
||||
>
|
||||
> 暂不支持备份图床已上传的图片。
|
||||
|
||||
# 有问题或者有更好的建议
|
||||
|
||||
@@ -68,8 +110,9 @@ Flutter-PicGo: 一个用于快速上传图片并获取图片URL链接的**手机
|
||||
|
||||
# 相关
|
||||
|
||||
- [PicGo](https://github.com/Molunerfinn/PicGo) : PicGo 的桌面版
|
||||
- [PicGo](https://github.com/Molunerfinn/PicGo):PicGo 的桌面版
|
||||
- [vs-picgo](https://github.com/PicGo/vs-picgo):PicGo 的 VS Code 版。
|
||||
- [sf-nest-admin](https://github.com/hackycy/sf-nest-admin):基于NestJs编写的带七牛文件管理的后台权限系统
|
||||
|
||||
# 致谢
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"iOS": {
|
||||
"versionName": "1.9.1",
|
||||
"versionCode": "22"
|
||||
"versionName": "1.9.2",
|
||||
"versionCode": "24"
|
||||
},
|
||||
"Android": {
|
||||
"versionName": "1.9.1",
|
||||
"versionCode": "22"
|
||||
"versionName": "1.9.2",
|
||||
"versionCode": "24"
|
||||
}
|
||||
}
|
||||
17
docs/注意事项.md
17
docs/注意事项.md
@@ -1,17 +0,0 @@
|
||||
|
||||
|
||||
### 功能建议或BUG提交
|
||||
|
||||
> 请尽量在Github页面中发起[issue](https://github.com/PicGo/flutter-picgo/issues),否则在其他地方比较难以管理和收集建议。
|
||||
|
||||
### 关于Github图片上传问题
|
||||
|
||||
> 由于国内访问Github慢的原因,API访问也会经常出错,建议切换别的图床进行使用。
|
||||
>
|
||||
> 或者配置host提升访问速度,这里提供一种方式:
|
||||
>
|
||||
> 
|
||||
>
|
||||
> 在路由器里面配置hosts,具体配置可以查看[Github520](https://github.com/521xueweihan/GitHub520)。
|
||||
>
|
||||
> 路由器配置hosts后连接Wi-Fi可以显著提升API的访问能力。
|
||||
@@ -144,7 +144,10 @@ class QiniuApi {
|
||||
/// 七牛管理验签拦截器
|
||||
class QiniuInterceptor extends InterceptorsWrapper {
|
||||
@override
|
||||
Future onRequest(RequestOptions options) async {
|
||||
Future onRequest(
|
||||
RequestOptions options,
|
||||
RequestInterceptorHandler handler,
|
||||
) async {
|
||||
if (options.path.contains(QiniuApi.BASE_URL)) {
|
||||
String ak = '${options.extra[QiniuApi.accessKey]}';
|
||||
String sk = '${options.extra[QiniuApi.secretKey]}';
|
||||
@@ -171,6 +174,6 @@ class QiniuInterceptor extends InterceptorsWrapper {
|
||||
'Authorization': 'QBox $accessToken',
|
||||
});
|
||||
}
|
||||
return options;
|
||||
return handler.next(options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,10 @@ class TcyunApi {
|
||||
/// TcYun验签拦截器
|
||||
class TcyunInterceptor extends InterceptorsWrapper {
|
||||
@override
|
||||
Future onRequest(RequestOptions options) async {
|
||||
Future onRequest(
|
||||
RequestOptions options,
|
||||
RequestInterceptorHandler handler,
|
||||
) async {
|
||||
if (options.path.contains(TcyunApi.BASE_URL)) {
|
||||
/// 生成 KeyTime
|
||||
var keytime = TcyunApi.buildKeyTime();
|
||||
@@ -166,6 +169,6 @@ class TcyunInterceptor extends InterceptorsWrapper {
|
||||
headers.addAll({'Authorization': realSign});
|
||||
options.headers = headers;
|
||||
}
|
||||
return options;
|
||||
return handler.next(options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,10 @@ class UpyunApi {
|
||||
|
||||
class UpyunInterceptor extends InterceptorsWrapper {
|
||||
@override
|
||||
Future onRequest(RequestOptions options) async {
|
||||
Future onRequest(
|
||||
RequestOptions options,
|
||||
RequestInterceptorHandler handler,
|
||||
) async {
|
||||
if (options.path.contains(UpyunApi.BASE_URL.replaceFirst('http://', ''))) {
|
||||
/// 请求方式,如:GET、POST、PUT、HEAD 等
|
||||
String method = options.method.toUpperCase();
|
||||
@@ -90,6 +93,6 @@ class UpyunInterceptor extends InterceptorsWrapper {
|
||||
'Authorization': 'UPYUN $operator:$realAuth',
|
||||
});
|
||||
}
|
||||
return options;
|
||||
return handler.next(options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,14 +83,14 @@ class ManageItem extends StatelessWidget {
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadiusDirectional.circular(2)),
|
||||
borderRadius: BorderRadiusDirectional.circular(8)),
|
||||
child: ExtendedImage.network(
|
||||
this.url,
|
||||
width: 50,
|
||||
height: 50,
|
||||
fit: BoxFit.cover,
|
||||
cache: true,
|
||||
border: Border.all(color: Colors.grey, width: 1.0),
|
||||
// border: Border.all(color: Colors.grey, width: 1.0),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
loadStateChanged: (state) => defaultLoadStateChanged(state),
|
||||
),
|
||||
|
||||
@@ -63,13 +63,13 @@ class _UploadItemState extends State<UploadItem> implements UploadItemContract {
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadiusDirectional.circular(2)),
|
||||
borderRadius: BorderRadiusDirectional.circular(8)),
|
||||
child: ExtendedImage.file(
|
||||
File(widget.file.path),
|
||||
width: 50,
|
||||
height: 50,
|
||||
fit: BoxFit.cover,
|
||||
border: Border.all(color: Colors.grey, width: 1.0),
|
||||
// border: Border.all(color: Colors.grey, width: 1.0),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
loadStateChanged: (state) => defaultLoadStateChanged(state),
|
||||
),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
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';
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ 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/handle_upload_page.dart';
|
||||
import 'package:flutter_picgo/views/upload_page/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';
|
||||
@@ -56,11 +55,6 @@ 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>;
|
||||
|
||||
@@ -50,7 +50,6 @@ 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);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_picgo/resources/pb_type_keys.dart';
|
||||
import 'package:flutter_picgo/resources/table_name_keys.dart';
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
|
||||
@@ -2,28 +2,28 @@ import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
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/model/uploaded.dart';
|
||||
import 'package:flutter_picgo/utils/extended.dart';
|
||||
import 'package:toast/toast.dart';
|
||||
|
||||
class ImagePreviewUtils {
|
||||
/// 打开图片预览页面
|
||||
static void open(BuildContext context, String content) {
|
||||
var item = new GalleryItem(id: '0', resource: '$content');
|
||||
static void open(BuildContext context, Uploaded content) {
|
||||
var page = GalleryPhotoViewWrapper(
|
||||
galleryItems: [item],
|
||||
galleryItems: [content],
|
||||
);
|
||||
Navigator.push(
|
||||
context,
|
||||
Platform.isAndroid
|
||||
? TransparentMaterialPageRoute(builder: (_) => page)
|
||||
: TransparentCupertinoPageRoute(builder: (_) => page),
|
||||
? MaterialPageRoute(builder: (_) => page)
|
||||
: CupertinoPageRoute(builder: (_) => page),
|
||||
);
|
||||
}
|
||||
|
||||
static void openMulti(
|
||||
BuildContext context, int index, List<GalleryItem> items) {
|
||||
static void openMulti(BuildContext context, int index, List<Uploaded> items) {
|
||||
var page = GalleryPhotoViewWrapper(
|
||||
galleryItems: items,
|
||||
initialIndex: index,
|
||||
@@ -31,21 +31,14 @@ class ImagePreviewUtils {
|
||||
Navigator.push(
|
||||
context,
|
||||
Platform.isAndroid
|
||||
? TransparentMaterialPageRoute(builder: (_) => page)
|
||||
: TransparentCupertinoPageRoute(builder: (_) => page));
|
||||
? MaterialPageRoute(builder: (_) => page)
|
||||
: CupertinoPageRoute(builder: (_) => page));
|
||||
}
|
||||
}
|
||||
|
||||
class GalleryItem {
|
||||
GalleryItem({this.id, this.resource});
|
||||
|
||||
final String id;
|
||||
final String resource;
|
||||
}
|
||||
|
||||
class GalleryPhotoViewWrapper extends StatefulWidget {
|
||||
final int initialIndex;
|
||||
final List<GalleryItem> galleryItems;
|
||||
final List<Uploaded> galleryItems;
|
||||
|
||||
GalleryPhotoViewWrapper({
|
||||
this.initialIndex = 0,
|
||||
@@ -85,44 +78,67 @@ class _GalleryPhotoViewWrapperState extends State<GalleryPhotoViewWrapper> {
|
||||
color: Colors.black,
|
||||
pageGestureAxis: SlideAxis.both),
|
||||
child: GestureDetector(
|
||||
child: ExtendedImageGesturePageView.builder(
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
var item = widget.galleryItems[index];
|
||||
Widget image = item.resource.startsWith('http')
|
||||
? ExtendedImage.network(
|
||||
item.resource,
|
||||
fit: BoxFit.contain,
|
||||
cache: true,
|
||||
mode: ExtendedImageMode.gesture,
|
||||
enableSlideOutPage: true,
|
||||
loadStateChanged: (state) =>
|
||||
defaultLoadStateChanged(state, iconSize: 50),
|
||||
)
|
||||
: ExtendedImage.file(
|
||||
File(item.resource),
|
||||
fit: BoxFit.contain,
|
||||
mode: ExtendedImageMode.gesture,
|
||||
enableSlideOutPage: true,
|
||||
loadStateChanged: (state) =>
|
||||
defaultLoadStateChanged(state, iconSize: 50),
|
||||
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,
|
||||
);
|
||||
image = Container(
|
||||
child: image,
|
||||
);
|
||||
if (index == currentIndex) {
|
||||
return Hero(
|
||||
tag: index,
|
||||
child: image,
|
||||
);
|
||||
} else {
|
||||
return image;
|
||||
}
|
||||
},
|
||||
itemCount: widget.galleryItems.length,
|
||||
controller: PageController(
|
||||
initialPage: currentIndex,
|
||||
),
|
||||
scrollDirection: Axis.horizontal,
|
||||
} 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();
|
||||
@@ -142,9 +158,41 @@ class _GalleryPhotoViewWrapperState extends State<GalleryPhotoViewWrapper> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text('复制链接'),
|
||||
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(context);
|
||||
_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);
|
||||
},
|
||||
),
|
||||
],
|
||||
@@ -154,9 +202,8 @@ class _GalleryPhotoViewWrapperState extends State<GalleryPhotoViewWrapper> {
|
||||
}
|
||||
|
||||
/// 复制链接
|
||||
_handleCopy(BuildContext context) {
|
||||
Clipboard.setData(
|
||||
ClipboardData(text: widget.galleryItems[currentIndex].resource));
|
||||
_handleCopy(String content, BuildContext context) {
|
||||
Clipboard.setData(ClipboardData(text: content));
|
||||
Toast.show('已复制到剪切板', context);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
|
||||
class LocalNotificationUtil {
|
||||
|
||||
@@ -21,7 +21,7 @@ class PermissionUtils {
|
||||
title: Text('警告'),
|
||||
content: Text(text),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
TextButton(
|
||||
child: Text('去设置'),
|
||||
onPressed: () {
|
||||
openAppSettings();
|
||||
|
||||
@@ -77,7 +77,7 @@ class GiteeImageUpload implements ImageUploadStrategy {
|
||||
await ImageUploadUtils.saveUploadedItem(uploadedItem);
|
||||
return uploadedItem;
|
||||
} on DioError catch (e) {
|
||||
if (e.type == DioErrorType.RESPONSE &&
|
||||
if (e.type == DioErrorType.response &&
|
||||
e.error.toString().indexOf('400') > 0) {
|
||||
throw GiteeError(error: '文件已存在!');
|
||||
} else {
|
||||
|
||||
@@ -64,7 +64,7 @@ class GithubImageUpload implements ImageUploadStrategy {
|
||||
throw GithubError(error: '读取配置文件错误!请重试');
|
||||
}
|
||||
} on DioError catch (e) {
|
||||
if (e.type == DioErrorType.RESPONSE &&
|
||||
if (e.type == DioErrorType.response &&
|
||||
e.error.toString().indexOf('422') > 0) {
|
||||
throw GithubError(error: '文件已存在!');
|
||||
} else {
|
||||
|
||||
@@ -31,16 +31,16 @@ class QiniuImageUpload extends ImageUploadStrategy {
|
||||
}
|
||||
return uploaded;
|
||||
} on DioError catch (e) {
|
||||
if (e.type == DioErrorType.RESPONSE &&
|
||||
if (e.type == DioErrorType.response &&
|
||||
e.error.toString().indexOf('400') > 0) {
|
||||
throw QiniuError(error: '400 请求报文格式错误');
|
||||
} else if (e.type == DioErrorType.RESPONSE &&
|
||||
} else if (e.type == DioErrorType.response &&
|
||||
e.error.toString().indexOf('401') > 0) {
|
||||
throw QiniuError(error: '401 管理凭证无效');
|
||||
} else if (e.type == DioErrorType.RESPONSE &&
|
||||
} else if (e.type == DioErrorType.response &&
|
||||
e.error.toString().indexOf('599') > 0) {
|
||||
throw QiniuError(error: '599 服务端操作失败');
|
||||
} else if (e.type == DioErrorType.RESPONSE &&
|
||||
} else if (e.type == DioErrorType.response &&
|
||||
e.error.toString().indexOf('612') > 0) {
|
||||
throw QiniuError(error: '612 待删除资源不存在');
|
||||
} else {
|
||||
@@ -88,16 +88,16 @@ class QiniuImageUpload extends ImageUploadStrategy {
|
||||
await ImageUploadUtils.saveUploadedItem(uploadedItem);
|
||||
return uploadedItem;
|
||||
} on DioError catch (e) {
|
||||
if (e.type == DioErrorType.RESPONSE &&
|
||||
if (e.type == DioErrorType.response &&
|
||||
e.error.toString().indexOf('400') > 0) {
|
||||
throw QiniuError(error: '400 请求报文格式错误');
|
||||
} else if (e.type == DioErrorType.RESPONSE &&
|
||||
} else if (e.type == DioErrorType.response &&
|
||||
e.error.toString().indexOf('401') > 0) {
|
||||
throw QiniuError(error: '401 管理凭证无效');
|
||||
} else if (e.type == DioErrorType.RESPONSE &&
|
||||
} else if (e.type == DioErrorType.response &&
|
||||
e.error.toString().indexOf('599') > 0) {
|
||||
throw QiniuError(error: '599 服务端操作失败');
|
||||
} else if (e.type == DioErrorType.RESPONSE &&
|
||||
} else if (e.type == DioErrorType.response &&
|
||||
e.error.toString().indexOf('612') > 0) {
|
||||
throw QiniuError(error: '612 待删除资源不存在');
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_picgo/api/tcyun_api.dart';
|
||||
import 'package:flutter_picgo/model/tcyun_config.dart';
|
||||
import 'package:flutter_picgo/model/uploaded.dart';
|
||||
|
||||
@@ -10,8 +10,10 @@ class PageNotFound extends StatelessWidget {
|
||||
),
|
||||
body: Container(
|
||||
child: Center(
|
||||
child: OutlineButton(
|
||||
color: Colors.blue,
|
||||
child: OutlinedButton(
|
||||
style: ButtonStyle(
|
||||
side:
|
||||
MaterialStateProperty.all(BorderSide(color: Colors.blue))),
|
||||
child: Text('关闭'),
|
||||
onPressed: () {
|
||||
Application.router.pop(context);
|
||||
|
||||
@@ -129,7 +129,7 @@ class _AlbumPageState extends State<AlbumPage> implements AlbumPageContract {
|
||||
height: 150,
|
||||
fit: BoxFit.cover,
|
||||
cache: true,
|
||||
border: Border.all(color: Colors.grey, width: 1.0),
|
||||
// border: Border.all(color: Colors.grey, width: 1.0),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
loadStateChanged: (state) =>
|
||||
defaultLoadStateChanged(state, iconSize: 30),
|
||||
@@ -197,12 +197,7 @@ class _AlbumPageState extends State<AlbumPage> implements AlbumPageContract {
|
||||
|
||||
/// 处理图片点击事件
|
||||
handleTap(int index) {
|
||||
ImagePreviewUtils.openMulti(
|
||||
context,
|
||||
index,
|
||||
_uploadeds.map((e) {
|
||||
return GalleryItem(id: e.id.toString(), resource: e.path);
|
||||
}).toList());
|
||||
ImagePreviewUtils.openMulti(context, index, _uploadeds);
|
||||
}
|
||||
|
||||
/// 处理图片双击
|
||||
@@ -220,7 +215,7 @@ class _AlbumPageState extends State<AlbumPage> implements AlbumPageContract {
|
||||
title: Text('确定删除吗'),
|
||||
content: Text('删除后无法恢复'),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
TextButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
|
||||
@@ -92,9 +92,11 @@ class _GiteeRepoPageState extends BaseLoadingPageState<GiteeRepoPage>
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
RaisedButton(
|
||||
color: Theme.of(context).accentColor,
|
||||
textColor: Colors.white,
|
||||
ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
backgroundColor:
|
||||
MaterialStateProperty.all(Theme.of(context).accentColor)),
|
||||
child: Text('刷新'),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
@@ -164,7 +166,7 @@ class _GiteeRepoPageState extends BaseLoadingPageState<GiteeRepoPage>
|
||||
title: Text('确定删除吗'),
|
||||
content: Text('删除后无法恢复'),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
TextButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, true);
|
||||
|
||||
@@ -92,9 +92,11 @@ class _GithubRepoPageState extends BaseLoadingPageState<GithubRepoPage>
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
RaisedButton(
|
||||
color: Theme.of(context).accentColor,
|
||||
textColor: Colors.white,
|
||||
ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
backgroundColor:
|
||||
MaterialStateProperty.all(Theme.of(context).accentColor)),
|
||||
child: Text('刷新'),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
@@ -164,7 +166,7 @@ class _GithubRepoPageState extends BaseLoadingPageState<GithubRepoPage>
|
||||
title: Text('确定删除吗'),
|
||||
content: Text('删除后无法恢复'),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
TextButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, true);
|
||||
|
||||
@@ -47,9 +47,11 @@ class _LskyRepoPageState extends BaseLoadingPageState<LskyRepoPage>
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
RaisedButton(
|
||||
color: Theme.of(context).accentColor,
|
||||
textColor: Colors.white,
|
||||
ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
backgroundColor:
|
||||
MaterialStateProperty.all(Theme.of(context).accentColor)),
|
||||
child: Text('刷新'),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
@@ -136,7 +138,7 @@ class _LskyRepoPageState extends BaseLoadingPageState<LskyRepoPage>
|
||||
title: Text('确定删除吗'),
|
||||
content: Text('删除后无法恢复'),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
TextButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, true);
|
||||
|
||||
@@ -52,9 +52,11 @@ class _QiniuRepoPageState extends BaseLoadingPageState<QiniuRepoPage>
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
RaisedButton(
|
||||
color: Theme.of(context).accentColor,
|
||||
textColor: Colors.white,
|
||||
ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
backgroundColor:
|
||||
MaterialStateProperty.all(Theme.of(context).accentColor)),
|
||||
child: Text('刷新'),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
@@ -121,7 +123,7 @@ class _QiniuRepoPageState extends BaseLoadingPageState<QiniuRepoPage>
|
||||
title: Text('确定删除吗'),
|
||||
content: Text('删除后无法恢复'),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
TextButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, true);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_picgo/api/qiniu_api.dart';
|
||||
import 'package:flutter_picgo/components/manage_item.dart';
|
||||
import 'package:flutter_picgo/model/qiniu_config.dart';
|
||||
|
||||
@@ -120,9 +120,11 @@ class _SMMSRepoPageState extends BaseLoadingPageState<SMMSRepoPage>
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
RaisedButton(
|
||||
color: Theme.of(context).accentColor,
|
||||
textColor: Colors.white,
|
||||
ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||
backgroundColor:
|
||||
MaterialStateProperty.all(Theme.of(context).accentColor)),
|
||||
child: Text('刷新'),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
@@ -181,7 +183,7 @@ class _SMMSRepoPageState extends BaseLoadingPageState<SMMSRepoPage>
|
||||
title: Text('确定删除吗'),
|
||||
content: Text('删除后无法恢复'),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
TextButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, true);
|
||||
|
||||
@@ -50,9 +50,12 @@ abstract class BasePBSettingPageState<T extends StatefulWidget>
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: RaisedButton(
|
||||
color: Theme.of(context).accentColor,
|
||||
textColor: Colors.white,
|
||||
child: ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor:
|
||||
MaterialStateProperty.all(Colors.white),
|
||||
backgroundColor: MaterialStateProperty.all(
|
||||
Theme.of(context).accentColor)),
|
||||
child: Text('保存'),
|
||||
onPressed: () {
|
||||
if (validate) {
|
||||
@@ -63,9 +66,12 @@ abstract class BasePBSettingPageState<T extends StatefulWidget>
|
||||
),
|
||||
SizedBox(width: 5.0),
|
||||
Expanded(
|
||||
child: RaisedButton(
|
||||
color: Colors.greenAccent,
|
||||
textColor: Colors.white,
|
||||
child: ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor:
|
||||
MaterialStateProperty.all(Colors.white),
|
||||
backgroundColor:
|
||||
MaterialStateProperty.all(Colors.greenAccent)),
|
||||
child: Text('设为默认图床'),
|
||||
onPressed: () {
|
||||
if (validate) {
|
||||
|
||||
@@ -50,7 +50,7 @@ class _PBSettingPageState extends State<PBSettingPage>
|
||||
'在PC端已经配置好的用户可以使用PicGo新版的生成图床配置二维码功能。\n\n' +
|
||||
'然后使用Flutter-PicGo直接扫描即可进行配置转换。'),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
TextButton(
|
||||
child: Text('已了解,去扫描'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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();
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
@@ -181,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
import 'package:flutter_picgo/components/upload_item/upload_item.dart';
|
||||
import 'package:flutter_picgo/utils/strings.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
@@ -116,15 +115,15 @@ class _HandleUploadPageState extends State<HandleUploadPage> {
|
||||
sp.getBool(SharedPreferencesKeys.settingIsTimestampRename) ?? false;
|
||||
|
||||
if (settingIsTimestampRename) {
|
||||
int timestamp = new DateTime.now().millisecondsSinceEpoch;
|
||||
|
||||
/// 处理时间戳命名
|
||||
var random = Random();
|
||||
for (int i = 0; i < widget.assets.length; i++) {
|
||||
/// 获取图片名
|
||||
String suffix = path.extension(tmp.path);
|
||||
|
||||
/// replace
|
||||
filesName[i] =
|
||||
'${new DateTime.now().millisecondsSinceEpoch.toString()}-${random.nextInt(100)}$suffix';
|
||||
filesName[i] = '${timestamp + i}$suffix';
|
||||
}
|
||||
}
|
||||
var settingIsUploadedRename =
|
||||
@@ -155,7 +154,7 @@ class _HandleUploadPageState extends State<HandleUploadPage> {
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
TextButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
|
||||
@@ -1,347 +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: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;
|
||||
|
||||
_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) {
|
||||
// debugPrint(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()));
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
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);
|
||||
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) {}
|
||||
}
|
||||
|
||||
/// 根据配置上传图片
|
||||
doUploadImage(File file, String renameImage) async {
|
||||
// 读取配置
|
||||
try {
|
||||
String pbType = await ImageUploadUtils.getDefaultPB();
|
||||
var uploader =
|
||||
ImageUploadUtils(UploadStrategyFactory.getUploadStrategy(pbType));
|
||||
var uploadedItem = await uploader.upload(file, renameImage);
|
||||
if (uploadedItem != null) {
|
||||
_view.uploadSuccess(uploadedItem.path);
|
||||
} else {
|
||||
_view.uploadFaild('上传失败!请重试');
|
||||
}
|
||||
} on DioError catch (e) {
|
||||
_view.uploadFaild('${e.message}');
|
||||
} catch (e) {
|
||||
_view.uploadFaild('$e');
|
||||
}
|
||||
}
|
||||
}
|
||||
21
pubspec.yaml
21
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.9.2+23
|
||||
version: 1.9.2+24
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
@@ -23,23 +23,22 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
shared_preferences: ^0.5.12+4
|
||||
dio: ^3.0.9
|
||||
package_info: ^0.4.1
|
||||
shared_preferences: ^2.0.5
|
||||
dio: ^4.0.0
|
||||
package_info: ^2.0.0
|
||||
sqflite: ^1.3.2+1
|
||||
fluro: ^1.7.7
|
||||
fluro: ^2.0.3
|
||||
toast: ^0.1.5
|
||||
json_serializable: ^3.3.0
|
||||
url_launcher: ^5.7.10
|
||||
permission_handler: ^5.0.1
|
||||
barcode_scan: ^3.0.1
|
||||
provider: ^4.1.3
|
||||
crypto: ^2.1.4
|
||||
provider: ^5.0.0
|
||||
crypto: ^3.0.1
|
||||
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
|
||||
pull_to_refresh: ^1.6.5
|
||||
wechat_assets_picker: ^5.1.3
|
||||
extended_image: ^4.0.1
|
||||
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
|
||||
@@ -17,14 +17,14 @@ main() {
|
||||
var sign = AliyunApi.buildSignature('LTAIsXml0iczvY0J',
|
||||
'yw8eO9Fa9Py2GAPRGG8N3GPKCeKCXl', 'PUT', 'zjyzy', 'test.txt');
|
||||
try {
|
||||
Response res = await NetUtils.getInstance().put(
|
||||
await NetUtils.getInstance().put(
|
||||
'https://zjyzy.oss-cn-shenzhen.aliyuncs.com/test.txt',
|
||||
options: Options(headers: {
|
||||
'Authorization': sign,
|
||||
'Date': HttpDate.format(new DateTime.now()),
|
||||
}, contentType: 'application/x-www-form-urlencoded'),
|
||||
);
|
||||
} on DioError catch (e) {}
|
||||
} on DioError catch (_) {}
|
||||
});
|
||||
|
||||
test('测试FormData提交图片', () async {
|
||||
@@ -43,7 +43,7 @@ main() {
|
||||
var sign = hmacsha1.convert(utf8.encode(originSign));
|
||||
var encodeSign = base64.encode(sign.bytes);
|
||||
try {
|
||||
Response res = await NetUtils.getInstance().post(
|
||||
await NetUtils.getInstance().post(
|
||||
'https://zjyzy.oss-cn-shenzhen.aliyuncs.com',
|
||||
data: FormData.fromMap({
|
||||
'key': 'logo.png',
|
||||
@@ -53,6 +53,6 @@ main() {
|
||||
'file': await MultipartFile.fromFile(pathname, filename: 'logo.png')
|
||||
}),
|
||||
options: Options(contentType: Headers.formUrlEncodedContentType));
|
||||
} on DioError catch (e) {}
|
||||
} on DioError catch (_) {}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,10 +4,8 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
main() {
|
||||
test('测试UpToken生成', () {
|
||||
String policy = QiniuApi.generatePutPolicy('image', 'test.png');
|
||||
var token = QiniuApi.generateUpToken(
|
||||
'CRd7Wa4PuSGvs4ArToPTLBMCigGGUY3sk3F8oc8W',
|
||||
'f2Jkrlyea5s8h8gLEToa9-k895GNM-BlmQ2RfxwU',
|
||||
policy);
|
||||
QiniuApi.generateUpToken('CRd7Wa4PuSGvs4ArToPTLBMCigGGUY3sk3F8oc8W',
|
||||
'f2Jkrlyea5s8h8gLEToa9-k895GNM-BlmQ2RfxwU', policy);
|
||||
});
|
||||
|
||||
test('测试AuthToken生成', () {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter_picgo/api/tcyun_api.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
main() {
|
||||
test('测试生成 KeyTime', () {});
|
||||
@@ -22,11 +19,11 @@ main() {
|
||||
|
||||
test('PostObjecy 提交', () async {
|
||||
try {
|
||||
String pathname = path.joinAll(
|
||||
[Directory.current.path, '..\\assets\\' 'images', 'logo.png']);
|
||||
String keyTime = TcyunApi.buildKeyTime();
|
||||
String policy = TcyunApi.buildPolicy('ap-nanjing', 'logo.png',
|
||||
'AKIDvb0B9rqfeOr44kt2ar46rO2cwzl6JwUk', keyTime);
|
||||
// String pathname = path.joinAll(
|
||||
// [Directory.current.path, '..\\assets\\' 'images', 'logo.png']);
|
||||
// String keyTime = TcyunApi.buildKeyTime();
|
||||
// String policy = TcyunApi.buildPolicy('ap-nanjing', 'logo.png',
|
||||
// 'AKIDvb0B9rqfeOr44kt2ar46rO2cwzl6JwUk', keyTime);
|
||||
// TcyunApi.postObject(
|
||||
// 'test-1253954259',
|
||||
// 'ap-nanjing',
|
||||
|
||||
Reference in New Issue
Block a user