From c1e394bf0fbc6426d2ae38e7c58154dfeb0c797f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phil=C3=A9as?= Date: Fri, 15 Dec 2023 18:03:48 +0100 Subject: [PATCH 01/13] Added vertical profiles logic in Settings pages. --- lib/models/profile.dart | 2 + lib/pages/home/profiles/profiles_page.dart | 62 +++++++++++++++---- lib/pages/home/settings/settings_page.dart | 2 + .../settings/widgets/switch_verticalmode.dart | 50 +++++++++++++++ lib/utils/storage_utils.dart | 10 ++- lib/utils/vertical.dart | 38 ++++++++++++ 6 files changed, 151 insertions(+), 13 deletions(-) create mode 100644 lib/pages/home/settings/widgets/switch_verticalmode.dart create mode 100644 lib/utils/vertical.dart diff --git a/lib/models/profile.dart b/lib/models/profile.dart index a317565..562bf4b 100644 --- a/lib/models/profile.dart +++ b/lib/models/profile.dart @@ -5,8 +5,10 @@ class Profile { const Profile({ required this.label, this.isDefault = false, + this.isVertical = false, }); final String label; final bool isDefault; + final bool isVertical; } diff --git a/lib/pages/home/profiles/profiles_page.dart b/lib/pages/home/profiles/profiles_page.dart index 40fac24..25f930f 100644 --- a/lib/pages/home/profiles/profiles_page.dart +++ b/lib/pages/home/profiles/profiles_page.dart @@ -10,6 +10,7 @@ import '../../../utils/shared_preferences_util.dart'; import '../../../utils/storage_utils.dart'; import '../../../utils/theme.dart'; import '../../../utils/utils.dart'; +import '../../../utils/vertical.dart'; class ProfilesPage extends StatefulWidget { const ProfilesPage({super.key}); @@ -31,6 +32,10 @@ class _ProfilesPageState extends State { final DailyEntryController dailyEntryController = Get.find(); + final List verticalModeSelector = [true, false]; + + bool _verticalModeSwitch = false; + @override void initState() { super.initState(); @@ -52,17 +57,22 @@ class _ProfilesPageState extends State { if (!storedProfiles.contains('Default')) { profiles.insert( 0, - const Profile(label: 'Default', isDefault: true), + const Profile(label: 'Default', isDefault: true, isVertical: false), ); } else { + + // Profiles strings ending with '_vertical' creates an Profile object with isVertical value true, as other not. profiles = storedProfiles.map( (e) { - if (e == 'Default') return Profile(label: e, isDefault: true); - return Profile(label: e); + if (e == 'Default') return Profile(label: e, isDefault: true, isVertical: false); + if (e.endsWith('_vertical')) return Profile(label: e.replaceAll('_vertical', ''), isVertical: true); + else return Profile(label: e, isVertical: false); }, ).toList(); } + + Utils.logInfo('${logTag}Stored Profiles are: $storedProfiles'); } @@ -88,6 +98,24 @@ class _ProfilesPageState extends State { 'newProfileTooltip'.tr, ), const SizedBox(height: 12), + Switch( + value: _verticalModeSwitch, + onChanged: (value) { + setState(() { + _verticalModeSwitch = value; + }); + }, + ), + /*ToggleButtons( + children: verticalModeTexts, + isSelected: [_isToggled, !_isToggled], + onPressed: (int index) { + setState(() { + _isToggled = index == 0; + }); + } + ),*/ + const SizedBox(height: 12), TextFormField( controller: _profileNameController, inputFormatters: [ @@ -140,13 +168,14 @@ class _ProfilesPageState extends State { actions: [ TextButton( onPressed: () async { - // Checks if the textfield is valid based on if the text passes all the validations we set + // Checks if the text field is valid based on if the text passes all the validations we set final bool isTextValid = _profileNameFormKey.currentState?.validate() ?? false; if (isTextValid) { // Create the profile directory for the new profile await StorageUtils.createSpecificProfileFolder( _profileNameController.text.trim(), + _verticalModeSwitch, ); Utils.logInfo( @@ -157,13 +186,17 @@ class _ProfilesPageState extends State { setState(() { profiles.insert( profiles.length, - Profile(label: _profileNameController.text.trim()), + Profile( + label: _profileNameController.text.trim(), + isVertical: _verticalModeSwitch), ); _profileNameController.clear(); }); // Add the modified profile list to persistence - final profileNamesToStringList = profiles.map((e) => e.label).toList(); + // Adds the string '_vertical' at the end of vertical profiles to keep this parameter persistent. + final profileNamesToStringList = profiles.map((e) => e.isVertical? '${e.label}_vertical' : e.label).toList(); + SharedPrefsUtil.putStringList('profiles', profileNamesToStringList); Navigator.pop(context); @@ -306,17 +339,24 @@ class _ProfilesPageState extends State { title: Text( profiles[index].isDefault ? 'default'.tr : profiles[index].label, ), - secondary: profiles[index].isDefault - ? null - : IconButton( + secondary: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + profiles[index].isVertical ? Icons.stay_current_portrait : Icons.stay_current_landscape, + ), + if(!profiles[index].isDefault) + IconButton( onPressed: () async { await _showDeleteProfileDialog(index); }, icon: const Icon( - Icons.delete_forever_rounded, - color: AppColors.mainColor, + Icons.delete_forever_rounded, + color: AppColors.mainColor, ), ), + ] + ), ), ); }, diff --git a/lib/pages/home/settings/settings_page.dart b/lib/pages/home/settings/settings_page.dart index ad3ac9d..86a13ac 100644 --- a/lib/pages/home/settings/settings_page.dart +++ b/lib/pages/home/settings/settings_page.dart @@ -9,6 +9,7 @@ import 'widgets/notifications_button.dart'; import 'widgets/preferences_button.dart'; import 'widgets/profiles_button.dart'; import 'widgets/switch_theme.dart'; +import 'widgets/switch_verticalmode.dart'; class SettingPage extends StatelessWidget { @override @@ -28,6 +29,7 @@ class SettingPage extends StatelessWidget { child: Column( children: [ SwitchThemeComponent(), + SwitchVerticalModeComponent(), PreferencesButton(), NotificationsButton(), ProfilesButton(), diff --git a/lib/pages/home/settings/widgets/switch_verticalmode.dart b/lib/pages/home/settings/widgets/switch_verticalmode.dart new file mode 100644 index 0000000..b44813d --- /dev/null +++ b/lib/pages/home/settings/widgets/switch_verticalmode.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../../utils/constants.dart'; +import '../../../../utils/vertical.dart'; + +class SwitchVerticalModeComponent extends StatefulWidget { + const SwitchVerticalModeComponent({Key? key}) : super(key: key); + @override + State createState() => _SwitchVerticalModeComponentState(); +} + +class _SwitchVerticalModeComponentState extends State { + final String title = 'verticalMode'.tr; + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 15.0), + child: Text( + title, + style: TextStyle( + fontSize: MediaQuery.of(context).size.width * 0.045, + ), + ), + ), + ValueBuilder( + initialValue: VerticalService().isVerticalMode(), + builder: (isChecked, updateFn) => Switch( + value: isChecked!, + onChanged: (value) { + updateFn(!VerticalService().isVerticalMode()); + VerticalService().switchVerticalMode(); + }, + activeTrackColor: AppColors.mainColor.withOpacity(0.4), + activeColor: AppColors.mainColor, + ), + ), + ], + ), + const Divider(), + ], + ); + } +} diff --git a/lib/utils/storage_utils.dart b/lib/utils/storage_utils.dart index d5565b8..fefe00e 100644 --- a/lib/utils/storage_utils.dart +++ b/lib/utils/storage_utils.dart @@ -411,10 +411,16 @@ class StorageUtils { } // Create specific profile folder in internal storage - static Future createSpecificProfileFolder(String profileName) async { + static Future createSpecificProfileFolder(String profileName, bool verticalMode) async { try { final String appPath = SharedPrefsUtil.getString('appPath'); - final String profilePath = '$appPath/Profiles/$profileName/'; + + // Vertical Profiles are stored in a folder ending with _vertical. + if(verticalMode) { + profileName = '${profileName}_vertical'; + } + + String profilePath = '$appPath/Profiles/$profileName/'; // Checking if the folder really exists, if not, then create it final io.Directory? profileDirectory = io.Directory(profilePath); diff --git a/lib/utils/vertical.dart b/lib/utils/vertical.dart new file mode 100644 index 0000000..abe3d8d --- /dev/null +++ b/lib/utils/vertical.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:one_second_diary/utils/utils.dart'; + +import 'constants.dart'; +import 'shared_preferences_util.dart'; + +class Vertical { + + +} + +class VerticalService { + final _key = 'isVerticalMode'; + + // Dark Mode is true by default + bool isVerticalMode() => SharedPrefsUtil.getBool(_key) ?? true; + + Future _saveVerticalMode(bool isDarkMode) => + SharedPrefsUtil.putBool(_key, isDarkMode); + + void switchVerticalMode() { + Utils.logInfo("Switched vertical mode"); + //Get.changeThemeMode(isDarkTheme() ? ThemeMode.light : ThemeMode.dark); + _saveVerticalMode(!isVerticalMode()); + } + + bool isProfileVertical(String profile) { + switch (profile) { + case "Sold": + return true; + case "Not Sold": + return false; + default: + return false; + } + } +} From 312db213cd113417bd682ec22cd356b69fa2a01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phil=C3=A9as?= Date: Sun, 17 Dec 2023 13:31:53 +0100 Subject: [PATCH 02/13] The beginnings of vertical mode * Create a system for creating vertical profiles. * When you select a vertical profile, create 1080x1920 videos. * When creating a snipper in vertical mode, checks the aspect ratio. If it's 4/3, crop it to fit 9/16. --- lib/models/profile.dart | 3 -- .../calendar_editor/calendar_editor_page.dart | 2 +- .../widgets/create_movie_button.dart | 2 +- lib/pages/home/profiles/profiles_page.dart | 3 +- lib/pages/save_video/save_video_page.dart | 8 +++-- lib/pages/save_video/widgets/save_button.dart | 30 ++++++++++++++-- lib/utils/utils.dart | 34 ++++++++++++++++--- 7 files changed, 65 insertions(+), 17 deletions(-) diff --git a/lib/models/profile.dart b/lib/models/profile.dart index 562bf4b..e99d7f8 100644 --- a/lib/models/profile.dart +++ b/lib/models/profile.dart @@ -1,6 +1,3 @@ -import 'package:flutter/material.dart'; - -@immutable class Profile { const Profile({ required this.label, diff --git a/lib/pages/home/calendar_editor/calendar_editor_page.dart b/lib/pages/home/calendar_editor/calendar_editor_page.dart index 02a837f..b2b50d3 100644 --- a/lib/pages/home/calendar_editor/calendar_editor_page.dart +++ b/lib/pages/home/calendar_editor/calendar_editor_page.dart @@ -79,7 +79,7 @@ class _CalendarEditorPageState extends State { } void setMediaStorePath() { - final currentProfile = Utils.getCurrentProfile(); + final currentProfile = Utils.getCurrentProfileString(); if (currentProfile.isEmpty || currentProfile == 'Default') { MediaStore.appFolder = 'OneSecondDiary'; } else { diff --git a/lib/pages/home/create_movie/widgets/create_movie_button.dart b/lib/pages/home/create_movie/widgets/create_movie_button.dart index 831c48b..646646e 100644 --- a/lib/pages/home/create_movie/widgets/create_movie_button.dart +++ b/lib/pages/home/create_movie/widgets/create_movie_button.dart @@ -106,7 +106,7 @@ class _CreateMovieButtonState extends State { ScaffoldMessenger.of(context).showSnackBar(snackBar); // Get current profile - final currentProfileName = Utils.getCurrentProfile(); + final currentProfileName = Utils.getCurrentProfileString(); // Videos folder String videosFolder = SharedPrefsUtil.getString('appPath'); diff --git a/lib/pages/home/profiles/profiles_page.dart b/lib/pages/home/profiles/profiles_page.dart index 25f930f..5898701 100644 --- a/lib/pages/home/profiles/profiles_page.dart +++ b/lib/pages/home/profiles/profiles_page.dart @@ -10,7 +10,6 @@ import '../../../utils/shared_preferences_util.dart'; import '../../../utils/storage_utils.dart'; import '../../../utils/theme.dart'; import '../../../utils/utils.dart'; -import '../../../utils/vertical.dart'; class ProfilesPage extends StatefulWidget { const ProfilesPage({super.key}); @@ -390,7 +389,7 @@ class _ProfilesPageState extends State { // Update daily entry final String today = DateFormatUtils.getToday(); - final String profile = Utils.getCurrentProfile(); + final String profile = Utils.getCurrentProfileObject().label; String todaysVideoPath = SharedPrefsUtil.getString('appPath'); if (profile.isEmpty) { todaysVideoPath = '$todaysVideoPath$today.mp4'; diff --git a/lib/pages/save_video/save_video_page.dart b/lib/pages/save_video/save_video_page.dart index f4bd990..a52e037 100644 --- a/lib/pages/save_video/save_video_page.dart +++ b/lib/pages/save_video/save_video_page.dart @@ -10,6 +10,7 @@ import 'package:image_picker/image_picker.dart'; import 'package:video_trimmer/video_trimmer.dart'; import '../../controllers/recording_settings_controller.dart'; +import '../../models/profile.dart'; import '../../routes/app_pages.dart'; import '../../utils/constants.dart'; import '../../utils/custom_checkbox_list_tile.dart'; @@ -66,7 +67,7 @@ class _SaveVideoPageState extends State { bool _isLocationProcessing = false; late final bool isDarkTheme = ThemeService().isDarkTheme(); - String selectedProfileName = Utils.getCurrentProfile(); + Profile selectedProfile = Utils.getCurrentProfileObject(); void _initCorrectDates() { final DateTime selectedDate = routeArguments['currentDate']; @@ -527,6 +528,7 @@ class _SaveVideoPageState extends State { textOutlineWidth: textOutlineStrokeWidth, determinedDate: routeArguments['currentDate'], isFromRecordingPage: routeArguments['isFromRecordingPage'], + isVertical: selectedProfile.isVertical, ), ), body: Column( @@ -596,7 +598,7 @@ class _SaveVideoPageState extends State { const SizedBox(width: 8), Flexible( child: Text( - selectedProfileName.isEmpty ? 'default'.tr : selectedProfileName, + selectedProfile.label.isEmpty ? 'default'.tr : selectedProfile.label, style: TextStyle( fontSize: MediaQuery.of(context).size.height * 0.019, ), @@ -617,7 +619,7 @@ class _SaveVideoPageState extends State { onPressed: () { Get.to(const ProfilesPage())?.then( (_) => setState(() { - selectedProfileName = Utils.getCurrentProfile(); + selectedProfile = Utils.getCurrentProfileObject(); }), ); }, diff --git a/lib/pages/save_video/widgets/save_button.dart b/lib/pages/save_video/widgets/save_button.dart index 1b62f6f..48803bd 100644 --- a/lib/pages/save_video/widgets/save_button.dart +++ b/lib/pages/save_video/widgets/save_button.dart @@ -34,6 +34,7 @@ class SaveButton extends StatefulWidget { required this.videoEndInMilliseconds, required this.determinedDate, required this.isFromRecordingPage, + required this.isVertical, }); // Finding controllers @@ -53,6 +54,7 @@ class SaveButton extends StatefulWidget { final double videoEndInMilliseconds; final DateTime determinedDate; final bool isFromRecordingPage; + final bool isVertical; @override _SaveButtonState createState() => _SaveButtonState(); @@ -315,9 +317,31 @@ class _SaveButtonState extends State { // Trim video to the selected range final trim = '-ss ${videoStartInMilliseconds}ms -to ${videoEndInMilliseconds}ms'; - // Scale video to 1920x1080 and add black padding if needed - const scale = - 'scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black'; + // If video is created in a vertical profile, checks the aspect ratio. + String scale = ''; + if(widget.isVertical) { + + // Checks the aspect ratio of the video. + await executeFFprobe( + '-v error -select_streams v:0 -show_entries stream=display_aspect_ratio -of default=nw=1:nk=1 "$videoPath"') + .then((session) async { + final returnCode = await session.getReturnCode(); + if (ReturnCode.isSuccess(returnCode)) { + final sessionLog = await session.getOutput(); + Utils.logInfo('résultat ffprobe : $sessionLog'); + // 4:3 vidéos (ex : produced by pixel devices in photo modes), will be scaled up to fit into 1080x1920. + if (sessionLog!.contains('4:3')) { + scale = 'scale=1080:1920,crop=1080:1920'; + Utils.logInfo('${logTag}4/3 video detected, cropping to 9/16.'); + } else { + scale = 'scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black'; + } + } + }); + // Scale video to 1920x1080 and add black padding if needed + } else { + scale = 'scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black'; + } // Add date to the video final date = diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 0bb05c2..c4710b1 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -12,6 +12,7 @@ import 'package:url_launcher/url_launcher.dart'; import '../controllers/video_count_controller.dart'; import '../enums/export_date_range.dart'; +import '../models/profile.dart'; import 'date_format_utils.dart'; import 'shared_preferences_util.dart'; import 'storage_utils.dart'; @@ -148,7 +149,7 @@ class Utils { logInfo('[Utils.writeTxt()] - Writing txt file to $txtPath'); // Get current profile - final currentProfileName = getCurrentProfile(); + final currentProfileName = getCurrentProfileString(); // Default directory String videosFolderPath = SharedPrefsUtil.getString('appPath'); @@ -253,7 +254,7 @@ class Utils { } /// Get current profile name, empty string if Default - static String getCurrentProfile() { + static String getCurrentProfileString() { // Get current profile String currentProfileName = ''; @@ -267,10 +268,35 @@ class Utils { final profileLog = currentProfileName == '' ? 'Default' : currentProfileName; logInfo('[Utils.getCurrentProfile()] - Selected profile: $profileLog'); - return currentProfileName; } + /// Get current profile object, with isVertical property + static Profile getCurrentProfileObject() { + // Get current profile + String currentProfileName = ''; + bool isVertical = false; + + final selectedProfileIndex = SharedPrefsUtil.getInt('selectedProfileIndex') ?? 0; + if (selectedProfileIndex != 0) { + final allProfiles = SharedPrefsUtil.getStringList('profiles'); + if (allProfiles != null) { + currentProfileName = allProfiles[selectedProfileIndex]; + + // Vertical profiles are stored with '_vertical' and the end, but shown without. + if(currentProfileName.endsWith('_vertical')) { + isVertical = true; + currentProfileName.replaceAll('_vertical', ''); + } + } + } + + final profileLog = currentProfileName == '' ? 'Default' : currentProfileName; + logInfo('[Utils.getCurrentProfile()] - Selected profile: $profileLog'); + + return Profile(label: currentProfileName, isVertical: isVertical); + } + /// Get all video files inside DCIM/OneSecondDiary/Movies folder static List getAllMovies({bool fullPath = false}) { logInfo('[Utils.getAllMovies()] - Asked for full path: $fullPath'); @@ -301,7 +327,7 @@ class Utils { static List getAllVideos({bool fullPath = false}) { logInfo('[Utils.getAllVideos()] - Asked for full path: $fullPath'); // Get current profile - final currentProfileName = getCurrentProfile(); + final currentProfileName = getCurrentProfileString(); // Default directory io.Directory directory = io.Directory(SharedPrefsUtil.getString('appPath')); From 9ce00253e10a9648d11de120ec6b6ce39aceb04d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phil=C3=A9as?= Date: Sun, 17 Dec 2023 13:43:09 +0100 Subject: [PATCH 03/13] Remove useless stuff --- lib/pages/home/settings/settings_page.dart | 2 - .../settings/widgets/switch_verticalmode.dart | 50 ------------------- lib/utils/vertical.dart | 38 -------------- 3 files changed, 90 deletions(-) delete mode 100644 lib/pages/home/settings/widgets/switch_verticalmode.dart delete mode 100644 lib/utils/vertical.dart diff --git a/lib/pages/home/settings/settings_page.dart b/lib/pages/home/settings/settings_page.dart index 86a13ac..ad3ac9d 100644 --- a/lib/pages/home/settings/settings_page.dart +++ b/lib/pages/home/settings/settings_page.dart @@ -9,7 +9,6 @@ import 'widgets/notifications_button.dart'; import 'widgets/preferences_button.dart'; import 'widgets/profiles_button.dart'; import 'widgets/switch_theme.dart'; -import 'widgets/switch_verticalmode.dart'; class SettingPage extends StatelessWidget { @override @@ -29,7 +28,6 @@ class SettingPage extends StatelessWidget { child: Column( children: [ SwitchThemeComponent(), - SwitchVerticalModeComponent(), PreferencesButton(), NotificationsButton(), ProfilesButton(), diff --git a/lib/pages/home/settings/widgets/switch_verticalmode.dart b/lib/pages/home/settings/widgets/switch_verticalmode.dart deleted file mode 100644 index b44813d..0000000 --- a/lib/pages/home/settings/widgets/switch_verticalmode.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - -import '../../../../utils/constants.dart'; -import '../../../../utils/vertical.dart'; - -class SwitchVerticalModeComponent extends StatefulWidget { - const SwitchVerticalModeComponent({Key? key}) : super(key: key); - @override - State createState() => _SwitchVerticalModeComponentState(); -} - -class _SwitchVerticalModeComponentState extends State { - final String title = 'verticalMode'.tr; - - @override - Widget build(BuildContext context) { - return Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.only(left: 15.0), - child: Text( - title, - style: TextStyle( - fontSize: MediaQuery.of(context).size.width * 0.045, - ), - ), - ), - ValueBuilder( - initialValue: VerticalService().isVerticalMode(), - builder: (isChecked, updateFn) => Switch( - value: isChecked!, - onChanged: (value) { - updateFn(!VerticalService().isVerticalMode()); - VerticalService().switchVerticalMode(); - }, - activeTrackColor: AppColors.mainColor.withOpacity(0.4), - activeColor: AppColors.mainColor, - ), - ), - ], - ), - const Divider(), - ], - ); - } -} diff --git a/lib/utils/vertical.dart b/lib/utils/vertical.dart deleted file mode 100644 index abe3d8d..0000000 --- a/lib/utils/vertical.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import 'package:one_second_diary/utils/utils.dart'; - -import 'constants.dart'; -import 'shared_preferences_util.dart'; - -class Vertical { - - -} - -class VerticalService { - final _key = 'isVerticalMode'; - - // Dark Mode is true by default - bool isVerticalMode() => SharedPrefsUtil.getBool(_key) ?? true; - - Future _saveVerticalMode(bool isDarkMode) => - SharedPrefsUtil.putBool(_key, isDarkMode); - - void switchVerticalMode() { - Utils.logInfo("Switched vertical mode"); - //Get.changeThemeMode(isDarkTheme() ? ThemeMode.light : ThemeMode.dark); - _saveVerticalMode(!isVerticalMode()); - } - - bool isProfileVertical(String profile) { - switch (profile) { - case "Sold": - return true; - case "Not Sold": - return false; - default: - return false; - } - } -} From ddd84b2bf4a7d553a690bf0774555b7b699fdd39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phil=C3=A9as?= Date: Fri, 22 Dec 2023 14:43:21 +0100 Subject: [PATCH 04/13] Updated ffmpeg command when 4/3 video. Changed the scale command when saving a 4:3 video, to crop into 9:16. --- lib/pages/save_video/widgets/save_button.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/save_video/widgets/save_button.dart b/lib/pages/save_video/widgets/save_button.dart index 48803bd..ae219ea 100644 --- a/lib/pages/save_video/widgets/save_button.dart +++ b/lib/pages/save_video/widgets/save_button.dart @@ -331,7 +331,7 @@ class _SaveButtonState extends State { Utils.logInfo('résultat ffprobe : $sessionLog'); // 4:3 vidéos (ex : produced by pixel devices in photo modes), will be scaled up to fit into 1080x1920. if (sessionLog!.contains('4:3')) { - scale = 'scale=1080:1920,crop=1080:1920'; + scale = 'scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920'; Utils.logInfo('${logTag}4/3 video detected, cropping to 9/16.'); } else { scale = 'scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black'; From 11651e25a5781d4eead6e1fe245b89797cf0de0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phil=C3=A9as?= Date: Fri, 22 Dec 2023 19:56:12 +0100 Subject: [PATCH 05/13] Adapt Calendar player to show vertical videos properly The VideoPlayer in the Calendar page now uses the Aspect Ratio of the selected video. --- lib/pages/home/calendar_editor/calendar_editor_page.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pages/home/calendar_editor/calendar_editor_page.dart b/lib/pages/home/calendar_editor/calendar_editor_page.dart index b2b50d3..e29c58c 100644 --- a/lib/pages/home/calendar_editor/calendar_editor_page.dart +++ b/lib/pages/home/calendar_editor/calendar_editor_page.dart @@ -478,7 +478,8 @@ class _CalendarEditorPageState extends State { children: [ Align( alignment: Alignment.center, - child: ClipRect( + child: AspectRatio( + aspectRatio: _controller!.value.aspectRatio, child: VideoPlayer( key: _videoPlayerKey, _controller!, From c235b3d0507367fc9a62da3035b7b3c314a2b5c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phil=C3=A9as?= Date: Sat, 23 Dec 2023 00:44:02 +0100 Subject: [PATCH 06/13] Better (vertical) profile creation. Dialog for creating profiles now have a text to indicate that the toggle is to activate the vertical profile option. When toggling it on, showing an snackbar explaining the mode. --- lib/lang/de.dart | 3 ++ lib/lang/en.dart | 3 ++ lib/lang/es.dart | 3 ++ lib/lang/fr.dart | 3 ++ lib/pages/home/profiles/profiles_page.dart | 55 +++++++++++++++------- 5 files changed, 49 insertions(+), 18 deletions(-) diff --git a/lib/lang/de.dart b/lib/lang/de.dart index 03c9aa2..2aa081e 100644 --- a/lib/lang/de.dart +++ b/lib/lang/de.dart @@ -110,6 +110,9 @@ const Map de = { 'profileNameCannotBeEmpty': 'Profilname kann nicht leer sein', 'reservedProfileName': 'Dies ist ein reservierter Profilname', 'creatingMovie': 'Verarbeitung... Bitte warten.\nDies kann mehrere Minuten dauern.', + 'verticalProfileName': 'Vertikales Profil', + 'verticalProfileActivated': 'Dieses Profil enthält nur Snippets im Hochformat.', + 'verticalProfileDisabled': 'Dieses Profil enthält nur Snippets im Querformat.', 'doNotCloseTheApp': 'Bitte schließen Sie die\nApp nicht', 'cancelMovieCreation': 'Film erstellen abbrechen', 'cancelMovieDesc': 'Möchtest Du wirklich abbrechen?', diff --git a/lib/lang/en.dart b/lib/lang/en.dart index 2b50cc0..5748d6e 100644 --- a/lib/lang/en.dart +++ b/lib/lang/en.dart @@ -111,6 +111,9 @@ const Map en = { 'All videos associated with this profile will also be permanently deleted. Are you sure to continue?', 'profileNameCannotBeEmpty': 'Profile name cannot be empty', 'reservedProfileName': 'This is a reserved profile name', + 'verticalProfileName': 'Vertical Profile', + 'verticalProfileActivated': 'This profile will contain portrait snippets only.', + 'verticalProfileDisabled': 'This profile will contain landscape snippets only.', 'creatingMovie': 'Processing... Please wait.\nThis can take several minutes.', 'doNotCloseTheApp': 'Do not close the app', 'cancelMovieCreation': 'Cancel movie creation', diff --git a/lib/lang/es.dart b/lib/lang/es.dart index e0e896a..5b270d0 100644 --- a/lib/lang/es.dart +++ b/lib/lang/es.dart @@ -110,6 +110,9 @@ const Map es = { 'Todos los videos asociados con este perfil también se eliminarán permanentemente.¿Estás seguro de continuar?', 'profileNameCannotBeEmpty': 'El nombre del perfil no puede estar vacío', 'reservedProfileName': 'Este es un nombre de perfil reservado', + 'verticalProfileName': 'Perfil vertical', + 'verticalProfileActivated': 'Este perfil sólo contendrá fragmentos verticales', + 'verticalProfileDisabled': 'Este perfil sólo contendrá fragmentos apaisados', 'creatingMovie': 'Procesando... Por favor espera.\nEsto puede tomar varios minutos.', 'doNotCloseTheApp': 'No cierres la aplicación', 'cancelMovieCreation': 'Cancelar creación de película', diff --git a/lib/lang/fr.dart b/lib/lang/fr.dart index 48cfb69..52dd5a5 100644 --- a/lib/lang/fr.dart +++ b/lib/lang/fr.dart @@ -111,6 +111,9 @@ const Map fr = { 'Toutes les vidéos associées à ce profil seront également supprimées en permanence. Êtes-vous sûr de continuer?', 'profileNameCannotBeEmpty': 'Le nom du profil ne peut pas être vide', 'reservedProfileName': 'Ceci est un nom de profil réservé', + 'verticalProfileName': 'Profil Vertical', + 'verticalProfileActivated': 'Ce profil contiendra uniquement des vidéos au format portrait.', + 'verticalProfileDisabled': 'Ce profil contiendra uniquement des vidéos au format paysage', 'creatingMovie': 'Traitement... Veuillez patienter.\nCela peut prendre quelques minutes.', 'doNotCloseTheApp': 'Ne fermez pas l\'application', 'cancelMovieCreation': 'Annuler la création du film', diff --git a/lib/pages/home/profiles/profiles_page.dart b/lib/pages/home/profiles/profiles_page.dart index 5898701..1b534b0 100644 --- a/lib/pages/home/profiles/profiles_page.dart +++ b/lib/pages/home/profiles/profiles_page.dart @@ -96,25 +96,44 @@ class _ProfilesPageState extends State { Text( 'newProfileTooltip'.tr, ), - const SizedBox(height: 12), - Switch( - value: _verticalModeSwitch, - onChanged: (value) { - setState(() { - _verticalModeSwitch = value; - }); - }, + const SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'verticalProfileName'.tr, + ), + Switch( + value: _verticalModeSwitch, + activeTrackColor: AppColors.mainColor.withOpacity(0.4), + activeColor: AppColors.mainColor, + onChanged: (value) { + setState(() { + _verticalModeSwitch = value; + final snackBar = SnackBar( + margin: const EdgeInsets.all(70.0), + behavior: SnackBarBehavior.floating, + backgroundColor: Colors.black54, + duration: const Duration(seconds: 3), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(25), + ), + ), + content: Text( + _verticalModeSwitch? + 'verticalProfileActivated'.tr : + 'verticalProfileDisabled'.tr + ), + ); + //TODO : Show the snackbar in the foreground. + ScaffoldMessenger.of(context).showSnackBar(snackBar); + }); + }, + ), + ], ), - /*ToggleButtons( - children: verticalModeTexts, - isSelected: [_isToggled, !_isToggled], - onPressed: (int index) { - setState(() { - _isToggled = index == 0; - }); - } - ),*/ - const SizedBox(height: 12), + const SizedBox(height: 24), TextFormField( controller: _profileNameController, inputFormatters: [ From ac83a5c47cfb13c862a32a1be31370653f898a56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phil=C3=A9as?= Date: Sat, 23 Dec 2023 00:44:26 +0100 Subject: [PATCH 07/13] =?UTF-8?q?Adding=20myself=20to=20contributors=20?= =?UTF-8?q?=F0=9F=98=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 15377bc..cb86299 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -8,6 +8,7 @@ - Harry Schiller (@waitingwittykitty) - David Coker (@daoxve) - Adrasteon (@AdrasteonDev) +- Philéas (@phileas_imt) ## Testing & Feedback - Augusto Vesco From 3452bdc71e901442a4e63cde45de5c80d9886184 Mon Sep 17 00:00:00 2001 From: Caio Pedroso Date: Mon, 25 Dec 2023 10:23:23 -0300 Subject: [PATCH 08/13] Fix analyze --- lib/pages/home/profiles/profiles_page.dart | 90 +++++++++++----------- lib/utils/storage_utils.dart | 4 +- 2 files changed, 46 insertions(+), 48 deletions(-) diff --git a/lib/pages/home/profiles/profiles_page.dart b/lib/pages/home/profiles/profiles_page.dart index 379d41f..7651b0d 100644 --- a/lib/pages/home/profiles/profiles_page.dart +++ b/lib/pages/home/profiles/profiles_page.dart @@ -59,19 +59,18 @@ class _ProfilesPageState extends State { const Profile(label: 'Default', isDefault: true, isVertical: false), ); } else { - // Profiles strings ending with '_vertical' creates an Profile object with isVertical value true, as other not. profiles = storedProfiles.map( (e) { if (e == 'Default') return Profile(label: e, isDefault: true, isVertical: false); - if (e.endsWith('_vertical')) return Profile(label: e.replaceAll('_vertical', ''), isVertical: true); - else return Profile(label: e, isVertical: false); + if (e.endsWith('_vertical')) + return Profile(label: e.replaceAll('_vertical', ''), isVertical: true); + else + return Profile(label: e, isVertical: false); }, ).toList(); } - - Utils.logInfo('${logTag}Stored Profiles are: $storedProfiles'); } @@ -104,32 +103,30 @@ class _ProfilesPageState extends State { 'verticalProfileName'.tr, ), Switch( - value: _verticalModeSwitch, - activeTrackColor: AppColors.mainColor.withOpacity(0.4), - activeColor: AppColors.mainColor, - onChanged: (value) { - setState(() { - _verticalModeSwitch = value; - final snackBar = SnackBar( - margin: const EdgeInsets.all(70.0), - behavior: SnackBarBehavior.floating, - backgroundColor: Colors.black54, - duration: const Duration(seconds: 3), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(25), - ), - ), - content: Text( - _verticalModeSwitch? - 'verticalProfileActivated'.tr : - 'verticalProfileDisabled'.tr + value: _verticalModeSwitch, + activeTrackColor: AppColors.mainColor.withOpacity(0.4), + activeColor: AppColors.mainColor, + onChanged: (value) { + setState(() { + _verticalModeSwitch = value; + final snackBar = SnackBar( + margin: const EdgeInsets.all(70.0), + behavior: SnackBarBehavior.floating, + backgroundColor: Colors.black54, + duration: const Duration(seconds: 3), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(25), ), - ); - //TODO : Show the snackbar in the foreground. - ScaffoldMessenger.of(context).showSnackBar(snackBar); - }); - }, + ), + content: Text(_verticalModeSwitch + ? 'verticalProfileActivated'.tr + : 'verticalProfileDisabled'.tr), + ); + + ScaffoldMessenger.of(context).showSnackBar(snackBar); + }); + }, ), ], ), @@ -216,7 +213,9 @@ class _ProfilesPageState extends State { // Add the modified profile list to persistence // Adds the string '_vertical' at the end of vertical profiles to keep this parameter persistent. - final profileNamesToStringList = profiles.map((e) => e.isVertical? '${e.label}_vertical' : e.label).toList(); + final profileNamesToStringList = profiles + .map((e) => e.isVertical ? '${e.label}_vertical' : e.label) + .toList(); SharedPrefsUtil.putStringList('profiles', profileNamesToStringList); @@ -377,24 +376,23 @@ class _ProfilesPageState extends State { color: ThemeService().isDarkTheme() ? Colors.white : Colors.black, ), ), - secondary: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - profiles[index].isVertical ? Icons.stay_current_portrait : Icons.stay_current_landscape, - ), - if(!profiles[index].isDefault) - IconButton( - onPressed: () async { - await _showDeleteProfileDialog(index); - }, - icon: const Icon( + secondary: Row(mainAxisSize: MainAxisSize.min, children: [ + Icon( + profiles[index].isVertical + ? Icons.stay_current_portrait + : Icons.stay_current_landscape, + ), + if (!profiles[index].isDefault) + IconButton( + onPressed: () async { + await _showDeleteProfileDialog(index); + }, + icon: const Icon( Icons.delete_forever_rounded, color: AppColors.mainColor, - ), ), - ] - ), + ), + ]), ), ); }, diff --git a/lib/utils/storage_utils.dart b/lib/utils/storage_utils.dart index 36fb619..ead09f0 100644 --- a/lib/utils/storage_utils.dart +++ b/lib/utils/storage_utils.dart @@ -416,11 +416,11 @@ class StorageUtils { final String appPath = SharedPrefsUtil.getString('appPath'); // Vertical Profiles are stored in a folder ending with _vertical. - if(verticalMode) { + if (verticalMode) { profileName = '${profileName}_vertical'; } - String profilePath = '$appPath/Profiles/$profileName/'; + final profilePath = '$appPath/Profiles/$profileName/'; // Checking if the folder really exists, if not, then create it final io.Directory? profileDirectory = io.Directory(profilePath); From bb61249ea5676719f98f6dbc3873031f4e21c3af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phil=C3=A9as?= Date: Tue, 26 Dec 2023 18:18:59 +0100 Subject: [PATCH 09/13] Fixed Subtitles editor pages so it fits 9/16. Added a ConstrainedBox to do so. --- .../video_subtitles_editor_page.dart | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/lib/pages/home/calendar_editor/video_subtitles_editor_page.dart b/lib/pages/home/calendar_editor/video_subtitles_editor_page.dart index 474d944..b9e8438 100644 --- a/lib/pages/home/calendar_editor/video_subtitles_editor_page.dart +++ b/lib/pages/home/calendar_editor/video_subtitles_editor_page.dart @@ -170,35 +170,41 @@ class _VideoSubtitlesEditorPageState extends State { children: [ GestureDetector( onTap: () => videoPlay(), - child: AspectRatio( - aspectRatio: 16 / 9, - child: Stack( - children: [ - VideoPlayer( - key: UniqueKey(), - _videoController, - ), - Center( - child: Opacity( - opacity: _opacity, - child: Container( - width: MediaQuery.of(context).size.width * 0.25, - height: MediaQuery.of(context).size.width * 0.25, - decoration: const BoxDecoration( - color: Colors.black45, - shape: BoxShape.circle, - ), - child: const Center( - child: Icon( - Icons.play_arrow, - size: 72.0, - color: Colors.white, + // ConstrainedBox to fit vertical videos without overflowing + child: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height * 0.7 + ), + child: AspectRatio( + aspectRatio: _videoController!.value.aspectRatio, + child: Stack( + children: [ + VideoPlayer( + key: UniqueKey(), + _videoController, + ), + Center( + child: Opacity( + opacity: _opacity, + child: Container( + width: MediaQuery.of(context).size.width * 0.25, + height: MediaQuery.of(context).size.width * 0.25, + decoration: const BoxDecoration( + color: Colors.black45, + shape: BoxShape.circle, + ), + child: const Center( + child: Icon( + Icons.play_arrow, + size: 72.0, + color: Colors.white, + ), ), ), ), ), - ), - ], + ], + ), ), ), ), From a953d27ce950c33170e54ad3f10a9928a5fc8f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phil=C3=A9as?= Date: Tue, 26 Dec 2023 18:32:59 +0100 Subject: [PATCH 10/13] Better play of 9/16 videos on calendar editor page. Added padding on buttons. Corrected the VideoPlayer border. --- .../calendar_editor/calendar_editor_page.dart | 123 +++++++++--------- 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/lib/pages/home/calendar_editor/calendar_editor_page.dart b/lib/pages/home/calendar_editor/calendar_editor_page.dart index 70c685d..87a9c54 100644 --- a/lib/pages/home/calendar_editor/calendar_editor_page.dart +++ b/lib/pages/home/calendar_editor/calendar_editor_page.dart @@ -435,55 +435,55 @@ class _CalendarEditorPageState extends State { Padding( padding: const EdgeInsets.symmetric(horizontal: 20.0), child: AspectRatio( - aspectRatio: 16 / 9, - child: Container( - decoration: BoxDecoration( - border: Border.all(color: mainColor), - ), - child: Stack( - children: [ - Center( - child: SizedBox( - height: 30, - width: 30, - child: Icon( - Icons.hourglass_bottom, - color: mainColor, - ), + aspectRatio: 16/9, + child: Stack( + children: [ + Center( + child: SizedBox( + height: 30, + width: 30, + child: Icon( + Icons.hourglass_bottom, + color: mainColor, ), ), - FutureBuilder( - future: initializeVideoPlayback(currentVideo), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const SizedBox.shrink(); - } - - if (snapshot.hasError) { - return Text( - '"Error loading video: " + ${snapshot.error}', - ); - } - - // Not sure if it works but if the videoController fails we try to restart the page - if (_controller?.value.hasError == true) { - WidgetsBinding.instance.addPostFrameCallback((_) { - _controller?.dispose(); - }); - Get.offAllNamed(Routes.HOME) - ?.then((_) => setState(() {})); - } - - // VideoPlayer - if (_controller != null && - _controller!.value.isInitialized) { - return Align( - alignment: Alignment.center, - child: Stack( - fit: StackFit.passthrough, - children: [ - Align( - alignment: Alignment.center, + ), + FutureBuilder( + future: initializeVideoPlayback(currentVideo), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const SizedBox.shrink(); + } + + if (snapshot.hasError) { + return Text( + '"Error loading video: " + ${snapshot.error}', + ); + } + + // Not sure if it works but if the videoController fails we try to restart the page + if (_controller?.value.hasError == true) { + WidgetsBinding.instance.addPostFrameCallback((_) { + _controller?.dispose(); + }); + Get.offAllNamed(Routes.HOME) + ?.then((_) => setState(() {})); + } + + // VideoPlayer + if (_controller != null && + _controller!.value.isInitialized) { + return Align( + alignment: Alignment.center, + child: Stack( + fit: StackFit.passthrough, + children: [ + Align( + alignment: Alignment.center, + child: Container( + decoration: BoxDecoration( + border: Border.all(color: mainColor), + ), child: AspectRatio( aspectRatio: _controller!.value.aspectRatio, child: VideoPlayer( @@ -492,23 +492,24 @@ class _CalendarEditorPageState extends State { ), ), ), - Controls( - controller: _controller, - ), - ], - ), - ); - } else { - return const SizedBox.shrink(); - } - }, - ), - ], - ), + ), + Controls( + controller: _controller, + ), + ], + ), + ); + } else { + return const SizedBox.shrink(); + } + }, + ), + ], ), ), ), - Flexible( + Padding( + padding: const EdgeInsets.only(top: 15), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ From 19922ff4ba5d77cb2f6b62a63287f1957efb554f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phil=C3=A9as?= Date: Tue, 26 Dec 2023 19:59:10 +0100 Subject: [PATCH 11/13] Refactor getCurrentProfile --- lib/models/profile.dart | 2 + .../calendar_editor/calendar_editor_page.dart | 2 +- .../video_subtitles_editor_page.dart | 2 +- .../widgets/create_movie_button.dart | 2 +- lib/pages/home/profiles/profiles_page.dart | 19 ++++---- lib/pages/save_video/save_video_page.dart | 13 ++++-- lib/utils/utils.dart | 43 ++++++------------- 7 files changed, 39 insertions(+), 44 deletions(-) diff --git a/lib/models/profile.dart b/lib/models/profile.dart index e99d7f8..809134a 100644 --- a/lib/models/profile.dart +++ b/lib/models/profile.dart @@ -1,11 +1,13 @@ class Profile { const Profile({ required this.label, + required this.storageString, this.isDefault = false, this.isVertical = false, }); final String label; + final String storageString; final bool isDefault; final bool isVertical; } diff --git a/lib/pages/home/calendar_editor/calendar_editor_page.dart b/lib/pages/home/calendar_editor/calendar_editor_page.dart index 87a9c54..1cf7d87 100644 --- a/lib/pages/home/calendar_editor/calendar_editor_page.dart +++ b/lib/pages/home/calendar_editor/calendar_editor_page.dart @@ -79,7 +79,7 @@ class _CalendarEditorPageState extends State { } void setMediaStorePath() { - final currentProfile = Utils.getCurrentProfileString(); + final currentProfile = Utils.getCurrentProfile().storageString; if (currentProfile.isEmpty || currentProfile == 'Default') { MediaStore.appFolder = 'OneSecondDiary'; } else { diff --git a/lib/pages/home/calendar_editor/video_subtitles_editor_page.dart b/lib/pages/home/calendar_editor/video_subtitles_editor_page.dart index b9e8438..9c3e5b2 100644 --- a/lib/pages/home/calendar_editor/video_subtitles_editor_page.dart +++ b/lib/pages/home/calendar_editor/video_subtitles_editor_page.dart @@ -176,7 +176,7 @@ class _VideoSubtitlesEditorPageState extends State { maxHeight: MediaQuery.of(context).size.height * 0.7 ), child: AspectRatio( - aspectRatio: _videoController!.value.aspectRatio, + aspectRatio: _videoController.value.aspectRatio, child: Stack( children: [ VideoPlayer( diff --git a/lib/pages/home/create_movie/widgets/create_movie_button.dart b/lib/pages/home/create_movie/widgets/create_movie_button.dart index 646646e..584ae4e 100644 --- a/lib/pages/home/create_movie/widgets/create_movie_button.dart +++ b/lib/pages/home/create_movie/widgets/create_movie_button.dart @@ -106,7 +106,7 @@ class _CreateMovieButtonState extends State { ScaffoldMessenger.of(context).showSnackBar(snackBar); // Get current profile - final currentProfileName = Utils.getCurrentProfileString(); + final currentProfileName = Utils.getCurrentProfile().storageString; // Videos folder String videosFolder = SharedPrefsUtil.getString('appPath'); diff --git a/lib/pages/home/profiles/profiles_page.dart b/lib/pages/home/profiles/profiles_page.dart index 7651b0d..509e93c 100644 --- a/lib/pages/home/profiles/profiles_page.dart +++ b/lib/pages/home/profiles/profiles_page.dart @@ -56,17 +56,17 @@ class _ProfilesPageState extends State { if (!storedProfiles.contains('Default')) { profiles.insert( 0, - const Profile(label: 'Default', isDefault: true, isVertical: false), + const Profile(label: 'Default', storageString: 'Default', isDefault: true, isVertical: false), ); } else { // Profiles strings ending with '_vertical' creates an Profile object with isVertical value true, as other not. profiles = storedProfiles.map( (e) { - if (e == 'Default') return Profile(label: e, isDefault: true, isVertical: false); + if (e == 'Default') return Profile(label: e, storageString: e, isDefault: true, isVertical: false); if (e.endsWith('_vertical')) - return Profile(label: e.replaceAll('_vertical', ''), isVertical: true); + return Profile(label: e.replaceAll('_vertical', ''), storageString: e, isVertical: true); else - return Profile(label: e, isVertical: false); + return Profile(label: e, storageString: e, isVertical: false); }, ).toList(); } @@ -206,6 +206,8 @@ class _ProfilesPageState extends State { profiles.length, Profile( label: _profileNameController.text.trim(), + storageString: _verticalModeSwitch? '${_profileNameController.text.trim()}_vertical' + : _profileNameController.text.trim(), isVertical: _verticalModeSwitch), ); _profileNameController.clear(); @@ -214,8 +216,7 @@ class _ProfilesPageState extends State { // Add the modified profile list to persistence // Adds the string '_vertical' at the end of vertical profiles to keep this parameter persistent. final profileNamesToStringList = profiles - .map((e) => e.isVertical ? '${e.label}_vertical' : e.label) - .toList(); + .map((e) => e.storageString).toList(); SharedPrefsUtil.putStringList('profiles', profileNamesToStringList); @@ -269,11 +270,11 @@ class _ProfilesPageState extends State { onPressed: () async { // Delete the profile directory for the specific profile await StorageUtils.deleteSpecificProfileFolder( - profiles[index].label, + profiles[index].storageString, ); Utils.logWarning( - '${logTag}Profile ${profiles[index].label} deleted!', + '${logTag}Profile ${profiles[index].storageString} deleted!', ); // Remove the profile from the list @@ -426,7 +427,7 @@ class _ProfilesPageState extends State { // Update daily entry final String today = DateFormatUtils.getToday(); - final String profile = Utils.getCurrentProfileObject().label; + final String profile = Utils.getCurrentProfile().label; String todaysVideoPath = SharedPrefsUtil.getString('appPath'); if (profile.isEmpty) { todaysVideoPath = '$todaysVideoPath$today.mp4'; diff --git a/lib/pages/save_video/save_video_page.dart b/lib/pages/save_video/save_video_page.dart index 3b5eab1..96edbc3 100644 --- a/lib/pages/save_video/save_video_page.dart +++ b/lib/pages/save_video/save_video_page.dart @@ -67,7 +67,7 @@ class _SaveVideoPageState extends State { bool _isLocationProcessing = false; late final bool isDarkTheme = ThemeService().isDarkTheme(); - Profile selectedProfile = Utils.getCurrentProfileObject(); + Profile selectedProfile = Utils.getCurrentProfile(); void _initCorrectDates() { final DateTime selectedDate = routeArguments['currentDate']; @@ -604,13 +604,20 @@ class _SaveVideoPageState extends State { const SizedBox(width: 8), Flexible( child: Text( - selectedProfile.label.isEmpty ? 'default'.tr : selectedProfile.label, + selectedProfile.label.isEmpty ? 'default'.tr : + selectedProfile.isVertical ? selectedProfile.label.replaceAll('_vertical', '') + : selectedProfile.label, style: TextStyle( fontSize: MediaQuery.of(context).size.height * 0.019, ), ), ), const SizedBox(width: 20), + Icon( + selectedProfile.isVertical? Icons.stay_current_portrait : + Icons.stay_current_landscape + ), + const SizedBox(width: 20), Flexible( child: TextButton( style: ButtonStyle( @@ -625,7 +632,7 @@ class _SaveVideoPageState extends State { onPressed: () { Get.to(const ProfilesPage())?.then( (_) => setState(() { - selectedProfile = Utils.getCurrentProfileObject(); + selectedProfile = Utils.getCurrentProfile(); }), ); }, diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index c4710b1..467d2b7 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -149,7 +149,7 @@ class Utils { logInfo('[Utils.writeTxt()] - Writing txt file to $txtPath'); // Get current profile - final currentProfileName = getCurrentProfileString(); + final currentProfileName = getCurrentProfile().storageString; // Default directory String videosFolderPath = SharedPrefsUtil.getString('appPath'); @@ -253,48 +253,33 @@ class Utils { return '$hoursString:$minutesString:$secondsString,$millisecondsString'; } - /// Get current profile name, empty string if Default - static String getCurrentProfileString() { + /// Get current profile object, empty string if Default. + /// As vertical profiles are saved with suffix '_vertical', + /// storageString = what's in storage, label = name without suffix. + static Profile getCurrentProfile() { // Get current profile - String currentProfileName = ''; - - final selectedProfileIndex = SharedPrefsUtil.getInt('selectedProfileIndex') ?? 0; - if (selectedProfileIndex != 0) { - final allProfiles = SharedPrefsUtil.getStringList('profiles'); - if (allProfiles != null) { - currentProfileName = allProfiles[selectedProfileIndex]; - } - } - - final profileLog = currentProfileName == '' ? 'Default' : currentProfileName; - logInfo('[Utils.getCurrentProfile()] - Selected profile: $profileLog'); - return currentProfileName; - } - - /// Get current profile object, with isVertical property - static Profile getCurrentProfileObject() { - // Get current profile - String currentProfileName = ''; + String currentProfileStorageString = ''; + String currentProfileLabel = ''; bool isVertical = false; final selectedProfileIndex = SharedPrefsUtil.getInt('selectedProfileIndex') ?? 0; if (selectedProfileIndex != 0) { final allProfiles = SharedPrefsUtil.getStringList('profiles'); if (allProfiles != null) { - currentProfileName = allProfiles[selectedProfileIndex]; + currentProfileStorageString = allProfiles[selectedProfileIndex]; - // Vertical profiles are stored with '_vertical' and the end, but shown without. - if(currentProfileName.endsWith('_vertical')) { + // Vertical profiles are stored with '_vertical' in storage, but shown without. + if(currentProfileStorageString.endsWith('_vertical')) { isVertical = true; - currentProfileName.replaceAll('_vertical', ''); + currentProfileLabel = currentProfileStorageString.replaceAll('_vertical', ''); } } } - final profileLog = currentProfileName == '' ? 'Default' : currentProfileName; + final profileLog = currentProfileStorageString == '' ? 'Default' : currentProfileStorageString; logInfo('[Utils.getCurrentProfile()] - Selected profile: $profileLog'); - return Profile(label: currentProfileName, isVertical: isVertical); + return Profile(storageString: currentProfileStorageString, label: currentProfileLabel, isVertical: isVertical); } /// Get all video files inside DCIM/OneSecondDiary/Movies folder @@ -327,7 +312,7 @@ class Utils { static List getAllVideos({bool fullPath = false}) { logInfo('[Utils.getAllVideos()] - Asked for full path: $fullPath'); // Get current profile - final currentProfileName = getCurrentProfileString(); + final currentProfileName = getCurrentProfile().storageString; // Default directory io.Directory directory = io.Directory(SharedPrefsUtil.getString('appPath')); From d64f745f6432a15be20aa76492714e37e1535ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Phil=C3=A9as?= Date: Tue, 26 Dec 2023 21:32:22 +0100 Subject: [PATCH 12/13] Add a check of mixed resolution when creating movie. --- lib/lang/en.dart | 4 ++ lib/lang/fr.dart | 6 ++- .../widgets/create_movie_button.dart | 39 +++++++++++++++++++ lib/pages/save_video/widgets/save_button.dart | 3 +- 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/lib/lang/en.dart b/lib/lang/en.dart index a4c85f1..7edb2c1 100644 --- a/lib/lang/en.dart +++ b/lib/lang/en.dart @@ -212,4 +212,8 @@ const Map en = { 'useAlternativeCalendarColors': 'Use alternative calendar colors', 'useAlternativeCalendarColorsDescription': 'Changes green and red in calendar to blue and yellow. Useful for colorblind people.', + 'mixedResolutionAlert' : 'Mixed Resolutions detected', + 'mixedResolutionAlertDescription' : 'At least one snippet seems to have a different resolution.\n\n' + 'This can cause unexpected results when using your film.\n\n' + 'Try to delete theses files or move them to a different profile.' }; diff --git a/lib/lang/fr.dart b/lib/lang/fr.dart index 77f38e7..02a3641 100644 --- a/lib/lang/fr.dart +++ b/lib/lang/fr.dart @@ -213,5 +213,9 @@ const Map fr = { 'Lorsqu\'il est activé, sélectionner des dates passées filtrera les vidéos par cette date. Lorsqu\'il est désactivé, toutes les vidéos seront affichées. Fonctionne uniquement avec le sélecteur de fichiers expérimental.', 'useAlternativeCalendarColors': 'Utilisez des couleurs de calendrier alternatives', 'useAlternativeCalendarColorsDescription': - 'Change le vert et le rouge dans le calendrier en bleu et jaune. Utile pour les personnes daltoniennes.' + 'Change le vert et le rouge dans le calendrier en bleu et jaune. Utile pour les personnes daltoniennes.', + 'mixedResolutionAlert' : 'Mix de résolutions détecté.', + 'mixedResolutionAlertDescription' : 'Au moins une vidéo semble avoir un mix de résolutions.\n\n' + 'Cela peut produire des résultats innatendus lorsque vous utilisez votre film.\n\n' + 'Essayez de supprimer ces fichiers ou de les déplacer dans un autre profil.' }; diff --git a/lib/pages/home/create_movie/widgets/create_movie_button.dart b/lib/pages/home/create_movie/widgets/create_movie_button.dart index 584ae4e..adfac09 100644 --- a/lib/pages/home/create_movie/widgets/create_movie_button.dart +++ b/lib/pages/home/create_movie/widgets/create_movie_button.dart @@ -39,6 +39,8 @@ class _CreateMovieButtonState extends State { final VideoCountController controller = Get.find(); bool isProcessing = false; String progress = ''; + String usedResolution = ''; + var mixedResolutionError = []; void _openVideo(String filePath) async { await OpenFilex.open(filePath); @@ -153,6 +155,27 @@ class _CreateMovieButtonState extends State { } }); + // Checks if there is a mix of horizontal/vertical videos by comparing their resolution. + await executeFFprobe( + '-v quiet -show_entries stream=width,height -of default=nw=1:nk=1 "$currentVideo"') + .then((session) async { + final returnCode = await session.getReturnCode(); + if (ReturnCode.isSuccess(returnCode)) { + final sessionLog = await session.getOutput(); + if (sessionLog == usedResolution) { + return; + } else if (usedResolution == '' && sessionLog!.isNotEmpty) { + usedResolution = sessionLog; + } else { + mixedResolutionError.add(currentVideo); + } + } else { + final sessionLog = await session.getLogsAsString(); + Utils.logError('${logTag}Error checking if $currentVideo was recorded on v1.5'); + Utils.logError('${logTag}Error: $sessionLog'); + } + }); + // Make sure all selected videos have a subtitles and audio stream before creating movie, and finally check their resolution, resizes if necessary. // To avoid asking permission for every single video, we make a copy and leave the original untouched if (!isV1point5) { @@ -278,6 +301,22 @@ class _CreateMovieButtonState extends State { }); } + // Show an error if multiple resolutions is detected. + if(mixedResolutionError.isNotEmpty) { + showDialog( + barrierDismissible: false, + context: Get.context!, + builder: (context) => CustomDialog( + isDoubleAction: false, + title: 'mixedResolutionAlert'.tr, + content: "${'mixedResolutionAlertDescription'.tr}\n\n${mixedResolutionError.toString()}", + actionText: 'Ok', + actionColor: Colors.red, + action: () => Get.offAllNamed(Routes.HOME), + ), + ); + } + if (mounted) { setState(() { progress = '$currentIndex / ${selectedVideos.length}'; diff --git a/lib/pages/save_video/widgets/save_button.dart b/lib/pages/save_video/widgets/save_button.dart index cd1d4ba..a61582e 100644 --- a/lib/pages/save_video/widgets/save_button.dart +++ b/lib/pages/save_video/widgets/save_button.dart @@ -328,8 +328,7 @@ class _SaveButtonState extends State { final returnCode = await session.getReturnCode(); if (ReturnCode.isSuccess(returnCode)) { final sessionLog = await session.getOutput(); - Utils.logInfo('résultat ffprobe : $sessionLog'); - // 4:3 vidéos (ex : produced by pixel devices in photo modes), will be scaled up to fit into 1080x1920. + // 4:3 videos (ex : produced by pixel devices in photo modes), will be scaled up to fit into 1080x1920. if (sessionLog!.contains('4:3')) { scale = 'scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920'; Utils.logInfo('${logTag}4/3 video detected, cropping to 9/16.'); From f032fd2dde5555a63e97f49ff61d41de17782449 Mon Sep 17 00:00:00 2001 From: Caio Pedroso Date: Mon, 1 Jan 2024 15:16:32 -0300 Subject: [PATCH 13/13] adjusts --- lib/lang/en.dart | 9 ++-- lib/lang/fr.dart | 8 ++-- lib/pages/home/base/home_page.dart | 4 +- .../home/base/widgets/bottom_app_bar.dart | 3 +- .../calendar_editor/calendar_editor_page.dart | 10 ++--- .../video_subtitles_editor_page.dart | 6 +-- .../widgets/select_video_from_storage.dart | 5 ++- .../widgets/view_movies_page.dart | 1 + .../widgets/switch_notifications.dart | 32 ++++---------- lib/pages/home/profiles/profiles_page.dart | 42 ++++++++++++------- .../settings/widgets/backup_tutorial.dart | 1 - .../home/settings/widgets/contact_button.dart | 1 - .../home/settings/widgets/github_button.dart | 1 - .../settings/widgets/language_chooser.dart | 1 - .../widgets/notifications_button.dart | 4 +- .../settings/widgets/preferences_button.dart | 4 +- .../settings/widgets/preferences_page.dart | 2 +- .../settings/widgets/profiles_button.dart | 4 +- .../home/settings/widgets/switch_theme.dart | 1 - lib/pages/save_video/save_video_page.dart | 22 +++++----- lib/utils/theme.dart | 1 + 21 files changed, 73 insertions(+), 89 deletions(-) diff --git a/lib/lang/en.dart b/lib/lang/en.dart index 7edb2c1..69a9f1c 100644 --- a/lib/lang/en.dart +++ b/lib/lang/en.dart @@ -212,8 +212,9 @@ const Map en = { 'useAlternativeCalendarColors': 'Use alternative calendar colors', 'useAlternativeCalendarColorsDescription': 'Changes green and red in calendar to blue and yellow. Useful for colorblind people.', - 'mixedResolutionAlert' : 'Mixed Resolutions detected', - 'mixedResolutionAlertDescription' : 'At least one snippet seems to have a different resolution.\n\n' - 'This can cause unexpected results when using your film.\n\n' - 'Try to delete theses files or move them to a different profile.' + 'mixedResolutionAlert': 'Mixed Resolutions detected', + 'mixedResolutionAlertDescription': + 'At least one snippet seems to have a different resolution.\n\n' + 'This can cause unexpected results when using your film.\n\n' + 'Try to delete theses files or move them to a different profile.' }; diff --git a/lib/lang/fr.dart b/lib/lang/fr.dart index 02a3641..c7f0058 100644 --- a/lib/lang/fr.dart +++ b/lib/lang/fr.dart @@ -214,8 +214,8 @@ const Map fr = { 'useAlternativeCalendarColors': 'Utilisez des couleurs de calendrier alternatives', 'useAlternativeCalendarColorsDescription': 'Change le vert et le rouge dans le calendrier en bleu et jaune. Utile pour les personnes daltoniennes.', - 'mixedResolutionAlert' : 'Mix de résolutions détecté.', - 'mixedResolutionAlertDescription' : 'Au moins une vidéo semble avoir un mix de résolutions.\n\n' - 'Cela peut produire des résultats innatendus lorsque vous utilisez votre film.\n\n' - 'Essayez de supprimer ces fichiers ou de les déplacer dans un autre profil.' + 'mixedResolutionAlert': 'Mix de résolutions détecté.', + 'mixedResolutionAlertDescription': 'Au moins une vidéo semble avoir un mix de résolutions.\n\n' + 'Cela peut produire des résultats innatendus lorsque vous utilisez votre film.\n\n' + 'Essayez de supprimer ces fichiers ou de les déplacer dans un autre profil.' }; diff --git a/lib/pages/home/base/home_page.dart b/lib/pages/home/base/home_page.dart index 5d2a558..b43fc91 100644 --- a/lib/pages/home/base/home_page.dart +++ b/lib/pages/home/base/home_page.dart @@ -19,9 +19,7 @@ class HomePage extends GetView { body: SizedBox( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, - child: Center( - child: Obx(() => _getSelectedPage(controller.activeIndex.value)), - ), + child: Obx(() => _getSelectedPage(controller.activeIndex.value)), ), ); } diff --git a/lib/pages/home/base/widgets/bottom_app_bar.dart b/lib/pages/home/base/widgets/bottom_app_bar.dart index 68f31e4..91d4039 100644 --- a/lib/pages/home/base/widgets/bottom_app_bar.dart +++ b/lib/pages/home/base/widgets/bottom_app_bar.dart @@ -4,7 +4,6 @@ import 'package:salomon_bottom_bar/salomon_bottom_bar.dart'; import '../../../../controllers/bottom_app_bar_index_controller.dart'; import '../../../../utils/constants.dart'; -import '../../../../utils/theme.dart'; SalomonBottomBarItem _bottomBarItem({ required IconData icon, @@ -28,7 +27,7 @@ class CustomBottomAppBar extends GetView { Widget build(BuildContext context) { return Obx( () => SalomonBottomBar( - backgroundColor: ThemeService().isDarkTheme() ? AppColors.dark : AppColors.light, + backgroundColor: Colors.black12.withOpacity(0.05), currentIndex: controller.activeIndex.value, onTap: controller.setBottomAppBarIndex, items: [ diff --git a/lib/pages/home/calendar_editor/calendar_editor_page.dart b/lib/pages/home/calendar_editor/calendar_editor_page.dart index 1cf7d87..e27ccf1 100644 --- a/lib/pages/home/calendar_editor/calendar_editor_page.dart +++ b/lib/pages/home/calendar_editor/calendar_editor_page.dart @@ -166,7 +166,7 @@ class _CalendarEditorPageState extends State { } bool shouldIgnoreExperimentalFilter() { - final useFilter = SharedPrefsUtil.getBool('useFilterInExperimentalPicker') ?? false; + final useFilter = SharedPrefsUtil.getBool('useFilterInExperimentalPicker') ?? true; if (!useFilter) return true; if (_selectedDate.day == DateTime.now().day && _selectedDate.month == DateTime.now().month && @@ -435,7 +435,7 @@ class _CalendarEditorPageState extends State { Padding( padding: const EdgeInsets.symmetric(horizontal: 20.0), child: AspectRatio( - aspectRatio: 16/9, + aspectRatio: 16 / 9, child: Stack( children: [ Center( @@ -466,13 +466,11 @@ class _CalendarEditorPageState extends State { WidgetsBinding.instance.addPostFrameCallback((_) { _controller?.dispose(); }); - Get.offAllNamed(Routes.HOME) - ?.then((_) => setState(() {})); + Get.offAllNamed(Routes.HOME)?.then((_) => setState(() {})); } // VideoPlayer - if (_controller != null && - _controller!.value.isInitialized) { + if (_controller != null && _controller!.value.isInitialized) { return Align( alignment: Alignment.center, child: Stack( diff --git a/lib/pages/home/calendar_editor/video_subtitles_editor_page.dart b/lib/pages/home/calendar_editor/video_subtitles_editor_page.dart index 9c3e5b2..ee6cfc6 100644 --- a/lib/pages/home/calendar_editor/video_subtitles_editor_page.dart +++ b/lib/pages/home/calendar_editor/video_subtitles_editor_page.dart @@ -172,9 +172,7 @@ class _VideoSubtitlesEditorPageState extends State { onTap: () => videoPlay(), // ConstrainedBox to fit vertical videos without overflowing child: ConstrainedBox( - constraints: BoxConstraints( - maxHeight: MediaQuery.of(context).size.height * 0.7 - ), + constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.7), child: AspectRatio( aspectRatio: _videoController.value.aspectRatio, child: Stack( @@ -224,7 +222,7 @@ class _VideoSubtitlesEditorPageState extends State { hintText: 'enterSubtitles'.tr.split('(').first, fillColor: ThemeService().isDarkTheme() ? Colors.black : Colors.white, hintStyle: TextStyle( - color: ThemeService().isDarkTheme() ? Colors.black : Colors.white, + color: ThemeService().isDarkTheme() ? Colors.white : Colors.black, ), filled: true, border: const OutlineInputBorder( diff --git a/lib/pages/home/create_movie/widgets/select_video_from_storage.dart b/lib/pages/home/create_movie/widgets/select_video_from_storage.dart index 5684730..6509309 100644 --- a/lib/pages/home/create_movie/widgets/select_video_from_storage.dart +++ b/lib/pages/home/create_movie/widgets/select_video_from_storage.dart @@ -43,6 +43,7 @@ class _SelectVideoFromStorageState extends State { Widget build(BuildContext context) { // Count all true in isSelected and return quantity final int totalSelected = isSelected?.where((element) => element).length ?? 0; + final aspectRatio = allVideos?.first.contains('_vertical') == true ? 0.5 : 1.0; return Scaffold( appBar: AppBar( iconTheme: const IconThemeData( @@ -115,9 +116,9 @@ class _SelectVideoFromStorageState extends State { cacheExtent: 99999, shrinkWrap: true, controller: scrollController, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, - childAspectRatio: 1.12, + childAspectRatio: aspectRatio, ), itemCount: allVideos!.length, itemBuilder: (context, index) { diff --git a/lib/pages/home/create_movie/widgets/view_movies_page.dart b/lib/pages/home/create_movie/widgets/view_movies_page.dart index 501bce9..51343cb 100644 --- a/lib/pages/home/create_movie/widgets/view_movies_page.dart +++ b/lib/pages/home/create_movie/widgets/view_movies_page.dart @@ -102,6 +102,7 @@ class _ViewMoviesState extends State { alignment: Alignment.center, child: Image.memory( snapshot.data![index] as Uint8List, + height: MediaQuery.sizeOf(context).height * 0.27, ), ), Align( diff --git a/lib/pages/home/notification/widgets/switch_notifications.dart b/lib/pages/home/notification/widgets/switch_notifications.dart index 2d3be4e..e8f499c 100644 --- a/lib/pages/home/notification/widgets/switch_notifications.dart +++ b/lib/pages/home/notification/widgets/switch_notifications.dart @@ -8,12 +8,10 @@ import '../../../../utils/theme.dart'; class SwitchNotificationsComponent extends StatefulWidget { @override - _SwitchNotificationsComponentState createState() => - _SwitchNotificationsComponentState(); + _SwitchNotificationsComponentState createState() => _SwitchNotificationsComponentState(); } -class _SwitchNotificationsComponentState - extends State { +class _SwitchNotificationsComponentState extends State { late bool isNotificationSwitchToggled; TimeOfDay scheduledTimeOfDay = const TimeOfDay(hour: 20, minute: 00); late bool isPersistentSwitchToggled; @@ -58,10 +56,7 @@ class _SwitchNotificationsComponentState await notificationService.turnOnNotifications(); await notificationService.scheduleNotification( - scheduledTimeOfDay.hour, - scheduledTimeOfDay.minute, - DateTime.now() - ); + scheduledTimeOfDay.hour, scheduledTimeOfDay.minute, DateTime.now()); } else { await notificationService.turnOffNotifications(); } @@ -139,22 +134,17 @@ class _SwitchNotificationsComponentState }); } - notificationService.setScheduledTime(newTimeOfDay.hour, - newTimeOfDay.minute); + notificationService.setScheduledTime(newTimeOfDay.hour, newTimeOfDay.minute); setState(() { scheduledTimeOfDay = newTimeOfDay; }); await notificationService.scheduleNotification( - scheduledTimeOfDay.hour, - scheduledTimeOfDay.minute, - DateTime.now() - ); + scheduledTimeOfDay.hour, scheduledTimeOfDay.minute, DateTime.now()); }, child: Container( - padding: - const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0), + padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -196,19 +186,16 @@ class _SwitchNotificationsComponentState } /// Schedule notification if switch in ON - if(isNotificationSwitchToggled && !isNotificationSwitchToggled){ + if (isNotificationSwitchToggled && !isNotificationSwitchToggled) { await notificationService.turnOnNotifications(); setState(() { isNotificationSwitchToggled = true; }); } - if(isNotificationSwitchToggled){ + if (isNotificationSwitchToggled) { await notificationService.scheduleNotification( - scheduledTimeOfDay.hour, - scheduledTimeOfDay.minute, - DateTime.now() - ); + scheduledTimeOfDay.hour, scheduledTimeOfDay.minute, DateTime.now()); } /// Update switch value @@ -222,7 +209,6 @@ class _SwitchNotificationsComponentState ], ), ), - const Divider(), ], ); } diff --git a/lib/pages/home/profiles/profiles_page.dart b/lib/pages/home/profiles/profiles_page.dart index 509e93c..b7a402d 100644 --- a/lib/pages/home/profiles/profiles_page.dart +++ b/lib/pages/home/profiles/profiles_page.dart @@ -56,15 +56,18 @@ class _ProfilesPageState extends State { if (!storedProfiles.contains('Default')) { profiles.insert( 0, - const Profile(label: 'Default', storageString: 'Default', isDefault: true, isVertical: false), + const Profile( + label: 'Default', storageString: 'Default', isDefault: true, isVertical: false), ); } else { // Profiles strings ending with '_vertical' creates an Profile object with isVertical value true, as other not. profiles = storedProfiles.map( (e) { - if (e == 'Default') return Profile(label: e, storageString: e, isDefault: true, isVertical: false); + if (e == 'Default') + return Profile(label: e, storageString: e, isDefault: true, isVertical: false); if (e.endsWith('_vertical')) - return Profile(label: e.replaceAll('_vertical', ''), storageString: e, isVertical: true); + return Profile( + label: e.replaceAll('_vertical', ''), storageString: e, isVertical: true); else return Profile(label: e, storageString: e, isVertical: false); }, @@ -206,7 +209,8 @@ class _ProfilesPageState extends State { profiles.length, Profile( label: _profileNameController.text.trim(), - storageString: _verticalModeSwitch? '${_profileNameController.text.trim()}_vertical' + storageString: _verticalModeSwitch + ? '${_profileNameController.text.trim()}_vertical' : _profileNameController.text.trim(), isVertical: _verticalModeSwitch), ); @@ -215,8 +219,7 @@ class _ProfilesPageState extends State { // Add the modified profile list to persistence // Adds the string '_vertical' at the end of vertical profiles to keep this parameter persistent. - final profileNamesToStringList = profiles - .map((e) => e.storageString).toList(); + final profileNamesToStringList = profiles.map((e) => e.storageString).toList(); SharedPrefsUtil.putStringList('profiles', profileNamesToStringList); @@ -371,18 +374,25 @@ class _ProfilesPageState extends State { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), - title: Text( - profiles[index].isDefault ? 'default'.tr : profiles[index].label, - style: TextStyle( - color: ThemeService().isDarkTheme() ? Colors.white : Colors.black, - ), + title: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + profiles[index].isDefault ? 'default'.tr : profiles[index].label, + style: TextStyle( + color: ThemeService().isDarkTheme() ? Colors.white : Colors.black, + ), + ), + const SizedBox( + width: 5.0, + ), + RotatedBox( + quarterTurns: profiles[index].isVertical ? 0 : -1, + child: const Icon(Icons.phone_android), + ), + ], ), secondary: Row(mainAxisSize: MainAxisSize.min, children: [ - Icon( - profiles[index].isVertical - ? Icons.stay_current_portrait - : Icons.stay_current_landscape, - ), if (!profiles[index].isDefault) IconButton( onPressed: () async { diff --git a/lib/pages/home/settings/widgets/backup_tutorial.dart b/lib/pages/home/settings/widgets/backup_tutorial.dart index d4c8916..22009f3 100644 --- a/lib/pages/home/settings/widgets/backup_tutorial.dart +++ b/lib/pages/home/settings/widgets/backup_tutorial.dart @@ -31,7 +31,6 @@ class BackupTutorial extends StatelessWidget { ), ), ), - const Divider(), ], ); } diff --git a/lib/pages/home/settings/widgets/contact_button.dart b/lib/pages/home/settings/widgets/contact_button.dart index c07de6c..4bb40a5 100644 --- a/lib/pages/home/settings/widgets/contact_button.dart +++ b/lib/pages/home/settings/widgets/contact_button.dart @@ -40,7 +40,6 @@ class ContactButton extends StatelessWidget { ), ), ), - const Divider(), ], ); } diff --git a/lib/pages/home/settings/widgets/github_button.dart b/lib/pages/home/settings/widgets/github_button.dart index f05d11e..f7820d8 100644 --- a/lib/pages/home/settings/widgets/github_button.dart +++ b/lib/pages/home/settings/widgets/github_button.dart @@ -31,7 +31,6 @@ class GithubButton extends StatelessWidget { ), ), ), - const Divider(), ], ); } diff --git a/lib/pages/home/settings/widgets/language_chooser.dart b/lib/pages/home/settings/widgets/language_chooser.dart index d499e0e..c902a79 100644 --- a/lib/pages/home/settings/widgets/language_chooser.dart +++ b/lib/pages/home/settings/widgets/language_chooser.dart @@ -58,7 +58,6 @@ class _LanguageChooserState extends State { ], ), ), - const Divider(), ], ); } diff --git a/lib/pages/home/settings/widgets/notifications_button.dart b/lib/pages/home/settings/widgets/notifications_button.dart index fda32fb..36b81e9 100644 --- a/lib/pages/home/settings/widgets/notifications_button.dart +++ b/lib/pages/home/settings/widgets/notifications_button.dart @@ -13,8 +13,7 @@ class NotificationsButton extends StatelessWidget { InkWell( onTap: () => Get.toNamed(Routes.NOTIFICATION), child: Ink( - padding: - const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0), + padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -29,7 +28,6 @@ class NotificationsButton extends StatelessWidget { ), ), ), - const Divider(), ], ); } diff --git a/lib/pages/home/settings/widgets/preferences_button.dart b/lib/pages/home/settings/widgets/preferences_button.dart index 9676c82..cebe3f2 100644 --- a/lib/pages/home/settings/widgets/preferences_button.dart +++ b/lib/pages/home/settings/widgets/preferences_button.dart @@ -22,8 +22,7 @@ class _PreferencesButtonState extends State { InkWell( onTap: () => Get.toNamed(Routes.PREFERENCES), child: Ink( - padding: const EdgeInsets.symmetric( - horizontal: 15.0, vertical: 10.0), + padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -38,7 +37,6 @@ class _PreferencesButtonState extends State { ), ), ), - const Divider(), ], ); } diff --git a/lib/pages/home/settings/widgets/preferences_page.dart b/lib/pages/home/settings/widgets/preferences_page.dart index cfb052a..a32080c 100644 --- a/lib/pages/home/settings/widgets/preferences_page.dart +++ b/lib/pages/home/settings/widgets/preferences_page.dart @@ -22,7 +22,7 @@ class _PreferencesPageState extends State { super.initState(); isCameraSwitchToggled = SharedPrefsUtil.getBool('forceNativeCamera') ?? false; isPickerSwitchToggled = SharedPrefsUtil.getBool('useExperimentalPicker') ?? true; - isPickerFilterSwitchToggled = SharedPrefsUtil.getBool('useFilterInExperimentalPicker') ?? false; + isPickerFilterSwitchToggled = SharedPrefsUtil.getBool('useFilterInExperimentalPicker') ?? true; isColorsSwitchToggled = SharedPrefsUtil.getBool('useAlternativeCalendarColors') ?? false; } diff --git a/lib/pages/home/settings/widgets/profiles_button.dart b/lib/pages/home/settings/widgets/profiles_button.dart index e6700eb..0164686 100644 --- a/lib/pages/home/settings/widgets/profiles_button.dart +++ b/lib/pages/home/settings/widgets/profiles_button.dart @@ -13,8 +13,7 @@ class ProfilesButton extends StatelessWidget { InkWell( onTap: () => Get.toNamed(Routes.PROFILES), child: Ink( - padding: - const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0), + padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -29,7 +28,6 @@ class ProfilesButton extends StatelessWidget { ), ), ), - const Divider(), ], ); } diff --git a/lib/pages/home/settings/widgets/switch_theme.dart b/lib/pages/home/settings/widgets/switch_theme.dart index 8834fc6..f47d068 100644 --- a/lib/pages/home/settings/widgets/switch_theme.dart +++ b/lib/pages/home/settings/widgets/switch_theme.dart @@ -43,7 +43,6 @@ class _SwitchThemeComponentState extends State { ), ], ), - const Divider(), ], ); } diff --git a/lib/pages/save_video/save_video_page.dart b/lib/pages/save_video/save_video_page.dart index 96edbc3..2c36757 100644 --- a/lib/pages/save_video/save_video_page.dart +++ b/lib/pages/save_video/save_video_page.dart @@ -604,20 +604,22 @@ class _SaveVideoPageState extends State { const SizedBox(width: 8), Flexible( child: Text( - selectedProfile.label.isEmpty ? 'default'.tr : - selectedProfile.isVertical ? selectedProfile.label.replaceAll('_vertical', '') - : selectedProfile.label, + selectedProfile.label.isEmpty + ? 'default'.tr + : selectedProfile.isVertical + ? selectedProfile.label.replaceAll('_vertical', '') + : selectedProfile.label, style: TextStyle( fontSize: MediaQuery.of(context).size.height * 0.019, ), ), ), - const SizedBox(width: 20), - Icon( - selectedProfile.isVertical? Icons.stay_current_portrait : - Icons.stay_current_landscape + const SizedBox(width: 5), + RotatedBox( + quarterTurns: selectedProfile.isVertical ? 0 : -1, + child: const Icon(Icons.phone_android), ), - const SizedBox(width: 20), + const SizedBox(width: 15), Flexible( child: TextButton( style: ButtonStyle( @@ -991,8 +993,8 @@ class _SaveVideoPageState extends State { autofocus: true, controller: customLocationTextController, textCapitalization: TextCapitalization.sentences, - style: TextStyle( - color: ThemeService().isDarkTheme() ? Colors.black : Colors.white, + style: const TextStyle( + color: Colors.white, ), decoration: InputDecoration( hintText: 'enterLocation'.tr, diff --git a/lib/utils/theme.dart b/lib/utils/theme.dart index 0e629fd..a77c772 100644 --- a/lib/utils/theme.dart +++ b/lib/utils/theme.dart @@ -36,6 +36,7 @@ class Themes { switchTheme: SwitchThemeData( thumbColor: MaterialStateProperty.all(AppColors.mainColor), trackColor: MaterialStateProperty.all(AppColors.rose), + trackOutlineColor: MaterialStateProperty.all(AppColors.mainColor), ), );