Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
PLGuerraDesigns committed Mar 20, 2024
2 parents 5651469 + 44b403e commit b02ad22
Show file tree
Hide file tree
Showing 17 changed files with 1,715 additions and 987 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## 2.1.0

- ENHANCED: Added an option tooltip message to the HoverScaleHandler.
- REVISED: JSON media data has been merged into a single list of media items containing the type, path and caption. This allows for easier management of media items and enables custom ordering of media items.
- REVISED: Updated Models to use the new media data structure.
- REVISED: Converted the details page body text to a selectable text widget.
- REVISED: Embedded the MediaBrowser into the MediaPlayer to allow for browsing while keeping the player visible.
- REVISED: Removed scroll under elevation for the App Bar.
- REVISED: Updated FrostedContainer styling.

## 2.0.13

- NEW: Added Pinch to Zoom functionality to images in the media player.
Expand Down
Binary file removed assets/images/personal/amg_gt3_wheel/image_7.jpg
Binary file not shown.
355 changes: 275 additions & 80 deletions assets/json/professional_experience.json

Large diffs are not rendered by default.

1,018 changes: 764 additions & 254 deletions assets/json/projects.json

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions lib/common/enums.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,20 @@ enum MediaType {
localVideo,
youTubeVideo,
}

/// Converts a media type to a string.
extension MediaTypeExtension on MediaType {
/// Converts a media type to a user-friendly string.
String get stringValue {
switch (this) {
case MediaType.localImage:
return 'Image';
case MediaType.networkImage:
return 'Image';
case MediaType.localVideo:
return 'Video';
case MediaType.youTubeVideo:
return 'YouTube Video';
}
}
}
6 changes: 4 additions & 2 deletions lib/models/app_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ class AppState extends ChangeNotifier {
String currentRoute = Strings.homeRoute;

/// Whether the media browser is visible.
bool mediaBrowserVisible = false;
bool _mediaBrowserVisible = false;

bool get mediaBrowserVisible => _mediaBrowserVisible;

/// Whether the projects have been loaded.
bool projectsLoaded = false;
Expand Down Expand Up @@ -97,7 +99,7 @@ class AppState extends ChangeNotifier {

/// Toggles the visibility of the media browser.
void toggleMediaBrowserVisibility() {
mediaBrowserVisible = !mediaBrowserVisible;
_mediaBrowserVisible = !_mediaBrowserVisible;
notifyListeners();
}

Expand Down
27 changes: 25 additions & 2 deletions lib/models/media_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,41 @@ import '../common/enums.dart';

/// A media item to be displayed in the gallery.
class MediaItem {
const MediaItem({
MediaItem({
required this.type,
required this.path,
required this.caption,
});

/// Creates a [MediaItem] from a JSON object.
factory MediaItem.fromJson(Map<String, dynamic> json) {
return MediaItem(
type: mediaTypeFromString(json['type'].toString()),
path: json['path'].toString(),
caption: json['caption'].toString(),
);
}

/// The type of media.
final MediaType type;

/// The path to the media.
final String path;
String path;

/// The caption to be displayed with the media.
final String caption;

/// Converts a string to a [MediaType].
static MediaType mediaTypeFromString(String type) {
switch (type) {
case 'localImage':
return MediaType.localImage;
case 'localVideo':
return MediaType.localVideo;
case 'youTubeVideo':
return MediaType.youTubeVideo;
default:
return MediaType.networkImage;
}
}
}
76 changes: 24 additions & 52 deletions lib/models/professional_experience.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import 'package:intl/intl.dart';
import 'package:unorm_dart/unorm_dart.dart' as unorm;

import '../common/enums.dart';
import 'media_item.dart';

class ProfessionalExperience {
ProfessionalExperience({
required this.company,
Expand All @@ -9,44 +12,41 @@ class ProfessionalExperience {
required this.location,
required this.startDate,
required this.finalDate,
required this.mediaItems,
required this.description,
required this.externalLinks,
required this.youtubeVideoIds,
required this.imageCount,
required this.videoCount,
required this.webImagePaths,
required this.localMediaCaptions,
});

/// Creates a [ProfessionalExperience] from a JSON object.
factory ProfessionalExperience.fromJson(Map<String, dynamic> json) {
List<MediaItem> mediaItems = <MediaItem>[];
if (json['media'] != null) {
mediaItems = (json['media'] as List<dynamic>)
.map((dynamic e) => MediaItem.fromJson(e as Map<String, dynamic>))
.toList();
}
for (int i = 0; i < mediaItems.length; i++) {
final MediaItem mediaItem = mediaItems[i];
if (mediaItem.type == MediaType.localImage ||
mediaItem.type == MediaType.localVideo) {
mediaItems[i].path =
'assets/images/professional/${json['folderName'].toString().toLowerCase().replaceAll(' ', '_')}/${mediaItem.path}';
}
}

return ProfessionalExperience(
company: json['company'].toString(),
folderName: json['folderName'].toString(),
role: json['role'].toString(),
location: json['location'].toString(),
description: json['description'].toString(),
startDate: DateTime.parse(json['startDate'].toString()),
mediaItems: mediaItems,
finalDate: json['endDate'] == null
? null
: DateTime.parse(
json['endDate'].toString(),
),
imageCount: int.parse(json['imageCount'].toString()),
webImagePaths: json['webImages'] == null
? <String>[]
: (json['webImages'] as List<dynamic>).map((dynamic e) {
return e.toString();
}).toList(),
videoCount: int.parse(json['videoCount'].toString()),
localMediaCaptions:
(json['mediaCaptions'] as List<dynamic>).map((dynamic e) {
return e.toString();
}).toList(),
youtubeVideoIds:
(json['youtubeVideoIds'] as List<dynamic>).map((dynamic e) {
return e.toString();
}).toList(),
externalLinks: (json['externalLinks'] as List<dynamic>)
.map((dynamic e) =>
Map<String, String>.from(e as Map<dynamic, dynamic>))
Expand Down Expand Up @@ -82,20 +82,11 @@ class ProfessionalExperience {
/// Relevant external links.
final List<Map<String, String>> externalLinks;

/// The number of images in the project.
final int imageCount;

/// The number of videos in the project.
final int videoCount;

/// The captions for local media.
final List<String> localMediaCaptions;

/// The paths for the web images in the project.
List<String> webImagePaths = <String>[];
/// The list of media items.
List<MediaItem> mediaItems;

/// The YouTube video IDs.
final List<String> youtubeVideoIds;
/// The total number of media items in the project.
int get totalMediaCount => mediaItems.length;

/// The base path for the media.
String get baseMediaPath => 'assets/images/professional/$folderName/';
Expand All @@ -116,23 +107,4 @@ class ProfessionalExperience {
}
return DateFormat('MMMM yyyy').format(finalDate!);
}

/// The paths for the videos in the project.
List<String> get videoPaths {
final List<String> paths = <String>[];
for (int i = 1; i < videoCount + 1; i++) {
paths.add('${baseMediaPath}video_$i.mp4');
}
return paths;
}

/// The paths for the images in the project.
List<String> get imagePaths {
final List<String> paths = <String>[];
paths.add(thumbnailPath);
for (int i = 1; i < imageCount; i++) {
paths.add('${baseMediaPath}image_$i.png');
}
return paths;
}
}
69 changes: 23 additions & 46 deletions lib/models/projects.dart
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
import 'package:intl/intl.dart';

import '../common/enums.dart';
import 'media_item.dart';

class Project {
Project({
required this.title,
required this.subtitle,
required this.description,
required this.startDate,
required this.finalDate,
required this.imageCount,
required this.localMediaCaptions,
required this.videoCount,
required this.externalLinks,
required this.webImagePaths,
required this.mediaItems,
required this.tags,
});

/// Creates a [Project] from a JSON object.
factory Project.fromJson(Map<String, dynamic> json) {
List<MediaItem> mediaItems = <MediaItem>[];
if (json['media'] != null) {
mediaItems = (json['media'] as List<dynamic>)
.map((dynamic e) => MediaItem.fromJson(e as Map<String, dynamic>))
.toList();
}
for (int i = 0; i < mediaItems.length; i++) {
final MediaItem mediaItem = mediaItems[i];
if (mediaItem.type == MediaType.localImage ||
mediaItem.type == MediaType.localVideo) {
mediaItems[i].path =
'assets/images/personal/${json['title'].toString().toLowerCase().replaceAll(' ', '_')}/${mediaItem.path}';
}
}

return Project(
title: json['title'].toString(),
subtitle: json['subtitle'].toString(),
Expand All @@ -25,17 +40,7 @@ class Project {
? null
: DateTime.parse(json['startDate'].toString()),
finalDate: DateTime.parse(json['finalDate'].toString()),
imageCount: int.parse(json['imageCount'].toString()),
webImagePaths: json['webImages'] == null
? <String>[]
: (json['webImages'] as List<dynamic>).map((dynamic e) {
return e.toString();
}).toList(),
localMediaCaptions:
(json['mediaCaptions'] as List<dynamic>).map((dynamic e) {
return e.toString();
}).toList(),
videoCount: int.parse(json['videoCount'].toString()),
mediaItems: mediaItems,
externalLinks: (json['externalLinks'] as List<dynamic>)
.map((dynamic e) =>
Map<String, String>.from(e as Map<dynamic, dynamic>))
Expand Down Expand Up @@ -64,50 +69,22 @@ class Project {
/// The description of the project.
final String description;

/// The number of images in the project.
final int imageCount;

/// The captions for local media.
final List<String> localMediaCaptions;

/// The number of videos in the project.
final int videoCount;

/// Relevant external links.
final List<Map<String, String>> externalLinks;

/// Relevant tags.
final List<String> tags;

/// The paths for the web images in the project.
List<String> webImagePaths = <String>[];
/// The list of media items.
List<MediaItem> mediaItems;

/// The total number of media items in the project.
int get totalMediaCount => imageCount + videoCount;
int get totalMediaCount => mediaItems.length;

/// The base path for the media.
String get baseMediaPath =>
'assets/images/personal/${title.toLowerCase().replaceAll(' ', '_')}/';

/// The paths for the images in the project.
List<String> get imagePaths {
final List<String> paths = <String>[];
paths.add(thumbnailPath);
for (int i = 1; i < imageCount; i++) {
paths.add('${baseMediaPath}image_$i.png');
}
return paths;
}

/// The paths for the videos in the project.
List<String> get videoPaths {
final List<String> paths = <String>[];
for (int i = 1; i < videoCount + 1; i++) {
paths.add('${baseMediaPath}video_$i.mp4');
}
return paths;
}

/// The path for the thumbnail.
String get thumbnailPath => '${baseMediaPath}thumbnail.png';

Expand Down
13 changes: 2 additions & 11 deletions lib/routes/app_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,10 @@ class AppRouter {
logoPath: professionalExperience.logoPath,
title: professionalExperience.company,
description: professionalExperience.description,
imagePaths: professionalExperience.imagePaths,
videoPaths: professionalExperience.videoPaths,
youtubeVideoIds: professionalExperience.youtubeVideoIds,
mediaCaptions:
professionalExperience.localMediaCaptions,
externalLinks: professionalExperience.externalLinks,
startDate: professionalExperience.startDateString,
finalDate: professionalExperience.finalDateString,
webImagePaths: professionalExperience.webImagePaths,
mediaItems: professionalExperience.mediaItems,
tags: const <String>[],
onPreviousPressed: () {
context.go(
Expand Down Expand Up @@ -114,14 +109,10 @@ class AppRouter {
title: project.title,
subtitle: project.subtitle,
description: project.description,
imagePaths: project.imagePaths,
videoPaths: project.videoPaths,
youtubeVideoIds: const <String>[],
mediaCaptions: project.localMediaCaptions,
externalLinks: project.externalLinks,
startDate: project.startDateString,
finalDate: project.finalDateString,
webImagePaths: project.webImagePaths,
mediaItems: project.mediaItems,
tags: project.tags,
onPreviousPressed: () {
context.go(
Expand Down
Loading

0 comments on commit b02ad22

Please sign in to comment.