diff --git a/lib/home/playlist.dart b/lib/home/playlist.dart index a4b36cd..87dea53 100644 --- a/lib/home/playlist.dart +++ b/lib/home/playlist.dart @@ -61,7 +61,7 @@ class _PlaylistPageState extends State { backgroundColor: Theme.of(context).primaryColor, appBar: AppBar( elevation: 0, - backgroundColor: context.primaryColor, + backgroundColor: context.accentColor.withAlpha(70), ), body: SafeArea( child: Selector>( @@ -74,58 +74,99 @@ class _PlaylistPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - Row( - children: [ - Expanded( - flex: 2, - child: Container( - height: 100, - padding: EdgeInsets.only( - left: 60, - ), - alignment: Alignment.centerLeft, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Text( - _loadHistory - ? s.settingsHistory - : s.homeMenuPlaylist, - style: TextStyle( - color: context.textColor, - fontSize: 30, + Container( + color: context.accentColor.withAlpha(70), + child: Row( + children: [ + Expanded( + flex: 2, + child: Container( + height: 100, + padding: EdgeInsets.only( + left: 60, + ), + alignment: Alignment.centerLeft, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + _loadHistory + ? s.settingsHistory + : s.homeMenuPlaylist, + style: TextStyle( + color: context.textColor, + fontSize: 30, + ), ), - ), - SizedBox(width: 5), - IconButton( - icon: _loadHistory - ? Icon(Icons.playlist_play) - : Icon(Icons.history), - onPressed: () => setState(() { - _loadHistory = !_loadHistory; - })) - ], - ), - _loadHistory - ? FutureBuilder( - future: _getListenTime(), - initialData: 0.0, - builder: (context, snapshot) => RichText( + SizedBox(width: 5), + IconButton( + icon: _loadHistory + ? Icon(Icons.playlist_play) + : Icon(Icons.history), + onPressed: () => setState(() { + _loadHistory = !_loadHistory; + })) + ], + ), + _loadHistory + ? FutureBuilder( + future: _getListenTime(), + initialData: 0.0, + builder: (context, snapshot) => + RichText( + text: TextSpan( + text: 'Today ', + style: GoogleFonts.cairo( + textStyle: TextStyle( + color: Theme.of(context) + .accentColor, + fontSize: 20, + ), + ), + children: [ + TextSpan( + text: + '${snapshot.data.toStringAsFixed(0)} ', + style: GoogleFonts.cairo( + textStyle: TextStyle( + color: context.accentColor, + fontSize: 25, + )), + ), + TextSpan( + text: 'mins', + style: TextStyle( + color: context.accentColor, + fontSize: 15, + )), + ], + ), + ), + ) + : RichText( text: TextSpan( - text: 'Today ', + text: episodes.length.toString(), style: GoogleFonts.cairo( textStyle: TextStyle( color: Theme.of(context).accentColor, - fontSize: 20, + fontSize: 25, ), ), children: [ TextSpan( - text: - '${snapshot.data.toStringAsFixed(0)} ', + text: episodes.length < 2 + ? 'episode' + : 'episodes', + style: TextStyle( + color: context.accentColor, + fontSize: 15, + )), + TextSpan( + text: _sumPlaylistLength(episodes) + .toString(), style: GoogleFonts.cairo( textStyle: TextStyle( color: context.accentColor, @@ -141,139 +182,99 @@ class _PlaylistPageState extends State { ], ), ), - ) - : RichText( - text: TextSpan( - text: episodes.length.toString(), - style: GoogleFonts.cairo( - textStyle: TextStyle( - color: - Theme.of(context).accentColor, - fontSize: 25, - ), - ), - children: [ - TextSpan( - text: episodes.length < 2 - ? 'episode' - : 'episodes', - style: TextStyle( - color: context.accentColor, - fontSize: 15, - )), - TextSpan( - text: _sumPlaylistLength(episodes) - .toString(), - style: GoogleFonts.cairo( - textStyle: TextStyle( - color: context.accentColor, - fontSize: 25, - )), - ), - TextSpan( - text: 'mins', - style: TextStyle( - color: context.accentColor, - fontSize: 15, - )), - ], - ), - ), - ], + ], + ), ), ), - ), - Expanded( - flex: 1, - child: Container( - alignment: Alignment.center, - padding: EdgeInsets.all(5.0), - margin: EdgeInsets.only(right: 20.0, bottom: 5.0), - decoration: data.item2 - ? BoxDecoration( - color: context.brightness == Brightness.dark - ? Colors.grey[800] - : Colors.grey[200], - borderRadius: - BorderRadius.all(Radius.circular(10.0)), - ) - : BoxDecoration(color: Colors.transparent), - child: data.item2 - // ? _topHeight < 90 - // ? Row( - // mainAxisAlignment: - // MainAxisAlignment.center, - // crossAxisAlignment: - // CrossAxisAlignment.center, - // children: [ - // CircleAvatar( - // radius: 12, - // backgroundImage: FileImage(File( - // "${episodes.first.imagePath}")), - // ), - // Padding( - // padding: EdgeInsets.symmetric( - // horizontal: 15), - // child: SizedBox( - // width: 20, - // height: 15, - // child: WaveLoader( - // color: context.accentColor, - // )), - // ), - // ], - // ) - ? Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - CircleAvatar( - radius: 15, - //backgroundColor: _c.withOpacity(0.5), - backgroundImage: FileImage( - File("${episodes.first.imagePath}")), - ), - Container( - width: 150, - alignment: Alignment.center, - child: Text( - episodes.first.title, - maxLines: 1, - overflow: TextOverflow.fade, - textAlign: TextAlign.center, + Expanded( + flex: 1, + child: Container( + alignment: Alignment.center, + padding: EdgeInsets.all(5.0), + margin: EdgeInsets.only(right: 20.0, bottom: 5.0), + decoration: data.item2 + ? BoxDecoration( + color: context.brightness == Brightness.dark + ? Colors.grey[800] + : Colors.grey[200], + borderRadius: + BorderRadius.all(Radius.circular(10.0)), + ) + : BoxDecoration(color: Colors.transparent), + child: data.item2 + // ? _topHeight < 90 + // ? Row( + // mainAxisAlignment: + // MainAxisAlignment.center, + // crossAxisAlignment: + // CrossAxisAlignment.center, + // children: [ + // CircleAvatar( + // radius: 12, + // backgroundImage: FileImage(File( + // "${episodes.first.imagePath}")), + // ), + // Padding( + // padding: EdgeInsets.symmetric( + // horizontal: 15), + // child: SizedBox( + // width: 20, + // height: 15, + // child: WaveLoader( + // color: context.accentColor, + // )), + // ), + // ], + // ) + ? Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + CircleAvatar( + radius: 15, + //backgroundColor: _c.withOpacity(0.5), + backgroundImage: FileImage(File( + "${episodes.first.imagePath}")), ), - ), - Padding( - padding: - EdgeInsets.symmetric(horizontal: 15), - child: SizedBox( - width: 20, - height: 15, - child: WaveLoader( - color: context.accentColor, - )), - ), - ], - ) - : IconButton( - icon: Icon(Icons.play_circle_filled, - size: 40, color: (context).accentColor), - onPressed: () { - audio.playlistLoad(); - // setState(() {}); - }), + Container( + width: 150, + alignment: Alignment.center, + child: Text( + episodes.first.title, + maxLines: 1, + overflow: TextOverflow.fade, + textAlign: TextAlign.center, + ), + ), + Padding( + padding: EdgeInsets.symmetric( + horizontal: 15), + child: SizedBox( + width: 20, + height: 15, + child: WaveLoader( + color: context.accentColor, + )), + ), + ], + ) + : IconButton( + icon: Icon(Icons.play_circle_filled, + size: 40, color: (context).accentColor), + onPressed: () { + audio.playlistLoad(); + // setState(() {}); + }), + ), ), - ), - ], - ), - Divider( - height: 3, + ], + ), ), Expanded( child: _loadHistory ? HistoryList() : ReorderableListView( - // scrollController: _playlistController, onReorder: (oldIndex, newIndex) { if (newIndex > oldIndex) { newIndex -= 1; @@ -330,8 +331,8 @@ class _DismissibleContainerState extends State { Widget _episodeTag(String text, Color color) { return Container( decoration: BoxDecoration( - color: color, borderRadius: BorderRadius.all(Radius.circular(15.0))), - height: 23.0, + color: color, borderRadius: BorderRadius.circular(15.0)), + height: 25.0, margin: EdgeInsets.only(right: 10.0), padding: EdgeInsets.symmetric(horizontal: 8.0), alignment: Alignment.center, @@ -355,7 +356,7 @@ class _DismissibleContainerState extends State { return AnimatedContainer( duration: Duration(milliseconds: 300), alignment: Alignment.center, - height: _delete ? 0 : 95.0, + height: _delete ? 0 : 90.0, child: _delete ? Container( color: Colors.transparent, @@ -391,8 +392,8 @@ class _DismissibleContainerState extends State { ), ], ), - height: 50, - color: Theme.of(context).accentColor, + height: 30, + color: context.accentColor, ), onDismissed: (direction) async { setState(() { @@ -417,65 +418,73 @@ class _DismissibleContainerState extends State { }), )); }, - child: Column( - children: [ - ListTile( - title: Container( - padding: EdgeInsets.only(top: 10.0, bottom: 5.0), - child: Text( - widget.episode.title, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - leading: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.unfold_more, color: c), - CircleAvatar( - backgroundColor: c.withOpacity(0.5), - backgroundImage: - FileImage(File(widget.episode.imagePath)), + child: SizedBox( + height: 90.0, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Expanded( + child: Center( + child: ListTile( + title: Container( + padding: EdgeInsets.only(top: 5.0, bottom: 5.0), + child: Text( + widget.episode.title, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + leading: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.unfold_more, color: c), + CircleAvatar( + backgroundColor: c.withOpacity(0.5), + backgroundImage: + FileImage(File(widget.episode.imagePath)), + ), + ], + ), + subtitle: Container( + padding: EdgeInsets.only(top: 5, bottom: 5), + height: 35, + child: Row( + children: [ + if (widget.episode.explicit == 1) + Container( + decoration: BoxDecoration( + color: Colors.red[800], + shape: BoxShape.circle), + height: 25.0, + width: 25.0, + margin: EdgeInsets.only(right: 10.0), + alignment: Alignment.center, + child: Text('E', + style: + TextStyle(color: Colors.white))), + if (widget.episode.duration != 0) + _episodeTag( + s.minsCount( + widget.episode.duration ~/ 60), + Colors.cyan[300]), + if (widget.episode.enclosureLength != null) + _episodeTag( + '${(widget.episode.enclosureLength) ~/ 1000000}MB', + Colors.lightBlue[300]), + ], + ), + ), + //trailing: Icon(Icons.menu), ), - ], - ), - subtitle: Container( - padding: EdgeInsets.only(top: 5, bottom: 10), - child: Row( - children: [ - (widget.episode.explicit == 1) - ? Container( - decoration: BoxDecoration( - color: Colors.red[800], - shape: BoxShape.circle), - height: 20.0, - width: 20.0, - margin: EdgeInsets.only(right: 10.0), - alignment: Alignment.center, - child: Text('E', - style: TextStyle(color: Colors.white))) - : Center(), - widget.episode.duration != 0 - ? _episodeTag( - s.minsCount(widget.episode.duration ~/ 60), - Colors.cyan[300]) - : Center(), - widget.episode.enclosureLength != null - ? _episodeTag( - '${(widget.episode.enclosureLength) ~/ 1000000}MB', - Colors.lightBlue[300]) - : Center(), - ], ), ), - //trailing: Icon(Icons.menu), - ), - // Divider( - // height: 2, - // ), - ], + Divider( + height: 2, + ), + ], + ), ), ), ); @@ -503,12 +512,12 @@ class _HistoryListState extends State { _loadMoreData() async { if (mounted) { setState(() { - _top = _top + 100; + _top = _top + 20; }); } } - int _top = 100; + int _top = 20; @override Widget build(BuildContext context) { @@ -538,83 +547,111 @@ class _HistoryListState extends State { (Theme.of(context).brightness == Brightness.light) ? episode.primaryColor.colorizedark() : episode.primaryColor.colorizeLight(); - return ListTile( - contentPadding: - EdgeInsets.only(left: 40, right: 20, top: 10), - onTap: () => audio.episodeLoad(episode), - leading: CircleAvatar( - backgroundColor: c.withOpacity(0.5), - backgroundImage: FileImage(File(episode.imagePath)), - ), - title: Text( - snapshot.data[index].title, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - subtitle: Row( - children: [ - Text( - date.toDate(context), - style: TextStyle( - fontSize: 15, - ), - ), - SizedBox(width: 5), - if (seekValue < 0.9) - Material( - color: Colors.transparent, - child: InkWell( - onTap: () async { - audio.episodeLoad(episode, - startPosition: - (seconds * 1000).toInt()); - }, - child: Container( - height: 20, - alignment: Alignment.center, - padding: - EdgeInsets.symmetric(horizontal: 5), - decoration: BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(10.0)), - color: context.accentColor, - ), - child: Text( - seconds.toTime, - style: TextStyle(color: Colors.white), - ), + return SizedBox( + height: 90.0, + child: Column( + children: [ + Expanded( + child: Center( + child: ListTile( + contentPadding: + EdgeInsets.only(left: 40, right: 20), + onTap: () => audio.episodeLoad(episode), + leading: CircleAvatar( + backgroundColor: c.withOpacity(0.5), + backgroundImage: + FileImage(File(episode.imagePath)), + ), + title: Text( + snapshot.data[index].title, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + subtitle: Row( + children: [ + Selector, bool>>( + selector: (_, audio) => Tuple2( + audio.queue.playlist, + audio.queueUpdate), + builder: (_, data, __) { + return data.item1.contains(episode) + ? IconButton( + icon: Icon( + Icons + .playlist_add_check, + color: context + .accentColor), + onPressed: () async { + audio.delFromPlaylist( + episode); + Fluttertoast.showToast( + msg: s + .toastRemovePlaylist, + gravity: + ToastGravity.BOTTOM, + ); + }) + : IconButton( + icon: Icon( + Icons.playlist_add, + color: + Colors.grey[700]), + onPressed: () async { + audio.addToPlaylist( + episode); + Fluttertoast.showToast( + msg: s.toastAddPlaylist, + gravity: + ToastGravity.BOTTOM, + ); + }); + }, + ), + if (seekValue < 0.9) + Material( + color: Colors.transparent, + child: InkWell( + onTap: () async { + audio.episodeLoad(episode, + startPosition: + (seconds * 1000) + .toInt()); + }, + child: Container( + height: 25, + alignment: Alignment.center, + padding: EdgeInsets.symmetric( + horizontal: 10), + decoration: BoxDecoration( + borderRadius: + BorderRadius.all( + Radius.circular( + 20.0)), + color: context.accentColor, + ), + child: Text( + s.timeLastPlayed( + seconds.toTime), + style: TextStyle( + color: Colors.white), + ), + ), + ), + ), + Spacer(), + Text( + date.toDate(context), + style: TextStyle( + fontSize: 15, + ), + ), + ], ), ), ), - SizedBox(width: 5), - Selector, bool>>( - selector: (_, audio) => Tuple2( - audio.queue.playlist, audio.queueUpdate), - builder: (_, data, __) { - return data.item1.contains(episode) - ? IconButton( - icon: Icon(Icons.playlist_add_check, - color: context.accentColor), - onPressed: () async { - audio.delFromPlaylist(episode); - Fluttertoast.showToast( - msg: s.toastRemovePlaylist, - gravity: ToastGravity.BOTTOM, - ); - }) - : IconButton( - icon: Icon(Icons.playlist_add, - color: Colors.grey[700]), - onPressed: () async { - audio.addToPlaylist(episode); - Fluttertoast.showToast( - msg: s.toastAddPlaylist, - gravity: ToastGravity.BOTTOM, - ); - }); - }, ), + Divider(height: 2) ], ), ); diff --git a/lib/local_storage/sqflite_localpodcast.dart b/lib/local_storage/sqflite_localpodcast.dart index 148aad3..f41358f 100644 --- a/lib/local_storage/sqflite_localpodcast.dart +++ b/lib/local_storage/sqflite_localpodcast.dart @@ -586,7 +586,7 @@ class DBHelper { } return 0; } catch (e) { - developer.log(e, name: 'Update podcast error'); + developer.log(e.toString(), name: 'Update podcast error'); return -1; } } diff --git a/lib/podcasts/podcast_detail.dart b/lib/podcasts/podcast_detail.dart index 75a24d9..1f4e9b9 100644 --- a/lib/podcasts/podcast_detail.dart +++ b/lib/podcasts/podcast_detail.dart @@ -20,13 +20,12 @@ import '../state/audio_state.dart'; import '../state/download_state.dart'; import '../type/episodebrief.dart'; import '../type/fireside_data.dart'; -import '../type/play_histroy.dart'; import '../type/podcastlocal.dart'; import '../util/audiopanel.dart'; import '../util/custom_widget.dart'; import '../util/episodegrid.dart'; import '../util/extension_helper.dart'; -import '../util/general_dialog.dart'; +import 'podcast_settings.dart'; class PodcastDetail extends StatefulWidget { PodcastDetail({Key key, @required this.podcastLocal, this.hide = false}) @@ -93,10 +92,12 @@ class _PodcastDetailState extends State { Future _updateRssItem(BuildContext context, PodcastLocal podcastLocal) async { var dbHelper = DBHelper(); final result = await dbHelper.updatePodcastRss(podcastLocal); - Fluttertoast.showToast( - msg: context.s.updateEpisodesCount(result), - gravity: ToastGravity.TOP, - ); + if (result >= 0) { + Fluttertoast.showToast( + msg: context.s.updateEpisodesCount(result), + gravity: ToastGravity.TOP, + ); + } if (result > 0) { var autoDownload = await dbHelper.getAutoDownload(podcastLocal.id); if (autoDownload) { @@ -163,19 +164,6 @@ class _PodcastDetailState extends State { return index; } - _markListened(String podcastId) async { - var dbHelper = DBHelper(); - var episodes = await dbHelper.getRssItem(podcastId, -1, reverse: true); - for (var episode in episodes) { - var marked = await dbHelper.checkMarked(episode); - if (!marked) { - final history = PlayHistory(episode.title, episode.enclosureUrl, 0, 1); - await dbHelper.saveHistory(history); - if (mounted) setState(() {}); - } - } - } - Widget podcastInfo(BuildContext context) { return Container( height: 170, @@ -308,33 +296,6 @@ class _PodcastDetailState extends State { ); } - _confirmMarkListened(BuildContext context) => generalDialog( - context, - title: Text(context.s.markConfirm), - content: Text(context.s.markConfirmContent), - actions: [ - FlatButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text( - context.s.cancel, - style: TextStyle(color: Colors.grey[600]), - ), - ), - FlatButton( - onPressed: () async { - Navigator.of(context).pop(); - await _markListened(widget.podcastLocal.id); - }, - child: Text( - context.s.confirm, - style: TextStyle(color: context.accentColor), - ), - ) - ], - ); - _customPopupMenu( {Widget child, String tooltip, @@ -370,7 +331,14 @@ class _PodcastDetailState extends State { widget.podcastLocal.rssUrl.launchUrl; break; case 2: - _confirmMarkListened(context); + Navigator.push( + context, + MaterialPageRoute( + fullscreenDialog: true, + builder: (context) => + PodcastSetting(podcastLocal: widget.podcastLocal), + ), + ); break; } }, @@ -398,7 +366,7 @@ class _PodcastDetailState extends State { child: Row( children: [ Icon( - Icons.rss_feed, + LineIcons.rss_square_solid, color: context.textColor, ), Padding( @@ -412,23 +380,15 @@ class _PodcastDetailState extends State { PopupMenuItem( value: 2, child: Container( - padding: EdgeInsets.only(left: 10), + padding: const EdgeInsets.only(left: 10), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - SizedBox( - width: 25, - height: 25, - child: CustomPaint( - painter: - ListenedAllPainter(context.textColor, stroke: 2)), - ), + Icon(LineIcons.cog_solid, color: context.textColor), Padding( padding: EdgeInsets.symmetric(horizontal: 5.0), ), - Text( - s.menuMarkAllListened, - ), + Text(s.settings), ], ), ), diff --git a/lib/podcasts/podcast_group.dart b/lib/podcasts/podcast_group.dart index cfe3e9d..cae1c1e 100644 --- a/lib/podcasts/podcast_group.dart +++ b/lib/podcasts/podcast_group.dart @@ -80,14 +80,14 @@ class _PodcastCardState extends State int _seconds; int _skipSeconds; - Future getSkipSecond(String id) async { + Future _getSkipSecond(String id) async { var dbHelper = DBHelper(); var seconds = await dbHelper.getSkipSeconds(id); _skipSeconds = seconds; return seconds; } - saveSkipSeconds(String id, int seconds) async { + _saveSkipSeconds(String id, int seconds) async { var dbHelper = DBHelper(); await dbHelper.saveSkipSeconds(id, seconds); } @@ -119,11 +119,6 @@ class _PodcastCardState extends State } } - String _stringForSeconds(double seconds) { - if (seconds == null) return null; - return '${(seconds ~/ 60)}:${(seconds.truncate() % 60).toString().padLeft(2, '0')}'; - } - @override void initState() { super.initState(); @@ -389,7 +384,8 @@ class _PodcastCardState extends State }, ), FutureBuilder( - future: getSkipSecond(widget.podcastLocal.id), + future: + _getSkipSecond(widget.podcastLocal.id), initialData: 0, builder: (context, snapshot) { return _buttonOnMenu( @@ -398,7 +394,7 @@ class _PodcastCardState extends State size: _value == 0 ? 1 : 20 * (_value), ), tooltip: - 'Skip${snapshot.data == 0 ? '' : _stringForSeconds(snapshot.data.toDouble())}', + 'Skip${snapshot.data == 0 ? '' : snapshot.data.toTime}', onTap: () { generalDialog( context, @@ -425,7 +421,7 @@ class _PodcastCardState extends State FlatButton( onPressed: () { Navigator.of(context).pop(); - saveSkipSeconds( + _saveSkipSeconds( widget.podcastLocal.id, _seconds); }, diff --git a/lib/state/audio_state.dart b/lib/state/audio_state.dart index 2ea814d..7fca03e 100644 --- a/lib/state/audio_state.dart +++ b/lib/state/audio_state.dart @@ -423,7 +423,7 @@ class AudioPlayerNotifier extends ChangeNotifier { } /// Reset error state. - if (_audioState != AudioProcessingState.error && _playing) { + if (_audioState != AudioProcessingState.error) { _remoteErrorMessage = null; } notifyListeners(); diff --git a/lib/state/podcast_group.dart b/lib/state/podcast_group.dart index 08a3f8c..8883024 100644 --- a/lib/state/podcast_group.dart +++ b/lib/state/podcast_group.dart @@ -58,7 +58,16 @@ class PodcastGroup { Future getPodcasts() async { var dbHelper = DBHelper(); if (podcastList != []) { - _podcasts = await dbHelper.getPodcastLocal(podcastList); + try { + _podcasts = await dbHelper.getPodcastLocal(podcastList); + } catch (e) { + await Future.delayed(Duration(milliseconds: 200)); + try { + _podcasts = await dbHelper.getPodcastLocal(podcastList); + } catch (e) { + developer.log(e.toString()); + } + } } }