Skip to content

Commit

Permalink
Merge branch 'develop' into fixbug/restore-artwrk-detail-screen
Browse files Browse the repository at this point in the history
  • Loading branch information
phuocbitmark authored May 24, 2024
2 parents 3650212 + b3ca4db commit 3cdd312
Show file tree
Hide file tree
Showing 16 changed files with 542 additions and 451 deletions.
2 changes: 1 addition & 1 deletion assets
131 changes: 81 additions & 50 deletions lib/model/ff_exhibition.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import 'package:autonomy_flutter/common/environment.dart';
import 'package:autonomy_flutter/model/ff_account.dart';
import 'package:autonomy_flutter/model/ff_series.dart';
import 'package:autonomy_flutter/model/ff_user.dart';
import 'package:autonomy_flutter/util/constants.dart';
import 'package:autonomy_flutter/util/exhibition_ext.dart';
import 'package:autonomy_flutter/util/string_ext.dart';
import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart';

class Exhibition {
final String id;
Expand All @@ -23,7 +27,7 @@ class Exhibition {
final List<FFContract>? contracts;
final FFArtist? partner;
final String type;
final List<ExhibitionEvent>? resources;
final List<Post>? posts;
final int status;

Exhibition({
Expand All @@ -44,7 +48,7 @@ class Exhibition {
this.contracts,
this.partner,
this.curator,
this.resources,
this.posts,
});

factory Exhibition.fromJson(Map<String, dynamic> json) => Exhibition(
Expand Down Expand Up @@ -74,8 +78,8 @@ class Exhibition {
curator: json['curator'] == null
? null
: FFCurator.fromJson(json['curator'] as Map<String, dynamic>),
resources: (json['resources'] as List<dynamic>?)
?.map((e) => ExhibitionEvent.fromJson(e as Map<String, dynamic>))
posts: (json['posts'] as List<dynamic>?)
?.map((e) => Post.fromJson(e as Map<String, dynamic>))
.toList(),
status: json['status'] as int,
);
Expand All @@ -97,7 +101,7 @@ class Exhibition {
'partner': partner?.toJson(),
'type': type,
'curator': curator?.toJson(),
'resources': resources?.map((e) => e.toJson()).toList(),
'posts': posts?.map((e) => e.toJson()).toList(),
'status': status,
};

Expand Down Expand Up @@ -126,7 +130,7 @@ class Exhibition {
List<FFContract>? contracts,
FFArtist? partner,
String? type,
List<ExhibitionEvent>? resources,
List<Post>? posts,
int? status,
}) =>
Exhibition(
Expand All @@ -146,7 +150,7 @@ class Exhibition {
contracts: contracts ?? this.contracts,
partner: partner ?? this.partner,
type: type ?? this.type,
resources: resources ?? this.resources,
posts: posts ?? this.posts,
status: status ?? this.status,
);
}
Expand Down Expand Up @@ -194,82 +198,109 @@ class ExhibitionDetail {
);
}

class ExhibitionEvent {
class Post {
final String id;
final String exhibitionID;
final String type;
final String slug;
final String title;
final DateTime? dateTime;
final String? description;
final Map<String, String>? links;
final String content;
final int? displayIndex;
final String coverURI;
final DateTime createdAt;
final DateTime updatedAt;
final MediaUri? mediaUri;
final DateTime? dateTime;
final String? description;
final String? author;
final String? exhibitionID;
final Exhibition? exhibition;

ExhibitionEvent({
Post({
required this.id,
required this.exhibitionID,
required this.type,
required this.slug,
required this.title,
required this.content,
required this.coverURI,
required this.createdAt,
required this.updatedAt,
this.dateTime,
this.description,
this.links,
this.mediaUri,
this.author,
this.displayIndex,
this.exhibitionID,
this.exhibition,
});

factory ExhibitionEvent.fromJson(Map<String, dynamic> json) =>
ExhibitionEvent(
factory Post.fromJson(Map<String, dynamic> json) => Post(
id: json['id'],
exhibitionID: json['exhibitionID'],
type: json['type'],
slug: json['slug'],
title: json['title'],
dateTime: DateTime.tryParse(json['dateTime'] ?? ''),
description: json['description'],
links: Map<String, String>.from(json['links'] ?? {}),
content: json['content'],
coverURI: json['coverURI'],
createdAt: DateTime.parse(json['createdAt']),
updatedAt: DateTime.parse(json['updatedAt']),
mediaUri: json['mediaUri'] == null
dateTime:
json['dateTime'] == null ? null : DateTime.parse(json['dateTime']),
description: json['description'],
author: json['author'],
displayIndex: json['displayIndex'],
exhibitionID: json['exhibitionID'],
exhibition: json['exhibition'] == null
? null
: MediaUri.fromJson(json['mediaUri'] as Map<String, dynamic>),
: Exhibition.fromJson(json['exhibition']),
);

// toJson
Map<String, dynamic> toJson() => {
'id': id,
'exhibitionID': exhibitionID,
'type': type,
'slug': slug,
'title': title,
'dateTime': dateTime?.toIso8601String(),
'description': description,
'links': links,
'content': content,
'coverURI': coverURI,
'createdAt': createdAt.toIso8601String(),
'updatedAt': updatedAt.toIso8601String(),
'mediaUri': mediaUri?.toJson(),
'dateTime': dateTime?.toIso8601String(),
'description': description,
'author': author,
'displayIndex': displayIndex,
'exhibitionID': exhibitionID,
'exhibition': exhibition?.toJson(),
};
}

class MediaUri {
final String url;
final String type;
final String? title;
enum MediaType {
image,
video,
}

MediaUri({
required this.url,
required this.type,
this.title,
});
extension PostExt on Post {
MediaType get mediaType {
final url = Uri.parse(coverURI);
if (youtubeDomains.any((domain) => url.host.contains(domain))) {
return MediaType.video;
}
return MediaType.image;
}

factory MediaUri.fromJson(Map<String, dynamic> json) => MediaUri(
url: json['url'],
type: json['type'],
title: json['title'],
);
String get displayType =>
type == 'close-up' ? 'close_up'.tr() : type.capitalize();

Map<String, dynamic> toJson() => {
'url': url,
'type': type,
'title': title,
};
String get thumbnailUrl {
if (mediaType == MediaType.image) {
return getFFUrl(coverURI);
} else {
final videoId = Uri.parse(coverURI).queryParameters['v'];
return 'https://img.youtube.com/vi/$videoId/maxresdefault.jpg';
}
}

String get previewUrl {
if (mediaType == MediaType.image) {
return getFFUrl(coverURI);
} else {
final videoId = Uri.parse(coverURI).queryParameters['v'];
return 'https://www.youtube.com/embed/$videoId?autoplay=1&loop=1&controls=0';
}
}
}
28 changes: 16 additions & 12 deletions lib/screen/collection_pro/artists_list_page/artists_list_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class _ArtistsListPageState extends State<ArtistsListPage> {
final _itemHeight = PredefinedCollectionItem.height + 1;
static const int _scrollDuration = 500;
static const int _scrollLag = 10;
bool _isDragging = false;

@override
void initState() {
Expand All @@ -47,6 +48,9 @@ class _ArtistsListPageState extends State<ArtistsListPage> {
}

void _scrollListener() {
if (_isDragging) {
return;
}
double offset = _scrollController.offset;
final targetIndex = (offset / _itemHeight).floor();
if (targetIndex < 0 || targetIndex >= _items.length) {
Expand Down Expand Up @@ -91,8 +95,8 @@ class _ArtistsListPageState extends State<ArtistsListPage> {
(element) => element.name.firstSearchCharacter == a);
if (index == -1) {
final nearestIndex = _items.lastIndexWhere((element) =>
_compareHeadCharacter(
element.name.firstSearchCharacter, a) <
element.name.firstSearchCharacter
.compareSearchKey(a) <
0);
if (nearestIndex == -1) {
await _scrollTo(0);
Expand All @@ -107,6 +111,16 @@ class _ArtistsListPageState extends State<ArtistsListPage> {
_selectedCharacter.value = a;
});
},
onDragEnd: () {
Future.delayed(
const Duration(
milliseconds: _scrollDuration + _scrollLag), () {
_isDragging = false;
});
},
onDragging: () {
_isDragging = true;
},
selectedCharacter: value,
)),
Expanded(
Expand Down Expand Up @@ -136,16 +150,6 @@ class _ArtistsListPageState extends State<ArtistsListPage> {
duration: const Duration(milliseconds: _scrollDuration),
curve: Curves.easeIn);
}

int _compareHeadCharacter(String a, String b) {
if (a == '#' && b != '#') {
return 1;
}
if (a != '#' && b == '#') {
return -1;
}
return a.compareTo(b);
}
}

class ArtistsListPagePayload {
Expand Down
26 changes: 7 additions & 19 deletions lib/screen/collection_pro/collection_pro_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class CollectionProState extends State<CollectionPro>
late bool _isLoaded;
late bool _showGetStartedBanner = false;
final _configurationService = injector<ConfigurationService>();
static const _maxArtistsView = 30;

@override
void initState() {
Expand Down Expand Up @@ -164,22 +165,7 @@ class CollectionProState extends State<CollectionPro>
)
.toList()
.filterByName(searchStr.value)
..sort((a, b) {
final aFirstCharacter = a.name.firstSearchCharacter;
final bFirstCharacter = b.name.firstSearchCharacter;
if (aFirstCharacter != '#' && bFirstCharacter != '#') {
return a.name!
.toUpperCase()
.compareTo(b.name!.toUpperCase());
}
if (aFirstCharacter == '#' && bFirstCharacter != '#') {
return 1;
}
if (aFirstCharacter != '#' && bFirstCharacter == '#') {
return -1;
}
return (a.name ?? '').compareTo(b.name ?? '');
});
..sort((a, b) => a.name.compareSearchKey(b.name));
setState(() {
_listPredefinedCollectionByArtist =
listPredefinedCollectionByArtist;
Expand Down Expand Up @@ -266,8 +252,9 @@ class CollectionProState extends State<CollectionPro>
delegate: SliverChildBuilderDelegate(
_predefinedCollectionByArtistBuilder,
childCount: min(
_listPredefinedCollectionByArtist.length + 1,
31),
_listPredefinedCollectionByArtist.length,
_maxArtistsView) +
1,
),
),
const SliverToBoxAdapter(
Expand Down Expand Up @@ -344,7 +331,8 @@ class CollectionProState extends State<CollectionPro>
const type = PredefinedCollectionType.artist;
final isSearching = searchStr.value.isNotEmpty;
final numberOfArtists = _listPredefinedCollectionByArtist.length;
final displaySeeAll = !isSearching && index == 0 && numberOfArtists > 30;
final displaySeeAll =
!isSearching && index == 0 && numberOfArtists > _maxArtistsView;
final Widget? action = displaySeeAll
? GestureDetector(
onTap: () async {
Expand Down
Loading

0 comments on commit 3cdd312

Please sign in to comment.