diff --git a/fastlane/metadata/android/en-US/changelogs/next.txt b/fastlane/metadata/android/en-US/changelogs/next.txt index b750e228..9c6c2604 100644 --- a/fastlane/metadata/android/en-US/changelogs/next.txt +++ b/fastlane/metadata/android/en-US/changelogs/next.txt @@ -12,4 +12,5 @@ * Fixed group deletion not updating the UI (#591) * Added support for opening redirect links from emails (#257) * Added pull-to-refresh and scroll-to-top on profiles (#589) -* Added support for sharing images (#556 - thanks to @ramosmauricio!) \ No newline at end of file +* Added support for sharing images (#556 - thanks @ramosmauricio!) +* Added support for muting media by default (#553 - thanks @johann-gambol!) \ No newline at end of file diff --git a/lib/constants.dart b/lib/constants.dart index a779af47..7bd96227 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -8,6 +8,7 @@ const optionHomePages = 'home.pages'; const optionHomeInitialTab = 'home.initial_tab'; const optionMediaSize = 'media.size'; +const optionMediaDefaultMute = 'media.mute'; const optionDownloadType = 'download.type'; const optionDownloadPath = 'download.path'; diff --git a/lib/group/_feed.dart b/lib/group/_feed.dart index d2bf8479..e5e92508 100644 --- a/lib/group/_feed.dart +++ b/lib/group/_feed.dart @@ -9,6 +9,7 @@ import 'package:fritter/database/repository.dart'; import 'package:fritter/generated/l10n.dart'; import 'package:fritter/group/group_screen.dart'; import 'package:fritter/profile/profile.dart'; +import 'package:fritter/tweet/_video.dart'; import 'package:fritter/tweet/conversation.dart'; import 'package:fritter/ui/errors.dart'; import 'package:fritter/utils/iterables.dart'; @@ -226,12 +227,17 @@ class _SubscriptionGroupFeedState extends State { ); } + var prefs = PrefService.of(context, listen: false); + return RefreshIndicator( onRefresh: () async { _pagingController.refresh(); }, - child: ChangeNotifierProvider( - create: (context) => TweetContextState(PrefService.of(context, listen: false).get(optionTweetsHideSensitive)), + child: MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => TweetContextState(prefs.get(optionTweetsHideSensitive))), + ChangeNotifierProvider(create: (_) => VideoContextState(prefs.get(optionMediaDefaultMute))), + ], child: PagedListView( scrollController: widget.scrollController, pagingController: _pagingController, diff --git a/lib/home/_saved.dart b/lib/home/_saved.dart index 0a7a9fbf..99399b4f 100644 --- a/lib/home/_saved.dart +++ b/lib/home/_saved.dart @@ -12,6 +12,7 @@ import 'package:fritter/generated/l10n.dart'; import 'package:fritter/home/home_screen.dart'; import 'package:fritter/profile/profile.dart'; import 'package:fritter/saved/saved_tweet_model.dart'; +import 'package:fritter/tweet/_video.dart'; import 'package:fritter/tweet/tweet.dart'; import 'package:fritter/ui/errors.dart'; import 'package:pref/pref.dart'; @@ -41,6 +42,8 @@ class _SavedScreenState extends State with AutomaticKeepAliveClient Widget build(BuildContext context) { var model = context.read(); + var prefs = PrefService.of(context, listen: false); + return NestedScrollView( controller: widget.scrollController, headerSliverBuilder: (context, innerBoxIsScrolled) { @@ -54,8 +57,11 @@ class _SavedScreenState extends State with AutomaticKeepAliveClient ) ]; }, - body: ChangeNotifierProvider( - create: (context) => TweetContextState(PrefService.of(context, listen: false).get(optionTweetsHideSensitive)), + body: MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => TweetContextState(prefs.get(optionTweetsHideSensitive))), + ChangeNotifierProvider(create: (_) => VideoContextState(prefs.get(optionMediaDefaultMute))), + ], child: ScopedBuilder>.transition( store: model, onError: (_, e) => FullPageErrorWidget( diff --git a/lib/main.dart b/lib/main.dart index 1fcee5d3..642adb16 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -169,6 +169,7 @@ Future main() async { optionHomePages: defaultHomePages.map((e) => e.id).toList(), optionLocale: optionLocaleDefault, optionMediaSize: 'medium', + optionMediaDefaultMute: true, optionNonConfirmationBiasMode: false, optionShouldCheckForUpdates: true, optionSubscriptionGroupsOrderByAscending: false, diff --git a/lib/profile/profile.dart b/lib/profile/profile.dart index 31bef7a9..44f2a3ca 100644 --- a/lib/profile/profile.dart +++ b/lib/profile/profile.dart @@ -10,6 +10,7 @@ import 'package:fritter/profile/_follows.dart'; import 'package:fritter/profile/_tweets.dart'; import 'package:fritter/profile/profile_model.dart'; import 'package:fritter/search/search.dart'; +import 'package:fritter/tweet/_video.dart'; import 'package:fritter/ui/errors.dart'; import 'package:fritter/ui/physics.dart'; import 'package:fritter/user.dart'; @@ -238,6 +239,7 @@ class _ProfileScreenBodyState extends State with TickerProvid var appBarHeight = profileStuffTop + avatarHeight + metadataHeight + 8 + descriptionHeight; var metadataTextStyle = const TextStyle(fontSize: 12.5); + var prefs = PrefService.of(context, listen: false); return Scaffold( body: Stack(children: [ @@ -481,8 +483,11 @@ class _ProfileScreenBodyState extends State with TickerProvid ))) ]; }, - body: ChangeNotifierProvider( - create: (context) => TweetContextState(PrefService.of(context, listen: false).get(optionTweetsHideSensitive)), + body: MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => TweetContextState(prefs.get(optionTweetsHideSensitive))), + ChangeNotifierProvider(create: (_) => VideoContextState(prefs.get(optionMediaDefaultMute))), + ], child: TabBarView( controller: _tabController, physics: const LessSensitiveScrollPhysics(), diff --git a/lib/search/search.dart b/lib/search/search.dart index 7bd65c87..d8278a2c 100644 --- a/lib/search/search.dart +++ b/lib/search/search.dart @@ -9,6 +9,7 @@ import 'package:fritter/generated/l10n.dart'; import 'package:fritter/profile/profile.dart'; import 'package:fritter/search/search_model.dart'; import 'package:fritter/subscriptions/users_model.dart'; +import 'package:fritter/tweet/_video.dart'; import 'package:fritter/tweet/tweet.dart'; import 'package:fritter/ui/errors.dart'; import 'package:fritter/user.dart'; @@ -75,6 +76,8 @@ class _SearchScreenState extends State<_SearchScreen> with SingleTickerProviderS Widget build(BuildContext context) { var subscriptionsModel = context.read(); + var prefs = PrefService.of(context, listen: false); + var defaultTheme = Theme.of(context); var searchTheme = defaultTheme.copyWith( appBarTheme: AppBarTheme( @@ -133,8 +136,11 @@ class _SearchScreenState extends State<_SearchScreen> with SingleTickerProviderS Tab(icon: Icon(Icons.comment)), ]), ), - ChangeNotifierProvider( - create: (context) => TweetContextState(PrefService.of(context, listen: false).get(optionTweetsHideSensitive)), + MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => TweetContextState(prefs.get(optionTweetsHideSensitive))), + ChangeNotifierProvider(create: (_) => VideoContextState(prefs.get(optionMediaDefaultMute))), + ], child: Expanded( child: TabBarView(controller: _tabController, children: [ TweetSearchResultList( diff --git a/lib/settings/_general.dart b/lib/settings/_general.dart index 0a8dd8da..f3a396f8 100644 --- a/lib/settings/_general.dart +++ b/lib/settings/_general.dart @@ -251,6 +251,12 @@ class SettingsGeneralFragment extends StatelessWidget { child: Text(L10n.of(context).large), ), ]), + /// TODO: translate + PrefSwitch( + pref: optionMediaDefaultMute, + title: Text('Mute videos'), + subtitle: Text('"Whether all videos should be muted by default"'), + ), PrefCheckbox( title: Text(L10n.of(context).hide_sensitive_tweets), subtitle: Text(L10n.of(context).whether_to_hide_tweets_marked_as_sensitive), diff --git a/lib/tweet/_video.dart b/lib/tweet/_video.dart index ce817152..0867d6ea 100644 --- a/lib/tweet/_video.dart +++ b/lib/tweet/_video.dart @@ -7,6 +7,7 @@ import 'package:fritter/tweet/_video_controls.dart'; import 'package:fritter/utils/downloads.dart'; import 'package:fritter/utils/iterables.dart'; import 'package:path/path.dart' as path; +import 'package:provider/provider.dart'; import 'package:video_player/video_player.dart'; import 'package:visibility_detector/visibility_detector.dart'; import 'package:wakelock/wakelock.dart'; @@ -71,6 +72,14 @@ class _TweetVideoState extends State { _videoController = VideoPlayerController.network(streamUrl!); + var model = context.read(); + var volume = model.isMuted ? 0.0 : _videoController!.value.volume; + _videoController!.setVolume(volume); + + _videoController!.addListener(() { + model.setIsMuted(_videoController!.value!.volume); + }); + _chewieController = ChewieController( aspectRatio: widget.metadata.aspectRatio, autoInitialize: true, @@ -218,3 +227,21 @@ class _VideoState extends State<_Video> { ); } } + +class VideoContextState extends ChangeNotifier{ + + bool isMuted; + + VideoContextState(this.isMuted); + + void setIsMuted(double volume){ + + if(isMuted && volume > 0 || !isMuted && volume == 0){ + isMuted = !isMuted; + } + + } + +} + +