From d897fd3c5531b79fd0406c3c0e89dbc62afcc067 Mon Sep 17 00:00:00 2001 From: Poolyum Date: Fri, 29 Mar 2019 19:17:02 +0900 Subject: [PATCH 01/16] =?UTF-8?q?[UPDATE]=20shared=5Fpreferences=20?= =?UTF-8?q?=ED=94=8C=EB=9F=AC=EA=B7=B8=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pubspec.yaml b/pubspec.yaml index 24be7df..dedaecb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,6 +23,7 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 rxdart: ^0.20.0 + shared_preferences: ^0.5.1+2 dev_dependencies: flutter_test: From 3297c9333212b7931123ca9a9971db3c5b988621 Mon Sep 17 00:00:00 2001 From: Poolyum Date: Fri, 29 Mar 2019 19:18:31 +0900 Subject: [PATCH 02/16] [UPDATE] track_schedule linted --- lib/models/track_schedule.dart | 36 +++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/lib/models/track_schedule.dart b/lib/models/track_schedule.dart index 3ab9db5..1bd04d8 100644 --- a/lib/models/track_schedule.dart +++ b/lib/models/track_schedule.dart @@ -1,18 +1,17 @@ -class ScheduleListModel{ +class ScheduleListModel { final List list; ScheduleListModel({this.list}); factory ScheduleListModel.fromJson(List parsedJson) { List lists = new List(); - lists = parsedJson.map((i)=>ScheduleModel.fromJson(i)).toList(); + lists = parsedJson.map((i) => ScheduleModel.fromJson(i)).toList(); - return ScheduleListModel( - list: lists - ); + return ScheduleListModel(list: lists); } } -class ScheduleModel{ + +class ScheduleModel { final int type; final String title; final String time; @@ -20,24 +19,29 @@ class ScheduleModel{ final String contents; List get names => speakers.map((speaker) => speaker.name).toList(); - List get avatarUrls => speakers.map((speaker) => speaker.avatarUrl).toList(); + List get avatarUrls => + speakers.map((speaker) => speaker.avatarUrl).toList(); - ScheduleModel({this.type, this.title, this.time, this.speakers, this.contents}); + ScheduleModel( + {this.type, this.title, this.time, this.speakers, this.contents}); - factory ScheduleModel.fromJson(Map parsedJson){ + factory ScheduleModel.fromJson(Map parsedJson) { final List speakers = (parsedJson['speakers'] as List) - ?.map((e) => e == null ? null : SpeakerModel.fromJson(e as Map)) - ?.toList() ?? []; + ?.map((e) => e == null + ? null + : SpeakerModel.fromJson(e as Map)) + ?.toList() ?? + []; return ScheduleModel( type: parsedJson['type'], title: parsedJson['title'], - time: parsedJson ['time'], + time: parsedJson['time'], speakers: speakers, - contents: parsedJson ['contents'] - ); + contents: parsedJson['contents']); } } -class SpeakerModel{ + +class SpeakerModel { final String name; final String avatarUrl; @@ -49,4 +53,4 @@ class SpeakerModel{ avatarUrl: parsedJson['avatarUrl'], ); } -} \ No newline at end of file +} From 8f07d0a6175952c0f1edd15eec50f8be13c17ba3 Mon Sep 17 00:00:00 2001 From: Poolyum Date: Fri, 29 Mar 2019 19:18:55 +0900 Subject: [PATCH 03/16] =?UTF-8?q?[UPDATE]=20schedule=20favorite=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20bloc=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bloc/schedule_like_bloc.dart | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 lib/bloc/schedule_like_bloc.dart diff --git a/lib/bloc/schedule_like_bloc.dart b/lib/bloc/schedule_like_bloc.dart new file mode 100644 index 0000000..9aef263 --- /dev/null +++ b/lib/bloc/schedule_like_bloc.dart @@ -0,0 +1,52 @@ +import 'dart:convert'; + +import 'package:rxdart/rxdart.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import './bloc_provider.dart'; + +class ScheduleLikeBloc implements BlocBase { + final _likeMap = BehaviorSubject>(); + Observable> get $likeMap => _likeMap.stream; + Base64Codec _base64 = Base64Codec(); + Utf8Codec _utf8 = Utf8Codec(); + Map _map = {}; + SharedPreferences prefs; + + ScheduleLikeBloc() { + init(); + } + + //71f6ceba9d965fdf5421a3e701286647cc03cf1d + + void init() async { + prefs = await SharedPreferences.getInstance(); + _map = json.decode(prefs.getString('dkf_schedule_like_map') ?? "{}"); + _likeMap.add(_map); + } + + Future addLike(String id) async { + _map[toBase64(id)] = true; + _likeMap.add(_map); + await prefs.setString('dkf_schedule_like_map', json.encode(_map)); + } + + Future removeLike(String id) async { + _map.remove(toBase64(id)); + _likeMap.add(_map); + await prefs.setString('dkf_schedule_like_map', json.encode(_map)); + } + + @override + void dispose() { + _likeMap.close(); + } + + String toBase64(String str) { + return _base64.encode(_utf8.encode(str)); + } + + String fromBase64(String str) { + return _base64.decode(str).toString(); + } +} From f6563ac285af227da1421fc59516c4703877a8e5 Mon Sep 17 00:00:00 2001 From: Poolyum Date: Fri, 29 Mar 2019 19:19:21 +0900 Subject: [PATCH 04/16] =?UTF-8?q?[UPDATE]=20schedule=20favorite=20bloc=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EC=97=AC=20favorite(liked)=20?= =?UTF-8?q?=EC=97=AC=EB=B6=80=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/schedule_page.dart | 71 +++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/lib/pages/schedule_page.dart b/lib/pages/schedule_page.dart index 52e231a..64e9e69 100644 --- a/lib/pages/schedule_page.dart +++ b/lib/pages/schedule_page.dart @@ -1,13 +1,16 @@ +import 'dart:io' show Platform; + +import 'package:droidknights/bloc/schedule_like_bloc.dart'; import 'package:droidknights/models/schedule_service.dart'; import 'package:droidknights/models/track_schedule.dart'; import 'package:droidknights/pages/session_detail_dialog.dart'; import 'package:droidknights/res/strings.dart'; import 'package:flutter/material.dart'; -import 'dart:io' show Platform; class SchedulePage extends StatelessWidget { static final int ITEMVIEW_TYPE_NORMAL = 0; static final int ITEMVIEW_TYPE_SESSTION = 1; + final ScheduleLikeBloc _likeBloc = new ScheduleLikeBloc(); Widget scheduleAppbar() { return SliverAppBar( @@ -29,18 +32,17 @@ class SchedulePage extends StatelessWidget { } Widget androidAppBarTitle() => Image.asset( - Strings.SCHEDULE_TAB_IMAGES_APP_BAR, - fit: BoxFit.fitHeight, - height: 25, - ); + Strings.SCHEDULE_TAB_IMAGES_APP_BAR, + fit: BoxFit.fitHeight, + height: 25, + ); - Widget iosAppBarTitle() => - Text( - Strings.SCHEDULE_TAB_APPBAR_TITLE, - style: new TextStyle( - fontSize: 24.0, - fontWeight: FontWeight.w600, - ), + Widget iosAppBarTitle() => Text( + Strings.SCHEDULE_TAB_APPBAR_TITLE, + style: new TextStyle( + fontSize: 24.0, + fontWeight: FontWeight.w600, + ), ); @override @@ -49,9 +51,10 @@ class SchedulePage extends StatelessWidget { length: 3, child: Scaffold( body: NestedScrollView( - headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) => [ - scheduleAppbar(), - ], + headerSliverBuilder: + (BuildContext context, bool innerBoxIsScrolled) => [ + scheduleAppbar(), + ], body: TabBarView( children: [ trackScreen(Strings.SCHEDULE_TAB_JSON_TRACK_SCREEN1), @@ -60,8 +63,7 @@ class SchedulePage extends StatelessWidget { ], ), ), - ) - ); + )); } Widget trackScreen(String filePath) { @@ -82,14 +84,24 @@ class SchedulePage extends StatelessWidget { } Widget _itemView(context, data) { - if (data.type == ITEMVIEW_TYPE_SESSTION) { - return _showItemSection(context, data); - } else { - return _showItemNormal(context, data); - } + return StreamBuilder( + stream: _likeBloc.$likeMap, + builder: (context, snapshot) { + if (!snapshot.hasData) return Container(); + return data.type == ITEMVIEW_TYPE_SESSTION + ? _showItemSection( + context, + data, + snapshot.data[_likeBloc.toBase64(data.title + data.time)] == + null + ? false + : snapshot + .data[_likeBloc.toBase64(data.title + data.time)]) + : _showItemNormal(context, data); + }); } - Widget _showItemSection(context, data) { + Widget _showItemSection(context, data, liked) { return ListTile( leading: Text( data.time, @@ -121,12 +133,14 @@ class SchedulePage extends StatelessWidget { fadeInDuration: const Duration(seconds: 0), fadeOutDuration: const Duration(seconds: 0), image: data.avatarUrls.first, - placeholder: Platform.isAndroid ? Strings.IMAGES_DK_PROFILE : Strings.IMAGES_DK_IOS_PROFILE, + placeholder: Platform.isAndroid + ? Strings.IMAGES_DK_PROFILE + : Strings.IMAGES_DK_IOS_PROFILE, fit: BoxFit.fitHeight, ), ), Padding(padding: const EdgeInsets.symmetric(horizontal: 6.0)), - Flexible( + Expanded( child: Container( constraints: BoxConstraints(minHeight: 60.0), child: Column( @@ -148,6 +162,13 @@ class SchedulePage extends StatelessWidget { ), ), ), + IconButton( + icon: Icon(liked ? Icons.favorite : Icons.favorite_border), + onPressed: () { + liked + ? _likeBloc.removeLike(data.title + data.time) + : _likeBloc.addLike(data.title + data.time); + }) ], ), ), From b06d960f604d3834f0112b610e538b2e114874b0 Mon Sep 17 00:00:00 2001 From: Poolyum Date: Fri, 29 Mar 2019 19:30:09 +0900 Subject: [PATCH 05/16] =?UTF-8?q?[UPDATE]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=A3=BC=EC=84=9D=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bloc/schedule_like_bloc.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/bloc/schedule_like_bloc.dart b/lib/bloc/schedule_like_bloc.dart index 9aef263..527c105 100644 --- a/lib/bloc/schedule_like_bloc.dart +++ b/lib/bloc/schedule_like_bloc.dart @@ -17,8 +17,6 @@ class ScheduleLikeBloc implements BlocBase { init(); } - //71f6ceba9d965fdf5421a3e701286647cc03cf1d - void init() async { prefs = await SharedPreferences.getInstance(); _map = json.decode(prefs.getString('dkf_schedule_like_map') ?? "{}"); From 47e08afa587043d1f839f1278abd7c6ca5bffbcc Mon Sep 17 00:00:00 2001 From: Poolyum Date: Fri, 29 Mar 2019 19:34:38 +0900 Subject: [PATCH 06/16] =?UTF-8?q?[UPDATE]=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=B0=B0=EA=B2=BD=20=ED=9D=B0?= =?UTF-8?q?=EC=83=89=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/session_detail_dialog.dart | 46 +++++++++++++++------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/lib/pages/session_detail_dialog.dart b/lib/pages/session_detail_dialog.dart index fda43ac..19bceab 100644 --- a/lib/pages/session_detail_dialog.dart +++ b/lib/pages/session_detail_dialog.dart @@ -1,9 +1,9 @@ +import 'dart:io' show Platform; import 'dart:math'; import 'package:droidknights/models/track_schedule.dart'; import 'package:droidknights/res/strings.dart'; import 'package:flutter/material.dart'; -import 'dart:io' show Platform; class SessionDetailDialog extends ModalRoute { final ScheduleModel sessionData; @@ -153,28 +153,32 @@ class SessionDetailDialog extends ModalRoute { Widget get profileImage { return new Hero( - tag: sessionData, - child: Row( - children: sessionData.speakers - .sublist(0, min(sessionData.speakers.length, 2)) - .map(avatarContainer) - .expand((w) => [w, Padding(padding: EdgeInsets.only(left: 8.0))]) - .toList()..removeLast(), - ) - ); + tag: sessionData, + child: Row( + children: sessionData.speakers + .sublist(0, min(sessionData.speakers.length, 2)) + .map(avatarContainer) + .expand((w) => [w, Padding(padding: EdgeInsets.only(left: 8.0))]) + .toList() + ..removeLast(), + )); } Widget avatarContainer(SpeakerModel speaker) { - return ClipOval( - child: FadeInImage.assetNetwork( - width: avatarSize, - height: avatarSize, - fadeInDuration: const Duration(seconds: 0), - fadeOutDuration: const Duration(seconds: 0), - image: speaker.avatarUrl, - placeholder: Platform.isAndroid ? Strings.IMAGES_DK_PROFILE : Strings.IMAGES_DK_IOS_PROFILE, - fit: BoxFit.fitHeight, - ) + return Container( + decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.white), + child: ClipOval( + child: FadeInImage.assetNetwork( + width: avatarSize, + height: avatarSize, + fadeInDuration: const Duration(seconds: 0), + fadeOutDuration: const Duration(seconds: 0), + image: speaker.avatarUrl, + placeholder: Platform.isAndroid + ? Strings.IMAGES_DK_PROFILE + : Strings.IMAGES_DK_IOS_PROFILE, + fit: BoxFit.fitHeight, + )), ); } -} \ No newline at end of file +} From c967856cf80d905e8a94145818edcddd381ae112 Mon Sep 17 00:00:00 2001 From: Poolyum Date: Fri, 29 Mar 2019 20:20:44 +0900 Subject: [PATCH 07/16] =?UTF-8?q?[UPDATE]=20=EB=A6=AC=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=9D=98=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EC=98=81=EC=97=AD=20=EB=B3=B4=EB=8D=94=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Runner.xcodeproj/project.pbxproj | 10 ++-------- lib/pages/schedule_page.dart | 27 ++++++++++++++++----------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 0e40f33..bf20a7d 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -244,24 +244,22 @@ buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", + "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", ); name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - ); outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", ); runOnlyForDeploymentPostprocessing = 0; @@ -274,15 +272,11 @@ buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", "${PODS_ROOT}/GoogleMaps/Maps/Frameworks/GoogleMaps.framework/Resources/GoogleMaps.bundle", ); name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - ); outputPaths = ( "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleMaps.bundle", ); diff --git a/lib/pages/schedule_page.dart b/lib/pages/schedule_page.dart index 64e9e69..aafbcd5 100644 --- a/lib/pages/schedule_page.dart +++ b/lib/pages/schedule_page.dart @@ -126,17 +126,22 @@ class SchedulePage extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - ClipOval( - child: FadeInImage.assetNetwork( - width: 56.0, - height: 56.0, - fadeInDuration: const Duration(seconds: 0), - fadeOutDuration: const Duration(seconds: 0), - image: data.avatarUrls.first, - placeholder: Platform.isAndroid - ? Strings.IMAGES_DK_PROFILE - : Strings.IMAGES_DK_IOS_PROFILE, - fit: BoxFit.fitHeight, + Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + border: new Border.all(color: Colors.grey, width: 1)), + child: ClipOval( + child: FadeInImage.assetNetwork( + width: 56.0, + height: 56.0, + fadeInDuration: const Duration(seconds: 0), + fadeOutDuration: const Duration(seconds: 0), + image: data.avatarUrls.first, + placeholder: Platform.isAndroid + ? Strings.IMAGES_DK_PROFILE + : Strings.IMAGES_DK_IOS_PROFILE, + fit: BoxFit.fitHeight, + ), ), ), Padding(padding: const EdgeInsets.symmetric(horizontal: 6.0)), From bd387738a3fed8e3fee549e25ddb93a60a7fc7b3 Mon Sep 17 00:00:00 2001 From: Poolyum Date: Fri, 29 Mar 2019 20:24:02 +0900 Subject: [PATCH 08/16] =?UTF-8?q?[UPDATE]=20shared=5Fpreferences=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EB=B2=84=EC=A0=84=20=EC=88=98?= =?UTF-8?q?=EC=A0=95,=20cached=5Fnetwork=5Fimage=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pubspec.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index dedaecb..977351d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,7 +23,8 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 rxdart: ^0.20.0 - shared_preferences: ^0.5.1+2 + shared_preferences: 0.4.0 + cached_network_image: 0.5.0 dev_dependencies: flutter_test: From 1786ef3b1e3523807ce1d2d607c7995760b6303f Mon Sep 17 00:00:00 2001 From: Poolyum Date: Fri, 29 Mar 2019 20:31:44 +0900 Subject: [PATCH 09/16] =?UTF-8?q?[UPDATE]=20=EC=8A=A4=EC=BC=80=EC=A5=B4=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EC=99=80=20=EB=94=94=ED=85=8C=EC=9D=BC=20=EB=8B=A4=EC=9D=B4?= =?UTF-8?q?=EC=96=BC=EB=A1=9C=EA=B7=B8=EC=97=90=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=BA=90?= =?UTF-8?q?=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/schedule_page.dart | 9 +++++---- lib/pages/session_detail_dialog.dart | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/pages/schedule_page.dart b/lib/pages/schedule_page.dart index aafbcd5..17a0c11 100644 --- a/lib/pages/schedule_page.dart +++ b/lib/pages/schedule_page.dart @@ -1,5 +1,6 @@ import 'dart:io' show Platform; +import 'package:cached_network_image/cached_network_image.dart'; import 'package:droidknights/bloc/schedule_like_bloc.dart'; import 'package:droidknights/models/schedule_service.dart'; import 'package:droidknights/models/track_schedule.dart'; @@ -131,15 +132,15 @@ class SchedulePage extends StatelessWidget { shape: BoxShape.circle, border: new Border.all(color: Colors.grey, width: 1)), child: ClipOval( - child: FadeInImage.assetNetwork( + child: FadeInImage( width: 56.0, height: 56.0, fadeInDuration: const Duration(seconds: 0), fadeOutDuration: const Duration(seconds: 0), - image: data.avatarUrls.first, - placeholder: Platform.isAndroid + image: CachedNetworkImageProvider(data.avatarUrls.first), + placeholder: AssetImage(Platform.isAndroid ? Strings.IMAGES_DK_PROFILE - : Strings.IMAGES_DK_IOS_PROFILE, + : Strings.IMAGES_DK_IOS_PROFILE), fit: BoxFit.fitHeight, ), ), diff --git a/lib/pages/session_detail_dialog.dart b/lib/pages/session_detail_dialog.dart index 19bceab..939d689 100644 --- a/lib/pages/session_detail_dialog.dart +++ b/lib/pages/session_detail_dialog.dart @@ -1,6 +1,7 @@ import 'dart:io' show Platform; import 'dart:math'; +import 'package:cached_network_image/cached_network_image.dart'; import 'package:droidknights/models/track_schedule.dart'; import 'package:droidknights/res/strings.dart'; import 'package:flutter/material.dart'; @@ -168,15 +169,15 @@ class SessionDetailDialog extends ModalRoute { return Container( decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.white), child: ClipOval( - child: FadeInImage.assetNetwork( + child: FadeInImage( width: avatarSize, height: avatarSize, fadeInDuration: const Duration(seconds: 0), fadeOutDuration: const Duration(seconds: 0), - image: speaker.avatarUrl, - placeholder: Platform.isAndroid + image: CachedNetworkImageProvider(speaker.avatarUrl), + placeholder: AssetImage(Platform.isAndroid ? Strings.IMAGES_DK_PROFILE - : Strings.IMAGES_DK_IOS_PROFILE, + : Strings.IMAGES_DK_IOS_PROFILE), fit: BoxFit.fitHeight, )), ); From b6ddee365cdea68b1e381a8e714c579113c091d1 Mon Sep 17 00:00:00 2001 From: ykc Date: Sat, 30 Mar 2019 16:51:07 +0900 Subject: [PATCH 10/16] =?UTF-8?q?[FIX]=20=ED=99=88=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EB=B0=94=ED=85=80=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EA=B2=8C=EC=9D=B4=EC=85=98=20=EB=88=84=EB=A5=BC=EB=95=8C?= =?UTF-8?q?=EB=A7=88=EB=8B=A4=20body=20=EC=83=88=EB=A1=9C=20=EA=B7=B8?= =?UTF-8?q?=EB=A6=AC=EB=8D=98=EA=B2=83=20=EA=B3=A0=EC=B9=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bloc/bloc_provider.dart | 57 ----------------------------- lib/bloc/tab_bloc.dart | 29 --------------- lib/droidknightsapp_home.dart | 67 +++++++++++++++++++++-------------- lib/main.dart | 10 +----- pubspec.yaml | 1 - 5 files changed, 42 insertions(+), 122 deletions(-) delete mode 100644 lib/bloc/bloc_provider.dart delete mode 100644 lib/bloc/tab_bloc.dart diff --git a/lib/bloc/bloc_provider.dart b/lib/bloc/bloc_provider.dart deleted file mode 100644 index 9ac725a..0000000 --- a/lib/bloc/bloc_provider.dart +++ /dev/null @@ -1,57 +0,0 @@ -import 'package:flutter/material.dart'; - -Type _typeOf() => T; - -abstract class BlocBase { - void dispose(); -} - -class BlocProvider extends StatefulWidget { - BlocProvider({ - Key key, - @required this.child, - @required this.bloc, - }): super(key: key); - - final Widget child; - final T bloc; - - @override - _BlocProviderState createState() => _BlocProviderState(); - - static T of(BuildContext context){ - final type = _typeOf<_BlocProviderInherited>(); - _BlocProviderInherited provider = - context.ancestorInheritedElementForWidgetOfExactType(type)?.widget; - return provider?.bloc; - } -} - -class _BlocProviderState extends State>{ - @override - void dispose(){ - widget.bloc?.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context){ - return new _BlocProviderInherited( - bloc: widget.bloc, - child: widget.child, - ); - } -} - -class _BlocProviderInherited extends InheritedWidget { - _BlocProviderInherited({ - Key key, - @required Widget child, - @required this.bloc, - }) : super(key: key, child: child); - - final T bloc; - - @override - bool updateShouldNotify(_BlocProviderInherited oldWidget) => false; -} \ No newline at end of file diff --git a/lib/bloc/tab_bloc.dart b/lib/bloc/tab_bloc.dart deleted file mode 100644 index 280692a..0000000 --- a/lib/bloc/tab_bloc.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:rxdart/rxdart.dart'; - -import './bloc_provider.dart'; - -class TabBloc implements BlocBase{ - - final _bottomTab = BehaviorSubject(); - Observable get $bottomTab => _bottomTab.stream; - - /* - * start bottom tab from Info - */ - TabBloc() { - _bottomTab.add(0); - } - - /* - * change tab - */ - void changeBottomTab(int index) { - print(index); - _bottomTab.add(index); - } - - @override - void dispose() { - - } -} \ No newline at end of file diff --git a/lib/droidknightsapp_home.dart b/lib/droidknightsapp_home.dart index 10e7c1d..4420753 100644 --- a/lib/droidknightsapp_home.dart +++ b/lib/droidknightsapp_home.dart @@ -3,32 +3,36 @@ import 'package:droidknights/pages/info_page.dart'; import 'package:droidknights/pages/schedule_page.dart'; import 'package:droidknights/res/strings.dart'; import 'package:flutter/material.dart'; - -import 'bloc/bloc_provider.dart'; -import 'bloc/tab_bloc.dart'; import 'package:flutter/cupertino.dart'; import 'dart:io' show Platform; -class DroidknightsAppHome extends StatelessWidget { + +class DroidknightsAppHome extends StatefulWidget { + @override + _DroidknightsAppHomeState createState() => _DroidknightsAppHomeState(); +} + +class _DroidknightsAppHomeState extends State { + + int _index = 0; + List _pages = [Platform.isAndroid ? InfoPage() : InfoIosPage(), SchedulePage()]; + @override Widget build(BuildContext context) { - final _tabBloc = BlocProvider.of(context); - return StreamBuilder( - stream: _tabBloc.$bottomTab, - builder: (context, snapshot) { - if (!snapshot.hasData) return Container(); - return Platform.isAndroid - ? createAndroidWidget(_tabBloc, snapshot) - : createIosWidget(); - }); + return Platform.isAndroid ? createAndroidWidget() : createIosWidget(); } - Widget createAndroidWidget(TabBloc _tabBloc, var snapshot) { + Widget createAndroidWidget() { + return Scaffold( - body: bodyPages(snapshot.data), + body: bodyPages(), bottomNavigationBar: BottomNavigationBar( - onTap: (int index) => _tabBloc.changeBottomTab(index), - currentIndex: snapshot.data, + onTap: (int index) => { + setState(() { + _index = index; + }) + }, + currentIndex: _index, items: [ BottomNavigationBarItem( icon: Icon(Icons.info), @@ -42,14 +46,25 @@ class DroidknightsAppHome extends StatelessWidget { )); } - Widget bodyPages(index) { - switch (index) { - case 0: - return Platform.isAndroid ? InfoPage() : InfoIosPage(); - case 1: - return SchedulePage(); - } - return null; + Widget bodyPages() { + return new Stack( + children: [ + new Offstage( + offstage: _index != 0, + child: new TickerMode( + enabled: _index == 0, + child: _pages[0], + ), + ), + new Offstage( + offstage: _index != 1, + child: new TickerMode( + enabled: _index == 1, + child: _pages[1], + ), + ), + ], + ); } Widget createIosWidget() { @@ -71,7 +86,7 @@ class DroidknightsAppHome extends StatelessWidget { tabBuilder: (context, index) { return CupertinoTabView( builder: (context) { - return bodyPages(index); + return bodyPages(); }, ); }, diff --git a/lib/main.dart b/lib/main.dart index 7fd27db..dc3b13e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,15 +4,7 @@ import 'package:flutter/material.dart'; import 'package:droidknights/droidknightsapp_home.dart'; import 'package:droidknights/res/strings.dart'; -import 'bloc/bloc_provider.dart'; -import 'bloc/tab_bloc.dart'; - -void main() => runApp( - BlocProvider( - bloc: TabBloc(), - child: MyApp() - ) -); +void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override diff --git a/pubspec.yaml b/pubspec.yaml index 24be7df..0bc3023 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -22,7 +22,6 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 - rxdart: ^0.20.0 dev_dependencies: flutter_test: From 3e633aacc408db33c98d57d842ba53b203c99fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=8C=E1=85=B5=E1=84=8B?= =?UTF-8?q?=E1=85=A7=E1=86=BC?= Date: Sat, 30 Mar 2019 16:54:03 +0900 Subject: [PATCH 11/16] =?UTF-8?q?=EC=95=B1=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=EB=B2=84=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Runner.xcodeproj/project.pbxproj | 6 +++++- ios/Runner/Info.plist | 2 -- pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 0e40f33..f27b884 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -195,6 +195,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, ); @@ -248,7 +249,7 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", + "${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework", "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", @@ -430,6 +431,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.droidknights.flutterdroidknights; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Profile; @@ -562,6 +564,7 @@ SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = On; SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -590,6 +593,7 @@ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_SWIFT3_OBJC_INFERENCE = On; SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 78b4216..46247c7 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -29,8 +29,6 @@ UISupportedInterfaceOrientations UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad diff --git a/pubspec.yaml b/pubspec.yaml index 24be7df..507c30e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ description: A new Flutter application for DroidKnights Festival 2019. # Both the version and the builder number may be overridden in flutter # build by specifying --build-name and --build-number, respectively. # Read more about versioning at semver.org. -version: 1.2.0+4 +version: 1.2.1+5 environment: sdk: ">=2.1.0 <3.0.0" From 45dbed7caadda6493bcc0148994b31bbde8724ca Mon Sep 17 00:00:00 2001 From: ykc Date: Sat, 30 Mar 2019 17:01:59 +0900 Subject: [PATCH 12/16] =?UTF-8?q?[FIX]=20iosWidget=EC=97=90=20onTap=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=97=86=EC=96=B4=EC=84=9C=20=EB=84=A3?= =?UTF-8?q?=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/droidknightsapp_home.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/droidknightsapp_home.dart b/lib/droidknightsapp_home.dart index 4420753..6852f90 100644 --- a/lib/droidknightsapp_home.dart +++ b/lib/droidknightsapp_home.dart @@ -19,7 +19,7 @@ class _DroidknightsAppHomeState extends State { @override Widget build(BuildContext context) { - return Platform.isAndroid ? createAndroidWidget() : createIosWidget(); + return createIosWidget(); } Widget createAndroidWidget() { @@ -71,6 +71,11 @@ class _DroidknightsAppHomeState extends State { return CupertinoTabScaffold( backgroundColor: const Color(0xFF112030), tabBar: CupertinoTabBar( + onTap: (int index) => { + setState(() { + _index = index; + }) + }, backgroundColor: CupertinoColors.lightBackgroundGray, items: [ BottomNavigationBarItem( From 89c094b713b5bee023c95e1ab12b6a20081d0c46 Mon Sep 17 00:00:00 2001 From: ykc Date: Sat, 30 Mar 2019 17:07:35 +0900 Subject: [PATCH 13/16] =?UTF-8?q?[FIX]=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=9A=A9=EC=9C=BC=EB=A1=9C=20=EB=84=A3=EC=9D=80=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/droidknightsapp_home.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/droidknightsapp_home.dart b/lib/droidknightsapp_home.dart index 6852f90..09633e2 100644 --- a/lib/droidknightsapp_home.dart +++ b/lib/droidknightsapp_home.dart @@ -19,7 +19,7 @@ class _DroidknightsAppHomeState extends State { @override Widget build(BuildContext context) { - return createIosWidget(); + return Platform.isAndroid ? createAndroidWidget() : createIosWidget(); } Widget createAndroidWidget() { From a3c845c21af562453013f9ad9b71556503d89613 Mon Sep 17 00:00:00 2001 From: ykc Date: Sat, 30 Mar 2019 19:31:04 +0900 Subject: [PATCH 14/16] =?UTF-8?q?splash=5Fscreen=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/splash_screen.dart | 55 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/lib/pages/splash_screen.dart b/lib/pages/splash_screen.dart index 0246da6..034852a 100644 --- a/lib/pages/splash_screen.dart +++ b/lib/pages/splash_screen.dart @@ -1,4 +1,3 @@ -import 'dart:async'; import 'dart:math'; import 'package:droidknights/const/route.dart'; @@ -7,6 +6,7 @@ import 'package:flutter/material.dart'; import 'dart:io' show Platform; const NUMBER_OF_STARS = 30; +const ANIMATION_TIME_MILL = 2500; class SplashScreen extends StatefulWidget { @@ -17,40 +17,33 @@ class SplashScreen extends StatefulWidget { } class SplashScreenState extends State with SingleTickerProviderStateMixin { + List> _animations; AnimationController _controller; - List> _topAndLefts; - - initState() { - try { - super.initState(); - - Random random = new Random(); - _topAndLefts = new List.generate(NUMBER_OF_STARS, (int i) => i) - .map((int i) => random.nextInt(500)) - .map((int left) => left.toDouble()) - .map((double left) => [left, random.nextInt(1000)]) - .map((size) => {'left': size[0], 'top': size[1] / 3.5}) - .toList(); + List> _topAndLefts; - _initAnimation(); + @override + void initState() { + super.initState(); - Timer(Duration(milliseconds: 2500), () async { - Navigator.pushReplacementNamed(context, Routes.HOME); - }); - } catch (e) { - print(e.toString()); - Navigator.pushReplacementNamed(context, Routes.HOME); - } + Random random = new Random(); + _topAndLefts = new List.generate(NUMBER_OF_STARS, (int i) => i) + .map((int i) => Point(random.nextInt(500).toDouble(), random.nextInt(1000) / 3.5)) + .toList(); + + _initAnimation(); } - dispose() { - _disposeAnimation(); - super.dispose(); + void animationListener(AnimationStatus status) { + if(status == AnimationStatus.completed) { + Navigator.pushReplacementNamed(context, Routes.HOME); + } } void _initAnimation() { - _controller = AnimationController(duration: Duration(milliseconds: 2000), vsync: this); + _controller = AnimationController(duration: Duration(milliseconds: ANIMATION_TIME_MILL), vsync: this); + + _controller.addStatusListener(animationListener); _animations = [ makeTweenAnimation(controller: _controller, begin: 0.2, end: 0.6), @@ -60,6 +53,12 @@ class SplashScreenState extends State with SingleTickerProviderSta _controller.forward(); } + @override + void dispose() { + _disposeAnimation(); + super.dispose(); + } + void _disposeAnimation() { _controller.dispose(); } @@ -122,8 +121,8 @@ class SplashScreenState extends State with SingleTickerProviderSta List _buildStars() => _topAndLefts.map((topAndLeft) => Positioned( - top: calculateAnimationValue(_animations[1], topAndLeft['top'] - 20, topAndLeft['top']), - left: topAndLeft['left'], + top: calculateAnimationValue(_animations[1], topAndLeft.y - 20, topAndLeft.y), + left: topAndLeft.x, child: Image.asset( 'assets/images/dk19_appicon_star.png', width: 6, From dd289c21c3ca8cb7ae3d4dbf5c8e4b8167187b2c Mon Sep 17 00:00:00 2001 From: ykc Date: Sat, 30 Mar 2019 19:42:35 +0900 Subject: [PATCH 15/16] Merge branch 'master' of https://github.com/ykc415/DroidKnights-Festival-2019-flutter --- lib/bloc/bloc_provider.dart | 57 +++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 lib/bloc/bloc_provider.dart diff --git a/lib/bloc/bloc_provider.dart b/lib/bloc/bloc_provider.dart new file mode 100644 index 0000000..9ac725a --- /dev/null +++ b/lib/bloc/bloc_provider.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; + +Type _typeOf() => T; + +abstract class BlocBase { + void dispose(); +} + +class BlocProvider extends StatefulWidget { + BlocProvider({ + Key key, + @required this.child, + @required this.bloc, + }): super(key: key); + + final Widget child; + final T bloc; + + @override + _BlocProviderState createState() => _BlocProviderState(); + + static T of(BuildContext context){ + final type = _typeOf<_BlocProviderInherited>(); + _BlocProviderInherited provider = + context.ancestorInheritedElementForWidgetOfExactType(type)?.widget; + return provider?.bloc; + } +} + +class _BlocProviderState extends State>{ + @override + void dispose(){ + widget.bloc?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context){ + return new _BlocProviderInherited( + bloc: widget.bloc, + child: widget.child, + ); + } +} + +class _BlocProviderInherited extends InheritedWidget { + _BlocProviderInherited({ + Key key, + @required Widget child, + @required this.bloc, + }) : super(key: key, child: child); + + final T bloc; + + @override + bool updateShouldNotify(_BlocProviderInherited oldWidget) => false; +} \ No newline at end of file From 314796029755c1fea2901054543c9887dd0f3afc Mon Sep 17 00:00:00 2001 From: Poolyum Date: Sun, 31 Mar 2019 04:06:11 +0900 Subject: [PATCH 16/16] =?UTF-8?q?[UPDATE]=20SharedPreferences=EC=9D=98=20s?= =?UTF-8?q?etString=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8A=94=20meth?= =?UTF-8?q?od=EC=9D=98=20=EB=A6=AC=ED=84=B4=ED=83=80=EC=9E=85=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EC=B6=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bloc/schedule_like_bloc.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/bloc/schedule_like_bloc.dart b/lib/bloc/schedule_like_bloc.dart index 527c105..7ec86fa 100644 --- a/lib/bloc/schedule_like_bloc.dart +++ b/lib/bloc/schedule_like_bloc.dart @@ -23,16 +23,18 @@ class ScheduleLikeBloc implements BlocBase { _likeMap.add(_map); } - Future addLike(String id) async { + Future addLike(String id) { _map[toBase64(id)] = true; _likeMap.add(_map); - await prefs.setString('dkf_schedule_like_map', json.encode(_map)); + prefs.setString('dkf_schedule_like_map', json.encode(_map)); + return prefs.commit(); } - Future removeLike(String id) async { + Future removeLike(String id) { _map.remove(toBase64(id)); _likeMap.add(_map); - await prefs.setString('dkf_schedule_like_map', json.encode(_map)); + prefs.setString('dkf_schedule_like_map', json.encode(_map)); + return prefs.commit(); } @override