diff --git a/.fandogh/fandogh.yaml b/.fandogh/fandogh.yaml index d7044ce..d089a85 100644 --- a/.fandogh/fandogh.yaml +++ b/.fandogh/fandogh.yaml @@ -3,7 +3,7 @@ name: app-dev spec: allow_http: false disable_default_domains: true - image: app-dev:1.5.0 + image: app-dev:1.5.4 image_pull_policy: IfNotPresent path: / replicas: 1 diff --git a/lib/views/home/studio/studio_details/studio_details_state.dart b/lib/views/home/studio/studio_details/studio_details_state.dart index 062ceec..bf7f5c8 100644 --- a/lib/views/home/studio/studio_details/studio_details_state.dart +++ b/lib/views/home/studio/studio_details/studio_details_state.dart @@ -18,6 +18,7 @@ class StudioDetailsState extends CoreProvier { StudioRequestArgs? podcastArgs; final List relatedQueue = []; bool _positionListenerActivated = false; + AppState alongSideState = AppState.idle; int _selectedDetailsIndex = 0; Timer? timer; @@ -69,6 +70,9 @@ class StudioDetailsState extends CoreProvier { MediaService.audioPlayerTag = 'podcast'; } appState = AppState.busy; + } else { + alongSideState = AppState.busy; + notifyListeners(); } final service = RequestService(RequestHelper.studioDetails(id, this.args)); await service.httpGet(); @@ -90,11 +94,15 @@ class StudioDetailsState extends CoreProvier { if (isForward == null && !forceFetch) { await _handlePodcastPlayback(studio); } + alongSideState = AppState.idle; appState = AppState.idle; return; } if (isForward == null) { appState = AppState.failed; + } else { + alongSideState = AppState.failed; + notifyListeners(); } } diff --git a/lib/views/home/studio/studio_details/widgets/studio_details_widget.dart b/lib/views/home/studio/studio_details/widgets/studio_details_widget.dart index 1248309..ebc9d4f 100644 --- a/lib/views/home/studio/studio_details/widgets/studio_details_widget.dart +++ b/lib/views/home/studio/studio_details/widgets/studio_details_widget.dart @@ -1,6 +1,7 @@ import 'package:didvan/config/design_config.dart'; import 'package:didvan/config/theme_data.dart'; import 'package:didvan/constants/app_icons.dart'; +import 'package:didvan/models/enums.dart'; import 'package:didvan/models/studio_details_data.dart'; import 'package:didvan/views/home/comments/comments.dart'; import 'package:didvan/views/home/comments/comments_state.dart'; @@ -9,6 +10,7 @@ import 'package:didvan/views/home/studio/studio_details/widgets/details_tab_bar. import 'package:didvan/views/home/widgets/overview/multitype.dart'; import 'package:didvan/views/home/widgets/tag_item.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; +import 'package:didvan/views/widgets/shimmer_placeholder.dart'; import 'package:didvan/views/widgets/skeleton_image.dart'; import 'package:didvan/views/widgets/state_handlers/state_handler.dart'; import 'package:flutter/material.dart'; @@ -42,25 +44,26 @@ class StudioDetailsWidget extends StatelessWidget { onCommentsTabSelected: onCommentsTabSelected ?? () {}, ), const SizedBox(height: 16), - StateHandler( - onRetry: () {}, - state: state, - builder: (context, state) { - if (state.selectedDetailsIndex == 0) { - return SingleChildScrollView( - // padding: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - ConstrainedBox( - constraints: BoxConstraints( - maxHeight: ds.height - - ds.width * 9 / 16 - - 144 - - MediaQuery.of(context).padding.top, - ), - child: Html( + ConstrainedBox( + constraints: BoxConstraints( + maxHeight: ds.height - + ds.width * 9 / 16 - + 144 - + MediaQuery.of(context).padding.top, + ), + child: StateHandler( + onRetry: () {}, + state: state, + builder: (context, state) { + if (state.selectedDetailsIndex == 0) { + return SingleChildScrollView( + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Html( data: state.studio.description, onAnchorTap: (href, context, map, element) => launch(href!), @@ -74,49 +77,51 @@ class StudioDetailsWidget extends StatelessWidget { ), }, ), - ), - if (state.studio.tags.isNotEmpty) + if (state.studio.tags.isNotEmpty) + const SizedBox(height: 20), + Wrap( + spacing: 8, + runSpacing: 8, + children: [ + for (var i = 0; + i < state.studio.tags.length; + i++) + TagItem(tag: state.studio.tags[i]), + ], + ), const SizedBox(height: 20), - Wrap( - spacing: 8, - runSpacing: 8, - children: [ - for (var i = 0; i < state.studio.tags.length; i++) - TagItem(tag: state.studio.tags[i]), - ], - ), - const SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const SizedBox(), - if (state.nextStudio != null) - _StudioPreview( - isNext: true, - studio: state.nextStudio!, - scrollController: scrollController, - ), - if (state.prevStudio != null) - _StudioPreview( - isNext: false, - studio: state.prevStudio!, - scrollController: scrollController, - ), - const SizedBox(), - ], - ) - ], - ), - ); - } - if (state.selectedDetailsIndex == 1) { - return ChangeNotifierProvider( - create: (context) => CommentsState(), - child: SizedBox( - height: ds.height - - ds.width * 9 / 16 - - 144 - - MediaQuery.of(context).padding.top, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const SizedBox(), + if (state.nextStudio != null && + state.alongSideState == AppState.idle) + _StudioPreview( + isNext: true, + studio: state.nextStudio!, + scrollController: scrollController, + ), + if (state.alongSideState == AppState.busy) + _StudioPreview.placeHolder, + if (state.prevStudio != null && + state.alongSideState == AppState.idle) + _StudioPreview( + isNext: false, + studio: state.prevStudio!, + scrollController: scrollController, + ), + if (state.alongSideState == AppState.busy) + _StudioPreview.placeHolder, + const SizedBox(), + ], + ), + ], + ), + ); + } + if (state.selectedDetailsIndex == 1) { + return ChangeNotifierProvider( + create: (context) => CommentsState(), child: Comments( pageData: { 'id': state.studio.id, @@ -126,38 +131,38 @@ class StudioDetailsWidget extends StatelessWidget { 'isPage': false, }, ), - ), - ); - } - return Column( - children: [ - if (state.studio.relatedContents.isEmpty) - for (var i = 0; i < 3; i++) + ); + } + return Column( + children: [ + if (state.studio.relatedContents.isEmpty) + for (var i = 0; i < 3; i++) + Padding( + padding: const EdgeInsets.only( + bottom: 8, + left: 16, + right: 16, + ), + child: MultitypeOverview.placeholder, + ), + for (var i = 0; + i < state.studio.relatedContents.length; + i++) Padding( padding: const EdgeInsets.only( bottom: 8, left: 16, right: 16, ), - child: MultitypeOverview.placeholder, + child: MultitypeOverview( + item: state.studio.relatedContents[i], + onMarkChanged: (id, value) {}, + ), ), - for (var i = 0; - i < state.studio.relatedContents.length; - i++) - Padding( - padding: const EdgeInsets.only( - bottom: 8, - left: 16, - right: 16, - ), - child: MultitypeOverview( - item: state.studio.relatedContents[i], - onMarkChanged: (id, value) {}, - ), - ), - ], - ); - }, + ], + ); + }, + ), ), ], ), @@ -237,4 +242,22 @@ class _StudioPreview extends StatelessWidget { ), ); } + + static Widget get placeHolder => SizedBox( + width: 88, + height: 216, + child: Column( + children: const [ + ShimmerPlaceholder(width: 88, height: 88), + SizedBox(height: 8), + ShimmerPlaceholder(height: 20, width: 20), + SizedBox(height: 16), + ShimmerPlaceholder(height: 14, width: 60), + SizedBox(height: 16), + ShimmerPlaceholder(height: 12, width: double.infinity), + SizedBox(height: 8), + ShimmerPlaceholder(height: 12, width: 40), + ], + ), + ); } diff --git a/lib/views/splash/splash.dart b/lib/views/splash/splash.dart index 6626557..b06a114 100644 --- a/lib/views/splash/splash.dart +++ b/lib/views/splash/splash.dart @@ -19,6 +19,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:provider/provider.dart'; import 'package:universal_html/html.dart' as html; +import 'package:universal_html/js.dart' as js; class Splash extends StatefulWidget { const Splash({Key? key}) : super(key: key); @@ -50,8 +51,8 @@ class _SplashState extends State { value: DesignConfig.systemUiOverlayStyle.copyWith( systemNavigationBarColor: Theme.of(context).colorScheme.background, ), - child: Scaffold( - body: Container( + child: Material( + child: Container( alignment: Alignment.center, padding: const EdgeInsets.all(60), color: Theme.of(context).colorScheme.background, diff --git a/lib/views/widgets/didvan/bnb.dart b/lib/views/widgets/didvan/bnb.dart index 8641ef5..002dea5 100644 --- a/lib/views/widgets/didvan/bnb.dart +++ b/lib/views/widgets/didvan/bnb.dart @@ -175,6 +175,8 @@ class _PlayerNavBar extends StatelessWidget { children: [ DidvanText( MediaService.currentPodcast!.title, + maxLines: 1, + overflow: TextOverflow.ellipsis, color: DesignConfig.isDark ? null : Theme.of(context).colorScheme.secondCTA, diff --git a/pubspec.yaml b/pubspec.yaml index 4f32cce..d54e6b4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -87,7 +87,7 @@ flutter: # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. - uses-material-design: true + uses-material-design: false # To add assets to your application, add an assets section, like this: assets: diff --git a/web/index.html b/web/index.html index a2dfb65..b00093f 100644 --- a/web/index.html +++ b/web/index.html @@ -60,7 +60,7 @@ } scriptLoaded = true; var scriptTag = document.createElement('script'); - scriptTag.src = 'main.dart.js'; + scriptTag.src = `main.dart.js?version=${Math.random()}`; scriptTag.type = 'application/javascript'; document.body.append(scriptTag); }