123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- import 'dart:io';
- import 'dart:ui';
- import 'package:flutter/material.dart';
- import 'package:implicitly_animated_reorderable_list/implicitly_animated_reorderable_list.dart';
- import 'package:implicitly_animated_reorderable_list/transitions.dart';
- import 'package:photos/core/configuration.dart';
- import 'package:photos/core/event_bus.dart';
- import 'package:photos/db/files_db.dart';
- import 'package:photos/events/backup_folders_updated_event.dart';
- import 'package:photos/models/file.dart';
- import 'package:photos/ui/common_elements.dart';
- import 'package:photos/ui/loading_widget.dart';
- import 'package:photos/ui/thumbnail_widget.dart';
- class BackupFolderSelectionPage extends StatefulWidget {
- final bool shouldSelectAll;
- final String buttonText;
- const BackupFolderSelectionPage({
- @required this.buttonText,
- this.shouldSelectAll = false,
- Key key,
- }) : super(key: key);
- @override
- _BackupFolderSelectionPageState createState() =>
- _BackupFolderSelectionPageState();
- }
- class _BackupFolderSelectionPageState extends State<BackupFolderSelectionPage> {
- final Set<String> _allFolders = <String>{};
- Set<String> _selectedFolders = <String>{};
- List<File> _latestFiles;
- Map<String, int> _itemCount;
- @override
- void initState() {
- _selectedFolders = Configuration.instance.getPathsToBackUp();
- FilesDB.instance.getLatestLocalFiles().then((files) async {
- _itemCount = await FilesDB.instance.getFileCountInDeviceFolders();
- setState(() {
- _latestFiles = files;
- _latestFiles.sort((first, second) {
- return first.deviceFolder
- .toLowerCase()
- .compareTo(second.deviceFolder.toLowerCase());
- });
- for (final file in _latestFiles) {
- _allFolders.add(file.deviceFolder);
- }
- if (widget.shouldSelectAll) {
- _selectedFolders.addAll(_allFolders);
- }
- _selectedFolders.removeWhere((folder) => !_allFolders.contains(folder));
- });
- });
- super.initState();
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(title: Text("select folders to backup")),
- body: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Padding(
- padding: EdgeInsets.all(12),
- ),
- Padding(
- padding: const EdgeInsets.only(left: 32, right: 32),
- child: Text(
- "the selected folders will be end-to-end encrypted and backed up",
- style: TextStyle(
- color: Colors.white.withOpacity(0.4),
- fontSize: 14,
- height: 1.3,
- ),
- textAlign: TextAlign.center,
- ),
- ),
- Padding(
- padding: EdgeInsets.all(10),
- ),
- _latestFiles == null
- ? Container()
- : GestureDetector(
- behavior: HitTestBehavior.translucent,
- child: Padding(
- padding: const EdgeInsets.fromLTRB(6, 6, 64, 6),
- child: Align(
- alignment: Alignment.centerRight,
- child: Text(
- _selectedFolders.length == _allFolders.length
- ? "unselect all"
- : "select all",
- textAlign: TextAlign.right,
- style: TextStyle(
- fontSize: 12,
- color: Colors.white.withOpacity(0.8),
- ),
- ),
- ),
- ),
- onTap: () {
- final hasSelectedAll =
- _selectedFolders.length == _allFolders.length;
- // Flip selection
- if (hasSelectedAll) {
- _selectedFolders.clear();
- } else {
- _selectedFolders.addAll(_allFolders);
- }
- _latestFiles.sort((first, second) {
- return first.deviceFolder
- .toLowerCase()
- .compareTo(second.deviceFolder.toLowerCase());
- });
- setState(() {});
- }),
- Expanded(child: _getFolders()),
- Padding(
- padding: EdgeInsets.all(20),
- ),
- Hero(
- tag: "select_folders",
- child: Container(
- padding: EdgeInsets.only(
- left: 60, right: 60, bottom: Platform.isIOS ? 60 : 32),
- child: button(
- widget.buttonText,
- fontSize: 18,
- onPressed: _selectedFolders.isEmpty
- ? null
- : () async {
- await Configuration.instance
- .setPathsToBackUp(_selectedFolders);
- Bus.instance.fire(BackupFoldersUpdatedEvent());
- Navigator.of(context).pop();
- },
- padding: EdgeInsets.fromLTRB(60, 20, 60, 20),
- ),
- ),
- ),
- ],
- ),
- );
- }
- Widget _getFolders() {
- if (_latestFiles == null) {
- return loadWidget;
- }
- _sortFiles();
- final scrollController = ScrollController();
- return Container(
- padding: EdgeInsets.only(left: 40, right: 40),
- child: Scrollbar(
- controller: scrollController,
- isAlwaysShown: true,
- child: Padding(
- padding: const EdgeInsets.only(right: 4),
- child: ImplicitlyAnimatedReorderableList<File>(
- controller: scrollController,
- items: _latestFiles,
- areItemsTheSame: (oldItem, newItem) =>
- oldItem.deviceFolder == newItem.deviceFolder,
- onReorderFinished: (item, from, to, newItems) {
- setState(() {
- _latestFiles
- ..clear()
- ..addAll(newItems);
- });
- },
- itemBuilder: (context, itemAnimation, file, index) {
- return Reorderable(
- key: ValueKey(file),
- builder: (context, dragAnimation, inDrag) {
- final t = dragAnimation.value;
- final elevation = lerpDouble(0, 8, t);
- final color = Color.lerp(
- Colors.white, Colors.white.withOpacity(0.8), t);
- return SizeFadeTransition(
- sizeFraction: 0.7,
- curve: Curves.easeInOut,
- animation: itemAnimation,
- child: Material(
- color: color,
- elevation: elevation,
- type: MaterialType.transparency,
- child: _getFileItem(file),
- ),
- );
- },
- );
- },
- ),
- ),
- ),
- );
- }
- Widget _getFileItem(File file) {
- final isSelected = _selectedFolders.contains(file.deviceFolder);
- return Padding(
- padding: const EdgeInsets.only(bottom: 1, right: 4),
- child: Container(
- decoration: BoxDecoration(
- border: Border.all(
- color: Colors.black,
- ),
- borderRadius: BorderRadius.all(
- Radius.circular(10),
- ),
- color: isSelected
- ? Color.fromRGBO(16, 32, 32, 1)
- : Color.fromRGBO(8, 18, 18, 0.4),
- ),
- padding: EdgeInsets.fromLTRB(20, 16, 20, 16),
- child: InkWell(
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Row(
- children: [
- _getThumbnail(file),
- Padding(padding: EdgeInsets.all(10)),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Container(
- constraints: BoxConstraints(maxWidth: 140),
- child: Text(
- file.deviceFolder,
- style: TextStyle(
- fontSize: 14,
- height: 1.5,
- color: isSelected
- ? Colors.white
- : Colors.white.withOpacity(0.7),
- ),
- overflow: TextOverflow.ellipsis,
- maxLines: 2,
- ),
- ),
- Padding(padding: EdgeInsets.all(2)),
- Text(
- _itemCount[file.deviceFolder].toString() +
- " item" +
- (_itemCount[file.deviceFolder] == 1 ? "" : "s"),
- textAlign: TextAlign.left,
- style: TextStyle(
- fontSize: 12,
- color: isSelected
- ? Colors.white.withOpacity(0.65)
- : Colors.white.withOpacity(0.4),
- ),
- ),
- ],
- ),
- ],
- ),
- Checkbox(
- value: isSelected,
- onChanged: (value) {
- if (value) {
- _selectedFolders.add(file.deviceFolder);
- } else {
- _selectedFolders.remove(file.deviceFolder);
- }
- setState(() {});
- },
- ),
- ],
- ),
- onTap: () {
- final value = !_selectedFolders.contains(file.deviceFolder);
- if (value) {
- _selectedFolders.add(file.deviceFolder);
- } else {
- _selectedFolders.remove(file.deviceFolder);
- }
- setState(() {});
- },
- ),
- ),
- );
- }
- void _sortFiles() {
- _latestFiles.sort((first, second) {
- if (_selectedFolders.contains(first.deviceFolder) &&
- _selectedFolders.contains(second.deviceFolder)) {
- return first.deviceFolder
- .toLowerCase()
- .compareTo(second.deviceFolder.toLowerCase());
- } else if (_selectedFolders.contains(first.deviceFolder)) {
- return -1;
- } else if (_selectedFolders.contains(second.deviceFolder)) {
- return 1;
- }
- return first.deviceFolder
- .toLowerCase()
- .compareTo(second.deviceFolder.toLowerCase());
- });
- }
- Widget _getThumbnail(File file) {
- return ClipRRect(
- borderRadius: BorderRadius.circular(4.0),
- child: SizedBox(
- child: ThumbnailWidget(
- file,
- shouldShowSyncStatus: false,
- key: Key("backup_selection_widget" + file.tag()),
- ),
- height: 60,
- width: 60,
- ),
- );
- }
- }
|