diff --git a/lib/data/show_notifier.dart b/lib/data/show_notifier.dart index 16aad62..faa9f9b 100644 --- a/lib/data/show_notifier.dart +++ b/lib/data/show_notifier.dart @@ -52,8 +52,8 @@ class ShowNotifier extends InputBasic with ChangeNotifier { } void _previewTracks(Video video) { - _assignDefault(video.audios); - _assignDefault(video.subtitles); + _assignDefaultAudio(video.audios); + _assignDefaultSubtitle(video.subtitles); sortTracks(); for (var audio in video.audios) { audio.title = TitleScanner.audio(audio, profile); @@ -69,13 +69,13 @@ class ShowNotifier extends InputBasic with ChangeNotifier { } } - void _assignDefault(List tracks) { + void _assignDefaultAudio(List tracks) { List matches = []; for (final flagOrder in profile.defaultFlagOrder) { if (flagOrder == 'default') { matches = tracks.where((track) { final isDefaultLanguage = - track.language.iso6393 == profile.defaultLanguage; + track.language.iso6393 == profile.defaultAudioLanguage; final orderableFlags = track.flags.values.where((flag) { return !['enabled', 'default'].contains(flag.definedKey); }).toList(); @@ -86,7 +86,7 @@ class ShowNotifier extends InputBasic with ChangeNotifier { } else { matches = tracks.where((track) { final isDefaultLanguage = - track.language.iso6393 == profile.defaultLanguage; + track.language.iso6393 == profile.defaultAudioLanguage; return track.flags[flagOrder]!.value && isDefaultLanguage; }).toList(); @@ -98,7 +98,49 @@ class ShowNotifier extends InputBasic with ChangeNotifier { } } for (final track in tracks) { - if (profile.languages.contains(track.language.iso6393)) { + if (profile.audioLanguages.contains(track.language.iso6393)) { + track.include = true; + if (matches.contains(track)) { + track.flags['default']!.value = true; + } else { + track.flags['default']!.value = false; + } + } else { + track.include = false; + } + } + } + + void _assignDefaultSubtitle(List tracks) { + List matches = []; + for (final flagOrder in profile.defaultFlagOrder) { + if (flagOrder == 'default') { + matches = tracks.where((track) { + final isDefaultLanguage = + track.language.iso6393 == profile.defaultSubtitleLanguage; + final orderableFlags = track.flags.values.where((flag) { + return !['enabled', 'default'].contains(flag.definedKey); + }).toList(); + + return orderableFlags.every((flag) => flag.value == false) && + isDefaultLanguage; + }).toList(); + } else { + matches = tracks.where((track) { + final isDefaultLanguage = + track.language.iso6393 == profile.defaultSubtitleLanguage; + + return track.flags[flagOrder]!.value && isDefaultLanguage; + }).toList(); + } + if (matches.isEmpty) { + continue; + } else { + break; + } + } + for (final track in tracks) { + if (profile.subtitleLanguages.contains(track.language.iso6393)) { track.include = true; if (matches.contains(track)) { track.flags['default']!.value = true; diff --git a/lib/data/user_profiles_notifier.dart b/lib/data/user_profiles_notifier.dart index 8b9ba82..eb2922d 100644 --- a/lib/data/user_profiles_notifier.dart +++ b/lib/data/user_profiles_notifier.dart @@ -23,8 +23,10 @@ class UserProfilesNotifier extends ChangeNotifier { 'hearing_impaired', 'default', ], - defaultLanguage: 'eng', - languages: UserProfile.defaultLanguages, + defaultAudioLanguage: 'eng', + audioLanguages: UserProfile.defaultLanguages, + defaultSubtitleLanguage: 'eng', + subtitleLanguages: UserProfile.defaultLanguages, modifiers: UserProfile.defaultModifiers, ), UserProfile( @@ -39,8 +41,10 @@ class UserProfilesNotifier extends ChangeNotifier { 'hearing_impaired', 'default', ], - defaultLanguage: 'eng', - languages: UserProfile.defaultLanguages, + defaultAudioLanguage: 'eng', + audioLanguages: UserProfile.defaultLanguages, + defaultSubtitleLanguage: 'eng', + subtitleLanguages: UserProfile.defaultLanguages, modifiers: UserProfile.defaultModifiers, ), ]; diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 63d93cc..14123f0 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -118,7 +118,6 @@ "videoTitleNote": "This will apply to the video file title and video track title", "audioTitleNote": "This will apply to the audio track title", "subtitleTitleNote": "This will apply to the subtitle track title", - "selectLanguageToInclude": "Select languages to include and choose to set as default", "languages": "Languages", "selectedLanguages": "Selected languages", "selectTrackFlagsAndReorder": "Select track flags and reorder which will set the Default flag based on order fallbacks", @@ -266,5 +265,7 @@ "addAttachments": "Add Attachments", "resetAndUseDefault": "Reset and use the default tool path", "sameAsOutput": "Same as output file title", - "textAlgorithmSubstitute": "Text matching substitute algorithm" + "textAlgorithmSubstitute": "Text matching substitute algorithm", + "selectSubtitleLanguageToInclude": "Select subtitle languages to include and choose to set as default", + "selectAudioLanguageToInclude": "Select audio languages to include and choose to set as default" } \ No newline at end of file diff --git a/lib/l10n/intl_fil.arb b/lib/l10n/intl_fil.arb index e3b2400..a7abb57 100644 --- a/lib/l10n/intl_fil.arb +++ b/lib/l10n/intl_fil.arb @@ -118,7 +118,6 @@ "videoTitleNote": "Ito ay mag a-apply sa pangalan ng file ng bidyo at sa pangalan ng track nito", "audioTitleNote": "Ito ay mag a-apply sa pangalan ng track ng audio", "subtitleTitleNote": "Ito ay mag a-apply sa pangalan ng track ng subtitle", - "selectLanguageToInclude": "Piliin ang mga lengguwaheng isasama at pumili rin ng maaring gawing default", "languages": "Mga lengguwahe", "selectedLanguages": "Mga pinili", "selectTrackFlagsAndReorder": "Pumili ng track flags at i-reorder, ito ay mag se-set ng Default flag base sa pagkakasunod ng fallbacks", @@ -266,5 +265,7 @@ "addAttachments": "Mag-add ng Attachments", "resetAndUseDefault": "I-reset at gamiting ang default path ng tool", "sameAsOutput": "Kapareho sa pangalan ng output file", - "textAlgorithmSubstitute": "Kapalit na pantugmang algoritmo sa text" + "textAlgorithmSubstitute": "Kapalit na pantugmang algoritmo sa text", + "selectSubtitleLanguageToInclude": "Piliin ang mga lengguwahe ng subtitle na isasama at pumili ng itatakdang default", + "selectAudioLanguageToInclude": "Piliin ang mga lengguwahe ng audio na isasama at pumili ng itatakdang default" } \ No newline at end of file diff --git a/lib/models/user_profile.dart b/lib/models/user_profile.dart index d38d6ee..6d2b14a 100644 --- a/lib/models/user_profile.dart +++ b/lib/models/user_profile.dart @@ -14,8 +14,10 @@ class UserProfile extends ChangeNotifier with EquatableMixin { this.audioExtraOptions = '', this.subtitleExtraOptions = '', this.attachmentExtraOptions = '', - this.defaultLanguage = '', - this.languages = const [], + this.defaultAudioLanguage = '', + this.audioLanguages = const [], + this.defaultSubtitleLanguage = '', + this.subtitleLanguages = const [], this.defaultFlagOrder = const [], this.modifiers = const [], this.useFolderName = true, @@ -174,7 +176,7 @@ class UserProfile extends ChangeNotifier with EquatableMixin { 'hin', 'spa', 'fre', - 'arb', + 'ara', 'ben', 'por', 'rus', @@ -192,8 +194,10 @@ class UserProfile extends ChangeNotifier with EquatableMixin { String audioExtraOptions; String subtitleExtraOptions; String attachmentExtraOptions; - String defaultLanguage; - List languages; + String defaultAudioLanguage; + List audioLanguages; + String defaultSubtitleLanguage; + List subtitleLanguages; List defaultFlagOrder; List modifiers; bool useFolderName; @@ -210,8 +214,10 @@ class UserProfile extends ChangeNotifier with EquatableMixin { audioExtraOptions: json['audioExtraOptions'], subtitleExtraOptions: json['subtitleExtraOptions'], attachmentExtraOptions: json['attachmentExtraOptions'], - defaultLanguage: json['defaultLanguage'], - languages: List.from(json['languages']), + defaultAudioLanguage: json['defaultAudioLanguage'], + audioLanguages: List.from(json['audioLanguages']), + defaultSubtitleLanguage: json['defaultSubtitleLanguage'], + subtitleLanguages: List.from(json['subtitleLanguages']), defaultFlagOrder: List.from(json['defaultFlagOrder']), modifiers: List.from( json['modifiers'].map((e) => TextModifier.fromJson(e))), @@ -230,8 +236,10 @@ class UserProfile extends ChangeNotifier with EquatableMixin { 'audioExtraOptions': audioExtraOptions, 'subtitleExtraOptions': subtitleExtraOptions, 'attachmentExtraOptions': attachmentExtraOptions, - 'defaultLanguage': defaultLanguage, - 'languages': languages, + 'defaultAudioLanguage': defaultAudioLanguage, + 'audioLanguages': audioLanguages, + 'defaultSubtitleLanguage': defaultSubtitleLanguage, + 'subtitleLanguages': subtitleLanguages, 'defaultFlagOrder': defaultFlagOrder, 'modifiers': modifiers, 'useFolderName': useFolderName, @@ -248,8 +256,10 @@ class UserProfile extends ChangeNotifier with EquatableMixin { String? audioExtraOptions, String? subtitleExtraOptions, String? attachmentExtraOptions, - String? defaultLanguage, - List? languages, + String? defaultAudioLanguage, + List? audioLanguages, + String? defaultSubtitleLanguage, + List? subtitleLanguages, List? defaultFlagOrder, List? modifiers, bool? useFolderName, @@ -266,8 +276,12 @@ class UserProfile extends ChangeNotifier with EquatableMixin { subtitleExtraOptions: subtitleExtraOptions ?? this.subtitleExtraOptions, attachmentExtraOptions: attachmentExtraOptions ?? this.attachmentExtraOptions, - defaultLanguage: defaultLanguage ?? this.defaultLanguage, - languages: languages ?? List.from(this.languages), + defaultAudioLanguage: defaultAudioLanguage ?? this.defaultAudioLanguage, + audioLanguages: audioLanguages ?? this.audioLanguages, + defaultSubtitleLanguage: + defaultSubtitleLanguage ?? this.defaultSubtitleLanguage, + subtitleLanguages: + subtitleLanguages ?? List.from(this.subtitleLanguages), defaultFlagOrder: defaultFlagOrder ?? List.from(this.defaultFlagOrder), modifiers: modifiers ?? List.from(this.modifiers), useFolderName: useFolderName ?? this.useFolderName, @@ -284,8 +298,10 @@ class UserProfile extends ChangeNotifier with EquatableMixin { String? audioExtraOptions, String? subtitleExtraOptions, String? attachmentExtraOptions, - String? defaultLanguage, - List? languages, + String? defaultAudioLanguage, + List? audioLanguages, + String? defaultSubtitleLanguage, + List? subtitleLanguages, List? defaultFlagOrder, List? modifiers, bool? useFolderName, @@ -302,42 +318,77 @@ class UserProfile extends ChangeNotifier with EquatableMixin { subtitleExtraOptions ?? this.subtitleExtraOptions; this.attachmentExtraOptions; attachmentExtraOptions ?? this.attachmentExtraOptions; - this.defaultLanguage = defaultLanguage ?? this.defaultLanguage; - this.languages = languages ?? this.languages; + this.defaultAudioLanguage = + defaultAudioLanguage ?? this.defaultAudioLanguage; + this.audioLanguages = audioLanguages ?? this.audioLanguages; + this.defaultSubtitleLanguage = + defaultSubtitleLanguage ?? this.defaultSubtitleLanguage; + this.subtitleLanguages = subtitleLanguages ?? this.subtitleLanguages; this.defaultFlagOrder = defaultFlagOrder ?? this.defaultFlagOrder; this.modifiers = modifiers ?? this.modifiers; this.useFolderName = useFolderName ?? this.useFolderName; notifyListeners(); } - void updateDefaultLanguage(String language) { - if (defaultLanguage == language) { - defaultLanguage = ''; + void updateDefaultAudioLanguage(String language) { + if (defaultAudioLanguage == language) { + defaultAudioLanguage = ''; } else { - defaultLanguage = language; + defaultAudioLanguage = language; } notifyListeners(); } - void updateLanguages(String iso6393, [bool add = true]) { + void updateAudioLanguages(String iso6393, [bool add = true]) { if (add) { - if (!languages.contains(iso6393)) { - languages = List.from(languages)..add(iso6393); + if (!audioLanguages.contains(iso6393)) { + audioLanguages = List.from(audioLanguages)..add(iso6393); } } else { - if (iso6393 == defaultLanguage) { - updateDefaultLanguage(iso6393); + if (iso6393 == defaultAudioLanguage) { + updateDefaultAudioLanguage(iso6393); } - languages = List.from(languages)..remove(iso6393); + audioLanguages = List.from(audioLanguages)..remove(iso6393); } notifyListeners(); } - void reorderLanguages(int oldIndex, int newIndex) { + void reorderAudioLanguages(int oldIndex, int newIndex) { if (newIndex > oldIndex) newIndex -= 1; - final languagesCopy = List.from(languages); + final languagesCopy = List.from(audioLanguages); final item = languagesCopy.removeAt(oldIndex); - languages = languagesCopy..insert(newIndex, item); + audioLanguages = languagesCopy..insert(newIndex, item); + notifyListeners(); + } + + void updateDefaultSubtitleLanguage(String language) { + if (defaultSubtitleLanguage == language) { + defaultSubtitleLanguage = ''; + } else { + defaultSubtitleLanguage = language; + } + notifyListeners(); + } + + void updateSubtitleLanguages(String iso6393, [bool add = true]) { + if (add) { + if (!subtitleLanguages.contains(iso6393)) { + subtitleLanguages = List.from(subtitleLanguages)..add(iso6393); + } + } else { + if (iso6393 == defaultSubtitleLanguage) { + updateDefaultSubtitleLanguage(iso6393); + } + subtitleLanguages = List.from(subtitleLanguages)..remove(iso6393); + } + notifyListeners(); + } + + void reorderSubtitleLanguages(int oldIndex, int newIndex) { + if (newIndex > oldIndex) newIndex -= 1; + final languagesCopy = List.from(subtitleLanguages); + final item = languagesCopy.removeAt(oldIndex); + subtitleLanguages = languagesCopy..insert(newIndex, item); notifyListeners(); } @@ -382,8 +433,10 @@ class UserProfile extends ChangeNotifier with EquatableMixin { audioExtraOptions, subtitleExtraOptions, attachmentExtraOptions, - defaultLanguage, - languages, + defaultAudioLanguage, + audioLanguages, + defaultSubtitleLanguage, + subtitleLanguages, defaultFlagOrder, modifiers, useFolderName, diff --git a/lib/screens/settings/settings_sections/profile_page/profile_page.dart b/lib/screens/settings/settings_sections/profile_page/profile_page.dart index b3efcea..8d6233f 100644 --- a/lib/screens/settings/settings_sections/profile_page/profile_page.dart +++ b/lib/screens/settings/settings_sections/profile_page/profile_page.dart @@ -622,13 +622,14 @@ class ProfilePage extends StatelessWidget { ], ), ), + // Select Audio Languages Expander( - header: Text(l10n.selectLanguageToInclude), + header: Text(l10n.selectAudioLanguageToInclude), trailing: Visibility( - visible: profile.defaultLanguage.isNotEmpty, - child: Text(profile.defaultLanguage.isNotEmpty + visible: profile.defaultAudioLanguage.isNotEmpty, + child: Text(profile.defaultAudioLanguage.isNotEmpty ? AppData.languageCodes - .identifyByCode(profile.defaultLanguage) + .identifyByCode(profile.defaultAudioLanguage) .name : ''), ), @@ -648,11 +649,10 @@ class ProfilePage extends StatelessWidget { key: const Key('Search Languages'), trailingIcon: const Icon(FluentIcons.search), - sorter: (text, items) => - Utilities.searchSorter(text, items), + sorter: Utilities.searchSorter, onSelected: (selected) { if (selected.value != null) { - profile.updateLanguages( + profile.updateAudioLanguages( selected.value!.iso6393); } }, @@ -676,20 +676,18 @@ class ProfilePage extends StatelessWidget { child: ReorderableListView.builder( shrinkWrap: true, buildDefaultDragHandles: false, - itemCount: editProfile.languages.length, - onReorder: (oldIndex, newIndex) => - editProfile.reorderLanguages( - oldIndex, newIndex), - proxyDecorator: (child, index, animation) => - _proxyDecorator( - child, index, animation), + itemCount: + editProfile.audioLanguages.length, + onReorder: + editProfile.reorderAudioLanguages, + proxyDecorator: _proxyDecorator, itemBuilder: (context, index) { final code = AppData.languageCodes - .identifyByCode(profile.languages + .identifyByCode(profile.audioLanguages .elementAt(index)); final isDefault = code.iso6393 == - editProfile.defaultLanguage; + editProfile.defaultAudioLanguage; return ReorderableDragStartListener( key: ValueKey(code), index: index, @@ -707,7 +705,7 @@ class ProfilePage extends StatelessWidget { semanticLabel: 'isDefault', checked: isDefault, onChanged: (val) => profile - .updateDefaultLanguage( + .updateDefaultAudioLanguage( code.iso6393), ), ), @@ -715,8 +713,138 @@ class ProfilePage extends StatelessWidget { trailing: IconButton( icon: const Icon( FluentIcons.remove), - onPressed: () => - editProfile.updateLanguages( + onPressed: () => editProfile + .updateAudioLanguages( + code.iso6393, false), + ), + title: SizedBox( + height: 28, + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + if (code.warn) ...[ + Tooltip( + message: + l10n.nonIso6392Hint, + child: const Icon( + FluentIcons.warning), + ), + const SizedBox(width: 6), + ], + Flexible( + child: Text(code.fullName), + ), + ], + ), + ), + ), + ), + ); + }, + ), + ), + ), + ], + ), + ), + ), + // Select Subtitle Languages + Expander( + header: Text(l10n.selectSubtitleLanguageToInclude), + trailing: Visibility( + visible: profile.defaultSubtitleLanguage.isNotEmpty, + child: Text(profile.defaultSubtitleLanguage.isNotEmpty + ? AppData.languageCodes + .identifyByCode( + profile.defaultSubtitleLanguage) + .name + : ''), + ), + content: ConstrainedBox( + constraints: const BoxConstraints(maxHeight: 500), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(' ${l10n.languages}: '), + Flexible( + child: AutoSuggestBox( + key: const Key('Search Languages'), + trailingIcon: + const Icon(FluentIcons.search), + sorter: Utilities.searchSorter, + onSelected: (selected) { + if (selected.value != null) { + profile.updateSubtitleLanguages( + selected.value!.iso6393); + } + }, + items: List.from( + AppData.languageCodes.items.map( + (code) { + return AutoSuggestBoxItem( + value: code, + label: code.fullCleanName, + ); + }, + ), + ), + ), + ), + ], + ), + Flexible( + child: InfoLabel( + label: ' ${l10n.selectedLanguages}: ', + child: ReorderableListView.builder( + shrinkWrap: true, + buildDefaultDragHandles: false, + itemCount: + editProfile.subtitleLanguages.length, + onReorder: + editProfile.reorderSubtitleLanguages, + proxyDecorator: _proxyDecorator, + itemBuilder: (context, index) { + final code = AppData.languageCodes + .identifyByCode(profile + .subtitleLanguages + .elementAt(index)); + + final isDefault = code.iso6393 == + editProfile.defaultSubtitleLanguage; + return ReorderableDragStartListener( + key: ValueKey(code), + index: index, + child: FluentTheme( + data: theme, + child: ListTile( + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(4)), + onPressed: () {}, + leading: SizedBox( + height: 30, + child: Center( + child: Checkbox( + semanticLabel: 'isDefault', + checked: isDefault, + onChanged: (val) => profile + .updateDefaultSubtitleLanguage( + code.iso6393), + ), + ), + ), + trailing: IconButton( + icon: const Icon( + FluentIcons.remove), + onPressed: () => editProfile + .updateSubtitleLanguages( code.iso6393, false), ), title: SizedBox( @@ -797,10 +925,8 @@ class ProfilePage extends StatelessWidget { buildDefaultDragHandles: false, itemCount: editProfile.defaultFlagOrder.length, - onReorder: (oldIndex, newIndex) => editProfile - .reorderFlagOrder(oldIndex, newIndex), - proxyDecorator: (child, index, animation) => - _proxyDecorator(child, index, animation), + onReorder: editProfile.reorderFlagOrder, + proxyDecorator: _proxyDecorator, itemBuilder: (context, index) { final flag = editProfile.defaultFlagOrder .elementAt(index); @@ -952,7 +1078,6 @@ class ProfilePage extends StatelessWidget { ); } else { sourceProfile.update( - defaultLanguage: editProfile.defaultLanguage, showTitleFormat: editProfile.showTitleFormat, videoTitleFormat: editProfile.videoTitleFormat, audioTitleFormat: editProfile.audioTitleFormat, @@ -961,7 +1086,10 @@ class ProfilePage extends StatelessWidget { audioExtraOptions: editProfile.audioExtraOptions, subtitleExtraOptions: editProfile.subtitleExtraOptions, attachmentExtraOptions: editProfile.attachmentExtraOptions, - languages: editProfile.languages, + defaultAudioLanguage: editProfile.defaultAudioLanguage, + audioLanguages: editProfile.audioLanguages, + defaultSubtitleLanguage: editProfile.defaultSubtitleLanguage, + subtitleLanguages: editProfile.subtitleLanguages, defaultFlagOrder: editProfile.defaultFlagOrder, name: editProfile.name, modifiers: editProfile.modifiers,