preload image from network in gallery mode
This commit is contained in:
parent
fd175feb80
commit
f5adcbd2e0
15
README.md
15
README.md
|
@ -109,16 +109,17 @@ VPN->代理->分流, 这三个功能如果同时设置, 您会在您手机的VPN
|
|||
sudo apt install xorg-dev
|
||||
```
|
||||
- 字体不显示
|
||||
1. 将字体文件复制到项目目录下
|
||||
```shell
|
||||
cp /usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf fonts/
|
||||
# 将字体文件复制到项目目录下
|
||||
mkdir -p fonts
|
||||
cp -f /usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf fonts/
|
||||
```
|
||||
2. 设置flutter打包的字体
|
||||
```yaml
|
||||
fonts:
|
||||
- family: Roboto
|
||||
fonts:
|
||||
- asset: fonts/DroidSansFallbackFull.ttf
|
||||
# 编辑 pubspec.yaml
|
||||
fonts:
|
||||
- family: Roboto
|
||||
fonts:
|
||||
- asset: fonts/DroidSansFallbackFull.ttf
|
||||
```
|
||||
|
||||
### 移动端 (gomobile)
|
||||
|
|
|
@ -35,10 +35,11 @@ func main() {
|
|||
if height <= 0 {
|
||||
height = 900
|
||||
}
|
||||
sizeOption := flutter.WindowInitialDimensions(width, height)
|
||||
options = append(options, sizeOption)
|
||||
//
|
||||
err := flutter.Run(append(options, mainOptions...)...)
|
||||
var runOptions []flutter.Option
|
||||
runOptions = append(runOptions, flutter.WindowInitialDimensions(width, height))
|
||||
runOptions = append(runOptions, options...)
|
||||
// ------
|
||||
err := flutter.Run(append(runOptions, mainOptions...)...)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
|
|
|
@ -169,37 +169,11 @@ func remoteImageData(params string) (string, error) {
|
|||
defer lock.Unlock()
|
||||
cache := comic_center.FindRemoteImage(fileServer, path)
|
||||
if cache == nil {
|
||||
buff, img, format, err := decodeFromUrl(fileServer, path)
|
||||
if err != nil {
|
||||
println(fmt.Sprintf("decode error : %s/static/%s %s", fileServer, path, err.Error()))
|
||||
return "", err
|
||||
}
|
||||
local :=
|
||||
fmt.Sprintf("%x",
|
||||
md5.Sum([]byte(fmt.Sprintf("%s$%s", fileServer, path))),
|
||||
)
|
||||
real := remotePath(local)
|
||||
err = ioutil.WriteFile(
|
||||
real,
|
||||
buff, os.FileMode(0600),
|
||||
)
|
||||
remote, err := decodeAndSaveImage(fileServer, path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
remote := comic_center.RemoteImage{
|
||||
FileServer: fileServer,
|
||||
Path: path,
|
||||
FileSize: int64(len(buff)),
|
||||
Format: format,
|
||||
Width: int32(img.Bounds().Dx()),
|
||||
Height: int32(img.Bounds().Dy()),
|
||||
LocalPath: local,
|
||||
}
|
||||
err = comic_center.SaveRemoteImage(&remote)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cache = &remote
|
||||
cache = remote
|
||||
}
|
||||
display := DisplayImageData{
|
||||
FileSize: cache.FileSize,
|
||||
|
@ -211,6 +185,56 @@ func remoteImageData(params string) (string, error) {
|
|||
return serialize(&display, nil)
|
||||
}
|
||||
|
||||
func remoteImagePreload(params string) error {
|
||||
var paramsStruct struct {
|
||||
FileServer string `json:"fileServer"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
json.Unmarshal([]byte(params), ¶msStruct)
|
||||
fileServer := paramsStruct.FileServer
|
||||
path := paramsStruct.Path
|
||||
lock := utils.HashLock(fmt.Sprintf("%s$%s", fileServer, path))
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
cache := comic_center.FindRemoteImage(fileServer, path)
|
||||
var err error
|
||||
if cache == nil {
|
||||
_, err = decodeAndSaveImage(fileServer, path)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func decodeAndSaveImage(fileServer string, path string) (*comic_center.RemoteImage, error) {
|
||||
buff, img, format, err := decodeFromUrl(fileServer, path)
|
||||
if err != nil {
|
||||
println(fmt.Sprintf("decode error : %s/static/%s %s", fileServer, path, err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
local :=
|
||||
fmt.Sprintf("%x",
|
||||
md5.Sum([]byte(fmt.Sprintf("%s$%s", fileServer, path))),
|
||||
)
|
||||
real := remotePath(local)
|
||||
err = ioutil.WriteFile(
|
||||
real,
|
||||
buff, os.FileMode(0600),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
remote := comic_center.RemoteImage{
|
||||
FileServer: fileServer,
|
||||
Path: path,
|
||||
FileSize: int64(len(buff)),
|
||||
Format: format,
|
||||
Width: int32(img.Bounds().Dx()),
|
||||
Height: int32(img.Bounds().Dy()),
|
||||
LocalPath: local,
|
||||
}
|
||||
err = comic_center.SaveRemoteImage(&remote)
|
||||
return &remote, err
|
||||
}
|
||||
|
||||
func downloadImagePath(path string) (string, error) {
|
||||
return downloadPath(path), nil
|
||||
}
|
||||
|
@ -565,6 +589,8 @@ func FlatInvoke(method string, params string) (string, error) {
|
|||
return "", importComicDownloadUsingSocket(params)
|
||||
case "remoteImageData":
|
||||
return remoteImageData(params)
|
||||
case "remoteImagePreload":
|
||||
return "", remoteImagePreload(params)
|
||||
case "clientIpSet":
|
||||
return clientIpSet()
|
||||
case "downloadImagePath":
|
||||
|
|
|
@ -150,6 +150,13 @@ class Method {
|
|||
return RemoteImageData.fromJson(json.decode(data));
|
||||
}
|
||||
|
||||
Future<dynamic> remoteImagePreload(String fileServer, String path) async {
|
||||
return _flatInvoke("remoteImagePreload", {
|
||||
"fileServer": fileServer,
|
||||
"path": path,
|
||||
});
|
||||
}
|
||||
|
||||
Future<String> downloadImagePath(String path) async {
|
||||
return await _flatInvoke("downloadImagePath", path);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pikapi/basic/Method.dart';
|
||||
|
||||
import '../Common.dart';
|
||||
|
||||
const galleryPrePreloadCount = 1;
|
||||
const galleryPreloadCount = 2;
|
|
@ -50,6 +50,6 @@ Widget shadowCategoriesActionButton(BuildContext context) {
|
|||
onPressed: () {
|
||||
chooseShadowCategories(context);
|
||||
},
|
||||
icon: Icon(Icons.dnd_forwardslash),
|
||||
icon: Icon(Icons.hide_source),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -165,7 +165,8 @@ Future<dynamic> initTheme() async {
|
|||
_androidVersion = await method.androidGetVersion();
|
||||
if (_androidVersion >= 29) {
|
||||
_androidNightMode =
|
||||
(await method.loadProperty(_nightModePropertyName, "false")) == "true";
|
||||
(await method.loadProperty(_nightModePropertyName, "false")) ==
|
||||
"true";
|
||||
_systemNight = (await method.androidGetUiMode()) == "NIGHT";
|
||||
EventChannel("ui_mode").receiveBroadcastStream().listen((event) {
|
||||
_systemNight = "$event" == "NIGHT";
|
||||
|
@ -185,23 +186,49 @@ Future<dynamic> chooseTheme(BuildContext buildContext) async {
|
|||
builder: (BuildContext context, StateSetter setState) {
|
||||
var list = <SimpleDialogOption>[];
|
||||
if (_androidVersion >= 29) {
|
||||
var onChange = (bool? v) async {
|
||||
if (v != null) {
|
||||
await method.saveProperty(
|
||||
_nightModePropertyName, "$v");
|
||||
_androidNightMode = v;
|
||||
}
|
||||
setState(() {});
|
||||
themeEvent.broadcast();
|
||||
};
|
||||
list.add(
|
||||
SimpleDialogOption(
|
||||
child: Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: _androidNightMode,
|
||||
onChanged: (bool? v) async {
|
||||
if (v != null) {
|
||||
await method.saveProperty(
|
||||
_nightModePropertyName, "$v");
|
||||
_androidNightMode = v;
|
||||
}
|
||||
setState(() {});
|
||||
themeEvent.broadcast();
|
||||
}),
|
||||
Text("随手机进入夜间模式"),
|
||||
],
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
onChange(!_androidNightMode);
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(top: 3, bottom: 3),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Theme
|
||||
.of(context)
|
||||
.dividerColor,
|
||||
width: 0.5,
|
||||
),
|
||||
bottom: BorderSide(
|
||||
color: Theme
|
||||
.of(context)
|
||||
.dividerColor,
|
||||
width: 0.5
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: _androidNightMode,
|
||||
onChanged: onChange,
|
||||
),
|
||||
Text("随手机进入夜间模式"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const ERROR_TYPE_NETWORK = "NETWORK_ERROR";
|
||||
const ERROR_TYPE_PERMISSION = "PERMISSION_ERROR";
|
||||
|
||||
// 错误的类型, 方便照展示和谐的提示
|
||||
String errorType(String error) {
|
||||
|
@ -11,5 +12,8 @@ String errorType(String error) {
|
|||
error.contains("deadline")) {
|
||||
return ERROR_TYPE_NETWORK;
|
||||
}
|
||||
if (error.contains("permission denied")) {
|
||||
return ERROR_TYPE_PERMISSION;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -60,23 +60,6 @@ class _ComicsScreenState extends State<ComicsScreen> {
|
|||
},
|
||||
);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
shadowCategoriesEvent.subscribe(_onShadowChange);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
shadowCategoriesEvent.unsubscribe(_onShadowChange);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onShadowChange(EventArgs? args) {
|
||||
setState(() {
|
||||
});
|
||||
}
|
||||
|
||||
Widget _chooseCategoryAction() => IconButton(
|
||||
onPressed: () async {
|
||||
String? category = await chooseListDialog(context, '请选择分类', [
|
||||
|
@ -142,6 +125,7 @@ class _ComicsScreenState extends State<ComicsScreen> {
|
|||
appBar = AppBar(
|
||||
title: Text(title),
|
||||
actions: [
|
||||
shadowCategoriesActionButton(context),
|
||||
chooseLayoutAction(context),
|
||||
_chooseCategoryAction(),
|
||||
],
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:pikapi/basic/Entities.dart';
|
||||
import 'package:pikapi/basic/Method.dart';
|
||||
import 'package:pikapi/basic/config/ListLayout.dart';
|
||||
import 'package:pikapi/basic/config/ShadowCategories.dart';
|
||||
|
||||
import 'components/ComicListBuilder.dart';
|
||||
|
||||
|
@ -25,6 +26,7 @@ class _RandomComicsScreenState extends State<RandomComicsScreen> {
|
|||
appBar: AppBar(
|
||||
title: Text('随机本子'),
|
||||
actions: [
|
||||
shadowCategoriesActionButton(context),
|
||||
chooseLayoutAction(context),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -2,10 +2,12 @@ import 'package:flutter/material.dart';
|
|||
import 'package:pikapi/basic/Entities.dart';
|
||||
import 'package:pikapi/basic/Method.dart';
|
||||
import 'package:pikapi/basic/config/ListLayout.dart';
|
||||
import 'package:pikapi/basic/config/ShadowCategories.dart';
|
||||
|
||||
import 'components/ComicListBuilder.dart';
|
||||
|
||||
class RankingsScreen extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
|
@ -13,6 +15,7 @@ class RankingsScreen extends StatelessWidget {
|
|||
appBar: AppBar(
|
||||
title: Text('排行榜'),
|
||||
actions: [
|
||||
shadowCategoriesActionButton(context),
|
||||
chooseLayoutAction(context),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -96,23 +96,6 @@ class _SearchScreenState extends State<SearchScreen> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
shadowCategoriesEvent.subscribe(_onShadowChange);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
shadowCategoriesEvent.unsubscribe(_onShadowChange);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onShadowChange(EventArgs? args) {
|
||||
setState(() {
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
|
|
@ -1,28 +1,51 @@
|
|||
import 'package:event/event.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pikapi/basic/Entities.dart';
|
||||
import 'package:pikapi/basic/config/ShadowCategories.dart';
|
||||
import 'package:pikapi/screens/components/ComicList.dart';
|
||||
import 'package:pikapi/screens/components/FitButton.dart';
|
||||
import 'ContentBuilder.dart';
|
||||
|
||||
class ComicListBuilder extends StatelessWidget {
|
||||
class ComicListBuilder extends StatefulWidget {
|
||||
final Future<List<ComicSimple>> future;
|
||||
final Future Function() reload;
|
||||
|
||||
ComicListBuilder(this.future, this.reload);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ComicListBuilderState();
|
||||
}
|
||||
|
||||
class _ComicListBuilderState extends State<ComicListBuilder> {
|
||||
@override
|
||||
void initState() {
|
||||
shadowCategoriesEvent.subscribe(_onShadowChange);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
shadowCategoriesEvent.unsubscribe(_onShadowChange);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onShadowChange(EventArgs? args) {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ContentBuilder(
|
||||
future: future,
|
||||
onRefresh: reload,
|
||||
future: widget.future,
|
||||
onRefresh: widget.reload,
|
||||
successBuilder:
|
||||
(BuildContext context, AsyncSnapshot<List<ComicSimple>> snapshot) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: reload,
|
||||
onRefresh: widget.reload,
|
||||
child: ComicList(
|
||||
snapshot.data!,
|
||||
appendWidget: FitButton(
|
||||
onPressed: reload,
|
||||
onPressed: widget.reload,
|
||||
text: '刷新',
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import 'package:event/event.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:pikapi/basic/Entities.dart';
|
||||
import 'package:pikapi/basic/config/PagerAction.dart';
|
||||
import 'package:pikapi/basic/config/ShadowCategories.dart';
|
||||
import 'package:pikapi/basic/enum/Sort.dart';
|
||||
import 'package:pikapi/screens/components/ComicList.dart';
|
||||
import 'package:pikapi/screens/components/ContentError.dart';
|
||||
|
@ -9,18 +11,41 @@ import 'package:pikapi/screens/components/FitButton.dart';
|
|||
import 'ContentLoading.dart';
|
||||
|
||||
// 漫画列页
|
||||
class ComicPager extends StatelessWidget {
|
||||
class ComicPager extends StatefulWidget {
|
||||
final Future<ComicsPage> Function(String sort, int page) fetchPage;
|
||||
|
||||
const ComicPager({required this.fetchPage});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ComicPagerState();
|
||||
}
|
||||
|
||||
class _ComicPagerState extends State<ComicPager> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
shadowCategoriesEvent.subscribe(_onShadowChange);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
shadowCategoriesEvent.unsubscribe(_onShadowChange);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onShadowChange(EventArgs? args) {
|
||||
setState(() {
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
switch (currentPagerAction) {
|
||||
case PagerAction.CONTROLLER:
|
||||
return ControllerComicPager(fetchPage: fetchPage);
|
||||
return ControllerComicPager(fetchPage: widget.fetchPage);
|
||||
case PagerAction.STREAM:
|
||||
return StreamComicPager(fetchPage: fetchPage);
|
||||
return StreamComicPager(fetchPage: widget.fetchPage);
|
||||
default:
|
||||
return Container();
|
||||
}
|
||||
|
|
|
@ -24,24 +24,67 @@ class ContentError extends StatelessWidget {
|
|||
case ERROR_TYPE_NETWORK:
|
||||
message = "连接不上啦, 请检查网络";
|
||||
break;
|
||||
case ERROR_TYPE_PERMISSION:
|
||||
message = "没有权限或路径不可用";
|
||||
break;
|
||||
default:
|
||||
message = "啊哦, 被玩坏了";
|
||||
break;
|
||||
}
|
||||
return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
|
||||
print("$error");
|
||||
print("$stackTrace");
|
||||
var width = constraints.maxWidth;
|
||||
var height = constraints.maxHeight;
|
||||
var min = width < height ? width : height;
|
||||
var iconSize = min / 2.3;
|
||||
var textSize = min / 16;
|
||||
var tipSize = min / 20;
|
||||
var infoSize = min / 30;
|
||||
if (contentFailedReloadAction ==
|
||||
ContentFailedReloadAction.TOUCH_LOADER) {
|
||||
return GestureDetector(
|
||||
onTap: onRefresh,
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
print("$error");
|
||||
print("$stackTrace");
|
||||
var width = constraints.maxWidth;
|
||||
var height = constraints.maxHeight;
|
||||
var min = width < height ? width : height;
|
||||
var iconSize = min / 2.3;
|
||||
var textSize = min / 16;
|
||||
var tipSize = min / 20;
|
||||
var infoSize = min / 30;
|
||||
if (contentFailedReloadAction ==
|
||||
ContentFailedReloadAction.TOUCH_LOADER) {
|
||||
return GestureDetector(
|
||||
onTap: onRefresh,
|
||||
child: ListView(
|
||||
children: [
|
||||
Container(
|
||||
height: height,
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(child: Container()),
|
||||
Container(
|
||||
child: Icon(
|
||||
Icons.wifi_off_rounded,
|
||||
size: iconSize,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
Container(height: min / 10),
|
||||
Container(
|
||||
padding: EdgeInsets.only(
|
||||
left: 30,
|
||||
right: 30,
|
||||
),
|
||||
child: Text(
|
||||
message,
|
||||
style: TextStyle(fontSize: textSize),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Text('(点击刷新)', style: TextStyle(fontSize: tipSize)),
|
||||
Container(height: min / 15),
|
||||
Text('$error', style: TextStyle(fontSize: infoSize)),
|
||||
Expanded(child: Container()),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return RefreshIndicator(
|
||||
onRefresh: onRefresh,
|
||||
child: ListView(
|
||||
children: [
|
||||
Container(
|
||||
|
@ -68,7 +111,7 @@ class ContentError extends StatelessWidget {
|
|||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Text('(点击刷新)', style: TextStyle(fontSize: tipSize)),
|
||||
Text('(下拉刷新)', style: TextStyle(fontSize: tipSize)),
|
||||
Container(height: min / 15),
|
||||
Text('$error', style: TextStyle(fontSize: infoSize)),
|
||||
Expanded(child: Container()),
|
||||
|
@ -78,45 +121,7 @@ class ContentError extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return RefreshIndicator(
|
||||
onRefresh: onRefresh,
|
||||
child: ListView(
|
||||
children: [
|
||||
Container(
|
||||
height: height,
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(child: Container()),
|
||||
Container(
|
||||
child: Icon(
|
||||
Icons.wifi_off_rounded,
|
||||
size: iconSize,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
Container(height: min / 10),
|
||||
Container(
|
||||
padding: EdgeInsets.only(
|
||||
left: 30,
|
||||
right: 30,
|
||||
),
|
||||
child: Text(
|
||||
message,
|
||||
style: TextStyle(fontSize: textSize),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Text('(下拉刷新)', style: TextStyle(fontSize: tipSize)),
|
||||
Container(height: min / 15),
|
||||
Text('$error', style: TextStyle(fontSize: infoSize)),
|
||||
Expanded(child: Container()),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,10 @@ import 'package:pikapi/basic/Cross.dart';
|
|||
import 'package:pikapi/basic/Entities.dart';
|
||||
import 'package:pikapi/basic/Method.dart';
|
||||
import 'package:pikapi/basic/config/FullScreenAction.dart';
|
||||
import 'package:pikapi/basic/config/GalleryPreloadCount.dart';
|
||||
import 'package:pikapi/basic/config/KeyboardController.dart';
|
||||
import 'package:pikapi/basic/config/ReaderDirection.dart';
|
||||
import 'package:pikapi/basic/config/ReaderType.dart';
|
||||
import 'package:pikapi/basic/config/VolumeController.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
import '../FilePhotoViewScreen.dart';
|
||||
import 'gesture_zoom_box.dart';
|
||||
|
@ -685,6 +685,27 @@ class _GalleryReaderState extends State<_GalleryReader> {
|
|||
_current = value + 1;
|
||||
_slider = value + 1;
|
||||
widget.struct.onPositionChange(value);
|
||||
if (galleryPrePreloadCount > 0) {
|
||||
for (var count = 1;
|
||||
count <= galleryPrePreloadCount && value - count >= 0;
|
||||
count++) {
|
||||
var target = widget.struct.images[value - count];
|
||||
if (target.downloadLocalPath == null) {
|
||||
method.remoteImagePreload(target.fileServer, target.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (galleryPreloadCount > 0) {
|
||||
for (var count = 1;
|
||||
count <= galleryPreloadCount &&
|
||||
value + count < widget.struct.images.length;
|
||||
count++) {
|
||||
var target = widget.struct.images[value + count];
|
||||
if (target.downloadLocalPath == null) {
|
||||
method.remoteImagePreload(target.fileServer, target.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
itemCount: widget.struct.images.length,
|
||||
|
|
|
@ -39,9 +39,9 @@ dependencies:
|
|||
filesystem_picker: ^2.0.0-nullsafety.0
|
||||
url_launcher: ^6.0.9
|
||||
clipboard: ^0.1.3
|
||||
flutter_datetime_picker: ^1.5.1
|
||||
photo_view: ^0.12.0
|
||||
multi_select_flutter: ^4.0.0
|
||||
flutter_datetime_picker: ^1.5.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Reference in New Issue