diff --git a/assets/translations/en.json b/assets/translations/en.json index 0095e67..7148a5d 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -6,37 +6,47 @@ { "tooltip": "Github", "url": "https://github.com/AladdineDev", - "iconCodePoint": "0xf09b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter" + "icon": { + "iconCodePoint": "0xefb7", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + } }, { "tooltip": "Twitter", "url": "https://twitter.com/AladdineDev", - "iconCodePoint": "0xe61b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter" + "icon": { + "iconCodePoint": "0xf0ea", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + } }, { "tooltip": "LinkedIn", "url": "https://www.linkedin.com/in/aladdine-dev", - "iconCodePoint": "0xf08c", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter" + "icon": { + "iconCodePoint": "0xeffb", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + } }, { "tooltip": "aladdine.abdou@gmail.com", "url": "mailto:aladdine.abdou@gmail.com", - "iconCodePoint": "0xf0e0", - "iconFontFamily": "FontAwesomeSolid", - "iconFontPackage": "font_awesome_flutter" + "icon": { + "iconCodePoint": "0xeaad", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + } }, { "tooltip": "+33 7 82 54 34 70", "url": "tel:+33782543470", - "iconCodePoint": "0xf095", - "iconFontFamily": "FontAwesomeSolid", - "iconFontPackage": "font_awesome_flutter" + "icon": { + "iconCodePoint": "0xecbb", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + } } ], "resumes": [ @@ -118,9 +128,11 @@ "name": "Portfolio", "description": "This open source project allows anyone to have an online portfolio in less than 10 minutes. It follows a riverpod-based architecture, using a feature-first approach for its structure. It is fully responsive and supports multiple themes as well as multiple languages.", "url": "https://github.com/AladdineDev/portfolio#readme", - "iconCodePoint": "0xf09b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter", + "icon": { + "iconCodePoint": "0xefb7", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + }, "screenshotPath": "assets/images/portfolio.png", "technologies": [ "Flutter", @@ -137,9 +149,11 @@ "name": "Learn Flow API", "description": "Learn Flow is a collaborative project focused on creating a solution that connects students and teachers. This REST API serves as an interface for the project's various clients, including Android, iOS, and Web. It notably offers authentication capabilities with JWT.", "url": "https://github.com/AladdineDev/learnflow-api#readme", - "iconCodePoint": "0xf09b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter", + "icon": { + "iconCodePoint": "0xefb7", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + }, "screenshotPath": "assets/images/learnflow-api.png", "technologies": [ "Node.js", @@ -153,9 +167,11 @@ "name": "Learn Flow Backoffice", "description": "This is the back-office build for managers in the Learn Flow project. This Single-Page App enables them to monitor activity such as user traffic and invoices associated with their applications and users.", "url": "https://github.com/AladdineDev/learnflow_backoffice#readme", - "iconCodePoint": "0xf09b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter", + "icon": { + "iconCodePoint": "0xefb7", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + }, "screenshotPath": "assets/images/learnflow-backoffice.png", "technologies": [ "Flutter", @@ -166,9 +182,11 @@ "name": "GSB-Frais", "description": "The GSB-Frais project is a web-based expense management application developed for medical representatives and accountants at the fictional company GSB. It facilitates the entry and review of monthly reports by medical representatives, while enabling accountants to process them.", "url": "https://github.com/AladdineDev/GSB-Frais#readme", - "iconCodePoint": "0xf09b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter", + "icon": { + "iconCodePoint": "0xefb7", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + }, "screenshotPath": "assets/images/gsb-frais.png", "technologies": [ "Symfony", @@ -183,9 +201,11 @@ "name": "GSB-RV-Visiteur-Serveur", "description": "The GSB project's REST API serves as an interface for various project clients, including Android, Desktop, and Web applications.", "url": "https://github.com/AladdineDev/GSB-RV-Visiteur-Serveur#readme", - "iconCodePoint": "0xf09b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter", + "icon": { + "iconCodePoint": "0xefb7", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + }, "screenshotPath": "assets/images/gsb-rv-visiteur-serveur.png", "technologies": [ "Flask", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index d3e4ec9..bf67e1e 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -6,37 +6,47 @@ { "tooltip": "Github", "url": "https://github.com/AladdineDev", - "iconCodePoint": "0xf09b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter" + "icon": { + "iconCodePoint": "0xefb7", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + } }, { "tooltip": "Twitter", "url": "https://twitter.com/AladdineDev", - "iconCodePoint": "0xe61b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter" + "icon": { + "iconCodePoint": "0xf0ea", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + } }, { "tooltip": "LinkedIn", "url": "https://www.linkedin.com/in/aladdine-dev", - "iconCodePoint": "0xf08c", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter" + "icon": { + "iconCodePoint": "0xeffb", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + } }, { "tooltip": "aladdine.abdou@gmail.com", "url": "mailto:aladdine.abdou@gmail.com", - "iconCodePoint": "0xf0e0", - "iconFontFamily": "FontAwesomeSolid", - "iconFontPackage": "font_awesome_flutter" + "icon": { + "iconCodePoint": "0xeaad", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + } }, { "tooltip": "+33 7 82 54 34 70", "url": "tel:+33782543470", - "iconCodePoint": "0xf095", - "iconFontFamily": "FontAwesomeSolid", - "iconFontPackage": "font_awesome_flutter" + "icon": { + "iconCodePoint": "0xecbb", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + } } ], "resumes": [ @@ -118,9 +128,11 @@ "name": "Portfolio", "description": "Ce projet open source permet à toute personne de disposer d’un portfolio en ligne en moins de 10 minutes. Il adopte une architecture basée sur Riverpod en suivant une approche feature-first pour sa structure. Il est entièrement responsive, et prend en charge plusieurs thèmes ainsi que plusieurs langues.", "url": "https://github.com/AladdineDev/portfolio#readme", - "iconCodePoint": "0xf09b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter", + "icon": { + "iconCodePoint": "0xefb7", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + }, "screenshotPath": "assets/images/portfolio.png", "technologies": [ "Flutter", @@ -137,9 +149,11 @@ "name": "Learn Flow API", "description": "Learn Flow est un projet de groupe visant à créer une solution de mise en relation d'élèves et d'enseignants. Cette API REST sert d'interface pour les différents clients du projet (Android, iOS et Web). Elle offre notamment des fonctionnalités d'authentification avec JWT.", "url": "https://github.com/AladdineDev/learnflow-api#readme", - "iconCodePoint": "0xf09b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter", + "icon": { + "iconCodePoint": "0xefb7", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + }, "screenshotPath": "assets/images/learnflow-api.png", "technologies": [ "Node.js", @@ -153,9 +167,11 @@ "name": "Learn Flow Backoffice", "description": "Il s'agit du back-office conçu pour les managers du projet Learn Flow. Cette Single-Page App leur permet de surveiller l'activité de leurs applications et utilisateurs (trafic, factures...).", "url": "https://github.com/AladdineDev/learnflow_backoffice#readme", - "iconCodePoint": "0xf09b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter", + "icon": { + "iconCodePoint": "0xefb7", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + }, "screenshotPath": "assets/images/learnflow-backoffice.png", "technologies": [ "Flutter", @@ -166,9 +182,11 @@ "name": "GSB-Frais", "description": "GSB-Frais est une application web de gestion des frais, développée pour les délégués médicaux et les comptables de l'entreprise fictive GSB. Elle facilite la saisie et la vérification des rapports mensuels des délégués médicaux, tout en permettant aux comptables de les traiter.", "url": "https://github.com/AladdineDev/GSB-Frais#readme", - "iconCodePoint": "0xf09b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter", + "icon": { + "iconCodePoint": "0xefb7", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + }, "screenshotPath": "assets/images/gsb-frais.png", "technologies": [ "Symfony", @@ -183,9 +201,11 @@ "name": "GSB-RV-Visiteur-Serveur", "description": "L'API REST du projet GSB sert d'interface pour les différents clients du projet (Android, Desktop et Web).", "url": "https://github.com/AladdineDev/GSB-RV-Visiteur-Serveur#readme", - "iconCodePoint": "0xf09b", - "iconFontFamily": "FontAwesomeBrands", - "iconFontPackage": "font_awesome_flutter", + "icon": { + "iconCodePoint": "0xefb7", + "iconFontFamily": "FontAwesome", + "iconFontPackage": "icons_plus" + }, "screenshotPath": "assets/images/gsb-rv-visiteur-serveur.png", "technologies": [ "Flask", diff --git a/lib/src/features/personal_info/domain/contact.dart b/lib/src/features/personal_info/domain/contact.dart index 1d8bfcd..52f751c 100644 --- a/lib/src/features/personal_info/domain/contact.dart +++ b/lib/src/features/personal_info/domain/contact.dart @@ -1,4 +1,5 @@ import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:portfolio/src/common/domain/icon.dart'; part 'contact.freezed.dart'; part 'contact.g.dart'; @@ -8,9 +9,7 @@ class Contact with _$Contact { const factory Contact({ String? tooltip, String? url, - String? iconCodePoint, - String? iconFontFamily, - String? iconFontPackage, + IconModel? icon, }) = _Contact; factory Contact.fromJson(Map json) => diff --git a/lib/src/features/personal_info/presentation/widgets/contact_bar.dart b/lib/src/features/personal_info/presentation/widgets/contact_bar.dart index b1d9277..d6fdbac 100644 --- a/lib/src/features/personal_info/presentation/widgets/contact_bar.dart +++ b/lib/src/features/personal_info/presentation/widgets/contact_bar.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:portfolio/src/features/personal_info/presentation/widgets/contact_icon_button.dart'; import 'package:portfolio/src/features/personal_info/domain/contact.dart'; -import 'package:portfolio/src/utils/launch_url_helper.dart'; -import 'package:portfolio/src/utils/scaffold_messenger_helper.dart'; class ContactBar extends ConsumerWidget { const ContactBar({super.key, required this.contacts}); @@ -14,64 +12,8 @@ class ContactBar extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return Wrap( children: contacts.map((contact) { - final iconData = _getIconData(contact); - final contactTooltip = contact.tooltip; - final contactUrl = contact.url; - if (contactTooltip == null || contactUrl == null) { - return const SizedBox.shrink(); - } - return IconButton( - tooltip: contact.tooltip, - onPressed: () async { - try { - await LaunchUrlHelper.launchURL(contactUrl); - } catch (e) { - if (context.mounted) { - ScaffoldMessengerHelper.showLaunchUrlError( - context, - url: contactUrl, - ); - } - } - }, - icon: iconData != null - ? Icon(iconData) - : Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.link), - const SizedBox(width: 4), - Text(contactTooltip), - ], - ), - padding: iconData == null ? null : _fixGithubIconPadding(iconData), - ); + return ContactIconButton(contact: contact); }).toList(), ); } - - IconData? _getIconData(Contact contact) { - final contactIconCodePoint = contact.iconCodePoint; - final contactIconFontFamily = contact.iconFontFamily; - final contactIconFontPackage = contact.iconFontPackage; - if (contactIconCodePoint != null && - contactIconFontFamily != null && - contactIconFontPackage != null) { - final contactIconCodePointHexa = int.tryParse(contactIconCodePoint); - if (contactIconCodePointHexa != null) { - final iconData = IconData( - contactIconCodePointHexa, - fontFamily: contactIconFontFamily, - fontPackage: contactIconFontPackage, - ); - return iconData; - } - } - return null; - } - - EdgeInsetsGeometry? _fixGithubIconPadding(IconData iconData) { - if (iconData != FontAwesomeIcons.discord) return null; - return const EdgeInsets.only(right: 6); - } } diff --git a/lib/src/features/project/domain/project.dart b/lib/src/features/project/domain/project.dart index b3eb631..ba92676 100644 --- a/lib/src/features/project/domain/project.dart +++ b/lib/src/features/project/domain/project.dart @@ -1,4 +1,5 @@ import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:portfolio/src/common/domain/icon.dart'; import 'package:portfolio/src/common/domain/link.dart'; part 'project.freezed.dart'; @@ -10,9 +11,7 @@ class Project with _$Project { String? name, String? description, String? url, - String? iconCodePoint, - String? iconFontFamily, - String? iconFontPackage, + IconModel? icon, String? screenshotPath, List? technologies, List? links, diff --git a/lib/src/features/project/presentation/widgets/project_image.dart b/lib/src/features/project/presentation/widgets/project_image.dart index 119aba4..3fb933e 100644 --- a/lib/src/features/project/presentation/widgets/project_image.dart +++ b/lib/src/features/project/presentation/widgets/project_image.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:portfolio/src/constants/transparent_image.dart'; import 'package:portfolio/src/features/project/domain/project.dart'; +import 'package:portfolio/src/common/widgets/icon.dart'; class ProjectImage extends ConsumerWidget { const ProjectImage({ @@ -80,7 +81,11 @@ class ProjectImage extends ConsumerWidget { duration: const Duration(seconds: 1), reverseDuration: const Duration(milliseconds: 500), firstChild: const SizedBox.shrink(), - secondChild: _buildIcon(), + secondChild: MyIcon( + icon: project.icon, + color: Colors.white, + size: 32, + ), ), ), ), @@ -99,28 +104,4 @@ class ProjectImage extends ConsumerWidget { placeholderFit: BoxFit.cover, ); } - - Widget _buildIcon() { - final projectIconCodePoint = project.iconCodePoint; - final projectIconFontFamily = project.iconFontFamily; - final projectIconFontPackage = project.iconFontPackage; - if (projectIconCodePoint != null && - projectIconFontFamily != null && - projectIconFontPackage != null) { - final projectIconCodePointHexa = int.tryParse(projectIconCodePoint); - if (projectIconCodePointHexa != null) { - final iconData = IconData( - projectIconCodePointHexa, - fontFamily: projectIconFontFamily, - fontPackage: projectIconFontPackage, - ); - return Icon( - color: Colors.white, - size: 32, - iconData, - ); - } - } - return const SizedBox.shrink(); - } }