didvan-app/lib/views/home/main/widgets/podcast_item.dart

197 lines
8.3 KiB
Dart

// ignore_for_file: avoid_web_libraries_in_flutter
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/home_page_content/content.dart';
import 'package:didvan/models/requests/studio.dart';
import 'package:didvan/models/studio_details_data.dart';
import 'package:didvan/services/media/media.dart';
import 'package:didvan/views/direct/widgets/audio_widget.dart';
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
import 'package:didvan/views/widgets/didvan/card.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:persian_number_utility/persian_number_utility.dart';
import 'package:provider/provider.dart';
import 'package:didvan/providers/user.dart';
import 'dart:html' as html;
class MainPagePodcastItem extends StatefulWidget {
final MainPageContentType content;
final String type = "podcast";
const MainPagePodcastItem({super.key, required this.content});
@override
State<MainPagePodcastItem> createState() => _MainPagePodcastItemState();
}
class _MainPagePodcastItemState extends State<MainPagePodcastItem> {
bool loading = false;
void _onMarkChange() {
UserProvider.changeItemMark(
widget.type,
widget.content.id,
!widget.content.marked,
);
setState(() => widget.content.marked = !widget.content.marked);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () async {
final state = context.read<StudioDetailsState>();
await state.getStudioDetails(
widget.content.id,
args: const StudioRequestArgs(page: 0, type: 'podcast'),
);
MediaService.currentPodcast = state.studio;
loading = true;
state.update();
final response =
await get(Uri.parse(widget.content.link.replaceAll('%3A', ':')));
final bytes = response.bodyBytes;
final blob = html.Blob([bytes]);
final blobUrl = html.Url.createObjectUrlFromBlob(blob);
await Future.delayed(const Duration(seconds: 3));
loading = false;
state.update();
MediaService.handleAudioPlayback(
audioSource: blobUrl,
id: widget.content.id,
isNetworkAudio: true,
isVoiceMessage: false,
);
},
child: Stack(
children: [
const SizedBox(
height: 180,
width: double.infinity,
),
Positioned.fill(
child: Center(
child: DidvanCard(
child: Row(
children: [
SizedBox(
width: MediaQuery.of(context).size.width / 3 - 15,
),
SizedBox(
width: MediaQuery.of(context).size.width * 2 / 3 - 60,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 12.0),
child: SizedBox(
child: AudioWidget(
id: widget.content.id,
audioUrl: widget.content.link,
audioMetaData: StudioDetailsData(
id: widget.content.id,
duration: widget.content.duration!,
title: widget.content.title,
description: '',
image: widget.content.image,
link: widget.content.link,
iframe: null,
createdAt: '',
order: 1,
marked: widget.content.marked,
comments: 0,
tags: [],
type: 'podcast',
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DidvanText(
widget.content.title,
style:
Theme.of(context).textTheme.bodyLarge,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 4),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
const Icon(
DidvanIcons.calendar_day_light,
size: 16,
),
const SizedBox(width: 4),
DidvanText(
DateTime.parse(
widget.content.subtitles[0])
.toPersianDateStr(),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context)
.textTheme
.bodySmall,
),
],
),
),
],
),
),
GestureDetector(
onTap: _onMarkChange,
child: Padding(
padding: const EdgeInsets.only(
left: 12, right: 12, bottom: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(
widget.content.marked
? DidvanIcons.bookmark_solid
: DidvanIcons.bookmark_regular,
color: widget.content.marked
? Theme.of(context)
.colorScheme
.secondary
: Theme.of(context)
.colorScheme
.caption),
],
),
),
)
],
)
],
),
),
],
),
),
),
),
SkeletonImage(
width: MediaQuery.of(context).size.width / 3 - 15,
height: 180,
imageUrl: widget.content.image,
),
],
),
);
}
}