Skip to content

Commit

Permalink
feat: close #217
Browse files Browse the repository at this point in the history
  • Loading branch information
lucien144 committed May 6, 2021
1 parent 305282f commit f7c5716
Show file tree
Hide file tree
Showing 18 changed files with 510 additions and 99 deletions.
2 changes: 1 addition & 1 deletion lib/components/MailListItem.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class _MailListItemState extends State<MailListItem> {
content: widget.mail.content,
topLeftWidget: PostAvatar(
widget.mail.direction == MailDirection.from ? widget.mail.participant : MainRepository().credentials.nickname,
description: '→ ${widget.mail.direction == MailDirection.to ? widget.mail.participant : MainRepository().credentials.nickname}, ~${Helpers.parseTime(widget.mail.time)}'
description: '→ ${widget.mail.direction == MailDirection.to ? widget.mail.participant : MainRepository().credentials.nickname}, ~${Helpers.relativeTime(widget.mail.time)}'
),
topRightWidget: Row(
children: <Widget>[
Expand Down
10 changes: 7 additions & 3 deletions lib/components/PullToRefreshList.dart
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ class _PullToRefreshListState extends State<PullToRefreshList> {
Column(
mainAxisSize: MainAxisSize.max,
children: [
if (widget.pinnedWidget is Widget) widget.pinnedWidget,
Expanded(
child: CustomScrollView(
physics: Platform.isIOS ? const AlwaysScrollableScrollPhysics() : const RefreshScrollPhysics(),
Expand Down Expand Up @@ -150,9 +149,10 @@ class _PullToRefreshListState extends State<PullToRefreshList> {
}

List<Widget> buildTheList(List _data) {
// If the list contains widgets
if (_data.first is Widget) {
if (widget.sliverListBuilder is Function) {
return [widget.sliverListBuilder(_data)];
return <Widget>[widget.sliverListBuilder(_data)];
} else {
return [
SliverList(
Expand All @@ -165,6 +165,7 @@ class _PullToRefreshListState extends State<PullToRefreshList> {
}
}

// If the list contains category headers
if (_data.first is Map && (_data.first as Map).containsKey('header')) {
List<Widget> _list = [];

Expand Down Expand Up @@ -201,6 +202,10 @@ class _PullToRefreshListState extends State<PullToRefreshList> {
setState(() => _hasError = false);
setState(() => _lastId = _result.lastId);
}

if (widget.pinnedWidget is Widget) {
_slivers.insert(0, SliverToBoxAdapter(child: widget.pinnedWidget));
}
} catch (error) {
setState(() => _hasError = true);

Expand Down Expand Up @@ -267,4 +272,3 @@ class DataProviderResult {
}

typedef Future<DataProviderResult> TDataProvider(int id);

157 changes: 118 additions & 39 deletions lib/components/post/Advertisement.dart
Original file line number Diff line number Diff line change
@@ -1,90 +1,169 @@
import 'package:flutter/material.dart';
import 'package:fyx/components/post/PostAvatar.dart';
import 'package:fyx/components/post/PostHeroAttachment.dart';
import 'package:fyx/components/post/PostHtml.dart';
import 'package:fyx/model/UserReferences.dart';
import 'package:fyx/model/enums/AdEnums.dart';
import 'package:fyx/model/post/Image.dart' as i;
import 'package:fyx/model/post/content/Advertisement.dart';
import 'package:fyx/theme/Helpers.dart';
import 'package:fyx/theme/T.dart';

class Advertisement extends StatelessWidget {
final ContentAdvertisement content;
final String title; // Ad title can be overwritten. Helpful in discussion page where content.fullName is null.
final String username;

const Advertisement(this.content, {this.title});
// If this widget needs to be displayed within PostListItem (in discussion) or as a standalone widget (pinned to pull-to-refresh)
bool get isStandaloneWidget => this.username is String && this.username.isNotEmpty;

String get heading => this.title ?? (content.fullName ?? '');

const Advertisement(this.content, {this.title, this.username});

Widget buildPriceWidget(BuildContext context) {
return Container(
padding: const EdgeInsets.all(6),
child: Text('${content.price.toString()} ${content.currency}',
style: DefaultTextStyle
.of(context)
.style
.copyWith(fontSize: 16, fontWeight: FontWeight.bold, color: T.COLOR_PRIMARY)),
decoration: BoxDecoration(color: Color(0xffa9ccd3), borderRadius: BorderRadius.circular(6)));
}

Widget buildTitleWidget(BuildContext context) {
return Text(heading, style: DefaultTextStyle
.of(context)
.style
.copyWith(fontSize: 20, fontWeight: FontWeight.bold));
}

Widget buildRefrencesWidget(BuildContext context) {
if (content.references is UserReferences) {
return RichText(
text: TextSpan(children: [
TextSpan(text: 'Reference: ', style: TextStyle(color: Colors.black38, fontSize: 10)),
if (content.references.positive > 0) TextSpan(text: '+${content.references.positive}', style: TextStyle(color: T.COLOR_PRIMARY, fontSize: 10)),
if (content.references.positive > 0 && content.references.negative < 0) TextSpan(text: ' / ', style: TextStyle(color: Colors.black38, fontSize: 10)),
if (content.references.negative < 0) TextSpan(text: '-${content.references.negative}', style: TextStyle(color: T.COLOR_ACCENT, fontSize: 10))
]),
);
}

return Text('');
}

Widget buildIconLabelWidget(IconData icon, String label, BuildContext context) {
return Container(
child: Row(
children: [
Icon(
icon,
size: 14,
),
SizedBox(width: 6),
Text(
label,
style: DefaultTextStyle
.of(context)
.style
.copyWith(fontSize: 12),
),
],
),
//decoration: BoxDecoration(color: T.COLOR_LIGHT, borderRadius: BorderRadius.circular(6), border: Border.all(color: T.COLOR_PRIMARY)),
);
}

@override
Widget build(BuildContext context) {
String heading = this.title ?? (content.fullName ?? '');

return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.baseline,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (heading.isNotEmpty) Flexible(child: Text(heading, style: DefaultTextStyle.of(context).style.copyWith(fontSize: 20, fontWeight: FontWeight.bold))),
if (content.price > 0) Container(
padding: const EdgeInsets.all(6),
child: Text('${content.price.toString()} ${content.currency}', style: DefaultTextStyle.of(context).style.copyWith(fontSize: 16, fontWeight: FontWeight.bold, color: T.COLOR_PRIMARY)),
decoration: BoxDecoration(color: Color(0xffa9ccd3), borderRadius: BorderRadius.circular(6))
if (this.isStandaloneWidget)
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [PostAvatar(this.username, descriptionWidget: buildRefrencesWidget(context)), buildPriceWidget(context)],
),
],
),
),
if (this.isStandaloneWidget)
buildTitleWidget(context)
else
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.baseline,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (heading.isNotEmpty) Flexible(child: buildTitleWidget(context)),
if (content.price > 0) buildPriceWidget(context),
],
),
SizedBox(
height: 6,
height: 8,
),
Row(
children: [
Container(
padding: const EdgeInsets.all(4),
child: Text(
content.type == AdTypeEnum.offer ? 'Nabízím' : 'Hledám',
style: DefaultTextStyle.of(context).style.copyWith(fontSize: 12, color: Colors.white),
style: DefaultTextStyle
.of(context)
.style
.copyWith(fontSize: 12, color: Colors.white),
),
decoration: BoxDecoration(color: content.type == AdTypeEnum.offer ? T.COLOR_SECONDARY : Color(0xff00B99D), borderRadius: BorderRadius.circular(6)),
),
if (content.location.isNotEmpty)
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Container(
padding: const EdgeInsets.all(4),
child: Row(
children: [
Icon(
Icons.location_on_outlined,
size: 14,
),
Text(
content.location,
style: DefaultTextStyle.of(context).style.copyWith(fontSize: 12),
),
],
),
//decoration: BoxDecoration(color: T.COLOR_LIGHT, borderRadius: BorderRadius.circular(6), border: Border.all(color: T.COLOR_PRIMARY)),
),
child: buildIconLabelWidget(Icons.location_on_outlined, content.location, context),
),
],
),
SizedBox(
height: 8,
),
if (content.summary.isNotEmpty) Text(content.summary),
if (content.photoIds.length > 0) Padding(
if (content.insertedAt > 0)
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: buildIconLabelWidget(Icons.calendar_today, Helpers.absoluteTime(content.insertedAt), context),
),
if (content.shipping.isNotEmpty)
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: buildIconLabelWidget(Icons.local_shipping_outlined, content.shipping, context),
),
if (content.summary.isNotEmpty)
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text(content.summary),
),
if (content.description.isNotEmpty) PostHtml(content.description),
if (content.photoIds.length > 0)
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: galleryWidget(context),
)
child: galleryWidget(context),
)
],
);
}

Widget galleryWidget(context) {
List<i.Image> images = content.photoIds.map((String thumb) {
String small = 'https://nyx.cz/$thumb';
String large = small.replaceAllMapped(RegExp(r'(square)(\.[a-z]{3,4})$'), (match) =>'original${match[2]}');
String large = small.replaceAllMapped(RegExp(r'(square)(\.[a-z]{3,4})$'), (match) => 'original${match[2]}');

return i.Image(large, small);
}).toList();
return Wrap(children: images.map((image) => PostHeroAttachment(image, images: images)).toList(), spacing: 8, runSpacing: 8,);
return Wrap(
children: images.map((image) => PostHeroAttachment(image, images: images)).toList(),
spacing: 8,
runSpacing: 8,
);
}
}
15 changes: 9 additions & 6 deletions lib/components/post/PostAvatar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import 'package:fyx/theme/T.dart';

class PostAvatar extends StatelessWidget {
final String nick;
final String description;
final bool isHighlighted;
String description;
Widget descriptionWidget;

String get image => Helpers.avatarUrl(nick);

PostAvatar(this.nick, {this.isHighlighted = false, this.description = ''});
PostAvatar(this.nick, {this.isHighlighted = false, this.description, this.descriptionWidget});

@override
Widget build(BuildContext context) {
Expand All @@ -37,10 +38,12 @@ class PostAvatar extends StatelessWidget {
)
],
),
Text(
description,
style: TextStyle(color: material.Colors.black38, fontSize: 10),
)
if (this.description is String)
Text(
description,
style: TextStyle(color: material.Colors.black38, fontSize: 10),
)
else if (this.descriptionWidget is Widget) this.descriptionWidget
],
)
]);
Expand Down
2 changes: 1 addition & 1 deletion lib/components/post/PostListItem.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class _PostListItemState extends State<PostListItem> {
onTap: () => showCupertinoModalPopup(context: context, builder: (BuildContext context) => PostAvatarActionSheet(user: _post.nick, idKlub: _post.idKlub,)),
child: PostAvatar(
_post.nick,
description: Helpers.parseTime(_post.time),
description: Helpers.relativeTime(_post.time),
),
),
topRightWidget: GestureDetector(
Expand Down
55 changes: 55 additions & 0 deletions lib/model/AccessRights.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
class AccessRights {
int _discussionId;
bool _arRead;
bool _arWrite;
bool _arDelete;
bool _arEdit;
bool _arRights;
int _daysLeft;

AccessRights({int discussionId, bool arRead, bool arWrite, bool arDelete, bool arEdit, bool arRights, int daysLeft}) {
this._discussionId = discussionId;
this._arRead = arRead;
this._arWrite = arWrite;
this._arDelete = arDelete;
this._arEdit = arEdit;
this._arRights = arRights;
this._daysLeft = daysLeft;
}

int get discussionId => _discussionId;

bool get canRead => _arRead;

bool get canWrite => _arWrite;

bool get canDelete => _arDelete;

bool get canEdit => _arEdit;

bool get canRights => _arRights;

int get daysLeft => _daysLeft;

AccessRights.fromJson(Map<String, dynamic> json) {
_discussionId = json['discussion_id'];
_arRead = json['ar_read'] ?? false;
_arWrite = json['ar_write'] ?? false;
_arDelete = json['ar_delete'] ?? false;
_arEdit = json['ar_edit'] ?? false;
_arRights = json['ar_rights'] ?? false;
_daysLeft = json['days_left'] ?? -1;
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['discussion_id'] = this._discussionId;
data['ar_read'] = this._arRead;
data['ar_write'] = this._arWrite;
data['ar_delete'] = this._arDelete;
data['ar_edit'] = this._arEdit;
data['ar_rights'] = this._arRights;
data['days_left'] = this._daysLeft;
return data;
}
}

0 comments on commit f7c5716

Please sign in to comment.