Skip to content

Commit

Permalink
feat: construct header section in detail view (#57)
Browse files Browse the repository at this point in the history
* construct header section in detail view

* remove test server code

* comment out unimplemented statements

* Update client/lib/widgets/detail/header.dart

Co-authored-by: Mo Kweon <[email protected]>

* Update client/lib/screens/detail_screen.dart

Co-authored-by: Mo Kweon <[email protected]>

* Update client/lib/widgets/detail/youtube.dart

Co-authored-by: Mo Kweon <[email protected]>

* part of information injected from Video object.

* remove unused imports

* update Video proto message

* update header to use updated Video proto message

Co-authored-by: Mo Kweon <[email protected]>
  • Loading branch information
deep-diver and kkweon authored Jun 7, 2021
1 parent f5dd85f commit bbba5e8
Show file tree
Hide file tree
Showing 13 changed files with 306 additions and 124 deletions.
2 changes: 1 addition & 1 deletion client/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c

COCOAPODS: 1.10.1
COCOAPODS: 1.10.0
28 changes: 28 additions & 0 deletions client/lib/protos/pkg/pr12er/messages.pb.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class Video extends $pb.GeneratedMessage {
..e<Category>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'category', $pb.PbFieldType.OE, defaultOrMaker: Category.CATEGORY_UNSPECIFIED, valueOf: Category.valueOf, enumValues: Category.values)
..a<$core.int>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'numberOfLike', $pb.PbFieldType.O3)
..pPS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'keywords')
..a<$core.int>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'numberOfViews', $pb.PbFieldType.O3)
..aOS(9, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'publishedDate')
..hasRequiredFields = false
;

Expand All @@ -34,6 +36,8 @@ class Video extends $pb.GeneratedMessage {
Category? category,
$core.int? numberOfLike,
$core.Iterable<$core.String>? keywords,
$core.int? numberOfViews,
$core.String? publishedDate,
}) {
final _result = create();
if (id != null) {
Expand All @@ -57,6 +61,12 @@ class Video extends $pb.GeneratedMessage {
if (keywords != null) {
_result.keywords.addAll(keywords);
}
if (numberOfViews != null) {
_result.numberOfViews = numberOfViews;
}
if (publishedDate != null) {
_result.publishedDate = publishedDate;
}
return _result;
}
factory Video.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
Expand Down Expand Up @@ -136,6 +146,24 @@ class Video extends $pb.GeneratedMessage {

@$pb.TagNumber(7)
$core.List<$core.String> get keywords => $_getList(6);

@$pb.TagNumber(8)
$core.int get numberOfViews => $_getIZ(7);
@$pb.TagNumber(8)
set numberOfViews($core.int v) { $_setSignedInt32(7, v); }
@$pb.TagNumber(8)
$core.bool hasNumberOfViews() => $_has(7);
@$pb.TagNumber(8)
void clearNumberOfViews() => clearField(8);

@$pb.TagNumber(9)
$core.String get publishedDate => $_getSZ(8);
@$pb.TagNumber(9)
set publishedDate($core.String v) { $_setString(8, v); }
@$pb.TagNumber(9)
$core.bool hasPublishedDate() => $_has(8);
@$pb.TagNumber(9)
void clearPublishedDate() => clearField(9);
}

class Detail extends $pb.GeneratedMessage {
Expand Down
4 changes: 3 additions & 1 deletion client/lib/protos/pkg/pr12er/messages.pbjson.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@ const Video$json = const {
const {'1': 'category', '3': 5, '4': 1, '5': 14, '6': '.pkg.pr12er.Category', '10': 'category'},
const {'1': 'number_of_like', '3': 6, '4': 1, '5': 5, '10': 'numberOfLike'},
const {'1': 'keywords', '3': 7, '4': 3, '5': 9, '10': 'keywords'},
const {'1': 'number_of_views', '3': 8, '4': 1, '5': 5, '10': 'numberOfViews'},
const {'1': 'published_date', '3': 9, '4': 1, '5': 9, '10': 'publishedDate'},
],
};

/// Descriptor for `Video`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List videoDescriptor = $convert.base64Decode('CgVWaWRlbxIOCgJpZBgBIAEoBVICaWQSFAoFdGl0bGUYAiABKAlSBXRpdGxlEhIKBGxpbmsYAyABKAlSBGxpbmsSHAoJcHJlc2VudGVyGAQgASgJUglwcmVzZW50ZXISMAoIY2F0ZWdvcnkYBSABKA4yFC5wa2cucHIxMmVyLkNhdGVnb3J5UghjYXRlZ29yeRIkCg5udW1iZXJfb2ZfbGlrZRgGIAEoBVIMbnVtYmVyT2ZMaWtlEhoKCGtleXdvcmRzGAcgAygJUghrZXl3b3Jkcw==');
final $typed_data.Uint8List videoDescriptor = $convert.base64Decode('CgVWaWRlbxIOCgJpZBgBIAEoBVICaWQSFAoFdGl0bGUYAiABKAlSBXRpdGxlEhIKBGxpbmsYAyABKAlSBGxpbmsSHAoJcHJlc2VudGVyGAQgASgJUglwcmVzZW50ZXISMAoIY2F0ZWdvcnkYBSABKA4yFC5wa2cucHIxMmVyLkNhdGVnb3J5UghjYXRlZ29yeRIkCg5udW1iZXJfb2ZfbGlrZRgGIAEoBVIMbnVtYmVyT2ZMaWtlEhoKCGtleXdvcmRzGAcgAygJUghrZXl3b3JkcxImCg9udW1iZXJfb2Zfdmlld3MYCCABKAVSDW51bWJlck9mVmlld3MSJQoOcHVibGlzaGVkX2RhdGUYCSABKAlSDXB1Ymxpc2hlZERhdGU=');
@$core.Deprecated('Use detailDescriptor instead')
const Detail$json = const {
'1': 'Detail',
Expand Down
83 changes: 38 additions & 45 deletions client/lib/screens/detail_screen.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import 'package:flutter/material.dart';
import 'package:pr12er/protos/pkg/pr12er/messages.pb.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
import 'package:pr12er/widgets/detail/header.dart';
import 'package:pr12er/utils/extractor.dart';
import 'package:pr12er/widgets/detail/youtube.dart';

class DetailScreenArguments {
final Video video;
Expand All @@ -12,59 +13,51 @@ class DetailScreenArguments {
class DetailScreen extends StatelessWidget {
static const String routeName = "detail_app";

Widget getHorizontalLine() {
return const Divider(
height: 5,
color: Colors.black,
indent: 5,
endIndent: 5,
);
}

@override
Widget build(BuildContext context) {
final args =
// ignore: cast_nullable_to_non_nullable
ModalRoute.of(context)!.settings.arguments as DetailScreenArguments;

return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
},
),
title: Text(args.video.title,
key: const ValueKey("$routeName/appBar/title")),
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
},
),
body: Detail(youtubeId: extractYoutubeId(args.video.link)));
}
}

