mirror of
https://github.com/meditohq/medito-app.git
synced 2024-09-11 12:15:46 +03:00
feat webview added for links
This commit is contained in:
parent
10c732ef9d
commit
7522ade84c
@ -21,6 +21,11 @@ if (flutterVersionName == null) {
|
||||
flutterVersionName = '1.0'
|
||||
}
|
||||
|
||||
def appMinSdkVersion = localProperties.getProperty('flutter.minSdkVersion').toInteger()
|
||||
if (appMinSdkVersion == null) {
|
||||
appMinSdkVersion = 21
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
@ -64,7 +69,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "meditofoundation.medito"
|
||||
minSdkVersion flutter.minSdkVersion
|
||||
minSdkVersion appMinSdkVersion
|
||||
targetSdkVersion flutter.targetSdkVersion
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
|
3
assets/images/ic-forward.svg
Normal file
3
assets/images/ic-forward.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.25 4.5L15.75 12L8.25 19.5" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 225 B |
3
assets/images/ic-link.svg
Normal file
3
assets/images/ic-link.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.25 17H7C5.61667 17 4.4375 16.5125 3.4625 15.5375C2.4875 14.5625 2 13.3833 2 12C2 10.6167 2.4875 9.4375 3.4625 8.4625C4.4375 7.4875 5.61667 7 7 7H11.25V8.5H7C6.03333 8.5 5.20833 8.84167 4.525 9.525C3.84167 10.2083 3.5 11.0333 3.5 12C3.5 12.9667 3.84167 13.7917 4.525 14.475C5.20833 15.1583 6.03333 15.5 7 15.5H11.25V17ZM8.125 12.75V11.25H15.875V12.75H8.125ZM12.75 17V15.5H17C17.9667 15.5 18.7917 15.1583 19.475 14.475C20.1583 13.7917 20.5 12.9667 20.5 12C20.5 11.0333 20.1583 10.2083 19.475 9.525C18.7917 8.84167 17.9667 8.5 17 8.5H12.75V7H17C18.3833 7 19.5625 7.4875 20.5375 8.4625C21.5125 9.4375 22 10.6167 22 12C22 13.3833 21.5125 14.5625 20.5375 15.5375C19.5625 16.5125 18.3833 17 17 17H12.75Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 829 B |
28
lib/components/buttons/close_button_component.dart
Normal file
28
lib/components/buttons/close_button_component.dart
Normal file
@ -0,0 +1,28 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CloseButtonComponent extends StatelessWidget {
|
||||
const CloseButtonComponent(
|
||||
{super.key,
|
||||
this.onPressed,
|
||||
this.isShowCircle = true,
|
||||
this.bgColor = Colors.black38,
|
||||
this.icColor = Colors.white});
|
||||
final void Function()? onPressed;
|
||||
final bool isShowCircle;
|
||||
final Color bgColor;
|
||||
final Color icColor;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialButton(
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
onPressed: onPressed,
|
||||
color: isShowCircle ? bgColor : null,
|
||||
padding: EdgeInsets.all(14),
|
||||
shape: isShowCircle ? CircleBorder() : null,
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: icColor,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -2,3 +2,5 @@ export 'shimmers/folder_shimmer_component.dart';
|
||||
export 'shimmers/session_shimmer_component.dart';
|
||||
export 'error_component.dart';
|
||||
export 'headers/collapsible_header_component.dart';
|
||||
export 'buttons/close_button_component.dart';
|
||||
export 'webview_component.dart';
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:Medito/components/components.dart';
|
||||
import 'package:Medito/constants/constants.dart';
|
||||
import 'package:Medito/utils/navigation_extra.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -58,7 +59,7 @@ class _CollapsibleHeaderComponentState
|
||||
physics: AlwaysScrollableScrollPhysics(),
|
||||
slivers: <Widget>[
|
||||
SliverAppBar(
|
||||
leading: leadingButton(),
|
||||
leading: _leadingButton(),
|
||||
leadingWidth: 80,
|
||||
expandedHeight: height,
|
||||
floating: false,
|
||||
@ -68,13 +69,13 @@ class _CollapsibleHeaderComponentState
|
||||
backgroundColor: MeditoColors.deepNight,
|
||||
centerTitle: false,
|
||||
flexibleSpace: FlexibleSpaceBar(
|
||||
title: title(context),
|
||||
background: bgImage(context),
|
||||
title: _title(context),
|
||||
background: _bgImage(context),
|
||||
),
|
||||
),
|
||||
SliverList(
|
||||
delegate: SliverChildListDelegate([
|
||||
if (widget.description != null) description(widget.description!),
|
||||
if (widget.description != null) _description(widget.description!),
|
||||
...widget.children
|
||||
]),
|
||||
),
|
||||
@ -82,23 +83,16 @@ class _CollapsibleHeaderComponentState
|
||||
);
|
||||
}
|
||||
|
||||
MaterialButton leadingButton() {
|
||||
return MaterialButton(
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
CloseButtonComponent _leadingButton() {
|
||||
return CloseButtonComponent(
|
||||
onPressed: () {
|
||||
router.pop();
|
||||
},
|
||||
color: _isShrink ? null : Colors.black38,
|
||||
padding: EdgeInsets.all(16),
|
||||
shape: _isShrink ? null : CircleBorder(),
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: Colors.white,
|
||||
),
|
||||
isShowCircle: !_isShrink,
|
||||
);
|
||||
}
|
||||
|
||||
Stack bgImage(BuildContext context) {
|
||||
Stack _bgImage(BuildContext context) {
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
@ -124,7 +118,7 @@ class _CollapsibleHeaderComponentState
|
||||
);
|
||||
}
|
||||
|
||||
Transform title(BuildContext context) {
|
||||
Transform _title(BuildContext context) {
|
||||
return Transform(
|
||||
// you can forcefully translate values left side using Transform
|
||||
transform: Matrix4.translationValues(_isShrink ? 0 : -40.0, 0.0, 0.0),
|
||||
@ -142,7 +136,7 @@ class _CollapsibleHeaderComponentState
|
||||
);
|
||||
}
|
||||
|
||||
Container description(String description) {
|
||||
Container _description(String description) {
|
||||
return Container(
|
||||
color: Colors.grey.shade900,
|
||||
child: Padding(
|
||||
|
48
lib/components/webview_component.dart
Normal file
48
lib/components/webview_component.dart
Normal file
@ -0,0 +1,48 @@
|
||||
import 'package:Medito/components/buttons/close_button_component.dart';
|
||||
import 'package:Medito/constants/colors/color_constants.dart';
|
||||
import 'package:Medito/views/main/app_bar_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
class WebViewComponent extends StatefulWidget {
|
||||
final String url;
|
||||
|
||||
const WebViewComponent({Key? key, required this.url}) : super(key: key);
|
||||
@override
|
||||
_WebViewComponentState createState() => _WebViewComponentState();
|
||||
}
|
||||
|
||||
class _WebViewComponentState extends State<WebViewComponent> {
|
||||
int _stackToView = 1;
|
||||
void _handleLoad(String value) {
|
||||
setState(() {
|
||||
_stackToView = 0;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: MeditoColors.greyIsTheNewGrey,
|
||||
appBar: MeditoAppBarWidget(
|
||||
hasCloseButton: true,
|
||||
),
|
||||
body: IndexedStack(
|
||||
index: _stackToView,
|
||||
children: [
|
||||
WebView(
|
||||
javascriptMode: JavascriptMode.unrestricted,
|
||||
onWebViewCreated: (WebViewController webViewController) {
|
||||
webViewController.loadUrl(widget.url);
|
||||
},
|
||||
onPageFinished: _handleLoad,
|
||||
),
|
||||
const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -3,4 +3,5 @@ export 'strings/asset_constants.dart';
|
||||
export 'strings/string_constants.dart';
|
||||
export 'styles/widget_styles.dart';
|
||||
export 'http/http_constants.dart';
|
||||
export 'types/type_constants.dart';
|
||||
export 'theme/text_theme.dart';
|
@ -1,3 +1,13 @@
|
||||
class AssetConstants {
|
||||
static const String dalle = 'assets/images/dalle.png';
|
||||
static const String icLink = 'assets/images/ic-link.svg';
|
||||
static const String icForward = 'assets/images/ic-forward.svg';
|
||||
static const String icColourfulHearts = 'assets/images/colourful_hearts.svg';
|
||||
static const String icSadFace = 'assets/images/ic_sad_face.svg';
|
||||
static const String icNeutralFace = 'assets/images/ic_neutral_face.svg';
|
||||
static const String icHappyFace = 'assets/images/ic_happy_face.svg';
|
||||
static const String icTwitter = 'assets/images/ic_twitter.svg';
|
||||
static const String icYoutube = 'assets/images/ic_youtube.svg';
|
||||
static const String icInsta = 'assets/images/ic_insta.svg';
|
||||
static const String icReddit = 'assets/images/ic_reddit.svg';
|
||||
}
|
||||
|
5
lib/constants/types/type_constants.dart
Normal file
5
lib/constants/types/type_constants.dart
Normal file
@ -0,0 +1,5 @@
|
||||
class TypeConstants {
|
||||
static const String LINK = 'link';
|
||||
static const String FOLDER = 'folder';
|
||||
static const String SESSION = 'session';
|
||||
}
|
@ -14,6 +14,9 @@ abstract class FolderModel with _$FolderModel {
|
||||
|
||||
factory FolderModel.fromJson(Map<String, Object?> json) =>
|
||||
_$FolderModelFromJson(json);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@freezed
|
||||
|
@ -11,7 +11,7 @@ abstract class SessionModel with _$SessionModel {
|
||||
required String coverUrl,
|
||||
required bool isPublished,
|
||||
required bool hasBackgroundSound,
|
||||
required SessionArtistModel artist,
|
||||
@Default(null) SessionArtistModel? artist,
|
||||
@Default([]) List<SessionAudioModel> audio}) = _SessionModel;
|
||||
|
||||
factory SessionModel.fromJson(Map<String, Object?> json) =>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import 'package:Medito/network/folder/new_folder_screen.dart';
|
||||
import 'package:Medito/components/components.dart';
|
||||
import 'package:Medito/utils/utils.dart';
|
||||
import 'package:Medito/views/btm_nav/downloads_widget.dart';
|
||||
import 'package:Medito/views/folder/folder_view.dart';
|
||||
@ -23,6 +23,7 @@ const String Folder3Path = '/folder/:fid/folder2/:f2id/folder3/:f3id';
|
||||
const String Player3 = '/folder/:fid/folder2/:f2id/folder3/:f3id/session/:sid';
|
||||
const String UrlPath = '/url';
|
||||
const String CollectionPath = '/app';
|
||||
const String webviewPath = '/webview';
|
||||
const String HomePath = '/';
|
||||
|
||||
final router = GoRouter(
|
||||
@ -36,6 +37,7 @@ final router = GoRouter(
|
||||
_getSessionRoute(),
|
||||
_getArticleRoute(),
|
||||
_getDailyRoute(),
|
||||
_getWebviewRoute(),
|
||||
GoRoute(
|
||||
path: 'app',
|
||||
routes: [_getPlayerRoute()],
|
||||
@ -46,6 +48,7 @@ final router = GoRouter(
|
||||
routes: [
|
||||
_getSessionRoute(),
|
||||
_getArticleRoute(),
|
||||
_getWebviewRoute(),
|
||||
GoRoute(
|
||||
path: 'folder2/:f2id',
|
||||
routes: [
|
||||
@ -102,6 +105,19 @@ GoRoute _getPlayerRoute() {
|
||||
);
|
||||
}
|
||||
|
||||
GoRoute _getWebviewRoute() {
|
||||
return GoRoute(
|
||||
path: 'webview',
|
||||
pageBuilder: (context, state) {
|
||||
final url = state.extra! as Map;
|
||||
return MaterialPage(
|
||||
key: state.pageKey,
|
||||
child: WebViewComponent(url: url['url']!),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
enum Screen {
|
||||
folder,
|
||||
player,
|
||||
@ -117,8 +133,8 @@ enum Screen {
|
||||
MaterialPage<void> getSessionOptionsMaterialPage(GoRouterState state) {
|
||||
return MaterialPage(
|
||||
key: state.pageKey,
|
||||
child: SessionViewScreen(
|
||||
id: state.params['sid'], screenKey: Screen.session),
|
||||
child:
|
||||
SessionViewScreen(id: state.params['sid'], screenKey: Screen.session),
|
||||
);
|
||||
}
|
||||
|
||||
@ -132,8 +148,7 @@ MaterialPage<void> getArticleMaterialPAge(GoRouterState state) {
|
||||
MaterialPage<void> getSessionOptionsDailyPage(GoRouterState state) {
|
||||
return MaterialPage(
|
||||
key: state.pageKey,
|
||||
child:
|
||||
SessionViewScreen(id: state.params['did'], screenKey: Screen.daily),
|
||||
child: SessionViewScreen(id: state.params['did'], screenKey: Screen.daily),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,11 @@ Widget getNetworkImageWidget(String? url) {
|
||||
return Image.network(url!, fit: BoxFit.fill, headers: headers);
|
||||
}
|
||||
|
||||
NetworkImage getNetworkImage(String url) {
|
||||
final headers = {HttpHeaders.authorizationHeader: CONTENT_TOKEN};
|
||||
return NetworkImage(url, headers: headers);
|
||||
}
|
||||
|
||||
Future<bool> checkConnectivity() async {
|
||||
var connectivityResult = await (Connectivity().checkConnectivity());
|
||||
return connectivityResult != ConnectivityResult.none;
|
||||
@ -115,6 +120,22 @@ extension EmptyOrNull on String? {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> showBottomModal(BuildContext context, Widget child) async {
|
||||
await showModalBottomSheet(
|
||||
context: context,
|
||||
barrierColor: MeditoColors.almostBlack,
|
||||
backgroundColor: MeditoColors.greyIsTheNewGrey,
|
||||
isScrollControlled: false,
|
||||
elevation: 10,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
),
|
||||
builder: (BuildContext context) {
|
||||
return FractionallySizedBox(heightFactor: 0.9, child: child);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
extension AssetUrl on String {
|
||||
String toAssetUrl() {
|
||||
return '${BASE_URL}assets/$this?download';
|
||||
|
@ -6,6 +6,7 @@ import 'package:Medito/utils/utils.dart';
|
||||
import 'package:Medito/view_model/folder/folder_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class FolderView extends ConsumerWidget {
|
||||
@ -45,8 +46,13 @@ class FolderView extends ConsumerWidget {
|
||||
children: folder.items
|
||||
.map(
|
||||
(e) => GestureDetector(
|
||||
onTap: () => _onListItemTap(e.id, e.type, ref.context),
|
||||
child: _buildListTile(context, e.name, e.subtitle, true),
|
||||
onTap: () => _onListItemTap(e.id, e.type, e.path, ref.context),
|
||||
child: _buildListTile(
|
||||
context,
|
||||
e.name,
|
||||
e.subtitle,
|
||||
e.type,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
@ -55,7 +61,7 @@ class FolderView extends ConsumerWidget {
|
||||
}
|
||||
|
||||
Container _buildListTile(
|
||||
BuildContext context, String? title, String? subtitle, bool showIcon) {
|
||||
BuildContext context, String? title, String? subtitle, String type) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
@ -73,7 +79,7 @@ class FolderView extends ConsumerWidget {
|
||||
if (title != null)
|
||||
Text(
|
||||
title,
|
||||
style: Theme.of(context).primaryTextTheme.bodyText1?.copyWith(
|
||||
style: Theme.of(context).primaryTextTheme.bodyLarge?.copyWith(
|
||||
color: MeditoColors.walterWhite,
|
||||
fontFamily: DmSans,
|
||||
height: 2),
|
||||
@ -81,7 +87,7 @@ class FolderView extends ConsumerWidget {
|
||||
if (subtitle != null)
|
||||
Text(
|
||||
subtitle,
|
||||
style: Theme.of(context).primaryTextTheme.bodyText1?.copyWith(
|
||||
style: Theme.of(context).primaryTextTheme.bodyLarge?.copyWith(
|
||||
fontFamily: DmMono,
|
||||
height: 2,
|
||||
color: MeditoColors.newGrey,
|
||||
@ -89,17 +95,18 @@ class FolderView extends ConsumerWidget {
|
||||
)
|
||||
],
|
||||
),
|
||||
if (showIcon) Icon(_getIcon(), color: Colors.white)
|
||||
if (type != TypeConstants.SESSION) _getIcon(type)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onListItemTap(int? id, String? type, BuildContext context) {
|
||||
void _onListItemTap(
|
||||
int? id, String? type, String? path, BuildContext context) {
|
||||
checkConnectivity().then((value) {
|
||||
if (value) {
|
||||
var location = GoRouter.of(context).location;
|
||||
if (type == 'folder') {
|
||||
if (type == TypeConstants.FOLDER) {
|
||||
if (location.contains('folder2')) {
|
||||
context.go(getPathFromString(
|
||||
Folder3Path, [location.split('/')[2], this.id, id.toString()]));
|
||||
@ -107,6 +114,9 @@ class FolderView extends ConsumerWidget {
|
||||
context
|
||||
.go(getPathFromString(Folder2Path, [this.id, id.toString()]));
|
||||
}
|
||||
} else if (type == TypeConstants.LINK) {
|
||||
context.go(location + webviewPath, extra: {'url': path!});
|
||||
// context.go(getPathFromString('url', [path.toString()]));
|
||||
} else {
|
||||
context.go(location + getPathFromString(type, [id.toString()]));
|
||||
}
|
||||
@ -116,9 +126,12 @@ class FolderView extends ConsumerWidget {
|
||||
});
|
||||
}
|
||||
|
||||
IconData _getIcon() {
|
||||
return Icons.check_circle_outline_sharp;
|
||||
// return Icons.article_outlined;
|
||||
// return Icons.arrow_forward_ios_sharp;
|
||||
Widget _getIcon(String type) {
|
||||
if (type == TypeConstants.FOLDER) {
|
||||
return SvgPicture.asset(AssetConstants.icForward);
|
||||
} else if (type == TypeConstants.LINK) {
|
||||
return SvgPicture.asset(AssetConstants.icLink);
|
||||
}
|
||||
return SizedBox();
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ class _AudioCompleteDialogState extends State<AudioCompleteDialog> {
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset('assets/images/colourful_hearts.svg'),
|
||||
SvgPicture.asset(AssetConstants.icColourfulHearts),
|
||||
Container(height: 16),
|
||||
Text(
|
||||
'Medito is keeping access to meditation free, forever. Say thanks by donating.',
|
||||
@ -135,7 +135,7 @@ class _AudioCompleteDialogState extends State<AudioCompleteDialog> {
|
||||
color: MeditoColors.darkMoon,
|
||||
onPressed: _sadPressed,
|
||||
child: SvgPicture.asset(
|
||||
'assets/images/ic_sad_face.svg',
|
||||
AssetConstants.icSadFace,
|
||||
),
|
||||
),
|
||||
Container(width: 12),
|
||||
@ -149,7 +149,7 @@ class _AudioCompleteDialogState extends State<AudioCompleteDialog> {
|
||||
color: MeditoColors.darkMoon,
|
||||
onPressed: _neutralFacePressed,
|
||||
child: SvgPicture.asset(
|
||||
'assets/images/ic_neutral_face.svg',
|
||||
AssetConstants.icNeutralFace,
|
||||
),
|
||||
),
|
||||
Container(width: 12),
|
||||
@ -163,7 +163,7 @@ class _AudioCompleteDialogState extends State<AudioCompleteDialog> {
|
||||
color: MeditoColors.darkMoon,
|
||||
onPressed: _happyFacePressed,
|
||||
child: SvgPicture.asset(
|
||||
'assets/images/ic_happy_face.svg',
|
||||
AssetConstants.icHappyFace,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -198,7 +198,7 @@ class _AudioCompleteDialogState extends State<AudioCompleteDialog> {
|
||||
padding: const EdgeInsets.all(16.0)),
|
||||
onPressed: _onTwitterTap,
|
||||
icon: SvgPicture.asset(
|
||||
'assets/images/ic_twitter.svg',
|
||||
AssetConstants.icTwitter,
|
||||
),
|
||||
label:
|
||||
Text('Twitter', style: TextStyle(color: Colors.white))),
|
||||
@ -212,7 +212,7 @@ class _AudioCompleteDialogState extends State<AudioCompleteDialog> {
|
||||
padding: const EdgeInsets.all(16.0)),
|
||||
onPressed: _onYoutubeTap,
|
||||
icon: SvgPicture.asset(
|
||||
'assets/images/ic_youtube.svg',
|
||||
AssetConstants.icYoutube,
|
||||
),
|
||||
label:
|
||||
Text('Youtube', style: TextStyle(color: Colors.white))),
|
||||
@ -231,7 +231,7 @@ class _AudioCompleteDialogState extends State<AudioCompleteDialog> {
|
||||
padding: const EdgeInsets.all(16.0)),
|
||||
onPressed: _onInstaTap,
|
||||
icon: SvgPicture.asset(
|
||||
'assets/images/ic_insta.svg',
|
||||
AssetConstants.icInsta,
|
||||
),
|
||||
label: Text('Instagram',
|
||||
style: TextStyle(color: Colors.white))),
|
||||
@ -245,7 +245,7 @@ class _AudioCompleteDialogState extends State<AudioCompleteDialog> {
|
||||
padding: const EdgeInsets.all(16.0)),
|
||||
onPressed: _onRedditTap,
|
||||
icon: SvgPicture.asset(
|
||||
'assets/images/ic_reddit.svg',
|
||||
AssetConstants.icReddit,
|
||||
),
|
||||
label:
|
||||
Text('Reddit', style: TextStyle(color: Colors.white))),
|
||||
|
@ -17,8 +17,10 @@ import 'dart:async';
|
||||
|
||||
import 'package:Medito/audioplayer/media_lib.dart';
|
||||
import 'package:Medito/audioplayer/medito_audio_handler.dart';
|
||||
import 'package:Medito/components/components.dart';
|
||||
import 'package:Medito/network/player/player_bloc.dart';
|
||||
import 'package:Medito/constants/constants.dart';
|
||||
import 'package:Medito/utils/navigation_extra.dart';
|
||||
import 'package:Medito/utils/shared_preferences_utils.dart';
|
||||
import 'package:Medito/utils/utils.dart';
|
||||
import 'package:Medito/views/main/app_bar_widget.dart';
|
||||
@ -104,31 +106,37 @@ class _PlayerWidgetState extends State<PlayerWidget> {
|
||||
}
|
||||
});
|
||||
|
||||
return Material(
|
||||
color: MeditoColors.greyIsTheNewBlack,
|
||||
child: Scaffold(
|
||||
extendBody: false,
|
||||
extendBodyBehindAppBar: true,
|
||||
appBar: _getAppBar(),
|
||||
body: Stack(
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
_buildImage(mediaItem?.artUri?.toString()),
|
||||
Container(height: 24),
|
||||
_buildTitleRows(),
|
||||
Expanded(child: SizedBox.shrink()),
|
||||
_buildPlayerButtonRow(mediaItem),
|
||||
Expanded(child: SizedBox.shrink()),
|
||||
// A seek bar.
|
||||
PositionIndicatorWidget(
|
||||
handler: _handler,
|
||||
bgSoundsStream: _bloc.bgSoundsListController?.stream),
|
||||
Container(height: 24),
|
||||
],
|
||||
),
|
||||
],
|
||||
return Scaffold(
|
||||
extendBody: false,
|
||||
extendBodyBehindAppBar: true,
|
||||
body: Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: getNetworkImage(mediaItem!.artUri.toString()),
|
||||
fit: BoxFit.fill,
|
||||
colorFilter: ColorFilter.mode(
|
||||
MeditoColors.almostBlack.withOpacity(0.5), BlendMode.overlay),
|
||||
),
|
||||
),
|
||||
child: SafeArea(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
CloseButtonComponent(
|
||||
onPressed: () => router.pop(),
|
||||
bgColor: MeditoColors.walterWhite,
|
||||
icColor: MeditoColors.almostBlack,
|
||||
),
|
||||
Spacer(),
|
||||
_buildTitleRows(),
|
||||
_buildPlayerButtonRow(mediaItem),
|
||||
// A seek bar.
|
||||
PositionIndicatorWidget(
|
||||
handler: _handler,
|
||||
bgSoundsStream: _bloc.bgSoundsListController?.stream),
|
||||
Container(height: 24),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -179,34 +187,27 @@ class _PlayerWidgetState extends State<PlayerWidget> {
|
||||
);
|
||||
}
|
||||
|
||||
PreferredSizeWidget _getAppBar() {
|
||||
return MeditoAppBarWidget(
|
||||
isTransparent: true,
|
||||
hasCloseButton: true,
|
||||
closePressed: _onBackPressed,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _getTitleRow(MediaItem? mediaItem) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 4.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
mediaItem?.title ?? 'Loading...',
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: buildTitleTheme(),
|
||||
)),
|
||||
child: Text(
|
||||
mediaItem?.title ?? 'Loading...',
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: buildTitleTheme(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TextStyle? buildTitleTheme() {
|
||||
return Theme.of(context).textTheme.headline1;
|
||||
return Theme.of(context).textTheme.displayLarge;
|
||||
}
|
||||
|
||||
Widget _getSubtitleWidget(MediaItem? mediaItem) {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:Medito/constants/constants.dart';
|
||||
import 'package:Medito/constants/constants.dart';
|
||||
import 'package:Medito/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
|
@ -1,26 +1,30 @@
|
||||
import 'package:Medito/audioplayer/audio_inherited_widget.dart';
|
||||
import 'package:Medito/audioplayer/media_lib.dart';
|
||||
import 'package:Medito/constants/constants.dart';
|
||||
import 'package:Medito/models/models.dart';
|
||||
import 'package:Medito/utils/navigation_extra.dart';
|
||||
import 'package:Medito/utils/utils.dart';
|
||||
import 'package:audio_service/audio_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class SessionButtons extends StatelessWidget {
|
||||
final List<SessionAudioModel> audios;
|
||||
const SessionButtons({super.key, required this.audios});
|
||||
final SessionModel sessionModel;
|
||||
const SessionButtons({super.key, required this.sessionModel});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
shrinkWrap: true,
|
||||
itemCount: audios.length,
|
||||
itemCount: sessionModel.audio.length,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, i) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
audios[i].guideName,
|
||||
sessionModel.audio[i].guideName,
|
||||
style: Theme.of(context).primaryTextTheme.bodyLarge?.copyWith(
|
||||
color: MeditoColors.walterWhite,
|
||||
),
|
||||
@ -41,14 +45,37 @@ class SessionButtons extends StatelessWidget {
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
children: audios[i].files.map((e) => _getGridItem(context, e)).toList(),
|
||||
children: sessionModel.audio[i].files
|
||||
.map((e) => _getGridItem(
|
||||
context,
|
||||
sessionModel.audio[i].guideName,
|
||||
'https://cdn.esawebb.org/archives/images/screen/weic2216b.jpg',
|
||||
e))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
InkWell _getGridItem(BuildContext context, SessionFilesModel files) {
|
||||
InkWell _getGridItem(
|
||||
BuildContext context,
|
||||
String title,
|
||||
String coverUrl,
|
||||
SessionFilesModel file,
|
||||
) {
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
context.go(GoRouter.of(context).location + files.path.toString());
|
||||
AudioHandler? _audioHandler =
|
||||
AudioHandlerInheritedWidget.of(context).audioHandler;
|
||||
var mediaItem = MediaItem(
|
||||
id: 'https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba.mp3',
|
||||
// id: file.path.toString(),
|
||||
title: title,
|
||||
duration: Duration(milliseconds: file.duration),
|
||||
artUri: Uri.parse(coverUrl),
|
||||
extras: {
|
||||
HAS_BG_SOUND: true,
|
||||
});
|
||||
_audioHandler.playMediaItem(mediaItem);
|
||||
context.go(GoRouter.of(context).location + PlayerPath);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
child: Ink(
|
||||
@ -62,7 +89,7 @@ class SessionButtons extends StatelessWidget {
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'${convertDurationToMinutes(milliseconds: files.duration)} mins',
|
||||
'${convertDurationToMinutes(milliseconds: file.duration)} mins',
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.bodyLarge
|
||||
|
@ -30,7 +30,7 @@ class SessionViewScreen extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
var sessions = ref.watch(fetchSessionsProvider(sessionId: 1));
|
||||
var sessions = ref.watch(fetchSessionsProvider(sessionId: int.parse(id!)));
|
||||
return Scaffold(
|
||||
body: sessions.when(
|
||||
skipLoadingOnRefresh: false,
|
||||
@ -86,7 +86,7 @@ class SessionViewScreen extends ConsumerWidget {
|
||||
),
|
||||
height16,
|
||||
SessionButtons(
|
||||
audios: sessionModel.audio,
|
||||
sessionModel: sessionModel,
|
||||
)
|
||||
],
|
||||
),
|
||||
|
@ -49,6 +49,7 @@ dependencies:
|
||||
json_annotation: ^4.7.0
|
||||
flutter_dotenv: ^5.0.2
|
||||
shimmer: ^2.0.0
|
||||
webview_flutter: ^2.8.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.3.3
|
||||
|
Loading…
Reference in New Issue
Block a user