2020-04-25 22:57:43 +00:00
|
|
|
import 'package:flutter/cupertino.dart';
|
2020-03-24 19:59:36 +00:00
|
|
|
import 'package:flutter/material.dart';
|
2020-05-06 16:43:03 +00:00
|
|
|
import 'package:like_button/like_button.dart';
|
2020-06-17 15:09:47 +00:00
|
|
|
import 'package:photos/core/cache/image_cache.dart';
|
2020-06-19 23:06:07 +00:00
|
|
|
import 'package:photos/favorite_files_repository.dart';
|
2020-06-19 23:03:26 +00:00
|
|
|
import 'package:photos/models/file_type.dart';
|
|
|
|
import 'package:photos/models/file.dart';
|
|
|
|
import 'package:photos/ui/video_widget.dart';
|
2020-05-04 20:08:20 +00:00
|
|
|
import 'package:photos/ui/zoomable_image.dart';
|
2020-06-13 18:47:48 +00:00
|
|
|
import 'package:photos/utils/date_time_util.dart';
|
2020-05-01 18:20:12 +00:00
|
|
|
import 'package:photos/utils/share_util.dart';
|
2020-05-02 16:28:54 +00:00
|
|
|
import 'package:logging/logging.dart';
|
2020-03-24 19:59:36 +00:00
|
|
|
|
2020-04-17 08:17:37 +00:00
|
|
|
class DetailPage extends StatefulWidget {
|
2020-06-19 23:03:26 +00:00
|
|
|
final List<File> files;
|
2020-04-18 14:10:31 +00:00
|
|
|
final int selectedIndex;
|
2020-03-24 19:59:36 +00:00
|
|
|
|
2020-06-19 23:03:26 +00:00
|
|
|
DetailPage(this.files, this.selectedIndex, {key}) : super(key: key);
|
2020-04-17 08:17:37 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
_DetailPageState createState() => _DetailPageState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _DetailPageState extends State<DetailPage> {
|
2020-05-06 16:43:03 +00:00
|
|
|
final _logger = Logger("DetailPageState");
|
2020-04-17 08:17:37 +00:00
|
|
|
bool _shouldDisableScroll = false;
|
2020-06-19 23:03:26 +00:00
|
|
|
List<File> _files;
|
2020-04-18 14:10:31 +00:00
|
|
|
int _selectedIndex = 0;
|
2020-04-23 20:00:20 +00:00
|
|
|
|
2020-03-24 19:59:36 +00:00
|
|
|
@override
|
2020-04-25 22:57:43 +00:00
|
|
|
void initState() {
|
2020-06-19 23:03:26 +00:00
|
|
|
_files = widget.files;
|
2020-04-18 14:10:31 +00:00
|
|
|
_selectedIndex = widget.selectedIndex;
|
2020-04-25 22:57:43 +00:00
|
|
|
super.initState();
|
|
|
|
}
|
2020-04-23 20:00:20 +00:00
|
|
|
|
2020-04-25 22:57:43 +00:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2020-05-06 16:43:03 +00:00
|
|
|
_logger.info("Opening " +
|
2020-06-19 23:03:26 +00:00
|
|
|
_files[_selectedIndex].toString() +
|
2020-04-27 15:28:03 +00:00
|
|
|
". " +
|
2020-04-25 22:57:43 +00:00
|
|
|
_selectedIndex.toString() +
|
|
|
|
" / " +
|
2020-06-19 23:03:26 +00:00
|
|
|
_files.length.toString() +
|
|
|
|
" files .");
|
2020-03-24 19:59:36 +00:00
|
|
|
return Scaffold(
|
2020-04-23 20:00:20 +00:00
|
|
|
appBar: _buildAppBar(),
|
2020-03-24 19:59:36 +00:00
|
|
|
body: Center(
|
|
|
|
child: Container(
|
2020-04-25 22:57:43 +00:00
|
|
|
child: _buildPageView(),
|
2020-03-24 19:59:36 +00:00
|
|
|
),
|
|
|
|
),
|
2020-06-20 10:06:55 +00:00
|
|
|
backgroundColor: Colors.black,
|
2020-03-24 19:59:36 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-04-27 11:57:40 +00:00
|
|
|
Widget _buildPageView() {
|
2020-06-17 15:09:47 +00:00
|
|
|
return PageView.builder(
|
2020-04-25 22:57:43 +00:00
|
|
|
itemBuilder: (context, index) {
|
2020-06-19 23:03:26 +00:00
|
|
|
final file = _files[index];
|
|
|
|
Widget content;
|
|
|
|
if (file.fileType == FileType.image) {
|
|
|
|
content = ZoomableImage(
|
|
|
|
file,
|
|
|
|
shouldDisableScroll: (value) {
|
|
|
|
setState(() {
|
|
|
|
_shouldDisableScroll = value;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
);
|
|
|
|
} else if (file.fileType == FileType.video) {
|
|
|
|
content = VideoWidget(file);
|
|
|
|
} else {
|
|
|
|
content = Icon(Icons.error);
|
|
|
|
}
|
|
|
|
_preloadFiles(index);
|
|
|
|
return content;
|
2020-04-25 22:57:43 +00:00
|
|
|
},
|
2020-06-17 15:09:47 +00:00
|
|
|
onPageChanged: (index) {
|
2020-06-18 18:39:05 +00:00
|
|
|
setState(() {
|
|
|
|
_selectedIndex = index;
|
|
|
|
});
|
2020-06-19 23:03:26 +00:00
|
|
|
_preloadFiles(index);
|
2020-04-25 22:57:43 +00:00
|
|
|
},
|
|
|
|
physics: _shouldDisableScroll
|
|
|
|
? NeverScrollableScrollPhysics()
|
|
|
|
: PageScrollPhysics(),
|
2020-06-10 21:36:01 +00:00
|
|
|
controller: PageController(initialPage: _selectedIndex),
|
2020-06-19 23:03:26 +00:00
|
|
|
itemCount: _files.length,
|
2020-04-25 22:57:43 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-06-19 23:03:26 +00:00
|
|
|
void _preloadFiles(int index) {
|
2020-06-17 15:09:47 +00:00
|
|
|
if (index > 0) {
|
2020-06-19 23:03:26 +00:00
|
|
|
_preloadFile(_files[index - 1]);
|
2020-06-17 15:09:47 +00:00
|
|
|
}
|
2020-06-19 23:03:26 +00:00
|
|
|
if (index < _files.length - 1) {
|
|
|
|
_preloadFile(_files[index + 1]);
|
2020-06-17 15:09:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-19 23:03:26 +00:00
|
|
|
void _preloadFile(File file) {
|
|
|
|
if (file.localId == null) {
|
|
|
|
file.getBytes().then((data) {
|
|
|
|
BytesLruCache.put(file, data);
|
2020-06-17 15:09:47 +00:00
|
|
|
});
|
|
|
|
} else {
|
2020-06-19 23:03:26 +00:00
|
|
|
final cachedFile = FileLruCache.get(file);
|
2020-06-17 15:09:47 +00:00
|
|
|
if (cachedFile == null) {
|
2020-06-19 23:03:26 +00:00
|
|
|
file.getAsset().then((asset) {
|
|
|
|
asset.file.then((assetFile) {
|
|
|
|
FileLruCache.put(file, assetFile);
|
2020-06-17 15:09:47 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-23 20:00:20 +00:00
|
|
|
AppBar _buildAppBar() {
|
2020-05-25 16:05:06 +00:00
|
|
|
final actions = List<Widget>();
|
2020-06-19 23:03:26 +00:00
|
|
|
if (_files[_selectedIndex].localId != null) {
|
2020-05-25 16:05:06 +00:00
|
|
|
actions.add(_getFavoriteButton());
|
|
|
|
}
|
2020-06-13 18:47:48 +00:00
|
|
|
actions.add(PopupMenuButton(
|
|
|
|
itemBuilder: (context) {
|
|
|
|
return [
|
|
|
|
PopupMenuItem(
|
|
|
|
value: 1,
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
Icon(Icons.share),
|
|
|
|
Padding(
|
|
|
|
padding: EdgeInsets.all(8),
|
|
|
|
),
|
|
|
|
Text("Share"),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
PopupMenuItem(
|
|
|
|
value: 2,
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
Icon(Icons.info),
|
|
|
|
Padding(
|
|
|
|
padding: EdgeInsets.all(8),
|
|
|
|
),
|
|
|
|
Text("Info"),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
];
|
|
|
|
},
|
|
|
|
onSelected: (value) {
|
|
|
|
if (value == 1) {
|
2020-06-19 23:03:26 +00:00
|
|
|
share(_files[_selectedIndex]);
|
2020-06-13 18:47:48 +00:00
|
|
|
} else if (value == 2) {
|
2020-06-19 23:03:26 +00:00
|
|
|
_displayInfo(_files[_selectedIndex]);
|
2020-06-13 18:47:48 +00:00
|
|
|
}
|
2020-05-25 16:05:06 +00:00
|
|
|
},
|
|
|
|
));
|
2020-04-23 20:00:20 +00:00
|
|
|
return AppBar(
|
2020-05-25 16:05:06 +00:00
|
|
|
actions: actions,
|
2020-04-23 20:00:20 +00:00
|
|
|
);
|
|
|
|
}
|
2020-05-06 16:43:03 +00:00
|
|
|
|
|
|
|
Widget _getFavoriteButton() {
|
2020-06-19 23:03:26 +00:00
|
|
|
final file = _files[_selectedIndex];
|
2020-05-06 16:43:03 +00:00
|
|
|
return LikeButton(
|
2020-06-19 23:03:26 +00:00
|
|
|
isLiked: FavoriteFilesRepository.instance.isLiked(file),
|
2020-05-06 16:43:03 +00:00
|
|
|
onTap: (oldValue) {
|
2020-06-19 23:03:26 +00:00
|
|
|
return FavoriteFilesRepository.instance.setLiked(file, !oldValue);
|
2020-05-06 16:43:03 +00:00
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
2020-06-13 18:47:48 +00:00
|
|
|
|
2020-06-19 23:03:26 +00:00
|
|
|
Future<void> _displayInfo(File file) async {
|
|
|
|
final asset = await file.getAsset();
|
2020-06-13 18:47:48 +00:00
|
|
|
return showDialog<void>(
|
|
|
|
context: context,
|
|
|
|
builder: (BuildContext context) {
|
2020-06-19 23:03:26 +00:00
|
|
|
var items = <Widget>[
|
|
|
|
Row(
|
|
|
|
children: [
|
|
|
|
Icon(Icons.timer),
|
|
|
|
Padding(padding: EdgeInsets.all(4)),
|
|
|
|
Text(getFormattedTime(
|
|
|
|
DateTime.fromMicrosecondsSinceEpoch(file.createTimestamp))),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
Padding(padding: EdgeInsets.all(4)),
|
|
|
|
Row(
|
|
|
|
children: [
|
|
|
|
Icon(Icons.folder),
|
|
|
|
Padding(padding: EdgeInsets.all(4)),
|
|
|
|
Text(file.deviceFolder),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
Padding(padding: EdgeInsets.all(4)),
|
|
|
|
];
|
|
|
|
if (file.fileType == FileType.image) {
|
|
|
|
items.add(Row(
|
|
|
|
children: [
|
|
|
|
Icon(Icons.photo_size_select_actual),
|
|
|
|
Padding(padding: EdgeInsets.all(4)),
|
|
|
|
Text(asset.width.toString() + " x " + asset.height.toString()),
|
|
|
|
],
|
|
|
|
));
|
|
|
|
} else {
|
|
|
|
items.add(Row(
|
|
|
|
children: [
|
|
|
|
Icon(Icons.timer),
|
|
|
|
Padding(padding: EdgeInsets.all(4)),
|
|
|
|
Text(asset.videoDuration.toString()),
|
|
|
|
],
|
|
|
|
));
|
|
|
|
}
|
2020-06-13 18:47:48 +00:00
|
|
|
return AlertDialog(
|
2020-06-19 23:03:26 +00:00
|
|
|
title: Text(file.title),
|
2020-06-13 18:47:48 +00:00
|
|
|
content: SingleChildScrollView(
|
|
|
|
child: ListBody(
|
2020-06-19 23:03:26 +00:00
|
|
|
children: items,
|
2020-06-13 18:47:48 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
actions: <Widget>[
|
|
|
|
FlatButton(
|
|
|
|
child: Text('Ok'),
|
|
|
|
onPressed: () {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
2020-04-23 20:00:20 +00:00
|
|
|
}
|