class Detail extends StatefulWidget {
final String youtubeId;

const Detail({required this.youtubeId});

@override
_DetailState createState() => _DetailState();
}

class _DetailState extends State<Detail> {
late final YoutubePlayerController _controller;

@override
void initState() {
super.initState();

_controller = YoutubePlayerController(
initialVideoId: widget.youtubeId,
);
}

@override
Widget build(BuildContext context) {
return YoutubePlayerBuilder(
player: YoutubePlayer(
controller: _controller,
title: Text(args.video.title,
key: const ValueKey("$routeName/appBar/title")),
),
body: CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildListDelegate([
YoutubeWidget(youtubeId: extractYoutubeId(args.video.link)),
Container(
margin: const EdgeInsets.only(top: 5, left: 10, right: 10),
child: Column(
children: [
HeaderWidget(video: args.video),
const SizedBox(height: 10),
getHorizontalLine(),
const SizedBox(height: 10),
],
),
)
]))
],
),
builder: (context, player) {
return Column(
children: [player],
);
},
);
}
}
10 changes: 10 additions & 0 deletions client/lib/widgets/detail/abstract.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'package:flutter/material.dart';

class AbstractWidget extends StatelessWidget {
const AbstractWidget({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Container();
}
}
68 changes: 68 additions & 0 deletions client/lib/widgets/detail/header.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
import 'package:pr12er/protos/pkg/pr12er/messages.pb.dart';

// ignore: must_be_immutable
class HeaderWidget extends StatelessWidget {
// this is a placeholder
// didILIkedIt should be replaced in the next future PR
// after defining user related information
bool didILikedIt = false;

late Video video;

HeaderWidget({Key? key, required this.video}) : super(key: key);

@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(top: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
...getPresenterWidgets(),
const SizedBox(width: 25),
...getViewNumbersWidgets(),
const SizedBox(width: 25),
...getDateWidgets(),
],
),
);
}

Widget getLikeIcon() {
if (didILikedIt) {
return const Icon(Icons.thumb_up_alt);
}
return const Icon(Icons.thumb_up_alt_outlined);
}

List<Widget> getViewNumbersWidgets() {
return [
const SizedBox(width: 8),
const Icon(Icons.remove_red_eye),
const SizedBox(width: 8),
Text(video.numberOfViews.toString(),
style: const TextStyle(fontSize: 18)),
const SizedBox(width: 15),
getLikeIcon(),
const SizedBox(width: 8),
Text(video.numberOfLike.toString(), style: const TextStyle(fontSize: 18)),
];
}

List<Widget> getPresenterWidgets() {
return [
Text(video.presenter,
style: const TextStyle(
color: Colors.black54, fontSize: 18, fontStyle: FontStyle.italic))
];
}

List<Widget> getDateWidgets() {
return [
const Icon(Icons.today),
const SizedBox(width: 8),
Text(video.publishedDate, style: const TextStyle(fontSize: 18))
];
}
}
10 changes: 10 additions & 0 deletions client/lib/widgets/detail/recommendataion.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'package:flutter/material.dart';

class RecommentationWidget extends StatelessWidget {
const RecommentationWidget({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Container();
}
}
10 changes: 10 additions & 0 deletions client/lib/widgets/detail/repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'package:flutter/material.dart';

class RepositoryWidget extends StatelessWidget {
const RepositoryWidget({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Container();
}
}
38 changes: 38 additions & 0 deletions client/lib/widgets/detail/youtube.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import 'package:flutter/material.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';

class YoutubeWidget extends StatefulWidget {
final String youtubeId;

const YoutubeWidget({Key? key, required this.youtubeId}) : super(key: key);

@override
_DetailState createState() => _DetailState();
}

class _DetailState extends State<YoutubeWidget> {
late final YoutubePlayerController _controller;

@override
void initState() {
super.initState();

_controller = YoutubePlayerController(
initialVideoId: widget.youtubeId,
);
}

@override
Widget build(BuildContext context) {
return YoutubePlayerBuilder(
player: YoutubePlayer(
controller: _controller,
),
builder: (context, player) {
return Column(
children: [player],
);
},
);
}
}
Loading

0 comments on commit bbba5e8

Please sign in to comment.