From 855dd187c8d27691206cb169a0015c37c31012de Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Fri, 8 Dec 2023 12:16:17 +0900 Subject: [PATCH 01/13] =?UTF-8?q?add:=20youtube=5Fplayer=5Fiframe=E3=82=92?= =?UTF-8?q?=E5=B0=8E=E5=85=A5=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pubspec.lock | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ pubspec.yaml | 1 + 2 files changed, 49 insertions(+) diff --git a/pubspec.lock b/pubspec.lock index 49290de5..7d7a271e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1002,6 +1002,38 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.0" + webview_flutter: + dependency: transitive + description: + name: webview_flutter + sha256: "42393b4492e629aa3a88618530a4a00de8bb46e50e7b3993fedbfdc5352f0dbf" + url: "https://pub.dev" + source: hosted + version: "4.4.2" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + sha256: "8326ee235f87605a2bfc444a4abc897f4abc78d83f054ba7d3d1074ce82b4fbf" + url: "https://pub.dev" + source: hosted + version: "3.12.1" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + sha256: "68e86162aa8fc646ae859e1585995c096c95fc2476881fa0c4a8d10f56013a5a" + url: "https://pub.dev" + source: hosted + version: "2.8.0" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + sha256: accdaaa49a2aca2dc3c3230907988954cdd23fed0a19525d6c9789d380f4dc76 + url: "https://pub.dev" + source: hosted + version: "3.9.4" win32: dependency: transitive description: @@ -1034,6 +1066,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" + youtube_player_iframe: + dependency: "direct main" + description: + name: youtube_player_iframe + sha256: d7aec9083430db4e5da83a3b5d7b7fcbb93cfa027d9f680ce3c7e7cd20724305 + url: "https://pub.dev" + source: hosted + version: "4.0.4" + youtube_player_iframe_web: + dependency: transitive + description: + name: youtube_player_iframe_web + sha256: c7020816031600349b56d2729d4e8be011fcb723ff7dc2dd0cdf72096a0e5ff4 + url: "https://pub.dev" + source: hosted + version: "2.0.2" sdks: dart: ">=3.2.0-42.2.beta <4.0.0" flutter: ">=3.14.0-0.2.pre" diff --git a/pubspec.yaml b/pubspec.yaml index afb4839e..85933f21 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,6 +35,7 @@ dependencies: riverpod_annotation: ^2.1.1 transparent_image: ^2.0.1 url_launcher: ^6.1.11 + youtube_player_iframe: ^4.0.4 dev_dependencies: build_runner: ^2.4.5 From 2502214951271cec04bc0a7b08fc9da0d6597417 Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Fri, 8 Dec 2023 12:17:46 +0900 Subject: [PATCH 02/13] =?UTF-8?q?add:=20youtube=E3=81=AE=E5=8B=95=E7=94=BB?= =?UTF-8?q?=E3=82=92=E5=9F=8B=E3=82=81=E8=BE=BC=E3=82=93=E3=81=A7=E3=81=BF?= =?UTF-8?q?=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../session/ui/detail/session_detail.dart | 2 ++ .../ui/detail/session_detail_content.dart | 20 ++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/features/session/ui/detail/session_detail.dart b/lib/features/session/ui/detail/session_detail.dart index 517eb479..2abc7f2b 100644 --- a/lib/features/session/ui/detail/session_detail.dart +++ b/lib/features/session/ui/detail/session_detail.dart @@ -28,6 +28,7 @@ class SessionDetail extends ConsumerWidget { cardPadding: 40, contentGap: 40, sectionGap: 80, + youtubeGap: MediaQuery.of(context).size.width / 1.5, bodyVerticalMargin: 20, sectionHeaderTextStyle: AppTextStyle.pcHeading1, sessionTitleTextStyle: textTheme.displayMedium!, @@ -38,6 +39,7 @@ class SessionDetail extends ConsumerWidget { cardPadding: 24, contentGap: 16, sectionGap: 80, + youtubeGap: double.infinity, bodyVerticalMargin: 16, sectionHeaderTextStyle: AppTextStyle.spHeading1, sessionTitleTextStyle: textTheme.displaySmall!, diff --git a/lib/features/session/ui/detail/session_detail_content.dart b/lib/features/session/ui/detail/session_detail_content.dart index f339a7ca..ebb18b84 100644 --- a/lib/features/session/ui/detail/session_detail_content.dart +++ b/lib/features/session/ui/detail/session_detail_content.dart @@ -4,6 +4,7 @@ import 'package:confwebsite2023/core/components/social_share.dart'; import 'package:confwebsite2023/core/gen/assets.gen.dart'; import 'package:confwebsite2023/core/theme.dart'; import 'package:confwebsite2023/features/session/data/session.dart'; +import 'package:confwebsite2023/features/session/ui/detail/youtube_url_mixin.dart'; import 'package:confwebsite2023/features/sponsor/data/sponsor.dart'; import 'package:confwebsite2023/features/sponsor/ui/detail/sponsor_detail_logo_card.dart'; import 'package:flutter/material.dart'; @@ -11,8 +12,9 @@ import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:url_launcher/link.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:youtube_player_iframe/youtube_player_iframe.dart'; -class SessionDetailContent extends StatelessWidget { +class SessionDetailContent extends StatelessWidget with YoutubeUrlMixin { const SessionDetailContent({ required this.session, required this.sponsor, @@ -21,6 +23,7 @@ class SessionDetailContent extends StatelessWidget { required this.contentGap, required this.sectionGap, required this.cardPadding, + required this.youtubeGap, required this.bodyVerticalMargin, super.key, }); @@ -32,6 +35,7 @@ class SessionDetailContent extends StatelessWidget { final double cardPadding; final double contentGap; final double sectionGap; + final double youtubeGap; final double bodyVerticalMargin; @override @@ -115,6 +119,18 @@ class SessionDetailContent extends StatelessWidget { bottom: contentGap / 2, ); + final youtubePlayer = Center( + child: SizedBox( + width: youtubeGap, + child: YoutubePlayer( + controller: YoutubePlayerController.fromVideoId( + videoId: getUrl(session.title), + params: const YoutubePlayerParams(showFullscreenButton: true), + ), + ), + ), + ); + final body = DecoratedBox( decoration: BoxDecoration( color: Colors.black.withOpacity(0.35), @@ -168,6 +184,8 @@ class SessionDetailContent extends StatelessWidget { profileBody, contentVerticalGap, Divider(color: baselineColorScheme.ref.secondary.secondary50), + contentVerticalGap, + youtubePlayer, MarkdownBody( data: session.abstract, styleSheet: MarkdownStyleSheet.fromTheme(theme).copyWith( From f1101d2e21d0cd4f3e4bb1c28070b4caecf09892 Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Fri, 8 Dec 2023 12:18:19 +0900 Subject: [PATCH 03/13] =?UTF-8?q?add:=20youtube=E3=81=AEurl=E3=81=AE?= =?UTF-8?q?=E5=88=87=E3=82=8A=E5=88=86=E3=81=91=E3=82=92=E6=9B=B8=E3=81=84?= =?UTF-8?q?=E3=81=A6=E3=81=BF=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../session/ui/detail/youtube_url_mixin.dart | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 lib/features/session/ui/detail/youtube_url_mixin.dart diff --git a/lib/features/session/ui/detail/youtube_url_mixin.dart b/lib/features/session/ui/detail/youtube_url_mixin.dart new file mode 100644 index 00000000..3d7ce762 --- /dev/null +++ b/lib/features/session/ui/detail/youtube_url_mixin.dart @@ -0,0 +1,34 @@ +mixin YoutubeUrlMixin { + String getUrl(String user) { + switch (user) { + case 'Flutter アプリにおけるテスト戦略の見直しと自動テストの導入': + return 'VHhZlTDfwIQ'; + case '詳解!Flutterにおける課金実装': + return 'NcfrY-EN8Pg'; + case 'Master of Flutter lifecycle': + return 'sznsAolD6dI'; + case 'Dartのコード自動生成の仕組みと、コード自動生成のパッケージを自作する方法について': + return 'EKoI-p1UnNk'; + case 'Flutterで構築する漫画ビューア': + return 'vCoG6BTNpAA'; + case 'Flutterアプリのセキュリティ対策を考えてみる': + return 'lObSpRxP1Do'; + case '我々にはなぜ Riverpod が必要なのか - InheritedWidget から始まる app state 管理手法の課題': + return '2SnTNFAzmY0'; + case '魅せろ! Flutter で目を惹く UI デザインを実装する': + return '6zLih07J3RU'; + case 'Add Material touch ripples': + return 'cMS2FzbhXJ8'; + case '出前館におけるFlutterの現在とこれから': + return 'bKnvn-Orpd0'; + case 'DartによるBFF構築・運用 〜Dart Frog×melos〜': + return 'jNmyr-TZVfU'; + case 'Master of Flutter lifecycle': + return 'sznsAolD6dI'; + case 'ゆめみの Flutter エンジニア育成方法': + return 'UGxzjYNHH90'; + default: + return ''; + } + } +} From a1e4450a18369bdbf24ece830c36d96f8205aace Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Fri, 8 Dec 2023 12:28:46 +0900 Subject: [PATCH 04/13] =?UTF-8?q?fix:=20=E9=87=8D=E8=A4=87=E3=81=97?= =?UTF-8?q?=E3=81=A6=E3=81=84=E3=81=9F=E3=82=BF=E3=82=A4=E3=83=88=E3=83=AB?= =?UTF-8?q?=E3=82=92=E5=89=8A=E9=99=A4=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/features/session/ui/detail/youtube_url_mixin.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/features/session/ui/detail/youtube_url_mixin.dart b/lib/features/session/ui/detail/youtube_url_mixin.dart index 3d7ce762..53468307 100644 --- a/lib/features/session/ui/detail/youtube_url_mixin.dart +++ b/lib/features/session/ui/detail/youtube_url_mixin.dart @@ -23,8 +23,6 @@ mixin YoutubeUrlMixin { return 'bKnvn-Orpd0'; case 'DartによるBFF構築・運用 〜Dart Frog×melos〜': return 'jNmyr-TZVfU'; - case 'Master of Flutter lifecycle': - return 'sznsAolD6dI'; case 'ゆめみの Flutter エンジニア育成方法': return 'UGxzjYNHH90'; default: From ef3a503ea1032cec4cebad9a11c3e652ab3b7589 Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Wed, 13 Dec 2023 10:04:46 +0900 Subject: [PATCH 05/13] =?UTF-8?q?fix:=20youtubeGap=20=3D>=20youtubeWidth?= =?UTF-8?q?=E3=81=AB=E4=BF=AE=E6=AD=A3=E3=81=97=E3=81=BE=E3=81=84=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/features/session/ui/detail/session_detail.dart | 4 ++-- lib/features/session/ui/detail/session_detail_content.dart | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/features/session/ui/detail/session_detail.dart b/lib/features/session/ui/detail/session_detail.dart index 2abc7f2b..e4095bac 100644 --- a/lib/features/session/ui/detail/session_detail.dart +++ b/lib/features/session/ui/detail/session_detail.dart @@ -28,7 +28,7 @@ class SessionDetail extends ConsumerWidget { cardPadding: 40, contentGap: 40, sectionGap: 80, - youtubeGap: MediaQuery.of(context).size.width / 1.5, + youtubeWidth: MediaQuery.of(context).size.width / 1.5, bodyVerticalMargin: 20, sectionHeaderTextStyle: AppTextStyle.pcHeading1, sessionTitleTextStyle: textTheme.displayMedium!, @@ -39,7 +39,7 @@ class SessionDetail extends ConsumerWidget { cardPadding: 24, contentGap: 16, sectionGap: 80, - youtubeGap: double.infinity, + youtubeWidth: double.infinity, bodyVerticalMargin: 16, sectionHeaderTextStyle: AppTextStyle.spHeading1, sessionTitleTextStyle: textTheme.displaySmall!, diff --git a/lib/features/session/ui/detail/session_detail_content.dart b/lib/features/session/ui/detail/session_detail_content.dart index ebb18b84..a911a9e0 100644 --- a/lib/features/session/ui/detail/session_detail_content.dart +++ b/lib/features/session/ui/detail/session_detail_content.dart @@ -23,7 +23,7 @@ class SessionDetailContent extends StatelessWidget with YoutubeUrlMixin { required this.contentGap, required this.sectionGap, required this.cardPadding, - required this.youtubeGap, + required this.youtubeWidth, required this.bodyVerticalMargin, super.key, }); @@ -35,7 +35,7 @@ class SessionDetailContent extends StatelessWidget with YoutubeUrlMixin { final double cardPadding; final double contentGap; final double sectionGap; - final double youtubeGap; + final double youtubeWidth; final double bodyVerticalMargin; @override @@ -121,7 +121,7 @@ class SessionDetailContent extends StatelessWidget with YoutubeUrlMixin { final youtubePlayer = Center( child: SizedBox( - width: youtubeGap, + width: youtubeWidth, child: YoutubePlayer( controller: YoutubePlayerController.fromVideoId( videoId: getUrl(session.title), From 86e781579beadc001b59c38c30425caff31bf184 Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Wed, 13 Dec 2023 10:08:02 +0900 Subject: [PATCH 06/13] =?UTF-8?q?fix:=20MediaQuery=E3=81=AE=E8=A8=98?= =?UTF-8?q?=E8=BC=89=E6=96=B9=E6=B3=95=E3=82=92=E4=BF=AE=E6=AD=A3=E3=81=97?= =?UTF-8?q?=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/features/session/ui/detail/session_detail.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/features/session/ui/detail/session_detail.dart b/lib/features/session/ui/detail/session_detail.dart index e4095bac..75a779e5 100644 --- a/lib/features/session/ui/detail/session_detail.dart +++ b/lib/features/session/ui/detail/session_detail.dart @@ -28,7 +28,7 @@ class SessionDetail extends ConsumerWidget { cardPadding: 40, contentGap: 40, sectionGap: 80, - youtubeWidth: MediaQuery.of(context).size.width / 1.5, + youtubeWidth: MediaQuery.sizeOf(context).width / 1.5, bodyVerticalMargin: 20, sectionHeaderTextStyle: AppTextStyle.pcHeading1, sessionTitleTextStyle: textTheme.displayMedium!, From daa9daf3583825494c3092f48cb52b58ed519cd2 Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Wed, 13 Dec 2023 10:46:08 +0900 Subject: [PATCH 07/13] =?UTF-8?q?fix:=20youtube=E3=81=AE=E3=83=AA=E3=83=B3?= =?UTF-8?q?=E3=82=AF=E3=82=92extension=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=97?= =?UTF-8?q?=E3=81=A6=E4=BF=AE=E6=AD=A3=E3=81=97=E3=81=A6=E3=81=BF=E3=81=BE?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/features/session/data/session.dart | 24 +++++++++++++- .../ui/detail/session_detail_content.dart | 5 ++- .../session/ui/detail/youtube_url_mixin.dart | 32 ------------------- 3 files changed, 25 insertions(+), 36 deletions(-) delete mode 100644 lib/features/session/ui/detail/youtube_url_mixin.dart diff --git a/lib/features/session/data/session.dart b/lib/features/session/data/session.dart index b7c47e07..6799dbca 100644 --- a/lib/features/session/data/session.dart +++ b/lib/features/session/data/session.dart @@ -9,7 +9,9 @@ part 'session.freezed.dart'; part 'session.g.dart'; @Freezed(unionKey: 'type') -sealed class Session with _$Session { +sealed + +class Session with _$Session { @JsonSerializable(fieldRename: FieldRename.snake) const factory Session.timeslot({ required String uuid, @@ -70,3 +72,23 @@ extension SessionTimeText on Session { return '$startsAtText〜$endsAtText'; } } + +extension SessionYoutubeUrlEx on TalkSession { + String get youtubeUrl { + return switch (uuid) { + '21abbd32-6864-487a-8066-c9d7f7e5e9be' => 'cMS2FzbhXJ8', + '5b402df3-9e5d-4c0b-80fa-61d9ba356594' => 'bKnvn-Orpd0', + '972ffbac-422b-4d4b-9686-f59c4438da04' => 'jNmyr-TZVfU', + '84b1350e-b76e-4cdc-884b-37a4a6e14846' => 'UGxzjYNHH90', + '090ad5b8-7066-40e6-8ca8-58fff766f046' => 'lObSpRxP1Do', + '0b32515e-2c80-45f4-8ea2-c6c269d2609f' => '2SnTNFAzmY0', + 'df52c995-5fbb-4ff0-abbc-e6332af98797' => 'VHhZlTDfwIQ', + '67df96a0-4f03-401a-b740-c296a5bcbd86' => 'NcfrY-EN8Pg', + 'f76c37b8-172d-4072-ad4a-bd870bc15728' => 'sznsAolD6dI', + 'd9cc75af-a3a2-4d0e-af6c-f12aa143ba4c' => 'EKoI-p1UnNk', + '076d093c-a1ff-4fe3-be58-8f8536c97de3' => 'vCoG6BTNpAA', + '2b0118b0-52d2-4a9c-a564-faf50651dea2' => '6zLih07J3RU', + _ => '', + }; + } +} diff --git a/lib/features/session/ui/detail/session_detail_content.dart b/lib/features/session/ui/detail/session_detail_content.dart index a911a9e0..af839e9b 100644 --- a/lib/features/session/ui/detail/session_detail_content.dart +++ b/lib/features/session/ui/detail/session_detail_content.dart @@ -4,7 +4,6 @@ import 'package:confwebsite2023/core/components/social_share.dart'; import 'package:confwebsite2023/core/gen/assets.gen.dart'; import 'package:confwebsite2023/core/theme.dart'; import 'package:confwebsite2023/features/session/data/session.dart'; -import 'package:confwebsite2023/features/session/ui/detail/youtube_url_mixin.dart'; import 'package:confwebsite2023/features/sponsor/data/sponsor.dart'; import 'package:confwebsite2023/features/sponsor/ui/detail/sponsor_detail_logo_card.dart'; import 'package:flutter/material.dart'; @@ -14,7 +13,7 @@ import 'package:url_launcher/link.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:youtube_player_iframe/youtube_player_iframe.dart'; -class SessionDetailContent extends StatelessWidget with YoutubeUrlMixin { +class SessionDetailContent extends StatelessWidget { const SessionDetailContent({ required this.session, required this.sponsor, @@ -124,7 +123,7 @@ class SessionDetailContent extends StatelessWidget with YoutubeUrlMixin { width: youtubeWidth, child: YoutubePlayer( controller: YoutubePlayerController.fromVideoId( - videoId: getUrl(session.title), + videoId: session.youtubeUrl, params: const YoutubePlayerParams(showFullscreenButton: true), ), ), diff --git a/lib/features/session/ui/detail/youtube_url_mixin.dart b/lib/features/session/ui/detail/youtube_url_mixin.dart deleted file mode 100644 index 53468307..00000000 --- a/lib/features/session/ui/detail/youtube_url_mixin.dart +++ /dev/null @@ -1,32 +0,0 @@ -mixin YoutubeUrlMixin { - String getUrl(String user) { - switch (user) { - case 'Flutter アプリにおけるテスト戦略の見直しと自動テストの導入': - return 'VHhZlTDfwIQ'; - case '詳解!Flutterにおける課金実装': - return 'NcfrY-EN8Pg'; - case 'Master of Flutter lifecycle': - return 'sznsAolD6dI'; - case 'Dartのコード自動生成の仕組みと、コード自動生成のパッケージを自作する方法について': - return 'EKoI-p1UnNk'; - case 'Flutterで構築する漫画ビューア': - return 'vCoG6BTNpAA'; - case 'Flutterアプリのセキュリティ対策を考えてみる': - return 'lObSpRxP1Do'; - case '我々にはなぜ Riverpod が必要なのか - InheritedWidget から始まる app state 管理手法の課題': - return '2SnTNFAzmY0'; - case '魅せろ! Flutter で目を惹く UI デザインを実装する': - return '6zLih07J3RU'; - case 'Add Material touch ripples': - return 'cMS2FzbhXJ8'; - case '出前館におけるFlutterの現在とこれから': - return 'bKnvn-Orpd0'; - case 'DartによるBFF構築・運用 〜Dart Frog×melos〜': - return 'jNmyr-TZVfU'; - case 'ゆめみの Flutter エンジニア育成方法': - return 'UGxzjYNHH90'; - default: - return ''; - } - } -} From a1c58b63e586b1194db1c61d286822d4f1dbe88e Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Wed, 13 Dec 2023 11:30:13 +0900 Subject: [PATCH 08/13] =?UTF-8?q?fix:=20YoutubePlayerController=E3=81=AEpr?= =?UTF-8?q?ovider=E3=82=92=E4=BD=9C=E6=88=90=E3=81=97=E3=81=A6=E3=81=BF?= =?UTF-8?q?=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../session/data/youtube_provider.dart | 16 +++ .../session/data/youtube_provider.g.dart | 118 ++++++++++++++++++ .../ui/detail/session_detail_content.dart | 11 +- 3 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 lib/features/session/data/youtube_provider.dart create mode 100644 lib/features/session/data/youtube_provider.g.dart diff --git a/lib/features/session/data/youtube_provider.dart b/lib/features/session/data/youtube_provider.dart new file mode 100644 index 00000000..1b42c0f6 --- /dev/null +++ b/lib/features/session/data/youtube_provider.dart @@ -0,0 +1,16 @@ +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:youtube_player_iframe/youtube_player_iframe.dart'; + +part 'youtube_provider.g.dart'; + +@riverpod +YoutubePlayerController youtubePlayerController( + YoutubePlayerControllerRef ref, + String videoId, +) { + final controller = YoutubePlayerController.fromVideoId( + videoId: videoId, + params: const YoutubePlayerParams(showFullscreenButton: true), + ); + return controller; +} diff --git a/lib/features/session/data/youtube_provider.g.dart b/lib/features/session/data/youtube_provider.g.dart new file mode 100644 index 00000000..2bbed0d7 --- /dev/null +++ b/lib/features/session/data/youtube_provider.g.dart @@ -0,0 +1,118 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: type=lint, duplicate_ignore + +part of 'youtube_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$youtubePlayerControllerHash() => + r'2c72583291f0910c5fc1a6aa35c4ddf65dda8fe8'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +typedef YoutubePlayerControllerRef + = AutoDisposeProviderRef; + +/// See also [youtubePlayerController]. +@ProviderFor(youtubePlayerController) +const youtubePlayerControllerProvider = YoutubePlayerControllerFamily(); + +/// See also [youtubePlayerController]. +class YoutubePlayerControllerFamily extends Family { + /// See also [youtubePlayerController]. + const YoutubePlayerControllerFamily(); + + /// See also [youtubePlayerController]. + YoutubePlayerControllerProvider call( + String videoId, + ) { + return YoutubePlayerControllerProvider( + videoId, + ); + } + + @override + YoutubePlayerControllerProvider getProviderOverride( + covariant YoutubePlayerControllerProvider provider, + ) { + return call( + provider.videoId, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'youtubePlayerControllerProvider'; +} + +/// See also [youtubePlayerController]. +class YoutubePlayerControllerProvider + extends AutoDisposeProvider { + /// See also [youtubePlayerController]. + YoutubePlayerControllerProvider( + this.videoId, + ) : super.internal( + (ref) => youtubePlayerController( + ref, + videoId, + ), + from: youtubePlayerControllerProvider, + name: r'youtubePlayerControllerProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$youtubePlayerControllerHash, + dependencies: YoutubePlayerControllerFamily._dependencies, + allTransitiveDependencies: + YoutubePlayerControllerFamily._allTransitiveDependencies, + ); + + final String videoId; + + @override + bool operator ==(Object other) { + return other is YoutubePlayerControllerProvider && other.videoId == videoId; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, videoId.hashCode); + + return _SystemHash.finish(hash); + } +} +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member diff --git a/lib/features/session/ui/detail/session_detail_content.dart b/lib/features/session/ui/detail/session_detail_content.dart index af839e9b..dc72f2c5 100644 --- a/lib/features/session/ui/detail/session_detail_content.dart +++ b/lib/features/session/ui/detail/session_detail_content.dart @@ -4,16 +4,18 @@ import 'package:confwebsite2023/core/components/social_share.dart'; import 'package:confwebsite2023/core/gen/assets.gen.dart'; import 'package:confwebsite2023/core/theme.dart'; import 'package:confwebsite2023/features/session/data/session.dart'; +import 'package:confwebsite2023/features/session/data/youtube_provider.dart'; import 'package:confwebsite2023/features/sponsor/data/sponsor.dart'; import 'package:confwebsite2023/features/sponsor/ui/detail/sponsor_detail_logo_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:url_launcher/link.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:youtube_player_iframe/youtube_player_iframe.dart'; -class SessionDetailContent extends StatelessWidget { +class SessionDetailContent extends ConsumerWidget { const SessionDetailContent({ required this.session, required this.sponsor, @@ -38,7 +40,7 @@ class SessionDetailContent extends StatelessWidget { final double bodyVerticalMargin; @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { final theme = Theme.of(context); final textTheme = theme.textTheme; @@ -122,9 +124,8 @@ class SessionDetailContent extends StatelessWidget { child: SizedBox( width: youtubeWidth, child: YoutubePlayer( - controller: YoutubePlayerController.fromVideoId( - videoId: session.youtubeUrl, - params: const YoutubePlayerParams(showFullscreenButton: true), + controller: ref.watch( + youtubePlayerControllerProvider(session.youtubeUrl), ), ), ), From 09169a45f54daa1d8cb36b1b77a56201da4fca84 Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Mon, 18 Dec 2023 09:52:37 +0900 Subject: [PATCH 09/13] =?UTF-8?q?fix:=20youtube=5Fprovider=E3=82=92?= =?UTF-8?q?=E5=89=8A=E9=99=A4=E3=81=97=E3=80=81contents=E5=86=85=E3=81=A7Y?= =?UTF-8?q?outubePlayerController=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=99?= =?UTF-8?q?=E3=82=8B=E5=AE=9F=E8=A3=85=E3=82=92=E3=81=97=E3=81=BE=E3=81=97?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../session/data/youtube_provider.dart | 16 --- .../session/data/youtube_provider.g.dart | 118 ------------------ .../ui/detail/session_detail_content.dart | 69 ++++++---- 3 files changed, 44 insertions(+), 159 deletions(-) delete mode 100644 lib/features/session/data/youtube_provider.dart delete mode 100644 lib/features/session/data/youtube_provider.g.dart diff --git a/lib/features/session/data/youtube_provider.dart b/lib/features/session/data/youtube_provider.dart deleted file mode 100644 index 1b42c0f6..00000000 --- a/lib/features/session/data/youtube_provider.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:youtube_player_iframe/youtube_player_iframe.dart'; - -part 'youtube_provider.g.dart'; - -@riverpod -YoutubePlayerController youtubePlayerController( - YoutubePlayerControllerRef ref, - String videoId, -) { - final controller = YoutubePlayerController.fromVideoId( - videoId: videoId, - params: const YoutubePlayerParams(showFullscreenButton: true), - ); - return controller; -} diff --git a/lib/features/session/data/youtube_provider.g.dart b/lib/features/session/data/youtube_provider.g.dart deleted file mode 100644 index 2bbed0d7..00000000 --- a/lib/features/session/data/youtube_provider.g.dart +++ /dev/null @@ -1,118 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: type=lint, duplicate_ignore - -part of 'youtube_provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$youtubePlayerControllerHash() => - r'2c72583291f0910c5fc1a6aa35c4ddf65dda8fe8'; - -/// Copied from Dart SDK -class _SystemHash { - _SystemHash._(); - - static int combine(int hash, int value) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + value); - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); - return hash ^ (hash >> 6); - } - - static int finish(int hash) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); - // ignore: parameter_assignments - hash = hash ^ (hash >> 11); - return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); - } -} - -typedef YoutubePlayerControllerRef - = AutoDisposeProviderRef; - -/// See also [youtubePlayerController]. -@ProviderFor(youtubePlayerController) -const youtubePlayerControllerProvider = YoutubePlayerControllerFamily(); - -/// See also [youtubePlayerController]. -class YoutubePlayerControllerFamily extends Family { - /// See also [youtubePlayerController]. - const YoutubePlayerControllerFamily(); - - /// See also [youtubePlayerController]. - YoutubePlayerControllerProvider call( - String videoId, - ) { - return YoutubePlayerControllerProvider( - videoId, - ); - } - - @override - YoutubePlayerControllerProvider getProviderOverride( - covariant YoutubePlayerControllerProvider provider, - ) { - return call( - provider.videoId, - ); - } - - static const Iterable? _dependencies = null; - - @override - Iterable? get dependencies => _dependencies; - - static const Iterable? _allTransitiveDependencies = null; - - @override - Iterable? get allTransitiveDependencies => - _allTransitiveDependencies; - - @override - String? get name => r'youtubePlayerControllerProvider'; -} - -/// See also [youtubePlayerController]. -class YoutubePlayerControllerProvider - extends AutoDisposeProvider { - /// See also [youtubePlayerController]. - YoutubePlayerControllerProvider( - this.videoId, - ) : super.internal( - (ref) => youtubePlayerController( - ref, - videoId, - ), - from: youtubePlayerControllerProvider, - name: r'youtubePlayerControllerProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') - ? null - : _$youtubePlayerControllerHash, - dependencies: YoutubePlayerControllerFamily._dependencies, - allTransitiveDependencies: - YoutubePlayerControllerFamily._allTransitiveDependencies, - ); - - final String videoId; - - @override - bool operator ==(Object other) { - return other is YoutubePlayerControllerProvider && other.videoId == videoId; - } - - @override - int get hashCode { - var hash = _SystemHash.combine(0, runtimeType.hashCode); - hash = _SystemHash.combine(hash, videoId.hashCode); - - return _SystemHash.finish(hash); - } -} -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member diff --git a/lib/features/session/ui/detail/session_detail_content.dart b/lib/features/session/ui/detail/session_detail_content.dart index dc72f2c5..941d8aaa 100644 --- a/lib/features/session/ui/detail/session_detail_content.dart +++ b/lib/features/session/ui/detail/session_detail_content.dart @@ -4,18 +4,16 @@ import 'package:confwebsite2023/core/components/social_share.dart'; import 'package:confwebsite2023/core/gen/assets.gen.dart'; import 'package:confwebsite2023/core/theme.dart'; import 'package:confwebsite2023/features/session/data/session.dart'; -import 'package:confwebsite2023/features/session/data/youtube_provider.dart'; import 'package:confwebsite2023/features/sponsor/data/sponsor.dart'; import 'package:confwebsite2023/features/sponsor/ui/detail/sponsor_detail_logo_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:url_launcher/link.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:youtube_player_iframe/youtube_player_iframe.dart'; -class SessionDetailContent extends ConsumerWidget { +class SessionDetailContent extends StatefulWidget { const SessionDetailContent({ required this.session, required this.sponsor, @@ -40,15 +38,38 @@ class SessionDetailContent extends ConsumerWidget { final double bodyVerticalMargin; @override - Widget build(BuildContext context, WidgetRef ref) { + State createState() => _SessionDetailContentState(); +} + +class _SessionDetailContentState extends State { + late YoutubePlayerController _controller; + + @override + void initState() { + super.initState(); + _controller = YoutubePlayerController.fromVideoId( + videoId: widget.session.youtubeUrl, + params: const YoutubePlayerParams(showFullscreenButton: true), + ); + } + + @override + Future dispose() async { + await _controller.close(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { final theme = Theme.of(context); final textTheme = theme.textTheme; - final contentVerticalGap = SizedBox(height: contentGap); - final sectionVerticalGap = SizedBox(height: sectionGap); - final bodyVerticalGap = SizedBox(height: bodyVerticalMargin); + final contentVerticalGap = SizedBox(height: widget.contentGap); + final sectionVerticalGap = SizedBox(height: widget.sectionGap); + final bodyVerticalGap = SizedBox(height: widget.bodyVerticalMargin); - final headerTitle = session.isSponsored ? 'Sponsor Session' : 'Session'; + final headerTitle = + widget.session.isSponsored ? 'Sponsor Session' : 'Session'; final headerGradient = GradientConstant.accent.primary; final header = ResponsiveWidget( largeWidget: SectionHeader.leftAlignment( @@ -66,7 +87,7 @@ class SessionDetailContent extends ConsumerWidget { final profileBody = Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (sponsor case final Sponsor sponsor) ...[ + if (widget.sponsor case final Sponsor sponsor) ...[ SponsorDetailLogoCard( assetName: sponsor.logoAssetName, cardWidth: 240, @@ -78,17 +99,17 @@ class SessionDetailContent extends ConsumerWidget { children: [ CircleAvatar( radius: 20, - backgroundImage: NetworkImage(session.speaker.avatarUrl), + backgroundImage: NetworkImage(widget.session.speaker.avatarUrl), ), Spaces.horizontal_8, Text( - session.speaker.name, + widget.session.speaker.name, style: textTheme.titleMedium, ), ], ), Spaces.vertical_16, - if (session.speaker.twitter case final String twitter) + if (widget.session.speaker.twitter case final String twitter) Link( uri: Uri.tryParse( 'https://twitter.com/$twitter', @@ -116,17 +137,15 @@ class SessionDetailContent extends ConsumerWidget { ); final hPadding = EdgeInsets.only( - top: contentGap, - bottom: contentGap / 2, + top: widget.contentGap, + bottom: widget.contentGap / 2, ); final youtubePlayer = Center( child: SizedBox( - width: youtubeWidth, + width: widget.youtubeWidth, child: YoutubePlayer( - controller: ref.watch( - youtubePlayerControllerProvider(session.youtubeUrl), - ), + controller: _controller, ), ), ); @@ -137,7 +156,7 @@ class SessionDetailContent extends ConsumerWidget { borderRadius: BorderRadius.circular(12), ), child: Padding( - padding: EdgeInsets.all(contentGap), + padding: EdgeInsets.all(widget.contentGap), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -145,7 +164,7 @@ class SessionDetailContent extends ConsumerWidget { children: [ Chip( label: Text( - session.track.name, + widget.session.track.name, ), backgroundColor: baselineColorScheme.ref.primary.primary40, ), @@ -153,18 +172,18 @@ class SessionDetailContent extends ConsumerWidget { ), Spaces.vertical_16, Text( - session.title, - style: sessionTitleTextStyle, + widget.session.title, + style: widget.sessionTitleTextStyle, ), Spaces.vertical_16, Text( - session.timeRangeLongText, + widget.session.timeRangeLongText, style: textTheme.headlineSmall, ), Spaces.vertical_16, OutlinedButton( onPressed: () async { - final url = Uri.parse(session.url); + final url = Uri.parse(widget.session.url); await launchUrl(url); }, style: OutlinedButton.styleFrom( @@ -187,7 +206,7 @@ class SessionDetailContent extends ConsumerWidget { contentVerticalGap, youtubePlayer, MarkdownBody( - data: session.abstract, + data: widget.session.abstract, styleSheet: MarkdownStyleSheet.fromTheme(theme).copyWith( p: textTheme.bodyLarge, pPadding: const EdgeInsets.symmetric(vertical: 8), From a8fa189870cfd94412abaf340aba60842ef58809 Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Mon, 18 Dec 2023 12:35:49 +0900 Subject: [PATCH 10/13] =?UTF-8?q?fix:=20=E6=94=B9=E8=A1=8C=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/features/session/data/session.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/features/session/data/session.dart b/lib/features/session/data/session.dart index 6799dbca..c95c9438 100644 --- a/lib/features/session/data/session.dart +++ b/lib/features/session/data/session.dart @@ -9,9 +9,7 @@ part 'session.freezed.dart'; part 'session.g.dart'; @Freezed(unionKey: 'type') -sealed - -class Session with _$Session { +sealed class Session with _$Session { @JsonSerializable(fieldRename: FieldRename.snake) const factory Session.timeslot({ required String uuid, From 470bf4971de4ad2989b6ea728f75442d806d1d90 Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Mon, 18 Dec 2023 12:39:13 +0900 Subject: [PATCH 11/13] =?UTF-8?q?fix:=20switch=E6=96=87=E3=81=AE=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=E3=82=92=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/features/session/data/session.dart | 32 ++++++++++++-------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/lib/features/session/data/session.dart b/lib/features/session/data/session.dart index c95c9438..6af8fd1f 100644 --- a/lib/features/session/data/session.dart +++ b/lib/features/session/data/session.dart @@ -72,21 +72,19 @@ extension SessionTimeText on Session { } extension SessionYoutubeUrlEx on TalkSession { - String get youtubeUrl { - return switch (uuid) { - '21abbd32-6864-487a-8066-c9d7f7e5e9be' => 'cMS2FzbhXJ8', - '5b402df3-9e5d-4c0b-80fa-61d9ba356594' => 'bKnvn-Orpd0', - '972ffbac-422b-4d4b-9686-f59c4438da04' => 'jNmyr-TZVfU', - '84b1350e-b76e-4cdc-884b-37a4a6e14846' => 'UGxzjYNHH90', - '090ad5b8-7066-40e6-8ca8-58fff766f046' => 'lObSpRxP1Do', - '0b32515e-2c80-45f4-8ea2-c6c269d2609f' => '2SnTNFAzmY0', - 'df52c995-5fbb-4ff0-abbc-e6332af98797' => 'VHhZlTDfwIQ', - '67df96a0-4f03-401a-b740-c296a5bcbd86' => 'NcfrY-EN8Pg', - 'f76c37b8-172d-4072-ad4a-bd870bc15728' => 'sznsAolD6dI', - 'd9cc75af-a3a2-4d0e-af6c-f12aa143ba4c' => 'EKoI-p1UnNk', - '076d093c-a1ff-4fe3-be58-8f8536c97de3' => 'vCoG6BTNpAA', - '2b0118b0-52d2-4a9c-a564-faf50651dea2' => '6zLih07J3RU', - _ => '', - }; - } + String get youtubeUrl => switch (uuid) { + '21abbd32-6864-487a-8066-c9d7f7e5e9be' => 'cMS2FzbhXJ8', + '5b402df3-9e5d-4c0b-80fa-61d9ba356594' => 'bKnvn-Orpd0', + '972ffbac-422b-4d4b-9686-f59c4438da04' => 'jNmyr-TZVfU', + '84b1350e-b76e-4cdc-884b-37a4a6e14846' => 'UGxzjYNHH90', + '090ad5b8-7066-40e6-8ca8-58fff766f046' => 'lObSpRxP1Do', + '0b32515e-2c80-45f4-8ea2-c6c269d2609f' => '2SnTNFAzmY0', + 'df52c995-5fbb-4ff0-abbc-e6332af98797' => 'VHhZlTDfwIQ', + '67df96a0-4f03-401a-b740-c296a5bcbd86' => 'NcfrY-EN8Pg', + 'f76c37b8-172d-4072-ad4a-bd870bc15728' => 'sznsAolD6dI', + 'd9cc75af-a3a2-4d0e-af6c-f12aa143ba4c' => 'EKoI-p1UnNk', + '076d093c-a1ff-4fe3-be58-8f8536c97de3' => 'vCoG6BTNpAA', + '2b0118b0-52d2-4a9c-a564-faf50651dea2' => '6zLih07J3RU', + _ => '', + }; } From fa9efa021782f449e722b39a04968560c630f342 Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Mon, 18 Dec 2023 12:46:11 +0900 Subject: [PATCH 12/13] =?UTF-8?q?add:=20youtubeUrl=E3=81=AB=E3=82=8F?= =?UTF-8?q?=E3=81=8B=E3=82=8A=E3=82=84=E3=81=99=E3=81=8F=E3=82=BF=E3=82=A4?= =?UTF-8?q?=E3=83=88=E3=83=AB=E3=82=92=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=81=A7=E8=A8=98=E8=BC=89=E3=81=97=E3=81=A6=E3=81=BF=E3=81=BE?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/features/session/data/session.dart | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/features/session/data/session.dart b/lib/features/session/data/session.dart index 6af8fd1f..3d5ff4ed 100644 --- a/lib/features/session/data/session.dart +++ b/lib/features/session/data/session.dart @@ -73,17 +73,29 @@ extension SessionTimeText on Session { extension SessionYoutubeUrlEx on TalkSession { String get youtubeUrl => switch (uuid) { + // Add Material touch ripples '21abbd32-6864-487a-8066-c9d7f7e5e9be' => 'cMS2FzbhXJ8', + // 出前館におけるFlutterの現在とこれから '5b402df3-9e5d-4c0b-80fa-61d9ba356594' => 'bKnvn-Orpd0', + // DartによるBFF構築・運用 〜Dart Frog×melos〜 '972ffbac-422b-4d4b-9686-f59c4438da04' => 'jNmyr-TZVfU', + // ゆめみの Flutter エンジニア育成方法 '84b1350e-b76e-4cdc-884b-37a4a6e14846' => 'UGxzjYNHH90', + // Flutterアプリのセキュリティ対策を考えてみる '090ad5b8-7066-40e6-8ca8-58fff766f046' => 'lObSpRxP1Do', + // 我々にはなぜ Riverpod が必要なのか - InheritedWidget から始まる app state 管理手法の課題 '0b32515e-2c80-45f4-8ea2-c6c269d2609f' => '2SnTNFAzmY0', + // Flutter アプリにおけるテスト戦略の見直しと自動テストの導入 'df52c995-5fbb-4ff0-abbc-e6332af98797' => 'VHhZlTDfwIQ', + // 詳解!Flutterにおける課金実装 '67df96a0-4f03-401a-b740-c296a5bcbd86' => 'NcfrY-EN8Pg', + // Master of Flutter lifecycle 'f76c37b8-172d-4072-ad4a-bd870bc15728' => 'sznsAolD6dI', + // Dartのコード自動生成の仕組みと、コード自動生成のパッケージを自作する方法について 'd9cc75af-a3a2-4d0e-af6c-f12aa143ba4c' => 'EKoI-p1UnNk', + // Flutterで構築する漫画ビューア '076d093c-a1ff-4fe3-be58-8f8536c97de3' => 'vCoG6BTNpAA', + // 魅せろ! Flutter で目を惹く UI デザインを実装する '2b0118b0-52d2-4a9c-a564-faf50651dea2' => '6zLih07J3RU', _ => '', }; From c3f7c139440ac62e3a91e48baf5bd106a3137edd Mon Sep 17 00:00:00 2001 From: iseruuuuu Date: Mon, 18 Dec 2023 13:20:52 +0900 Subject: [PATCH 13/13] =?UTF-8?q?fix:=20Stateful=E3=81=8B=E3=82=89HookWidg?= =?UTF-8?q?et=E3=81=AB=E5=A4=89=E6=9B=B4=E3=81=97=E3=81=A6=E3=81=BF?= =?UTF-8?q?=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/detail/session_detail_content.dart | 77 ++++++++----------- 1 file changed, 32 insertions(+), 45 deletions(-) diff --git a/lib/features/session/ui/detail/session_detail_content.dart b/lib/features/session/ui/detail/session_detail_content.dart index 941d8aaa..66187490 100644 --- a/lib/features/session/ui/detail/session_detail_content.dart +++ b/lib/features/session/ui/detail/session_detail_content.dart @@ -7,13 +7,14 @@ import 'package:confwebsite2023/features/session/data/session.dart'; import 'package:confwebsite2023/features/sponsor/data/sponsor.dart'; import 'package:confwebsite2023/features/sponsor/ui/detail/sponsor_detail_logo_card.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:url_launcher/link.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:youtube_player_iframe/youtube_player_iframe.dart'; -class SessionDetailContent extends StatefulWidget { +class SessionDetailContent extends HookWidget { const SessionDetailContent({ required this.session, required this.sponsor, @@ -37,39 +38,25 @@ class SessionDetailContent extends StatefulWidget { final double youtubeWidth; final double bodyVerticalMargin; - @override - State createState() => _SessionDetailContentState(); -} - -class _SessionDetailContentState extends State { - late YoutubePlayerController _controller; - - @override - void initState() { - super.initState(); - _controller = YoutubePlayerController.fromVideoId( - videoId: widget.session.youtubeUrl, - params: const YoutubePlayerParams(showFullscreenButton: true), - ); - } - - @override - Future dispose() async { - await _controller.close(); - super.dispose(); - } - @override Widget build(BuildContext context) { final theme = Theme.of(context); final textTheme = theme.textTheme; - - final contentVerticalGap = SizedBox(height: widget.contentGap); - final sectionVerticalGap = SizedBox(height: widget.sectionGap); - final bodyVerticalGap = SizedBox(height: widget.bodyVerticalMargin); - - final headerTitle = - widget.session.isSponsored ? 'Sponsor Session' : 'Session'; + late YoutubePlayerController controller; + useEffect( + () { + controller = YoutubePlayerController.fromVideoId( + videoId: session.youtubeUrl, + params: const YoutubePlayerParams(showFullscreenButton: true), + ); + return controller.close; + }, + [], + ); + final contentVerticalGap = SizedBox(height: contentGap); + final sectionVerticalGap = SizedBox(height: sectionGap); + final bodyVerticalGap = SizedBox(height: bodyVerticalMargin); + final headerTitle = session.isSponsored ? 'Sponsor Session' : 'Session'; final headerGradient = GradientConstant.accent.primary; final header = ResponsiveWidget( largeWidget: SectionHeader.leftAlignment( @@ -87,7 +74,7 @@ class _SessionDetailContentState extends State { final profileBody = Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (widget.sponsor case final Sponsor sponsor) ...[ + if (sponsor case final Sponsor sponsor) ...[ SponsorDetailLogoCard( assetName: sponsor.logoAssetName, cardWidth: 240, @@ -99,17 +86,17 @@ class _SessionDetailContentState extends State { children: [ CircleAvatar( radius: 20, - backgroundImage: NetworkImage(widget.session.speaker.avatarUrl), + backgroundImage: NetworkImage(session.speaker.avatarUrl), ), Spaces.horizontal_8, Text( - widget.session.speaker.name, + session.speaker.name, style: textTheme.titleMedium, ), ], ), Spaces.vertical_16, - if (widget.session.speaker.twitter case final String twitter) + if (session.speaker.twitter case final String twitter) Link( uri: Uri.tryParse( 'https://twitter.com/$twitter', @@ -137,15 +124,15 @@ class _SessionDetailContentState extends State { ); final hPadding = EdgeInsets.only( - top: widget.contentGap, - bottom: widget.contentGap / 2, + top: contentGap, + bottom: contentGap / 2, ); final youtubePlayer = Center( child: SizedBox( - width: widget.youtubeWidth, + width: youtubeWidth, child: YoutubePlayer( - controller: _controller, + controller: controller, ), ), ); @@ -156,7 +143,7 @@ class _SessionDetailContentState extends State { borderRadius: BorderRadius.circular(12), ), child: Padding( - padding: EdgeInsets.all(widget.contentGap), + padding: EdgeInsets.all(contentGap), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -164,7 +151,7 @@ class _SessionDetailContentState extends State { children: [ Chip( label: Text( - widget.session.track.name, + session.track.name, ), backgroundColor: baselineColorScheme.ref.primary.primary40, ), @@ -172,18 +159,18 @@ class _SessionDetailContentState extends State { ), Spaces.vertical_16, Text( - widget.session.title, - style: widget.sessionTitleTextStyle, + session.title, + style: sessionTitleTextStyle, ), Spaces.vertical_16, Text( - widget.session.timeRangeLongText, + session.timeRangeLongText, style: textTheme.headlineSmall, ), Spaces.vertical_16, OutlinedButton( onPressed: () async { - final url = Uri.parse(widget.session.url); + final url = Uri.parse(session.url); await launchUrl(url); }, style: OutlinedButton.styleFrom( @@ -206,7 +193,7 @@ class _SessionDetailContentState extends State { contentVerticalGap, youtubePlayer, MarkdownBody( - data: widget.session.abstract, + data: session.abstract, styleSheet: MarkdownStyleSheet.fromTheme(theme).copyWith( p: textTheme.bodyLarge, pPadding: const EdgeInsets.symmetric(vertical: 8),