Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve custom selection page #42

Merged
merged 3 commits into from
Dec 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/lang/de.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,6 @@ const Map<String, String> de = {
'dateRange': 'Datumsbereich',
'clipsFound': 'Clips gefunden',
'enterSubtitles': 'Untertitel eingeben',
'totalSelected': 'Gesamt ausgewählt: ',
'selectVideos': 'Videos auswählen',
};
2 changes: 2 additions & 0 deletions lib/lang/en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,6 @@ const Map<String, String> en = {
'dateRange': 'Date Range',
'clipsFound': 'Clips Found',
'enterSubtitles': 'Enter subtitles',
'totalSelected': 'Total Selected: ',
'selectVideos': 'Select videos',
};
2 changes: 2 additions & 0 deletions lib/lang/es.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,6 @@ const Map<String, String> es = {
'dateRange': 'Rango de fechas',
'clipsFound': 'Clips encontrados',
'enterSubtitles': 'Introducir subtítulos',
'totalSelected': 'Total seleccionado: ',
'selectVideos': 'Seleccionar videos',
};
2 changes: 2 additions & 0 deletions lib/lang/fr.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,6 @@ const Map<String, String> fr = {
'dateRange': 'Date Range',
'clipsFound': 'Clips trouvés',
'enterSubtitles': 'Entrer le sous-titre',
'totalSelected': 'Total sélectionné: ',
'selectVideos': 'Sélectionnez les vidéos',
};
2 changes: 2 additions & 0 deletions lib/lang/id.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,6 @@ const Map<String, String> id = {
'dateRange': 'Rentang tanggal',
'clipsFound': 'Klip ditemukan',
'enterSubtitles': 'Masukkan subjudul',
'totalSelected': 'Total dipilih: ',
'selectVideos': 'Pilih video',
};
2 changes: 2 additions & 0 deletions lib/lang/pt.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,6 @@ const Map<String, String> pt = {
'dateRange': 'Período',
'clipsFound': 'Clipes encontrados',
'enterSubtitles': 'Digite uma legenda',
'totalSelected': 'Total selecionado: ',
'selectVideos': 'Escolha os vídeos',
};
2 changes: 2 additions & 0 deletions lib/lang/zh.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,6 @@ const Map<String, String> zh = {
'dateRange': '日期范围',
'clipsFound': '找到夹子',
'enterSubtitles': '输入字幕',
'totalSelected': '总选定: ',
'selectVideos': '选择视频',
};
176 changes: 107 additions & 69 deletions lib/pages/home/create_movie/widgets/select_video_from_storage.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:one_second_diary/utils/lazy_future_builder.dart';
import 'package:get/get.dart';
import 'package:video_thumbnail/video_thumbnail.dart';

import '../../../../utils/lazy_future_builder.dart';
import '../../../../utils/utils.dart';
import 'create_movie_button.dart';

Expand All @@ -18,6 +21,7 @@ class _SelectVideoFromStorageState extends State<SelectVideoFromStorage> {
late List<String> allVideos;
late List<bool> isSelected;
late List<GlobalKey> globalKeys;
Map<String, Uint8List?> thumbnails = {};
final ScrollController scrollController = ScrollController();

@override
Expand All @@ -34,88 +38,114 @@ class _SelectVideoFromStorageState extends State<SelectVideoFromStorage> {
final int totalSelected = isSelected.where((element) => element).length;
return Scaffold(
appBar: AppBar(
title: const Text('Select videos'),
title: Text('selectVideos'.tr),
actions: [
IconButton(
icon: const Icon(Icons.deselect),
onPressed: () {
setState(() {
isSelected = List.filled(allVideos.length, false);
});
},
),
IconButton(
icon: const Icon(Icons.select_all),
onPressed: () {
setState(() {
isSelected = List.filled(allVideos.length, true);
});
},
),
],
),
body: Column(
children: [
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.symmetric(vertical: 20.0),
// TODO: translate
child: Text(
'Total selected: $totalSelected',
'${'totalSelected'.tr}$totalSelected',
),
),
Expanded(
child: GridView.builder(
cacheExtent: 100,
shrinkWrap: true,
child: Scrollbar(
thickness: 10,
thumbVisibility: true,
controller: scrollController,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 1.12,
),
itemCount: allVideos.length,
itemBuilder: (context, index) {
return Column(
children: [
Text(
allVideos[index].split('/').last.split('.mp4')[0],
key: globalKeys[index],
),
GestureDetector(
onTap: () {
setState(() {
isSelected[index] = !isSelected[index];
});
if (isSelected[index] &&
index != allVideos.length - 1) {
scrollController.position.ensureVisible(
globalKeys[index + 1]
.currentContext!
.findRenderObject()!,
duration: const Duration(milliseconds: 750),
);
}
},
child: Container(
margin: const EdgeInsets.all(15.0),
decoration: BoxDecoration(
border: Border.all(
color:
isSelected[index] ? Colors.green : Colors.white,
width: isSelected[index] ? 3 : 0,
interactive: true,
radius:
const Radius.circular(10), // give the thumb rounded corners
child: GridView.builder(
addAutomaticKeepAlives: true,
cacheExtent: 100,
shrinkWrap: true,
controller: scrollController,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 1.12,
),
itemCount: allVideos.length,
itemBuilder: (context, index) {
return Column(
children: [
Text(
allVideos[index].split('/').last.split('.mp4')[0],
key: globalKeys[index],
),
GestureDetector(
onTap: () {
setState(() {
isSelected[index] = !isSelected[index];
});
if (isSelected[index] &&
index != allVideos.length - 1) {
scrollController.position.ensureVisible(
globalKeys[index + 1]
.currentContext!
.findRenderObject()!,
duration: const Duration(milliseconds: 750),
);
}
},
child: Container(
margin: const EdgeInsets.all(15.0),
decoration: BoxDecoration(
border: Border.all(
color: isSelected[index]
? Colors.green
: Colors.white,
width: isSelected[index] ? 4 : 1,
),
borderRadius: BorderRadius.circular(5),
),
borderRadius: BorderRadius.circular(5),
),
child: LazyFutureBuilder(
future: () => getThumbnail(allVideos[index]),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return const Center(
child: SizedBox(
height: 30,
width: 30,
child: CircularProgressIndicator(),
),
);
}
child: LazyFutureBuilder(
future: () => getThumbnail(allVideos[index]),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return const Center(
child: SizedBox(
height: 30,
width: 30,
child: CircularProgressIndicator(),
),
);
}

if (snapshot.hasError) {
// TODO: translate
return Text(
'An error occured: ${snapshot.error}',
);
}
return Image.memory(snapshot.data as Uint8List);
},
if (snapshot.hasError) {
return Text(
'${snapshot.error}',
);
}
return Image.memory(snapshot.data as Uint8List);
},
),
),
),
),
],
);
},
],
);
},
),
),
),
if (totalSelected >= 2) ...{
Expand All @@ -133,9 +163,17 @@ class _SelectVideoFromStorageState extends State<SelectVideoFromStorage> {
}

Future<Uint8List?> getThumbnail(String video) async {
return await VideoThumbnail.thumbnailData(
if (thumbnails.containsKey(video)) {
return thumbnails[video];
}
final thumbnail = await VideoThumbnail.thumbnailData(
video: File(video).path,
imageFormat: ImageFormat.JPEG,
quality: 8,
);
setState(() {
thumbnails[video] = thumbnail;
});
return thumbnail;
}
}