├── lib ├── src │ ├── theme │ │ ├── config.dart │ │ ├── theme_button.dart │ │ └── custom_theme.dart │ ├── html_open_link.dart │ ├── configure_web.dart │ ├── achievements │ │ ├── data.dart │ │ └── card.dart │ ├── education │ │ ├── data.dart │ │ └── card.dart │ ├── experience │ │ ├── data.dart │ │ └── card.dart │ ├── json_service.dart │ ├── contact_me │ │ ├── data.dart │ │ ├── contact_me_button.dart │ │ └── my_bio.dart │ ├── whatIDo │ │ ├── data.dart │ │ └── progress.dart │ ├── home │ │ ├── introduction.dart │ │ ├── resume.dart │ │ ├── about.dart │ │ ├── data.dart │ │ ├── my_name.dart │ │ ├── designation.dart │ │ └── social_media_bar.dart │ ├── custom │ │ └── custom_text.dart │ ├── nav_bar │ │ ├── title_bar.dart │ │ ├── nav_bar.dart │ │ └── nav_bar_btn.dart │ └── projects │ │ ├── data.dart │ │ └── card.dart ├── tabs │ ├── scroll_controller.dart │ ├── tabs.dart │ ├── achievements.dart │ ├── education.dart │ ├── projects.dart │ ├── experience.dart │ ├── home.dart │ ├── what_i_do.dart │ └── contact_me.dart ├── main.dart └── app.dart ├── assets ├── what_i_do │ ├── c.png │ ├── bash.png │ ├── cpp.png │ ├── git.png │ ├── java.png │ ├── linux.png │ ├── flutter.png │ ├── python.png │ └── constant │ │ ├── checklist.png │ │ └── checklist-light.png ├── experience │ ├── GDSC.png │ ├── ekko.png │ ├── credanic.png │ ├── rcctechz.png │ ├── opensource.png │ ├── coding-ninjas.png │ └── constant │ │ └── experience.png ├── education │ ├── gitaram.png │ ├── rcciit.png │ ├── stxaviers.png │ └── constant │ │ └── education.png ├── contact_me │ ├── picture.png │ └── constant │ │ ├── picture.png │ │ ├── location.png │ │ └── location-dark.png ├── home │ └── constant │ │ ├── email.png │ │ ├── github.png │ │ ├── link.png │ │ ├── medium.png │ │ ├── facebook.png │ │ ├── leetcode.png │ │ ├── linkedin.png │ │ ├── twitter.png │ │ ├── instagram.png │ │ └── stackoverflow.png ├── fonts │ ├── FjallaOne-Regular.ttf │ ├── Montserrat-Medium.ttf │ ├── SourceCodePro-SemiBold.ttf │ └── font_OFL │ │ ├── OFL-Montserrat.txt │ │ ├── OFL-FjallaOne.txt │ │ └── OFL-SourceCodePro.txt ├── projects │ └── constant │ │ ├── forks.png │ │ └── stars.png ├── achievements │ └── constant │ │ └── achievement.png ├── readme.md └── portfolio.json ├── .gitignore ├── .metadata ├── web ├── manifest.json ├── index.html └── style.css ├── pubspec.yaml ├── LICENSE ├── .github └── workflows │ └── build.yml ├── README.md └── analysis_options.yaml /lib/src/theme/config.dart: -------------------------------------------------------------------------------- 1 | import 'custom_theme.dart'; 2 | 3 | CustomTheme currentTheme = CustomTheme(); 4 | -------------------------------------------------------------------------------- /assets/what_i_do/c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/what_i_do/c.png -------------------------------------------------------------------------------- /assets/experience/GDSC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/experience/GDSC.png -------------------------------------------------------------------------------- /assets/experience/ekko.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/experience/ekko.png -------------------------------------------------------------------------------- /assets/what_i_do/bash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/what_i_do/bash.png -------------------------------------------------------------------------------- /assets/what_i_do/cpp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/what_i_do/cpp.png -------------------------------------------------------------------------------- /assets/what_i_do/git.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/what_i_do/git.png -------------------------------------------------------------------------------- /assets/what_i_do/java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/what_i_do/java.png -------------------------------------------------------------------------------- /assets/what_i_do/linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/what_i_do/linux.png -------------------------------------------------------------------------------- /assets/education/gitaram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/education/gitaram.png -------------------------------------------------------------------------------- /assets/education/rcciit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/education/rcciit.png -------------------------------------------------------------------------------- /assets/what_i_do/flutter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/what_i_do/flutter.png -------------------------------------------------------------------------------- /assets/what_i_do/python.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/what_i_do/python.png -------------------------------------------------------------------------------- /assets/contact_me/picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/contact_me/picture.png -------------------------------------------------------------------------------- /assets/education/stxaviers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/education/stxaviers.png -------------------------------------------------------------------------------- /assets/experience/credanic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/experience/credanic.png -------------------------------------------------------------------------------- /assets/experience/rcctechz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/experience/rcctechz.png -------------------------------------------------------------------------------- /assets/home/constant/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/home/constant/email.png -------------------------------------------------------------------------------- /assets/home/constant/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/home/constant/github.png -------------------------------------------------------------------------------- /assets/home/constant/link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/home/constant/link.png -------------------------------------------------------------------------------- /assets/home/constant/medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/home/constant/medium.png -------------------------------------------------------------------------------- /assets/experience/opensource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/experience/opensource.png -------------------------------------------------------------------------------- /assets/home/constant/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/home/constant/facebook.png -------------------------------------------------------------------------------- /assets/home/constant/leetcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/home/constant/leetcode.png -------------------------------------------------------------------------------- /assets/home/constant/linkedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/home/constant/linkedin.png -------------------------------------------------------------------------------- /assets/home/constant/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/home/constant/twitter.png -------------------------------------------------------------------------------- /assets/experience/coding-ninjas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/experience/coding-ninjas.png -------------------------------------------------------------------------------- /assets/fonts/FjallaOne-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/fonts/FjallaOne-Regular.ttf -------------------------------------------------------------------------------- /assets/fonts/Montserrat-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/fonts/Montserrat-Medium.ttf -------------------------------------------------------------------------------- /assets/home/constant/instagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/home/constant/instagram.png -------------------------------------------------------------------------------- /assets/projects/constant/forks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/projects/constant/forks.png -------------------------------------------------------------------------------- /assets/projects/constant/stars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/projects/constant/stars.png -------------------------------------------------------------------------------- /assets/contact_me/constant/picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/contact_me/constant/picture.png -------------------------------------------------------------------------------- /assets/home/constant/stackoverflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/home/constant/stackoverflow.png -------------------------------------------------------------------------------- /assets/contact_me/constant/location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/contact_me/constant/location.png -------------------------------------------------------------------------------- /assets/education/constant/education.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/education/constant/education.png -------------------------------------------------------------------------------- /assets/experience/constant/experience.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/experience/constant/experience.png -------------------------------------------------------------------------------- /assets/fonts/SourceCodePro-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/fonts/SourceCodePro-SemiBold.ttf -------------------------------------------------------------------------------- /assets/what_i_do/constant/checklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/what_i_do/constant/checklist.png -------------------------------------------------------------------------------- /lib/src/html_open_link.dart: -------------------------------------------------------------------------------- 1 | import 'dart:html' as html; 2 | 3 | void htmlOpenLink(String url) { 4 | html.window.open(url, '_blank'); 5 | } 6 | -------------------------------------------------------------------------------- /assets/achievements/constant/achievement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/achievements/constant/achievement.png -------------------------------------------------------------------------------- /assets/contact_me/constant/location-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/contact_me/constant/location-dark.png -------------------------------------------------------------------------------- /assets/what_i_do/constant/checklist-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danger-ahead/flutter_dev_folio/HEAD/assets/what_i_do/constant/checklist-light.png -------------------------------------------------------------------------------- /lib/src/configure_web.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_web_plugins/flutter_web_plugins.dart'; 2 | 3 | void configureApp() { 4 | setUrlStrategy(PathUrlStrategy()); 5 | } 6 | -------------------------------------------------------------------------------- /lib/tabs/scroll_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; 2 | 3 | final ItemScrollController scroll = ItemScrollController(); 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | _site/ 4 | .sass-cache/ 5 | .jekyll-cache/ 6 | .flutter-plugins 7 | .flutter-plugins-dependencies 8 | .packages 9 | 10 | /test/ 11 | /build/flutter_assets/ 12 | *.dill 13 | .dart_tool/ 14 | .dart_tool/package_config.json 15 | .dart_tool/package_config_subset 16 | /build/ 17 | pubspec.lock 18 | dotenv 19 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: f4abaa0735eba4dfd8f33f73363911d63931fe03 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /lib/src/achievements/data.dart: -------------------------------------------------------------------------------- 1 | import '../json_service.dart'; 2 | 3 | List> achievements() { 4 | final List> totalAchievements = []; 5 | final List temp = []; 6 | 7 | for (final k in JSONService.response['achievements'].values) { 8 | for (final l in k.values) temp.add(l.toString()); 9 | 10 | totalAchievements.add([...temp]); 11 | temp.clear(); 12 | } 13 | return totalAchievements; 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/education/data.dart: -------------------------------------------------------------------------------- 1 | import '../json_service.dart'; 2 | 3 | List> education() { 4 | final List> totalEducation = []; 5 | final List temp = []; 6 | 7 | for (final k in JSONService.response['education'].values) { 8 | for (final l in k.values) temp.add(l.toString()); 9 | 10 | if (temp[5] == '') temp[5] = 'constant/education.png'; 11 | totalEducation.add([...temp]); 12 | temp.clear(); 13 | } 14 | return totalEducation; 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/experience/data.dart: -------------------------------------------------------------------------------- 1 | import '../json_service.dart'; 2 | 3 | List> experience() { 4 | final List> totalExperience = []; 5 | final List temp = []; 6 | 7 | for (final k in JSONService.response['experience'].values) { 8 | for (final l in k.values) temp.add(l.toString()); 9 | 10 | if (temp[4] == '') temp[4] = 'constant/experience.png'; 11 | totalExperience.add([...temp]); 12 | temp.clear(); 13 | } 14 | return totalExperience; 15 | } 16 | -------------------------------------------------------------------------------- /assets/readme.md: -------------------------------------------------------------------------------- 1 | **NOTE: DO NOT CHANGE THE ASSETS UNDER `constant/` SUBDIRECTORIES IN EACH DIRECTORY** 2 | 3 | --- 4 | Some of the icons have been designed by: Freepik, Uniconlabs and Hight Quality Icons from www.flaticon.com 5 | -------------------------------------------------------------------------------- /lib/src/json_service.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/cupertino.dart'; 4 | import 'package:flutter/services.dart'; 5 | 6 | class JSONService extends ChangeNotifier { 7 | static late final String json; 8 | static late final response; 9 | static bool hasLoaded = false; 10 | 11 | init() async { 12 | json = await rootBundle.loadString('assets/portfolio.json'); 13 | response = jsonDecode(json); 14 | hasLoaded = true; 15 | notifyListeners(); 16 | } 17 | } 18 | 19 | JSONService jsonService = JSONService(); 20 | -------------------------------------------------------------------------------- /lib/src/contact_me/data.dart: -------------------------------------------------------------------------------- 1 | import '../json_service.dart'; 2 | 3 | List contactMe() { 4 | final List contactMeDetails = []; 5 | 6 | for (final k in JSONService.response['contact_me'].values) 7 | contactMeDetails.add(k.toString()); 8 | 9 | return contactMeDetails; 10 | } 11 | 12 | List nameAndLink() { 13 | return [ 14 | JSONService.response['name_and_link'][0].toString(), 15 | JSONService.response['name_and_link'][1].toString() 16 | ]; 17 | } 18 | 19 | String bio() { 20 | return JSONService.response['bio'].toString(); 21 | } 22 | -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shourya", 3 | "short_name": "shourya", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /lib/tabs/tabs.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'achievements.dart'; 4 | import 'contact_me.dart'; 5 | import 'education.dart'; 6 | import 'experience.dart'; 7 | import 'home.dart'; 8 | import 'projects.dart'; 9 | import 'what_i_do.dart'; 10 | 11 | export 'achievements.dart'; 12 | export 'contact_me.dart'; 13 | export 'education.dart'; 14 | export 'experience.dart'; 15 | export 'home.dart'; 16 | export 'projects.dart'; 17 | export 'scroll_controller.dart'; 18 | export 'what_i_do.dart'; 19 | 20 | List widgetList = [ 21 | const HomePage(), 22 | WhatIdo(), 23 | Education(), 24 | Experience(), 25 | Projects(), 26 | Achievements(), 27 | const ContactMe(), 28 | ]; 29 | -------------------------------------------------------------------------------- /lib/src/whatIDo/data.dart: -------------------------------------------------------------------------------- 1 | import '../json_service.dart'; 2 | 3 | List> whatIdo() { 4 | final proficiency = JSONService.response['what_i_do']['proficiency'].toList(); 5 | final tools = JSONService.response['what_i_do']['tools'].toList(); 6 | 7 | final List totalProficiency = []; 8 | final List totalTools = []; 9 | final List> total = []; 10 | 11 | for (int k = 0; k < int.parse(proficiency.length.toString()); k++) 12 | totalProficiency.add(proficiency[k].toString()); 13 | 14 | for (int k = 0; k < int.parse(tools.length.toString()); k++) 15 | totalTools.add(tools[k].toString()); 16 | 17 | total.add(totalProficiency); 18 | total.add(totalTools); 19 | 20 | return total; 21 | } 22 | -------------------------------------------------------------------------------- /lib/src/home/introduction.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Introduction extends StatelessWidget { 4 | const Introduction({ 5 | Key? key, 6 | required this.word, 7 | required this.textScaleFactor, 8 | }) : super(key: key); 9 | 10 | final String word; 11 | final double textScaleFactor; 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Padding( 16 | padding: const EdgeInsets.symmetric(horizontal: 12.0), 17 | child: Text( 18 | word, 19 | textScaler: TextScaler.linear(textScaleFactor), 20 | style: TextStyle( 21 | fontFamily: 'SourceCodePro', 22 | letterSpacing: 2, 23 | fontWeight: FontWeight.w500, 24 | color: Theme.of(context).primaryColorLight, 25 | ), 26 | ), 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/custom/custom_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CustomText extends StatelessWidget { 4 | const CustomText( 5 | {Key? key, 6 | required this.text, 7 | required this.fontSize, 8 | this.isTextAlignCenter = true, 9 | required this.color}) 10 | : super(key: key); 11 | 12 | final String text; 13 | final Color color; 14 | final double fontSize; 15 | final bool isTextAlignCenter; 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | return Text(text, 20 | textAlign: isTextAlignCenter ? TextAlign.center : TextAlign.left, 21 | style: TextStyle( 22 | fontFamily: 'Montserrat', 23 | letterSpacing: 2, 24 | fontSize: fontSize, 25 | color: color, 26 | fontWeight: FontWeight.w500, 27 | )); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/contact_me/contact_me_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../../tabs/contact_me.dart'; 3 | import '../custom/custom_text.dart'; 4 | import '../education/data.dart'; 5 | 6 | class ContactMeButton extends StatelessWidget { 7 | ContactMeButton({Key? key}) : super(key: key); 8 | 9 | final List> data = education(); 10 | @override 11 | Widget build(BuildContext context) { 12 | return Visibility( 13 | visible: data.isNotEmpty, 14 | child: TextButton( 15 | child: CustomText( 16 | text: 'CONTACT ME', 17 | fontSize: 20, 18 | color: Theme.of(context).primaryColor), 19 | onPressed: () => Navigator.push( 20 | context, 21 | MaterialPageRoute(builder: (context) => const ContactMe()), 22 | ), 23 | ), 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/nav_bar/title_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class TitleBar extends StatelessWidget { 4 | const TitleBar( 5 | {Key? key, 6 | required this.height, 7 | required this.width, 8 | required this.title}) 9 | : super(key: key); 10 | 11 | final double height, width; 12 | final String title; 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Container( 17 | padding: EdgeInsets.only(bottom: height * 0.04), 18 | color: Theme.of(context).scaffoldBackgroundColor, 19 | width: width * 0.9, 20 | alignment: Alignment.topLeft, 21 | child: Text( 22 | title, 23 | style: TextStyle( 24 | fontFamily: 'SourceCodePro', 25 | letterSpacing: 10.5, 26 | color: Theme.of(context).primaryColorLight, 27 | fontSize: 20), 28 | ), 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/theme/theme_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'config.dart'; 4 | 5 | class ThemeButton extends StatefulWidget { 6 | const ThemeButton({Key? key}) : super(key: key); 7 | @override 8 | ThemeButtonState createState() => ThemeButtonState(); 9 | } 10 | 11 | class ThemeButtonState extends State { 12 | @override 13 | Widget build(BuildContext context) { 14 | return IconButton( 15 | hoverColor: Colors.transparent, 16 | focusColor: Colors.transparent, 17 | splashColor: Colors.transparent, 18 | highlightColor: Colors.transparent, 19 | color: Theme.of(context).primaryColorLight, 20 | onPressed: () { 21 | currentTheme.toggleTheme(); 22 | setState(() {}); 23 | }, 24 | icon: currentTheme.currentTheme == ThemeMode.dark 25 | ? const Icon(Icons.wb_sunny) 26 | : const Icon(Icons.nightlight), 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/home/resume.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../custom/custom_text.dart'; 4 | import '../html_open_link.dart'; 5 | import 'data.dart'; 6 | 7 | class Resume extends StatelessWidget { 8 | Resume({ 9 | Key? key, 10 | required this.width, 11 | }) : super(key: key); 12 | 13 | final double width; 14 | 15 | final String data = resume(); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | return Padding( 20 | padding: data == '' 21 | ? EdgeInsets.zero 22 | : EdgeInsets.only(right: width * 0.019), 23 | child: Visibility( 24 | visible: data != '', 25 | child: TextButton( 26 | onPressed: () => htmlOpenLink(data), 27 | child: CustomText( 28 | text: 'MY RESUME', 29 | fontSize: 20, 30 | color: Theme.of(context).primaryColor)), 31 | )); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/home/about.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'data.dart'; 3 | 4 | class About extends StatelessWidget { 5 | About({ 6 | Key? key, 7 | required this.fontSize, 8 | }) : super(key: key); 9 | 10 | final double fontSize; 11 | final String gotAbout = about(); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Padding( 16 | padding: const EdgeInsets.fromLTRB(12.0, 5.0, 12.0, 30.0), 17 | child: Column( 18 | children: [ 19 | Padding( 20 | padding: const EdgeInsets.only(top: 30.0), 21 | child: Text( 22 | gotAbout, 23 | style: TextStyle( 24 | fontFamily: 'SourceCodePro', 25 | letterSpacing: 2.5, 26 | color: Theme.of(context).primaryColorLight, 27 | fontSize: fontSize), 28 | ), 29 | ), 30 | ], 31 | ), 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/src/theme/custom_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CustomTheme extends ChangeNotifier { 4 | bool isDarkTheme = true; 5 | ThemeMode get currentTheme => isDarkTheme ? ThemeMode.dark : ThemeMode.light; 6 | 7 | void toggleTheme() { 8 | isDarkTheme = !isDarkTheme; 9 | notifyListeners(); 10 | } 11 | 12 | static ThemeData get lightTheme { 13 | return ThemeData( 14 | scaffoldBackgroundColor: Colors.white, 15 | hoverColor: const Color(0xFF1a4b6e).withOpacity(0.225), 16 | cardColor: const Color(0xFF519259), 17 | primaryColor: const Color(0xFF064635), 18 | primaryColorDark: Colors.white54, 19 | primaryColorLight: Colors.black, 20 | ); 21 | } 22 | 23 | static ThemeData get darkTheme { 24 | return ThemeData( 25 | scaffoldBackgroundColor: const Color(0xFF171c28), 26 | hoverColor: const Color(0xFF1a4b6e), 27 | cardColor: const Color(0xFF10576e), 28 | primaryColor: const Color(0xFF02bbe5), 29 | primaryColorDark: const Color(0xFF6c7582), 30 | primaryColorLight: Colors.white, 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/contact_me/my_bio.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'data.dart'; 3 | 4 | class MyBio extends StatelessWidget { 5 | MyBio({ 6 | Key? key, 7 | required this.fontSize, 8 | }) : super(key: key); 9 | 10 | final double fontSize; 11 | final String getBio = bio(); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return (getBio == '') 16 | ? const Center() 17 | : Padding( 18 | padding: const EdgeInsets.fromLTRB(12.0, 5.0, 12.0, 30.0), 19 | child: Column( 20 | children: [ 21 | Padding( 22 | padding: const EdgeInsets.only(top: 30.0), 23 | child: Text( 24 | '"$getBio"', 25 | style: TextStyle( 26 | fontFamily: 'SourceCodePro', 27 | letterSpacing: 2, 28 | color: Theme.of(context).primaryColorLight, 29 | fontSize: fontSize), 30 | ), 31 | ), 32 | ], 33 | ), 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/home/data.dart: -------------------------------------------------------------------------------- 1 | import '../json_service.dart'; 2 | 3 | String about() { 4 | return JSONService.response['about'].toString(); 5 | } 6 | 7 | String resume() { 8 | return JSONService.response['resume_download_link'].toString(); 9 | } 10 | 11 | String name() { 12 | return JSONService.response['name_and_link'][0].toString(); 13 | } 14 | 15 | List designation() { 16 | final List result = []; 17 | 18 | for (int i = 0; 19 | i < 20 | int.parse( 21 | JSONService.response['designation'].toList().length.toString()); 22 | i++) 23 | result.add(JSONService.response['designation'].toList()[i].toString()); 24 | return result; 25 | } 26 | 27 | List> socialMedia() { 28 | final List> result = []; 29 | 30 | final List temp = []; 31 | 32 | for (final k in JSONService.response['social_media'].keys) { 33 | for (int i = 0; 34 | i < 35 | int.parse( 36 | JSONService.response['social_media'][k].length.toString()); 37 | i++) { 38 | temp.add(JSONService.response['social_media'][k][i].toString()); 39 | } 40 | result.add([...temp]); 41 | temp.clear(); 42 | } 43 | 44 | return result; 45 | } 46 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'app.dart'; 3 | import 'src/configure_web.dart'; 4 | import 'src/json_service.dart'; 5 | import 'src/theme/config.dart'; 6 | import 'src/theme/custom_theme.dart'; 7 | 8 | void main() { 9 | configureApp(); 10 | runApp(const MyApp()); 11 | } 12 | 13 | class MyApp extends StatefulWidget { 14 | const MyApp({Key? key}) : super(key: key); 15 | @override 16 | _MyAppState createState() => _MyAppState(); 17 | } 18 | 19 | class _MyAppState extends State { 20 | @override 21 | void initState() { 22 | super.initState(); 23 | currentTheme.addListener(() { 24 | setState(() {}); 25 | }); 26 | jsonService.init(); 27 | jsonService.addListener(() { 28 | setState(() {}); 29 | }); 30 | } 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | return JSONService.hasLoaded == true 35 | ? MaterialApp( 36 | debugShowCheckedModeBanner: false, 37 | theme: CustomTheme.lightTheme, 38 | darkTheme: CustomTheme.darkTheme, 39 | themeMode: currentTheme.currentTheme, 40 | home: const App(), 41 | ) 42 | : const Center(child: CircularProgressIndicator()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_dev_folio 2 | description: portfolio 3 | 4 | publish_to: 'none' 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: ">=2.12.0 <3.0.0" 10 | 11 | dependencies: 12 | flutter_web_plugins: 13 | sdk: flutter 14 | flutter: 15 | sdk: flutter 16 | cupertino_icons: ^1.0.2 17 | http: ^0.13.4 18 | scrollable_positioned_list: ^0.2.3 19 | 20 | dev_dependencies: 21 | flutter_test: 22 | sdk: flutter 23 | 24 | flutter: 25 | uses-material-design: true 26 | 27 | fonts: 28 | - family: SourceCodePro 29 | fonts: 30 | - asset: assets/fonts/SourceCodePro-SemiBold.ttf 31 | - family: FjallaOne 32 | fonts: 33 | - asset: assets/fonts/FjallaOne-Regular.ttf 34 | - family: Montserrat 35 | fonts: 36 | - asset: assets/fonts/Montserrat-Medium.ttf 37 | 38 | assets: 39 | - assets/home/ 40 | - assets/home/constant/ 41 | - assets/what_i_do/ 42 | - assets/what_i_do/constant/ 43 | - assets/experience/ 44 | - assets/experience/constant/ 45 | - assets/contact_me/ 46 | - assets/contact_me/constant/ 47 | - assets/education/ 48 | - assets/education/constant/ 49 | - assets/projects/ 50 | - assets/projects/constant/ 51 | - assets/achievements/ 52 | - assets/portfolio.json 53 | - dotenv 54 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021, SHOURYA SHIKHAR GHOSH 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /lib/src/home/my_name.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'data.dart'; 3 | 4 | class MyName extends StatelessWidget { 5 | MyName({ 6 | Key? key, 7 | required this.isMobile, 8 | required this.context, 9 | }) : super(key: key); 10 | 11 | final bool isMobile; 12 | final BuildContext context; 13 | final String data = name(); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | final double width = MediaQuery.of(context).size.width; 18 | return Padding( 19 | padding: const EdgeInsets.symmetric(horizontal: 12.0), 20 | child: isMobile 21 | ? Column( 22 | crossAxisAlignment: CrossAxisAlignment.start, 23 | children: List.generate(data.split(' ').length, (int i) { 24 | return SizedBox( 25 | width: width - width * 0.4, 26 | child: FittedBox( 27 | fit: BoxFit.cover, 28 | child: Text( 29 | data.split(' ')[i], 30 | textScaler: const TextScaler.linear(4.5), 31 | style: TextStyle( 32 | fontFamily: 'FjallaOne', 33 | // letterSpacing: 10.5, 34 | fontWeight: FontWeight.w500, 35 | color: Theme.of(context).primaryColor, 36 | ), 37 | ), 38 | ), 39 | ); 40 | })) 41 | : Text(data, 42 | textScaler: const TextScaler.linear(7), 43 | style: TextStyle( 44 | fontFamily: 'FjallaOne', 45 | letterSpacing: 20.5, 46 | color: Theme.of(context).primaryColor, 47 | fontWeight: FontWeight.w500, 48 | ))); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/app.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; 3 | 4 | import 'src/nav_bar/nav_bar.dart'; 5 | import 'src/theme/theme_button.dart'; 6 | import 'tabs/tabs.dart'; 7 | 8 | class App extends StatelessWidget { 9 | const App({Key? key}) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | final double height = MediaQuery.of(context).size.height; 14 | final double width = MediaQuery.of(context).size.width; 15 | return LayoutBuilder(builder: (context, constraints) { 16 | if (constraints.maxWidth < 1000) { 17 | return Scaffold( 18 | floatingActionButton: FloatingActionButton( 19 | onPressed: () {}, 20 | backgroundColor: Theme.of(context).scaffoldBackgroundColor, 21 | child: const ThemeButton(), 22 | ), 23 | body: ScrollablePositionedList.builder( 24 | physics: const BouncingScrollPhysics(), 25 | minCacheExtent: double.infinity, 26 | shrinkWrap: true, 27 | itemCount: 7, 28 | itemScrollController: scroll, 29 | itemBuilder: (context, index) { 30 | return widgetList[index]; 31 | }), 32 | ); 33 | } else { 34 | return Scaffold( 35 | appBar: PreferredSize( 36 | preferredSize: Size(width, height * 0.07), 37 | child: const NavBar(isDarkModeBtnVisible: true)), 38 | body: ScrollablePositionedList.builder( 39 | physics: const BouncingScrollPhysics(), 40 | minCacheExtent: double.infinity, 41 | shrinkWrap: true, 42 | itemCount: 7, 43 | itemScrollController: scroll, 44 | itemBuilder: (context, index) { 45 | return widgetList[index]; 46 | }), 47 | ); 48 | } 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Deploy 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout repository 14 | uses: actions/checkout@v2 15 | 16 | - name: Check if dotenv exists 17 | run: | 18 | if [[ -f dotenv ]]; then 19 | echo "Already present, ignoring." 20 | else 21 | : > dotenv 22 | fi 23 | 24 | - name: Set up Flutter 25 | uses: subosito/flutter-action@v2 26 | with: 27 | channel: "stable" 28 | flutter-version: 3.22.0 29 | 30 | - name: Get dependencies 31 | run: flutter pub get 32 | 33 | - name: Run analyze 34 | run: flutter analyze . 35 | 36 | - name: Build release 37 | run: flutter build web --web-renderer html --release 38 | 39 | - name: Upload artifacts 40 | uses: actions/upload-artifact@v1 41 | with: 42 | name: build 43 | path: build 44 | 45 | deploy-build: 46 | needs: build 47 | 48 | runs-on: ubuntu-latest 49 | 50 | steps: 51 | - name: Clone the repoitory 52 | uses: actions/checkout@v2 53 | with: 54 | ref: master-deploy 55 | 56 | - name: Configure git 57 | run: | 58 | git config --global user.email ${GITHUB_ACTOR}@gmail.com 59 | git config --global user.name ${GITHUB_ACTOR} 60 | 61 | - name: Download website build 62 | uses: actions/download-artifact@v1 63 | with: 64 | name: build 65 | path: build 66 | 67 | - name: Commit and Push 68 | run: | 69 | if [ $(git status --porcelain=v1 2>/dev/null | wc -l) != "0" ] ; then 70 | git add -f . 71 | git commit -m "gh-actions deployed a new build" 72 | git push --force https://github.com/${GITHUB_REPOSITORY}.git HEAD:master-deploy 73 | fi 74 | -------------------------------------------------------------------------------- /lib/src/nav_bar/nav_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../theme/theme_button.dart'; 4 | import 'nav_bar_btn.dart'; 5 | 6 | //The top Nav Bar 7 | class NavBar extends StatelessWidget { 8 | const NavBar({ 9 | Key? key, 10 | required this.isDarkModeBtnVisible, 11 | }) : super(key: key); 12 | 13 | final bool isDarkModeBtnVisible; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return Container( 18 | color: Theme.of(context).scaffoldBackgroundColor, 19 | child: Row( 20 | mainAxisAlignment: MainAxisAlignment.spaceAround, 21 | children: [ 22 | UnderlinedButton( 23 | context: context, 24 | tabNumber: 0, 25 | btnNumber: ' 00. ', 26 | btnName: 'Home'), 27 | UnderlinedButton( 28 | context: context, 29 | tabNumber: 1, 30 | btnNumber: ' 01. ', 31 | btnName: 'What I Do'), 32 | UnderlinedButton( 33 | context: context, 34 | tabNumber: 2, 35 | btnNumber: ' 02. ', 36 | btnName: 'Education'), 37 | UnderlinedButton( 38 | context: context, 39 | tabNumber: 3, 40 | btnNumber: ' 03. ', 41 | btnName: 'Experience'), 42 | UnderlinedButton( 43 | context: context, 44 | tabNumber: 4, 45 | btnNumber: ' 04. ', 46 | btnName: 'Projects'), 47 | UnderlinedButton( 48 | context: context, 49 | tabNumber: 5, 50 | btnNumber: ' 05. ', 51 | btnName: 'Achievements'), 52 | UnderlinedButton( 53 | context: context, 54 | tabNumber: 6, 55 | btnNumber: ' 06. ', 56 | btnName: 'Contact Me'), 57 | Visibility( 58 | visible: isDarkModeBtnVisible, 59 | child: const ThemeButton(), 60 | ) 61 | ], 62 | ), 63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/src/home/designation.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../custom/custom_text.dart'; 4 | import 'data.dart'; 5 | 6 | class Designation extends StatelessWidget { 7 | Designation({ 8 | Key? key, 9 | required this.isMobile, 10 | required this.context, 11 | }) : super(key: key); 12 | 13 | final bool isMobile; 14 | final BuildContext context; 15 | final List data = designation(); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | return Row( 20 | children: [ 21 | Icon( 22 | Icons.play_arrow_rounded, 23 | color: Theme.of(context).primaryColorLight, 24 | size: isMobile ? 50 : 60, 25 | ), 26 | TextSwapController( 27 | data: data, 28 | isMobile: isMobile, 29 | ), 30 | ], 31 | ); 32 | } 33 | } 34 | 35 | class TextSwapController extends StatefulWidget { 36 | const TextSwapController({ 37 | Key? key, 38 | required this.data, 39 | required this.isMobile, 40 | }) : super(key: key); 41 | 42 | final List data; 43 | final bool isMobile; 44 | 45 | @override 46 | _TextSwapControllerState createState() => _TextSwapControllerState(); 47 | } 48 | 49 | class _TextSwapControllerState extends State { 50 | @override 51 | void initState() { 52 | super.initState(); 53 | _timer(); 54 | } 55 | 56 | @override 57 | void dispose() { 58 | super.dispose(); 59 | _timer(); 60 | } 61 | 62 | void _timer() { 63 | Future.delayed(const Duration(seconds: 1)).then((_) { 64 | if (mounted) setState(() {}); 65 | _timer(); 66 | }); 67 | } 68 | 69 | int i = 0; 70 | @override 71 | Widget build(BuildContext context) { 72 | if (widget.data.length == i) i = 0; 73 | return CustomText( 74 | text: widget.isMobile 75 | ? widget.data[i++].replaceAll(' ', '\n') 76 | : widget.data[i++], 77 | isTextAlignCenter: false, 78 | fontSize: widget.isMobile ? 40 : 60, 79 | color: Theme.of(context).primaryColorLight); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lib/tabs/achievements.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../src/achievements/card.dart'; 4 | import '../src/achievements/data.dart'; 5 | import '../src/nav_bar/title_bar.dart'; 6 | 7 | class Achievements extends StatelessWidget { 8 | Achievements({Key? key}) : super(key: key); 9 | 10 | final List> data = achievements(); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | final double width = MediaQuery.of(context).size.width; 15 | final double height = MediaQuery.of(context).size.height; 16 | 17 | return Column(children: [ 18 | TitleBar(height: height, width: width, title: 'ACHIEVEMENTS'), 19 | Padding( 20 | padding: EdgeInsets.only(bottom: height * 0.1), 21 | child: LayoutBuilder( 22 | builder: (BuildContext context, BoxConstraints constraints) { 23 | if (constraints.maxWidth < 1000) { 24 | return Column( 25 | children: List.generate(data.length, (int i) { 26 | return Container( 27 | padding: EdgeInsets.fromLTRB(30.0, 0.0, 30.0, height * 0.05), 28 | child: AchievementsCard( 29 | desc: data[i][0], 30 | link: data[i][1], 31 | isMobile: true, 32 | ), 33 | ); 34 | }), 35 | ); 36 | } else { 37 | int storage = -1; 38 | return Column( 39 | children: List.generate( 40 | data.length % 3 == 0 ? data.length ~/ 3 : data.length ~/ 3 + 1, 41 | (int i) => Padding( 42 | padding: EdgeInsets.only(bottom: width * 0.03), 43 | child: Row( 44 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 45 | children: List.generate( 46 | (data.length - storage - 1) >= 3 47 | ? 3 48 | : data.length - storage - 1, (int index) { 49 | storage = index + i * 3; 50 | return AchievementsCard( 51 | desc: data[index + i * 3][0], 52 | link: data[index + i * 3][1], 53 | isMobile: false, 54 | ); 55 | }), 56 | ), 57 | ), 58 | ), 59 | ); 60 | } 61 | }), 62 | ) 63 | ]); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/tabs/education.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../src/education/card.dart'; 4 | import '../src/education/data.dart'; 5 | import '../src/nav_bar/title_bar.dart'; 6 | 7 | class Education extends StatelessWidget { 8 | Education({Key? key}) : super(key: key); 9 | 10 | final List> data = education(); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | final double width = MediaQuery.of(context).size.width; 15 | final double height = MediaQuery.of(context).size.height; 16 | 17 | return Column(children: [ 18 | TitleBar(height: height, width: width, title: 'EDUCATION'), 19 | Padding( 20 | padding: EdgeInsets.only(bottom: height * 0.1), 21 | child: LayoutBuilder( 22 | builder: (BuildContext context, BoxConstraints constraints) { 23 | if (constraints.maxWidth < 1000) { 24 | return Column( 25 | children: List.generate( 26 | data.length, 27 | (int i) => Padding( 28 | padding: EdgeInsets.only( 29 | left: 30.0, right: 30.0, bottom: height * 0.05), 30 | child: EducationDesktop( 31 | instiution: data[i][0], 32 | location: data[i][1], 33 | desc: data[i][3], 34 | grades: data[i][4], 35 | years: data[i][2], 36 | image: data[i][5], 37 | ), 38 | ), 39 | ), 40 | ); 41 | } else { 42 | return Row( 43 | mainAxisAlignment: MainAxisAlignment.center, 44 | children: [ 45 | SizedBox( 46 | width: width * 0.8, 47 | child: Column( 48 | children: List.generate( 49 | data.length, 50 | (int i) => Padding( 51 | padding: EdgeInsets.only(bottom: height * 0.025), 52 | child: EducationDesktop( 53 | instiution: data[i][0], 54 | location: data[i][1], 55 | desc: data[i][3], 56 | grades: data[i][4], 57 | years: data[i][2], 58 | image: data[i][5], 59 | ), 60 | ), 61 | ), 62 | ), 63 | ), 64 | ], 65 | ); 66 | } 67 | }), 68 | ) 69 | ]); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/tabs/projects.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../src/nav_bar/title_bar.dart'; 4 | import '../src/projects/card.dart'; 5 | import '../src/projects/data.dart'; 6 | 7 | class Projects extends StatelessWidget { 8 | Projects({Key? key}) : super(key: key); 9 | 10 | final List> data = projects(); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | final double width = MediaQuery.of(context).size.width; 15 | final double height = MediaQuery.of(context).size.height; 16 | return Column(children: [ 17 | TitleBar(height: height, width: width, title: 'PROJECTS'), 18 | Padding( 19 | padding: EdgeInsets.only(bottom: height * 0.1), 20 | child: LayoutBuilder( 21 | builder: (BuildContext context, BoxConstraints constraints) { 22 | if (constraints.maxWidth < 1000) { 23 | return Column( 24 | children: List.generate(data.length, (int i) { 25 | return Container( 26 | padding: EdgeInsets.fromLTRB(30.0, 0.0, 30.0, height * 0.05), 27 | child: ProjectsCard( 28 | title: data[i][0], 29 | techStack: data[i][1], 30 | desc: data[i][2], 31 | link: data[i][3], 32 | isMobile: true, 33 | ), 34 | ); 35 | }), 36 | ); 37 | } else { 38 | int storage = -1; 39 | return Column( 40 | children: List.generate( 41 | data.length % 3 == 0 ? data.length ~/ 3 : data.length ~/ 3 + 1, 42 | (int i) => Padding( 43 | padding: EdgeInsets.only(bottom: width * 0.03), 44 | child: Row( 45 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 46 | children: List.generate( 47 | (data.length - storage - 1) >= 3 48 | ? 3 49 | : data.length - storage - 1, (int index) { 50 | storage = index + i * 3; 51 | return ProjectsCard( 52 | title: data[index + i * 3][0], 53 | techStack: data[index + i * 3][1], 54 | desc: data[index + i * 3][2], 55 | link: data[index + i * 3][3], 56 | isMobile: false, 57 | ); 58 | }), 59 | ), 60 | ), 61 | ), 62 | ); 63 | } 64 | }), 65 | ) 66 | ]); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lib/src/achievements/card.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../custom/custom_text.dart'; 4 | import '../html_open_link.dart'; 5 | import '../theme/config.dart'; 6 | 7 | class AchievementsCard extends StatefulWidget { 8 | const AchievementsCard( 9 | {Key? key, 10 | required this.desc, 11 | required this.isMobile, 12 | required this.link}) 13 | : super(key: key); 14 | 15 | final String desc, link; 16 | final bool isMobile; 17 | @override 18 | _AchievementsCardState createState() => _AchievementsCardState(); 19 | } 20 | 21 | class _AchievementsCardState extends State { 22 | bool isHover = false; 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | final double height = MediaQuery.of(context).size.height; 27 | final double width = MediaQuery.of(context).size.width; 28 | return AnimatedContainer( 29 | decoration: BoxDecoration( 30 | boxShadow: [ 31 | BoxShadow( 32 | color: isHover ? Colors.black12 : Colors.black45, 33 | blurRadius: 10.0, 34 | offset: const Offset(8, 12), 35 | ) 36 | ], 37 | ), 38 | duration: const Duration(milliseconds: 200), 39 | padding: EdgeInsets.only( 40 | top: isHover ? height * 0.005 : height * 0.01, 41 | bottom: !isHover ? height * 0.005 : height * 0.01), 42 | child: InkWell( 43 | onHover: (bool value) { 44 | setState(() { 45 | isHover = value; 46 | }); 47 | }, 48 | onTap: () => htmlOpenLink(widget.link), 49 | child: Container( 50 | alignment: Alignment.topCenter, 51 | padding: EdgeInsets.only( 52 | top: height * 0.04, 53 | left: width * 0.015, 54 | right: width * 0.015, 55 | bottom: height * 0.04), 56 | width: !widget.isMobile ? width * 0.28 : width, 57 | decoration: BoxDecoration( 58 | boxShadow: [ 59 | BoxShadow( 60 | color: isHover ? Colors.black12 : Colors.black45, 61 | blurRadius: 10.0, 62 | offset: const Offset(8, 12), 63 | ) 64 | ], 65 | color: currentTheme.currentTheme == ThemeMode.dark 66 | ? Theme.of(context).cardColor 67 | : Theme.of(context).primaryColor, 68 | borderRadius: BorderRadius.circular( 69 | 5.0, 70 | ), 71 | ), 72 | child: Center( 73 | child: SingleChildScrollView( 74 | child: CustomText( 75 | text: widget.desc, fontSize: 18, color: Colors.white))), 76 | ), 77 | ), 78 | ); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /lib/src/projects/data.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/services.dart'; 4 | import 'package:http/http.dart' as http; 5 | 6 | import '../json_service.dart'; 7 | 8 | //checking if dotenv starts with "ghp" 9 | //https://github.blog/changelog/2021-03-31-authentication-token-format-updates-are-generally-available/#:~:text=ghp_%20for%20Personal%20Access%20Tokens 10 | 11 | List> projects() { 12 | final List> totalProjects = []; 13 | final List temp = []; 14 | 15 | for (final k in JSONService.response['projects'].values) { 16 | for (final l in k.values) temp.add(l.toString()); 17 | 18 | totalProjects.add([...temp]); 19 | temp.clear(); 20 | } 21 | return totalProjects; 22 | } 23 | 24 | Future> starsAndForks(String repo) async { 25 | final String loadDotenv = await rootBundle.loadString('dotenv'); 26 | final List words = repo.split('/'); 27 | http.Response response; 28 | if (loadDotenv.startsWith('ghp')) { 29 | response = await http.get( 30 | Uri.https('api.github.com', 31 | 'repos/${words[words.length - 2]}/${words[words.length - 1]}'), 32 | headers: { 33 | 'Authorization': 'Bearer $loadDotenv', 34 | }, 35 | ); 36 | } else { 37 | response = await http.get( 38 | Uri.https('api.github.com', 39 | 'repos/${words[words.length - 2]}/${words[words.length - 1]}'), 40 | ); 41 | } 42 | final information = jsonDecode(response.body); 43 | 44 | final List starsForks = [ 45 | information['stargazers_count'].toString(), 46 | information['forks'].toString() 47 | ]; 48 | 49 | return starsForks; 50 | } 51 | 52 | Future> github(String repo) async { 53 | final String loadDotenv = await rootBundle.loadString('dotenv'); 54 | final List words = repo.split('/'); 55 | http.Response response; 56 | if (loadDotenv.startsWith('ghp')) { 57 | response = await http.get( 58 | Uri.https( 59 | 'api.github.com', 'repos/danger-ahead/${words[words.length - 1]}'), 60 | headers: { 61 | 'Authorization': 'Bearer $loadDotenv', 62 | }, 63 | ); 64 | } else { 65 | response = await http.get( 66 | Uri.https( 67 | 'api.github.com', 'repos/danger-ahead/${words[words.length - 1]}'), 68 | ); 69 | } 70 | final information = jsonDecode(response.body); 71 | 72 | final List starsForks = [ 73 | information['full_name'] 74 | .toString() 75 | .split('/')[information['full_name'].toString().split('/').length - 1], 76 | information['language'].toString(), 77 | information['description'].toString(), 78 | information['stargazers_count'].toString(), 79 | information['forks'].toString() 80 | ]; 81 | 82 | return starsForks; 83 | } 84 | -------------------------------------------------------------------------------- /lib/tabs/experience.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../src/experience/card.dart'; 4 | import '../src/experience/data.dart'; 5 | import '../src/nav_bar/title_bar.dart'; 6 | 7 | class Experience extends StatelessWidget { 8 | Experience({Key? key}) : super(key: key); 9 | 10 | final List> data = experience(); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | final double width = MediaQuery.of(context).size.width; 15 | final double height = MediaQuery.of(context).size.height; 16 | return Column(children: [ 17 | TitleBar(height: height, width: width, title: 'EXPERIENCE'), 18 | Padding( 19 | padding: EdgeInsets.only(bottom: height * 0.1), 20 | child: LayoutBuilder( 21 | builder: (BuildContext context, BoxConstraints constraints) { 22 | if (constraints.maxWidth < 1000) { 23 | return Column( 24 | children: List.generate(data.length, (int i) { 25 | return Padding( 26 | padding: EdgeInsets.only( 27 | left: 30.0, right: 30.0, bottom: height * 0.05), 28 | child: ExperienceCard( 29 | image: data[i][4], 30 | title: data[i][0], 31 | role: data[i][1], 32 | period: data[i][2], 33 | desc: data[i][3], 34 | isMobile: true, 35 | ), 36 | ); 37 | }), 38 | ); 39 | } else { 40 | int storage = -1; 41 | return Column( 42 | children: List.generate( 43 | data.length % 3 == 0 ? data.length ~/ 3 : data.length ~/ 3 + 1, 44 | (int i) => Padding( 45 | padding: EdgeInsets.only(bottom: width * 0.03), 46 | child: Row( 47 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 48 | children: List.generate( 49 | (data.length - storage - 1) >= 3 50 | ? 3 51 | : data.length - storage - 1, (int index) { 52 | storage = index + i * 3; 53 | return ExperienceCard( 54 | image: data[index + i * 3][4], 55 | title: data[index + i * 3][0], 56 | role: data[index + i * 3][1], 57 | period: data[index + i * 3][2], 58 | desc: data[index + i * 3][3], 59 | isMobile: false, 60 | ); 61 | }), 62 | ), 63 | ), 64 | ), 65 | ); 66 | } 67 | }), 68 | ) 69 | ]); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/src/whatIDo/progress.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../custom/custom_text.dart'; 4 | 5 | class Progress extends StatefulWidget { 6 | const Progress( 7 | {Key? key, 8 | required this.width, 9 | required this.widthSecondContainer, 10 | required this.title, 11 | required this.sizeProficiencyName, 12 | required this.sizePercentage}) 13 | : super(key: key); 14 | @override 15 | _ProgressState createState() => _ProgressState(); 16 | 17 | final double width, widthSecondContainer, sizeProficiencyName, sizePercentage; 18 | final String title; 19 | } 20 | 21 | class _ProgressState extends State 22 | with SingleTickerProviderStateMixin { 23 | late AnimationController animationController; 24 | 25 | @override 26 | void initState() { 27 | animationController = AnimationController( 28 | vsync: this, 29 | duration: const Duration(seconds: 2), 30 | upperBound: widget.widthSecondContainer / 100, 31 | ); 32 | animationController.addListener(() { 33 | setState(() {}); 34 | }); 35 | animationController.forward(); 36 | super.initState(); 37 | } 38 | 39 | @override 40 | void dispose() { 41 | animationController.dispose(); 42 | super.dispose(); 43 | } 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | final double percentage = animationController.value * 100; 48 | return FittedBox( 49 | fit: BoxFit.cover, 50 | child: Padding( 51 | padding: const EdgeInsets.only( 52 | top: 15.0, 53 | ), 54 | child: Column( 55 | children: [ 56 | SizedBox( 57 | width: widget.width / 1.2, 58 | child: Row( 59 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 60 | children: [ 61 | CustomText( 62 | text: widget.title, 63 | fontSize: widget.sizeProficiencyName, 64 | color: Theme.of(context).primaryColorLight), 65 | CustomText( 66 | text: '${percentage.toStringAsFixed(0)}%', 67 | fontSize: widget.sizePercentage, 68 | color: Theme.of(context).primaryColorLight) 69 | ], 70 | ), 71 | ), 72 | SizedBox( 73 | width: widget.width / 1.2, 74 | height: 20, 75 | child: ClipRRect( 76 | borderRadius: const BorderRadius.all(Radius.circular(20)), 77 | child: LinearProgressIndicator( 78 | value: animationController.value, 79 | valueColor: 80 | AlwaysStoppedAnimation(Theme.of(context).cardColor), 81 | backgroundColor: Theme.of(context).cardColor.withOpacity(0.5), 82 | ), 83 | ), 84 | ), 85 | ], 86 | ), 87 | ), 88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /lib/src/nav_bar/nav_bar_btn.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../tabs/tabs.dart'; 4 | 5 | TextStyle textStyle(double fontSize, Color color) => TextStyle( 6 | fontFamily: 'Montserrat', 7 | fontSize: fontSize, 8 | color: color, 9 | fontWeight: FontWeight.bold, 10 | ); 11 | 12 | //The buttons in the top Nav Bar 13 | class UnderlinedButton extends StatefulWidget { 14 | const UnderlinedButton( 15 | {Key? key, 16 | required this.context, 17 | required this.btnName, 18 | required this.btnNumber, 19 | required this.tabNumber}) 20 | : super(key: key); 21 | 22 | @override 23 | _UnderlinedButtonState createState() => _UnderlinedButtonState(); 24 | 25 | final BuildContext context; 26 | final String btnName, btnNumber; 27 | final int tabNumber; 28 | } 29 | 30 | class _UnderlinedButtonState extends State { 31 | bool _isHover = false; 32 | @override 33 | Widget build(BuildContext context) { 34 | return InkWell( 35 | borderRadius: BorderRadius.circular(5.0), 36 | hoverColor: Colors.transparent, 37 | onTap: () => scroll.scrollTo( 38 | index: widget.tabNumber, 39 | duration: const Duration(milliseconds: 2000)), 40 | onHover: (bool value) => setState(() => _isHover = value), 41 | child: SizedBox( 42 | width: MediaQuery.of(context).size.width * 0.13, 43 | child: Column( 44 | mainAxisAlignment: MainAxisAlignment.center, 45 | crossAxisAlignment: CrossAxisAlignment.start, 46 | children: [ 47 | Container( 48 | alignment: Alignment.topRight, 49 | child: Visibility( 50 | visible: _isHover, 51 | child: Container( 52 | height: MediaQuery.of(context).size.height * 0.004, 53 | width: MediaQuery.of(context).size.width * 0.045, 54 | decoration: BoxDecoration( 55 | color: Theme.of(context).primaryColor, 56 | borderRadius: BorderRadius.circular(50), 57 | ), 58 | ), 59 | ), 60 | ), 61 | Row( 62 | mainAxisAlignment: MainAxisAlignment.center, 63 | children: [ 64 | Text(widget.btnNumber, 65 | style: textStyle(11, Theme.of(context).primaryColorLight)), 66 | Text(widget.btnName, 67 | style: textStyle(15, Theme.of(context).primaryColor)), 68 | ], 69 | ), 70 | Visibility( 71 | visible: _isHover, 72 | child: Container( 73 | height: MediaQuery.of(context).size.height * 0.004, 74 | width: MediaQuery.of(context).size.width * 0.045, 75 | decoration: BoxDecoration( 76 | color: Theme.of(context).primaryColor, 77 | borderRadius: BorderRadius.circular(50), 78 | ), 79 | ), 80 | ), 81 | ], 82 | ), 83 | ), 84 | ); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /lib/src/home/social_media_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../html_open_link.dart'; 4 | import 'data.dart'; 5 | 6 | class SocialMediaBar extends StatelessWidget { 7 | SocialMediaBar({Key? key, required this.height}) : super(key: key); 8 | final List> data = socialMedia(); 9 | final double height; 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | final List currentSupportedSocialMedia = [ 14 | 'email', 15 | 'facebook', 16 | 'github', 17 | 'instagram', 18 | 'linkedin', 19 | 'medium', 20 | 'stackoverflow', 21 | 'twitter', 22 | 'leetcode' 23 | ]; 24 | return Padding( 25 | padding: EdgeInsets.only(top: height * 0.03), 26 | child: FittedBox( 27 | fit: BoxFit.cover, 28 | child: Row( 29 | children: List.generate(data.length, (int i) { 30 | return IconButton( 31 | iconSize: 50.0, 32 | hoverColor: Colors.transparent, 33 | icon: (data[i][1] != '' && 34 | currentSupportedSocialMedia.contains(data[i][1])) 35 | ? SocialMediaButton( 36 | image: 'assets/home/constant/${data[i][1]}.png', 37 | link: data[i][0], 38 | height: height) 39 | : SocialMediaButton( 40 | image: 'assets/home/constant/link.png', 41 | link: data[i][0], 42 | height: height, 43 | ), 44 | onPressed: () { 45 | htmlOpenLink(data[i][0]); 46 | }); 47 | }), 48 | ), 49 | )); 50 | } 51 | } 52 | 53 | class SocialMediaButton extends StatefulWidget { 54 | const SocialMediaButton( 55 | {Key? key, required this.image, required this.height, required this.link}) 56 | : super(key: key); 57 | @override 58 | _SocialMediaButton createState() => _SocialMediaButton(); 59 | 60 | final String image, link; 61 | final double height; 62 | } 63 | 64 | class _SocialMediaButton extends State { 65 | bool isHover = false; 66 | 67 | @override 68 | Widget build(BuildContext context) { 69 | return AnimatedContainer( 70 | duration: const Duration(milliseconds: 200), 71 | padding: EdgeInsets.only( 72 | top: isHover ? widget.height * 0.005 : widget.height * 0.01, 73 | bottom: !isHover ? widget.height * 0.005 : widget.height * 0.01), 74 | child: InkWell( 75 | hoverColor: Colors.transparent, 76 | splashColor: Colors.transparent, 77 | focusColor: Colors.transparent, 78 | highlightColor: Colors.transparent, 79 | onTap: () { 80 | htmlOpenLink(widget.link); 81 | }, 82 | onHover: (bool val) { 83 | setState(() { 84 | isHover = val; 85 | }); 86 | }, 87 | child: Image.asset( 88 | widget.image, 89 | ), 90 | ), 91 | ); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /lib/tabs/home.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import '../src/home/about.dart'; 4 | import '../src/home/data.dart'; 5 | import '../src/home/designation.dart'; 6 | import '../src/home/introduction.dart'; 7 | import '../src/home/my_name.dart'; 8 | import '../src/home/resume.dart'; 9 | import '../src/home/social_media_bar.dart'; 10 | 11 | class HomePage extends StatefulWidget { 12 | const HomePage({Key? key}) : super(key: key); 13 | 14 | @override 15 | State createState() => _HomePageState(); 16 | } 17 | 18 | class _HomePageState extends State { 19 | @override 20 | void initState() { 21 | super.initState(); 22 | WidgetsBinding.instance.addPostFrameCallback((_) { 23 | Future.microtask(() { 24 | SystemChrome.setApplicationSwitcherDescription( 25 | ApplicationSwitcherDescription( 26 | label: 'Meet ${name().split(' ').first}', 27 | primaryColor: Colors.black.value, 28 | )); 29 | }); 30 | }); 31 | } 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | final double width = MediaQuery.of(context).size.width; 36 | final double height = MediaQuery.of(context).size.height; 37 | return Padding( 38 | padding: EdgeInsets.only(bottom: height * 0.1), 39 | child: SizedBox( 40 | child: LayoutBuilder( 41 | builder: (BuildContext context, BoxConstraints constraints) { 42 | if (constraints.maxWidth < 1000) { 43 | return Padding( 44 | padding: EdgeInsets.symmetric(horizontal: width * 0.024), 45 | child: Column( 46 | crossAxisAlignment: CrossAxisAlignment.start, 47 | children: [ 48 | Padding( 49 | padding: EdgeInsets.only(top: height * 0.07), 50 | child: const Introduction( 51 | word: 'Hello,\nI am', textScaleFactor: 3), 52 | ), 53 | MyName( 54 | isMobile: true, 55 | context: context, 56 | ), 57 | Designation(isMobile: true, context: context), 58 | SocialMediaBar( 59 | height: height, 60 | ), 61 | About(fontSize: 24), 62 | Padding( 63 | padding: EdgeInsets.only(bottom: height * 0.029), 64 | child: OverflowBar( 65 | children: [ 66 | Resume( 67 | width: 0, 68 | ), 69 | ], 70 | ), 71 | ), 72 | ], 73 | ), 74 | ); 75 | } else { 76 | return Padding( 77 | padding: 78 | EdgeInsets.only(top: height * 0.08, bottom: height * 0.07), 79 | child: Column( 80 | crossAxisAlignment: CrossAxisAlignment.start, 81 | children: [ 82 | Padding( 83 | padding: EdgeInsets.symmetric(horizontal: width * 0.032), 84 | child: Column( 85 | crossAxisAlignment: CrossAxisAlignment.start, 86 | children: [ 87 | const Introduction( 88 | word: 'Hello, I am', textScaleFactor: 3.5), 89 | FittedBox( 90 | fit: BoxFit.cover, 91 | child: MyName( 92 | isMobile: false, 93 | context: context, 94 | )), 95 | Designation(isMobile: false, context: context), 96 | SocialMediaBar( 97 | height: height, 98 | ), 99 | About(fontSize: 30), 100 | Padding( 101 | padding: EdgeInsets.only(bottom: height * 0.026), 102 | child: Row( 103 | children: [ 104 | Resume( 105 | width: width, 106 | ), 107 | ], 108 | ), 109 | ), 110 | ], 111 | ), 112 | ), 113 | ], 114 | ), 115 | ); 116 | } 117 | }), 118 | ), 119 | ); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /assets/fonts/font_OFL/OFL-Montserrat.txt: -------------------------------------------------------------------------------- 1 | Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat) 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /assets/fonts/font_OFL/OFL-FjallaOne.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 by Sorkin Type Co (www.sorkintype.com), with Reserved Font Name 'Fjalla' 2 | 3 | Fjalla is a trademark of Sorkin Type Co. 4 | 5 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 6 | This license is copied below, and is also available with a FAQ at: 7 | http://scripts.sil.org/OFL 8 | 9 | 10 | ----------------------------------------------------------- 11 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 12 | ----------------------------------------------------------- 13 | 14 | PREAMBLE 15 | The goals of the Open Font License (OFL) are to stimulate worldwide 16 | development of collaborative font projects, to support the font creation 17 | efforts of academic and linguistic communities, and to provide a free and 18 | open framework in which fonts may be shared and improved in partnership 19 | with others. 20 | 21 | The OFL allows the licensed fonts to be used, studied, modified and 22 | redistributed freely as long as they are not sold by themselves. The 23 | fonts, including any derivative works, can be bundled, embedded, 24 | redistributed and/or sold with any software provided that any reserved 25 | names are not used by derivative works. The fonts and derivatives, 26 | however, cannot be released under any other type of license. The 27 | requirement for fonts to remain under this license does not apply 28 | to any document created using the fonts or their derivatives. 29 | 30 | DEFINITIONS 31 | "Font Software" refers to the set of files released by the Copyright 32 | Holder(s) under this license and clearly marked as such. This may 33 | include source files, build scripts and documentation. 34 | 35 | "Reserved Font Name" refers to any names specified as such after the 36 | copyright statement(s). 37 | 38 | "Original Version" refers to the collection of Font Software components as 39 | distributed by the Copyright Holder(s). 40 | 41 | "Modified Version" refers to any derivative made by adding to, deleting, 42 | or substituting -- in part or in whole -- any of the components of the 43 | Original Version, by changing formats or by porting the Font Software to a 44 | new environment. 45 | 46 | "Author" refers to any designer, engineer, programmer, technical 47 | writer or other person who contributed to the Font Software. 48 | 49 | PERMISSION & CONDITIONS 50 | Permission is hereby granted, free of charge, to any person obtaining 51 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 52 | redistribute, and sell modified and unmodified copies of the Font 53 | Software, subject to the following conditions: 54 | 55 | 1) Neither the Font Software nor any of its individual components, 56 | in Original or Modified Versions, may be sold by itself. 57 | 58 | 2) Original or Modified Versions of the Font Software may be bundled, 59 | redistributed and/or sold with any software, provided that each copy 60 | contains the above copyright notice and this license. These can be 61 | included either as stand-alone text files, human-readable headers or 62 | in the appropriate machine-readable metadata fields within text or 63 | binary files as long as those fields can be easily viewed by the user. 64 | 65 | 3) No Modified Version of the Font Software may use the Reserved Font 66 | Name(s) unless explicit written permission is granted by the corresponding 67 | Copyright Holder. This restriction only applies to the primary font name as 68 | presented to the users. 69 | 70 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 71 | Software shall not be used to promote, endorse or advertise any 72 | Modified Version, except to acknowledge the contribution(s) of the 73 | Copyright Holder(s) and the Author(s) or with their explicit written 74 | permission. 75 | 76 | 5) The Font Software, modified or unmodified, in part or in whole, 77 | must be distributed entirely under this license, and must not be 78 | distributed under any other license. The requirement for fonts to 79 | remain under this license does not apply to any document created 80 | using the Font Software. 81 | 82 | TERMINATION 83 | This license becomes null and void if any of the above conditions are 84 | not met. 85 | 86 | DISCLAIMER 87 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 88 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 89 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 90 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 91 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 92 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 93 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 94 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 95 | OTHER DEALINGS IN THE FONT SOFTWARE. 96 | -------------------------------------------------------------------------------- /assets/fonts/font_OFL/OFL-SourceCodePro.txt: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Meet Developer 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | 67 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /lib/src/experience/card.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../custom/custom_text.dart'; 4 | import '../theme/config.dart'; 5 | 6 | class ExperienceCard extends StatefulWidget { 7 | const ExperienceCard( 8 | {Key? key, 9 | required this.image, 10 | required this.title, 11 | required this.desc, 12 | required this.period, 13 | required this.role, 14 | required this.isMobile}) 15 | : super(key: key); 16 | 17 | final String image, title, desc, period, role; 18 | final bool isMobile; 19 | 20 | @override 21 | _ExperienceCardState createState() => _ExperienceCardState(); 22 | } 23 | 24 | class _ExperienceCardState extends State { 25 | bool isHover = false; 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | final double width = MediaQuery.of(context).size.width; 30 | final double height = MediaQuery.of(context).size.height; 31 | return AnimatedContainer( 32 | decoration: BoxDecoration( 33 | boxShadow: [ 34 | BoxShadow( 35 | color: isHover ? Colors.black12 : Colors.black45, 36 | blurRadius: 10.0, 37 | offset: const Offset(8, 12), 38 | ) 39 | ], 40 | ), 41 | duration: const Duration(milliseconds: 200), 42 | padding: EdgeInsets.only( 43 | top: isHover ? height * 0.005 : height * 0.01, 44 | bottom: !isHover ? height * 0.005 : height * 0.01), 45 | child: InkWell( 46 | onHover: (bool value) { 47 | setState(() { 48 | isHover = value; 49 | }); 50 | }, 51 | onTap: () {}, 52 | child: Container( 53 | alignment: Alignment.topCenter, 54 | padding: const EdgeInsets.only( 55 | top: 5.0, 56 | ), 57 | width: !widget.isMobile ? width * 0.28 : width, 58 | decoration: BoxDecoration( 59 | boxShadow: [ 60 | BoxShadow( 61 | color: isHover ? Colors.black12 : Colors.black45, 62 | blurRadius: 10.0, 63 | offset: const Offset(8, 12), 64 | ) 65 | ], 66 | color: Theme.of(context).scaffoldBackgroundColor, 67 | borderRadius: BorderRadius.circular( 68 | 5.0, 69 | ), 70 | border: Border.all( 71 | width: 3, 72 | color: currentTheme.currentTheme == ThemeMode.dark 73 | ? Theme.of(context).cardColor 74 | : Theme.of(context).primaryColor, 75 | ), 76 | ), 77 | child: Column( 78 | children: [ 79 | Image.asset( 80 | 'assets/experience/${widget.image}', 81 | scale: 1.1, 82 | ), 83 | Container( 84 | alignment: Alignment.topCenter, 85 | padding: EdgeInsets.only( 86 | top: height * 0.02, 87 | left: width * 0.015, 88 | right: width * 0.01, 89 | bottom: height * 0.02), 90 | width: !widget.isMobile ? width * 0.28 : width, 91 | decoration: BoxDecoration( 92 | color: currentTheme.currentTheme == ThemeMode.dark 93 | ? Theme.of(context).cardColor 94 | : Theme.of(context).primaryColor, 95 | borderRadius: const BorderRadius.only( 96 | bottomLeft: Radius.circular(5.0), 97 | bottomRight: Radius.circular(5.0), 98 | ), 99 | ), 100 | child: Center( 101 | child: Column( 102 | children: [ 103 | FittedBox( 104 | fit: BoxFit.cover, 105 | child: CustomText( 106 | text: widget.title, 107 | fontSize: 25, 108 | color: Colors.white)), 109 | Padding( 110 | padding: const EdgeInsets.only(top: 5.0, bottom: 16.0), 111 | child: FittedBox( 112 | fit: BoxFit.cover, 113 | child: CustomText( 114 | text: widget.role, 115 | fontSize: 14, 116 | color: Colors.white)), 117 | ), 118 | Padding( 119 | padding: const EdgeInsets.only(bottom: 12.0), 120 | child: FittedBox( 121 | fit: BoxFit.cover, 122 | child: CustomText( 123 | text: widget.period, 124 | fontSize: 15, 125 | color: Colors.white)), 126 | ), 127 | CustomText( 128 | text: widget.desc, fontSize: 15, color: Colors.white), 129 | ], 130 | ), 131 | ), 132 | ), 133 | ], 134 | ), 135 | ), 136 | ), 137 | ); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /web/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #171c28; 3 | } 4 | 5 | * { 6 | border: 0; 7 | box-sizing: border-box; 8 | margin: 0; 9 | padding: 0; 10 | } 11 | :root { 12 | --dur: 2s; 13 | --bg: #e3e4e8; 14 | --fg: #171c28; 15 | font-size: calc(12px + (24 - 12)*(100vw - 320px)/(2560 - 320)); 16 | } 17 | body { 18 | background: var(--bg); 19 | color: var(--fg); 20 | display: flex; 21 | font: 1em/1.5 sans-serif; 22 | height: 100vh; 23 | overflow: hidden; 24 | } 25 | .preloader, .box, .box__inner, .box__inner div { 26 | transform-style: preserve-3d; 27 | } 28 | .preloader { 29 | margin: auto; 30 | position: relative; 31 | width: 12em; 32 | height: 24em; 33 | } 34 | .box, .box__inner, .box__inner div, .line { 35 | position: absolute; 36 | } 37 | .box, .box__inner div, .line__inner { 38 | animation-timing-function: ease-in-out; 39 | animation-iteration-count: infinite; 40 | } 41 | .box, .line__inner { 42 | animation-duration: var(--dur); 43 | } 44 | .box__inner div, .line__inner { 45 | background: var(--fg); 46 | } 47 | /* Boxes */ 48 | .box, .box__inner { 49 | width: 100%; 50 | height: 50%; 51 | } 52 | .box { 53 | animation-name: popOut; 54 | top: 50%; 55 | perspective: 25em; 56 | transform-origin: 50% 75%; 57 | z-index: 1; 58 | } 59 | .box + .box { 60 | animation-delay: calc(var(--dur)/-2); 61 | } 62 | .box__inner, .box__inner div { 63 | animation-delay: inherit; 64 | animation-duration: inherit; 65 | } 66 | .box__inner { 67 | transform: rotateX(50deg); 68 | transform-origin: 50% 25%; 69 | } 70 | .box__inner div { 71 | box-shadow: 0 0 0 0.2em var(--bg) inset; 72 | } 73 | .box__back-flap, .box__front-flap, .box__front { 74 | width: 6em; 75 | } 76 | .box__left-flap, .box__right-flap, .box__front { 77 | height: 6em; 78 | } 79 | .box__back-flap, .box__front-flap { 80 | left: 3em; 81 | height: 3em; 82 | } 83 | .box__left-flap, .box__right-flap { 84 | top: 3em; 85 | width: 3em; 86 | } 87 | .box__back-flap { 88 | animation-name: backFlap; 89 | transform: rotateX(-180deg); 90 | transform-origin: 50% 100%; 91 | } 92 | .box__right-flap { 93 | animation-name: rightFlap; 94 | left: 9em; 95 | transform: rotateY(-179deg); 96 | transform-origin: 0 50%; 97 | } 98 | .box__front-flap { 99 | animation-name: frontFlap; 100 | top: 9em; 101 | transform: rotateX(180deg); 102 | transform-origin: 50% 0; 103 | } 104 | .box__left-flap { 105 | animation-name: leftFlap; 106 | transform: rotateY(179deg); 107 | transform-origin: 100% 50%; 108 | } 109 | .box__front { 110 | top: 3em; 111 | left: 3em; 112 | transform: rotateX(-90deg) translateY(50%) translateZ(3em); 113 | } 114 | /* Lines */ 115 | .line, .line__inner { 116 | border-radius: 0.1em; 117 | } 118 | .line { 119 | top: 0; 120 | left: calc(50% - 0.1em); 121 | width: 0.2em; 122 | height: 6em; 123 | overflow: hidden; 124 | transform-origin: 50% 0.1em; 125 | } 126 | .line:nth-child(n + 5) { 127 | top: 90%; 128 | transform: translateY(2em); 129 | } 130 | .line:nth-child(3) { 131 | left: calc(50% - 1.1em); 132 | } 133 | .line:nth-child(4) { 134 | left: calc(50% + 0.9em); 135 | } 136 | .line:nth-child(5) { 137 | transform: rotate(-90deg) translateY(2em); 138 | } 139 | .line:nth-child(6) { 140 | transform: rotate(-45deg); 141 | } 142 | .line:nth-child(7) { 143 | transform: translateY(-0.5em); 144 | } 145 | .line:nth-child(8) { 146 | transform: rotate(45deg); 147 | } 148 | .line:nth-child(9) { 149 | transform: rotate(90deg) translateY(2em); 150 | } 151 | .line__inner { 152 | animation-duration: calc(var(--dur)/2); 153 | width: 100%; 154 | height: 100%; 155 | } 156 | .line:nth-child(n + 3):nth-child(-n + 4) .line__inner { 157 | animation-name: falling; 158 | } 159 | .line:nth-child(n + 5):nth-child(-n + 9) .line__inner { 160 | animation-name: landing; 161 | transform: translateY(-100%); 162 | } 163 | /* Dark Mode */ 164 | @media (prefers-color-scheme: dark) { 165 | :root { 166 | --bg: #171c28; 167 | --fg: #e3e4e8; 168 | } 169 | } 170 | /* Animations */ 171 | @keyframes backFlap { 172 | from, 33% { transform: rotateX(-180deg); } 173 | 41% { transform: rotateX(10deg); } 174 | 45% { transform: rotateX(-27deg); } 175 | 50%, to { transform: rotateX(-15deg); } 176 | } 177 | @keyframes rightFlap { 178 | from, 33% { transform: rotateY(-179deg); } 179 | 41% { transform: rotateY(10deg); } 180 | 45% { transform: rotateY(-27deg); } 181 | 50%, to { transform: rotateY(-15deg); } 182 | } 183 | @keyframes frontFlap { 184 | from, 33% { transform: rotateX(180deg); } 185 | 41% { transform: rotateX(-10deg); } 186 | 45% { transform: rotateX(27deg); } 187 | 50%, to { transform: rotateX(15deg); } 188 | } 189 | @keyframes leftFlap { 190 | from, 33% { transform: rotateY(179deg); } 191 | 41% { transform: rotateY(-10deg); } 192 | 45% { transform: rotateY(27deg); } 193 | 50%, to { transform: rotateY(15deg); } 194 | } 195 | @keyframes popOut { 196 | from, 21% { transform: translateZ(1px) translateY(0) scale(0,0); } 197 | 33% { transform: translateZ(1px) translateY(-100%) scale(0.75,1.5); } 198 | 41% { transform: translateZ(1px) translateY(-100%) scale(1,1); } 199 | 42%,50% { transform: translateZ(0) translateY(-100%) scale(1,1); } 200 | 55% { transform: translateZ(0) translateY(-100%) scale(0.75,1.5); } 201 | 60% { transform: translateZ(0) translateY(0) scale(1.5,0.75); } 202 | 67% { transform: translateZ(0) translateY(0) scale(1,1); } 203 | to { transform: translateZ(0) translateY(0) scale(0,0); } 204 | } 205 | @keyframes falling { 206 | from, 12% { transform: translateY(0%); } 207 | 28%, to { transform: translateY(100%); } 208 | } 209 | @keyframes landing { 210 | from, 17% { transform: translateY(-100%); } 211 | 41%, to { transform: translateY(100%); } 212 | } 213 | -------------------------------------------------------------------------------- /lib/src/education/card.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../custom/custom_text.dart'; 4 | import '../theme/config.dart'; 5 | 6 | class EducationDesktop extends StatefulWidget { 7 | const EducationDesktop( 8 | {Key? key, 9 | required this.instiution, 10 | required this.location, 11 | required this.desc, 12 | required this.grades, 13 | required this.years, 14 | required this.image}) 15 | : super(key: key); 16 | 17 | final String instiution, location, years, grades, desc, image; 18 | @override 19 | _EducationDesktopState createState() => _EducationDesktopState(); 20 | } 21 | 22 | class _EducationDesktopState extends State { 23 | bool isHover = false; 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | final double height = MediaQuery.of(context).size.height; 28 | final double width = MediaQuery.of(context).size.width; 29 | return AnimatedContainer( 30 | decoration: BoxDecoration( 31 | boxShadow: [ 32 | BoxShadow( 33 | color: isHover ? Colors.black12 : Colors.black45, 34 | blurRadius: 10.0, 35 | offset: const Offset(8, 12), 36 | ) 37 | ], 38 | ), 39 | duration: const Duration(milliseconds: 200), 40 | padding: EdgeInsets.only( 41 | top: isHover ? height * 0.005 : height * 0.01, 42 | bottom: !isHover ? height * 0.005 : height * 0.01), 43 | child: InkWell( 44 | onHover: (bool value) { 45 | setState(() { 46 | isHover = value; 47 | }); 48 | }, 49 | onTap: () {}, 50 | child: Container( 51 | alignment: Alignment.topCenter, 52 | padding: EdgeInsets.only( 53 | top: height * 0.04, 54 | left: width * 0.015, 55 | right: width * 0.015, 56 | bottom: height * 0.04), 57 | width: width / 1.15, 58 | decoration: BoxDecoration( 59 | boxShadow: [ 60 | BoxShadow( 61 | color: isHover ? Colors.black12 : Colors.black45, 62 | blurRadius: 10.0, 63 | offset: const Offset(8, 12), 64 | ) 65 | ], 66 | color: currentTheme.currentTheme == ThemeMode.dark 67 | ? Theme.of(context).cardColor 68 | : Theme.of(context).primaryColor, 69 | borderRadius: BorderRadius.circular( 70 | 5.0, 71 | ), 72 | ), 73 | child: Column( 74 | children: [ 75 | Visibility( 76 | visible: width < 1000, 77 | child: Container( 78 | width: 50, 79 | height: 50, 80 | margin: const EdgeInsets.only(bottom: 5.0), 81 | decoration: BoxDecoration( 82 | borderRadius: BorderRadius.circular(5.0), 83 | image: DecorationImage( 84 | image: AssetImage('assets/education/${widget.image}'), 85 | fit: BoxFit.cover, 86 | ), 87 | ), 88 | ), 89 | ), 90 | Row( 91 | children: [ 92 | Visibility( 93 | visible: width >= 1000, 94 | child: Container( 95 | width: 100, 96 | height: 100, 97 | decoration: BoxDecoration( 98 | borderRadius: BorderRadius.circular(5.0), 99 | image: DecorationImage( 100 | image: AssetImage('assets/education/${widget.image}'), 101 | fit: BoxFit.cover, 102 | ), 103 | ), 104 | ), 105 | ), 106 | Expanded( 107 | flex: 2, 108 | child: Column( 109 | children: [ 110 | FittedBox( 111 | fit: BoxFit.cover, 112 | child: CustomText( 113 | text: widget.instiution, 114 | fontSize: 20, 115 | color: Colors.white)), 116 | Padding( 117 | padding: const EdgeInsets.only(bottom: 5.0), 118 | child: FittedBox( 119 | fit: BoxFit.cover, 120 | child: CustomText( 121 | text: widget.location, 122 | fontSize: 10, 123 | color: Colors.white)), 124 | ), 125 | FittedBox( 126 | fit: BoxFit.cover, 127 | child: Padding( 128 | padding: const EdgeInsets.only(bottom: 11.0), 129 | child: CustomText( 130 | text: widget.years != '' 131 | ? 'Years of study: ${widget.years}' 132 | : '', 133 | fontSize: 12, 134 | color: Colors.white), 135 | )), 136 | FittedBox( 137 | fit: BoxFit.cover, 138 | child: CustomText( 139 | text: widget.desc, 140 | fontSize: 13, 141 | color: Colors.white)), 142 | FittedBox( 143 | fit: BoxFit.cover, 144 | child: CustomText( 145 | text: widget.grades != '' 146 | ? 'Grades Achieved: ${widget.grades}' 147 | : '', 148 | fontSize: 12, 149 | color: Colors.white)), 150 | ], 151 | ), 152 | ), 153 | ], 154 | ), 155 | ], 156 | ), 157 | ), 158 | ), 159 | ); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Looking for *collaborators* and *maintainers*. Feel free to connect! 2 | # **Developer Portfolio ⚡️** 3 | ## *It's minimal, beautiful and responsive!* 4 | ### **Don't have or don't know Flutter?** 5 | - ### **Editing a JSON is all you have to do.** 6 | Made for people who are looking for a ready-made portfolio. Because making a portfolio out of scratch is tiring. Feel free to use it as-is or customise it just the way you want it to be. 7 | 8 | ### **Portfolio Sections** 9 | ✔️ Skills\ 10 | ✔️ Summary and About me\ 11 | ✔️ Contact me\ 12 | ✔️ Education\ 13 | ✔️ Work Experience\ 14 | ✔️ Open Source Projects Connected hosted with GitHub\ 15 | ✔️ Other Projects\ 16 | ✔️ Achievements 17 | 18 | ## **Change and customize every section according to your need** 19 | 20 | #### Personalize page content in `/assets/portfolio.json` and modify it as per your needs. You can also change the title in `web/index.html` to change the title of your portfolio site. **For reference, check out my personal [portfolio.json](https://github.com/danger-ahead/flutter_dev_folio/blob/personal/assets/portfolio.json).** 21 | ***IMPORTANT: Don't want to share some details or don't have an image file? Keep the value of the respective field empty (will load a template image or in case of text, will display no text. Your site won't look bad 😉)*** 22 | - Your name and link. 23 | ```json 24 | "name_and_link": [ 25 | "your name", 26 | "a link (preferably github) of your choice" 27 | ], 28 | ``` 29 | - The tagline section in the home page, add as many as you want. 30 | ```json 31 | "designation": [ 32 | "first tagline", 33 | "second tagline" 34 | ], 35 | ``` 36 | - Your social media handles. **Currently supports icons for Facebook, GitHub, LeetCode, Linkedin, Twitter, Medium, Stack Overflow, Twitter and email. Specify the name of the social media in small letters in the json**. *If you want to add link to something else, simply keep the name value empty (will load a button with template image).* 37 | ```json 38 | "social_media": { 39 | "1": [ 40 | "your github link", 41 | "specify the name of the social media" 42 | ], 43 | "2": [ 44 | "https://linkedin.com/example", 45 | "linkedin" 46 | ], 47 | "3": [ 48 | "https://another-link.com", 49 | "" 50 | ], 51 | }, 52 | ``` 53 | - About and Bio section. 54 | ```json 55 | "about": "a small about section for the home page", 56 | "bio": "a more detailed about for the contact me page" 57 | ``` 58 | - Adding proficiency and used tools in What I do page.
Simply place the image files (64x64) in `assets/what_i_do/` and add the names in the json accordingly. In the example below, I have places 2 images (flutter.png and linux.png) under `assets/what_i_do/`.
To add proficiency in a particular language or tool, place it like this: `tool--proficiency_percentage`. Add as many tools or proficiency items as you want. 59 | ```json 60 | "what_i_do": { 61 | "tools": [ 62 | "flutter.png", 63 | "linux.png", 64 | ], 65 | "proficiency": [ 66 | "Flutter--50", 67 | "C/C++/Java/Python--60", 68 | ] 69 | }, 70 | ``` 71 | - Education page.
Place institute logo image file (128x128) under `assets/education/`. 72 | ```json 73 | "education": { 74 | "1": { 75 | "institute": "RCC Institute of Information Technology", 76 | "location": "Kolkata", 77 | "years": "2020 - 2024", 78 | "description": "B.Tech in CSE", 79 | "grades": "9.53 YGPA", 80 | "logo": "rcciit.png" 81 | }, 82 | "2": { 83 | "institute": "Gitaram Academy", 84 | "location": "Berhampore", 85 | "years": "2018 - 2020", 86 | "description": "Physics, Chemistry, Mathematics, Computer Science", 87 | "grades": "84%", 88 | "logo": "" 89 | }, 90 | }, 91 | ``` 92 | - Experience page.
Place logo image file (128x128) under `assets/experience/`. 93 | ```json 94 | "experience": { 95 | "1": { 96 | "name": "Google Developer Student Club", 97 | "role": "Cybersecurity core member", 98 | "period": "September, 2021 - Present", 99 | "description": "Helped in organizing and conducting technical workshops, for community members.", 100 | "image_name": "GDSC.png" 101 | }, 102 | }, 103 | ``` 104 | - Projects page.
**You can either fill out all the details of a particular project or just the GitHub link (if you want to fetch and use the details provided in the GitHub repo).**
***Note:** The GitHub link (in both the cases) is required to fetch the number of stars and forks.* 105 | ```json 106 | "projects": { 107 | "1": { 108 | "name": "flutter_dev_folio", 109 | "tech_stack_used": "Flutter", 110 | "description": "Minimal, Beautiful and responsive portfolio site template", 111 | "general_or_github_link": "https://github.com/danger-ahead/flutter_dev_folio" 112 | }, 113 | "2": { 114 | "name": "", 115 | "tech_stack_used": "", 116 | "description": "", 117 | "general_or_github_link": "https://github.com/danger-ahead/roBOT" 118 | }, 119 | } 120 | ``` 121 | - Achievements page.
You can add a link where visitors can view or validate your achievement. 122 | ```json 123 | "achievements": { 124 | "1": { 125 | "description": "your achievement", 126 | "link": "https://some-link.com/view-certificate" 127 | }, 128 | } 129 | ``` 130 | - Contact me page. 131 | ```json 132 | "contact_me": { 133 | "location": "your location", 134 | "open_for_opportunities": "Yes or No", 135 | "picture": "picture.png" 136 | }, 137 | ``` 138 | 139 | ## How to deploy, run or test locally 140 | ```bash 141 | # Clone this repository 142 | git clone https://github.com/danger-ahead/flutter_dev_folio 143 | 144 | # Go into the repository 145 | cd flutter_dev_folio 146 | 147 | # Create dotenv. No need to add any token now, GitHub API serves requests without authorisation. 148 | : > dotenv 149 | 150 | # Get dependencies 151 | flutter pub get 152 | 153 | # Start a local dev server 154 | # We'll be using the HTML renderer 155 | flutter run -d chrome --web-renderer html 156 | ``` 157 | 158 | ## **Deployment** 159 | flutter_dev_folio uses the GitHub API for fetching details from GitHub. The API is currently rate limited to 60 requests/hour. To overcome this, we would need a `GitHub Personal Access Token` placed in the `dotenv`. 160 | 161 | **[Generate a new token](https://github.com/settings/tokens) with only `public_repo` scope.**

***IMPORTANT NOTE: TO USE PERSONAL ACCESS TOKEN FOR API CALLS, YOU NEED TO MANUALLY DEPLOY THE BUILT PROJECT. AS YOU CAN'T VERSION CONTROL THE `dotenv`***.

Create a `dotenv` file here: 162 | ```bash 163 | - flutter_dev_folio 164 | - assets 165 | - lib 166 | - web 167 | - dotenv <-- create it here 168 | - .gitignore 169 | - pubspec.lock 170 | - pubspec.yaml 171 | - README.md 172 | ``` 173 | Then paste the PERSONAL ACCESS TOKEN and run `flutter build web --web-renderer html --release`. This will create the `build/` directory containing all your build files. You can now simply deploy the `build/web/`. 174 | 175 | **Or,** You can create an empty `dotenv` file and run (and deploy) the project. *Caution: This will limit the GitHub API to 60 requests/hour.* 176 | 177 | ***Or alternatively, Enable workflows in your fork and edit the json (and/or other files as per your wish) in your fork. Then commit and push. GitHub actions will soon generate the build files in the `master-deploy` branch. The generated build files will have rate limited API access.*** 178 | 179 | ## For the future 180 | This project is still very much in beta stage. 181 | - Adding more sections 182 | - Adding animations in different parts while loading the screens 183 | - Embedding and connecting Twitter, Medium or Linkedin 184 | 185 | Consider opening a PR if you can help me with these. 186 | 187 | --- 188 | If you'd like to contribute and make this much better for other users, have a look at the [issues](https://github.com/danger-ahead/flutter_dev_folio/issues). 189 | 190 | Created something awesome for your fork of the portfolio and want to share it? Feel free to open a [pull request](https://github.com/danger-ahead/flutter_dev_folio/pulls). 191 | -------------------------------------------------------------------------------- /lib/tabs/what_i_do.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../src/custom/custom_text.dart'; 4 | import '../src/nav_bar/title_bar.dart'; 5 | import '../src/theme/config.dart'; 6 | import '../src/whatIDo/data.dart'; 7 | import '../src/whatIDo/progress.dart'; 8 | 9 | class WhatIdo extends StatelessWidget { 10 | WhatIdo({Key? key}) : super(key: key); 11 | 12 | final List> data = whatIdo(); 13 | static final whatIDoKey = GlobalKey(); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | final double height = MediaQuery.of(context).size.height; 18 | final double width = MediaQuery.of(context).size.width; 19 | return Padding( 20 | padding: const EdgeInsets.all(8.0), 21 | child: Column(children: [ 22 | TitleBar(height: height, width: width, title: 'WHAT I DO'), 23 | Padding( 24 | padding: EdgeInsets.only(bottom: height * 0.1), 25 | child: LayoutBuilder( 26 | builder: (BuildContext context, BoxConstraints constraints) { 27 | if (constraints.maxWidth < 1000) { 28 | int storage = -1; 29 | return Column( 30 | crossAxisAlignment: CrossAxisAlignment.start, 31 | children: [ 32 | Padding( 33 | padding: const EdgeInsets.fromLTRB(15, 10, 15, 20), 34 | child: CustomText( 35 | text: '⚡ I have a good proficiency in:', 36 | fontSize: 15, 37 | color: Theme.of(context).primaryColorLight), 38 | ), 39 | Padding( 40 | padding: const EdgeInsets.only( 41 | bottom: 25.0, 42 | left: 15.0, 43 | right: 15.0, 44 | ), 45 | child: Row( 46 | mainAxisAlignment: MainAxisAlignment.spaceAround, 47 | children: [ 48 | Image.asset( 49 | currentTheme.currentTheme == ThemeMode.dark 50 | ? 'assets/what_i_do/constant/checklist.png' 51 | : 'assets/what_i_do/constant/checklist-light.png', 52 | scale: 2, 53 | ), 54 | Column( 55 | children: List.generate( 56 | data[0].length, 57 | (int index) => Progress( 58 | width: width / 1.55, 59 | widthSecondContainer: 60 | double.parse(data[0][index].split('--')[1]), 61 | title: data[0][index].split('--')[0], 62 | sizeProficiencyName: 12, 63 | sizePercentage: 10, 64 | ), 65 | ), 66 | ), 67 | ], 68 | ), 69 | ), 70 | Padding( 71 | padding: const EdgeInsets.fromLTRB(15, 30, 15, 20), 72 | child: CustomText( 73 | text: data[1].isNotEmpty 74 | ? '⚡ Some languages & tools I use:' 75 | : '', 76 | fontSize: 15, 77 | color: Theme.of(context).primaryColorLight), 78 | ), 79 | Padding( 80 | padding: const EdgeInsets.fromLTRB(15, 25, 15, 20), 81 | child: Column( 82 | children: List.generate( 83 | data[1].length % 4 == 0 84 | ? data[1].length ~/ 4 85 | : data[1].length ~/ 4 + 1, 86 | (int i) => Padding( 87 | padding: const EdgeInsets.only(bottom: 20.0), 88 | child: Row( 89 | mainAxisAlignment: MainAxisAlignment.spaceAround, 90 | children: List.generate( 91 | (data[1].length - storage - 1) >= 4 92 | ? 4 93 | : data[1].length - storage - 1, 94 | (int index) { 95 | storage = index + i * 4; 96 | return Image.asset( 97 | 'assets/what_i_do/${data[1][index + i * 4]}', 98 | ); 99 | }), 100 | ), 101 | ), 102 | ), 103 | ), 104 | ), 105 | ], 106 | ); 107 | } else { 108 | int storage = -1; 109 | return Column( 110 | crossAxisAlignment: CrossAxisAlignment.start, 111 | children: [ 112 | Padding( 113 | padding: const EdgeInsets.fromLTRB(70, 10, 70, 20), 114 | child: CustomText( 115 | text: '⚡ I have a good proficiency in:', 116 | fontSize: 35, 117 | color: Theme.of(context).primaryColorLight), 118 | ), 119 | Padding( 120 | padding: const EdgeInsets.only(bottom: 25.0), 121 | child: Row( 122 | mainAxisAlignment: MainAxisAlignment.spaceAround, 123 | children: [ 124 | Column( 125 | children: List.generate( 126 | data[0].length, 127 | (int index) => Progress( 128 | width: width / 2, 129 | widthSecondContainer: 130 | double.parse(data[0][index].split('--')[1]), 131 | title: data[0][index].split('--')[0], 132 | sizeProficiencyName: 22, 133 | sizePercentage: 15, 134 | ), 135 | ), 136 | ), 137 | Image.asset( 138 | currentTheme.currentTheme == ThemeMode.dark 139 | ? 'assets/what_i_do/constant/checklist.png' 140 | : 'assets/what_i_do/constant/checklist-light.png', 141 | ), 142 | ], 143 | ), 144 | ), 145 | Padding( 146 | padding: const EdgeInsets.fromLTRB(70, 30, 70, 20), 147 | child: CustomText( 148 | text: data[1].isNotEmpty 149 | ? '⚡ Some languages & tools I use:' 150 | : '', 151 | fontSize: 35, 152 | color: Theme.of(context).primaryColorLight), 153 | ), 154 | Padding( 155 | padding: const EdgeInsets.only( 156 | top: 25.0, 157 | bottom: 20.0, 158 | ), 159 | child: Column( 160 | children: List.generate( 161 | data[1].length % 8 == 0 162 | ? data[1].length ~/ 8 163 | : data[1].length ~/ 8 + 1, 164 | (int i) => Padding( 165 | padding: const EdgeInsets.only(bottom: 20.0), 166 | child: Row( 167 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 168 | children: List.generate( 169 | (data[1].length - storage - 1) >= 8 170 | ? 8 171 | : data[1].length - storage - 1, 172 | (int index) { 173 | storage = index + i * 8; 174 | return Image.asset( 175 | 'assets/what_i_do/${data[1][index + i * 8]}', 176 | ); 177 | }), 178 | ), 179 | ), 180 | ), 181 | ), 182 | ), 183 | ], 184 | ); 185 | } 186 | }), 187 | ) 188 | ]), 189 | ); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /lib/src/projects/card.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../custom/custom_text.dart'; 4 | import '../html_open_link.dart'; 5 | import '../theme/config.dart'; 6 | import 'data.dart'; 7 | 8 | class ProjectsCard extends StatefulWidget { 9 | const ProjectsCard( 10 | {Key? key, 11 | required this.title, 12 | required this.techStack, 13 | required this.desc, 14 | required this.link, 15 | required this.isMobile}) 16 | : super(key: key); 17 | 18 | final String title, techStack, desc, link; 19 | final bool isMobile; 20 | @override 21 | _ProjectsCardState createState() => _ProjectsCardState(); 22 | } 23 | 24 | class _ProjectsCardState extends State { 25 | bool isHover = false; 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | final double height = MediaQuery.of(context).size.height; 30 | final double width = MediaQuery.of(context).size.width; 31 | return AnimatedContainer( 32 | decoration: BoxDecoration( 33 | boxShadow: [ 34 | BoxShadow( 35 | color: isHover ? Colors.black12 : Colors.black45, 36 | blurRadius: 10.0, 37 | offset: const Offset(8, 12), 38 | ) 39 | ], 40 | ), 41 | duration: const Duration(milliseconds: 200), 42 | padding: EdgeInsets.only( 43 | top: isHover ? height * 0.005 : height * 0.01, 44 | bottom: !isHover ? height * 0.005 : height * 0.01), 45 | child: InkWell( 46 | onHover: (bool value) { 47 | setState(() { 48 | isHover = value; 49 | }); 50 | }, 51 | onTap: () => htmlOpenLink(widget.link), 52 | child: Container( 53 | alignment: Alignment.topCenter, 54 | padding: EdgeInsets.only( 55 | top: height * 0.02, 56 | left: width * 0.015, 57 | right: width * 0.015, 58 | bottom: height * 0.02), 59 | width: !widget.isMobile ? width * 0.28 : width, 60 | decoration: BoxDecoration( 61 | boxShadow: [ 62 | BoxShadow( 63 | color: isHover ? Colors.black12 : Colors.black45, 64 | blurRadius: 10.0, 65 | offset: const Offset(8, 12), 66 | ) 67 | ], 68 | color: currentTheme.currentTheme == ThemeMode.dark 69 | ? Theme.of(context).cardColor 70 | : Theme.of(context).primaryColor, 71 | borderRadius: BorderRadius.circular( 72 | 5.0, 73 | ), 74 | ), 75 | child: (widget.title == '' && widget.link != '') 76 | ? FutureBuilder( 77 | future: github(widget.link), 78 | builder: 79 | (BuildContext context, AsyncSnapshot snapshot) { 80 | if (snapshot.hasData) { 81 | final List data = snapshot.data as List; 82 | return Column( 83 | children: [ 84 | Center( 85 | child: Column( 86 | children: [ 87 | FittedBox( 88 | fit: BoxFit.cover, 89 | child: CustomText( 90 | text: data[0], 91 | fontSize: 25, 92 | color: Colors.white)), 93 | Padding( 94 | padding: const EdgeInsets.only( 95 | top: 5.0, bottom: 16.0), 96 | child: FittedBox( 97 | fit: BoxFit.cover, 98 | child: CustomText( 99 | text: data[1], 100 | fontSize: 14, 101 | color: Colors.white)), 102 | ), 103 | CustomText( 104 | text: data[2], 105 | fontSize: 15, 106 | color: Colors.white), 107 | ], 108 | ), 109 | ), 110 | Row( 111 | children: [ 112 | Image.asset('assets/projects/constant/stars.png', 113 | scale: 2), 114 | Padding( 115 | padding: const EdgeInsets.only(right: 24.0), 116 | child: CustomText( 117 | text: ' ${data[3]}', 118 | fontSize: 12, 119 | color: Colors.white), 120 | ), 121 | Image.asset('assets/projects/constant/forks.png', 122 | scale: 2), 123 | CustomText( 124 | text: ' ${data[4]}', 125 | fontSize: 12, 126 | color: Colors.white), 127 | ], 128 | ), 129 | ], 130 | ); 131 | } 132 | return const Center(); 133 | }) 134 | : Column( 135 | children: [ 136 | Center( 137 | child: Column( 138 | children: [ 139 | FittedBox( 140 | fit: BoxFit.cover, 141 | child: CustomText( 142 | text: widget.title, 143 | fontSize: 25, 144 | color: Colors.white)), 145 | Padding( 146 | padding: 147 | const EdgeInsets.only(top: 5.0, bottom: 16.0), 148 | child: FittedBox( 149 | fit: BoxFit.cover, 150 | child: CustomText( 151 | text: widget.techStack, 152 | fontSize: 14, 153 | color: Colors.white)), 154 | ), 155 | CustomText( 156 | text: widget.desc, 157 | fontSize: 15, 158 | color: Colors.white), 159 | ], 160 | ), 161 | ), 162 | FutureBuilder( 163 | future: starsAndForks(widget.link), 164 | builder: (BuildContext context, 165 | AsyncSnapshot snapshot) { 166 | if (snapshot.hasData) { 167 | final List data = 168 | snapshot.data as List; 169 | if (data[1] == 'null' && data[0] == 'null') 170 | return const Center(); 171 | return Padding( 172 | padding: 173 | const EdgeInsets.only(top: 8.0, left: 5.0), 174 | child: Row( 175 | children: [ 176 | Image.asset( 177 | 'assets/projects/constant/stars.png', 178 | scale: 2), 179 | Padding( 180 | padding: const EdgeInsets.only(right: 24.0), 181 | child: CustomText( 182 | text: ' ${data[0]}', 183 | fontSize: 12, 184 | color: Colors.white), 185 | ), 186 | Image.asset( 187 | 'assets/projects/constant/forks.png', 188 | scale: 2), 189 | CustomText( 190 | text: ' ${data[1]}', 191 | fontSize: 12, 192 | color: Colors.white), 193 | ], 194 | ), 195 | ); 196 | } 197 | return const Center(); 198 | }), 199 | ], 200 | ), 201 | ), 202 | ), 203 | ); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /assets/portfolio.json: -------------------------------------------------------------------------------- 1 | { 2 | "name_and_link": [ 3 | "Shourya Shikhar Ghosh", 4 | "https://github.com/danger-ahead/" 5 | ], 6 | "designation": [ 7 | "CS Undergrad.", 8 | "Flutter Developer." 9 | ], 10 | "resume_download_link": "https://docs.google.com/document/d/15T64f6XCPKDaJX7CUFDIqly-H4PcudLTWDlKGxb9IvQ/edit?usp=sharing/export?format=pdf", 11 | "social_media": { 12 | "1": [ 13 | "https://github.com/danger-ahead/", 14 | "github" 15 | ], 16 | "2": [ 17 | "https://leetcode.com/danger-ahead/", 18 | "leetcode" 19 | ], 20 | "3": [ 21 | "https://linkedin.com/in/shourya-shikhar/", 22 | "linkedin" 23 | ], 24 | "4": [ 25 | "https://stackoverflow.com/users/10951873/shourya-shikhar", 26 | "stackoverflow" 27 | ], 28 | "5": [ 29 | "https://twitter.com/___shourya___/", 30 | "twitter" 31 | ], 32 | "6": [ 33 | "mailto:danger.ahead@pm.me", 34 | "email" 35 | ] 36 | }, 37 | "contact_me": { 38 | "location": "Kolkata, India", 39 | "open_for_opportunities": "Yes", 40 | "picture": "picture.png" 41 | }, 42 | "about": "A passionate Software Developer 🚀 | Open Source enthusiast 📝 | Maintainer 👷", 43 | "bio": "Sophomore CS Engineering student. I spend my leisure time contributing to open source projects and browsing Stack Overflow. I've hands-on experience in working on several projects that use Python, Node.js, Flutter, Java, etc. Most of my projects are released as open-source on GitHub.", 44 | "what_i_do": { 45 | "tools": [ 46 | "flutter.png", 47 | "linux.png", 48 | "c.png", 49 | "cpp.png", 50 | "java.png", 51 | "python.png", 52 | "bash.png", 53 | "git.png" 54 | ], 55 | "proficiency": [ 56 | "Flutter--50", 57 | "C/C++/Java/Python--60", 58 | "GNU/Linux--30", 59 | "Git--65" 60 | ] 61 | }, 62 | "education": { 63 | "1": { 64 | "institute": "RCC Institute of Information Technology", 65 | "location": "Kolkata", 66 | "years": "2020 - 2024", 67 | "description": "B.Tech in CSE", 68 | "grades": "9.53 YGPA", 69 | "logo": "rcciit.png" 70 | }, 71 | "2": { 72 | "institute": "Gitaram Academy", 73 | "location": "Berhampore", 74 | "years": "2018 - 2020", 75 | "description": "Physics, Chemistry, Mathematics, Computer Science", 76 | "grades": "84%", 77 | "logo": "gitaram.png" 78 | }, 79 | "3": { 80 | "institute": "The St. Xavier's School", 81 | "location": "Malda", 82 | "years": "2004 - 2018", 83 | "description": "Secondary Education", 84 | "grades": "94%", 85 | "logo": "stxaviers.png" 86 | } 87 | }, 88 | "experience": { 89 | "1": { 90 | "name": "Ekko", 91 | "role": "Web and App Intern", 92 | "period": "June, 2022 - Present", 93 | "description": "Working in the web and app team.", 94 | "image_name": "ekko.png" 95 | }, 96 | "2": { 97 | "name": "Credanic", 98 | "role": "Flutter SDE Intern", 99 | "period": "December, 2021 - February, 2021", 100 | "description": "Worked in the Flutter App Dev Team.", 101 | "image_name": "credanic.png" 102 | }, 103 | "3": { 104 | "name": "Google Developer Student Club", 105 | "role": "Cybersecurity core member", 106 | "period": "September, 2021 - Present", 107 | "description": "Helped in organizing and conducting technical workshops, and informative webinars for community members.", 108 | "image_name": "GDSC.png" 109 | }, 110 | "4": { 111 | "name": "RccTechz - RCCIIT Tech Chapter", 112 | "role": "Member", 113 | "period": "March, 2021 - March, 2022", 114 | "description": "Official Tech chapter of RCCIIT, RCCTechz. Contributed to Club activities, helped other members with projects and helped coordinate workshops.", 115 | "image_name": "rcctechz.png" 116 | }, 117 | "5": { 118 | "name": "Coding Ninjas", 119 | "role": "Campus Ambassador", 120 | "period": "August, 2021 - February, 2022", 121 | "description": "Promoting the company's courses, sharing referrals and conducting workshops.", 122 | "image_name": "coding-ninjas.png" 123 | }, 124 | "6": { 125 | "name": "Open Source", 126 | "role": "Contributor", 127 | "period": "December, 2020 - Present", 128 | "description": "Completed Hacktoberfest'21 with 6 merged pull requests.", 129 | "image_name": "opensource.png" 130 | } 131 | }, 132 | "projects": { 133 | "1": { 134 | "name": "Regalia '22 Backend", 135 | "tech_stack_used": "FastAPI and MongoDB (using Python)", 136 | "description": "Backend of Regalia '22, RCCIIT's cultural fest. Handled total entries for 1.2K+ attendees on both the event days each. Also handled on-spot registrations (including sending passes through email using MAILGUN API) and free entries, without encountering a single production bug.", 137 | "general_or_github_link": "https://github.com/danger-ahead/regalia-2022-backend" 138 | }, 139 | "2": { 140 | "name": "TechTrix '22 Backend", 141 | "tech_stack_used": "FastAPI and MongoDB (using Python)", 142 | "description": "Made the backend of TechTrix '22, RCCIIT's tech fest. Handled 435+ participants, 60+ coordinators, and 560+ event registrations, without encountering a single production bug.", 143 | "general_or_github_link": "https://github.com/danger-ahead/techtrix22-backend" 144 | }, 145 | "3": { 146 | "name": "Calculator", 147 | "tech_stack_used": "Flutter", 148 | "description": "Calculator app based on Soft UI (neumorphism), having simple and advanced modes. Also has a history section to save previously performed operations (using FLUTTER SQLITE). Supports 3 theme modes - system default, light and dark. State management approach used - RIVERPOD. PUBLISHED ON F-DROID.", 149 | "general_or_github_link": "https://github.com/belelaritra/Neumorphic_Calculator" 150 | }, 151 | "4": { 152 | "name": "flutter_dev_folio", 153 | "tech_stack_used": "Flutter", 154 | "description": "Minimal, Beautiful and responsive portfolio site template.", 155 | "general_or_github_link": "https://github.com/danger-ahead/flutter_dev_folio" 156 | }, 157 | "5": { 158 | "name": "roBOT - Discord bot", 159 | "tech_stack_used": "Python, MongoDB, REST APIs", 160 | "description": "Bot with administrative commands (for kick, ban, mute, etc) and other fun commands (for memes, movies, jokes, etc).", 161 | "general_or_github_link": "https://github.com/danger-ahead/roBOT" 162 | }, 163 | "6": { 164 | "name": "cinephilic", 165 | "tech_stack_used": "HTML, CS, JS", 166 | "description": "A chrome extension for showing the current trending movies in new tab.", 167 | "general_or_github_link": "https://github.com/quasar-rcciit/cinephilic" 168 | }, 169 | "7": { 170 | "name": "Dictionary", 171 | "tech_stack_used": "Flutter, SQLite, REST APIs", 172 | "description": "Multi-language dictionary app with support for audio pronunciation (English only).", 173 | "general_or_github_link": "https://github.com/danger-ahead/flutter_dictionary" 174 | }, 175 | "8":{ 176 | "name": "Note", 177 | "tech_stack_used": "JAVA, MySQL", 178 | "description": "Simple terminal based Note Taking Application.", 179 | "general_or_github_link": "https://github.com/danger-ahead/Note" 180 | }, 181 | "9":{ 182 | "name": "Enigma-tic-cryption", 183 | "tech_stack_used": "C++", 184 | "description": "Follows the exact encryption method used by the enigma. Has multiple modes for setting different rotors.", 185 | "general_or_github_link": "https://github.com/danger-ahead/enigma-tic-cryption" 186 | } 187 | }, 188 | "achievements": { 189 | "1": { 190 | "description": "Worked in a team (Quasar) at HackNPitch’21 (hackathon organised by JU E-Cell ) and ranked in the top 6 (earned the special mention tag) among 50+ other teams across India.", 191 | "link": "https://www.linkedin.com/posts/juecell_hacknpitch-include-hackathon-activity-6849231722333249536-qqw2" 192 | }, 193 | "2": { 194 | "description": "Won Filecoin track prize from Filecoin for the best use of Filecoin and/or IPFS in a hackathon project (worth Rs. 20,000).", 195 | "link": "https://www.linkedin.com/posts/shourya-shikhar_dapp-filecoin-decentralized-activity-6889903951555235840-FuLM" 196 | }, 197 | "3": { 198 | "description": "Have 600+ reputation points in Stack Overflow.", 199 | "link": "https://stackoverflow.com/users/10951873/shourya-shikhar" 200 | }, 201 | "4": { 202 | "description": "Completed 30 Days of Google Cloud '21.\n- Completed Cloud Engineering Track\n- Completed Data Science & Machine Learning Track", 203 | "link": "https://www.qwiklabs.com/public_profiles/d317f0a6-63b7-4c9f-be77-066e75ba3c6a" 204 | }, 205 | "5": { 206 | "description": "Completed Hacktoberfest '21 with 6 merged PRs.", 207 | "link": "https://www.linkedin.com/posts/shourya-shikhar_hacktoberfest2021-hacktoberfest-opensource-activity-6857565719031361536-OpX8" 208 | } 209 | } 210 | } -------------------------------------------------------------------------------- /lib/tabs/contact_me.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../src/contact_me/data.dart'; 4 | import '../src/contact_me/my_bio.dart'; 5 | import '../src/custom/custom_text.dart'; 6 | import '../src/home/social_media_bar.dart'; 7 | import '../src/html_open_link.dart'; 8 | import '../src/theme/config.dart'; 9 | import '../src/theme/custom_theme.dart'; 10 | 11 | class ContactMe extends StatefulWidget { 12 | const ContactMe({Key? key}) : super(key: key); 13 | 14 | @override 15 | _ContactMeState createState() => _ContactMeState(); 16 | } 17 | 18 | class _ContactMeState extends State { 19 | final List data = contactMe(); 20 | final List getNameAndLink = nameAndLink(); 21 | bool isHover = false; 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | final double width = MediaQuery.of(context).size.width; 26 | final double height = MediaQuery.of(context).size.height; 27 | 28 | Widget imageWidget(double scale) { 29 | return AnimatedContainer( 30 | duration: const Duration(milliseconds: 200), 31 | padding: EdgeInsets.only( 32 | top: isHover ? height * 0.005 : height * 0.01, 33 | bottom: !isHover ? height * 0.005 : height * 0.01), 34 | child: InkWell( 35 | onTap: () {}, 36 | onHover: (bool value) { 37 | setState(() { 38 | isHover = value; 39 | }); 40 | }, 41 | hoverColor: Colors.transparent, 42 | splashColor: Colors.transparent, 43 | focusColor: Colors.transparent, 44 | highlightColor: Colors.transparent, 45 | child: ClipOval( 46 | child: data[2] != '' 47 | ? Image.asset('assets/contact_me/${data[2]}', scale: scale) 48 | : Image.asset('assets/contact_me/constant/picture.png', 49 | scale: scale)), 50 | ), 51 | ); 52 | } 53 | 54 | return Column( 55 | mainAxisAlignment: MainAxisAlignment.center, 56 | children: [ 57 | LayoutBuilder( 58 | builder: (BuildContext context, BoxConstraints constraints) { 59 | if (constraints.maxWidth < 1000) { 60 | return Padding( 61 | padding: const EdgeInsets.symmetric(horizontal: 10.0), 62 | child: Column( 63 | children: [ 64 | CustomText( 65 | text: 'Reach Out to me!', 66 | fontSize: 28, 67 | color: Theme.of(context).primaryColorLight), 68 | Padding( 69 | padding: const EdgeInsets.symmetric(vertical: 5.0), 70 | child: Container( 71 | decoration: BoxDecoration( 72 | shape: BoxShape.circle, 73 | border: Border.all( 74 | width: 7, 75 | color: CustomTheme.darkTheme.cardColor, 76 | )), 77 | child: imageWidget(2.7)), 78 | ), 79 | Padding( 80 | padding: const EdgeInsets.symmetric(vertical: 5.0), 81 | child: CustomText( 82 | text: 83 | 'DISCUSS A PROJECT OR JUST WANT TO SAY HI? MY INBOX IS OPEN FOR ALL.', 84 | fontSize: 18, 85 | color: Theme.of(context) 86 | .primaryColorLight 87 | .withOpacity(0.7)), 88 | ), 89 | MyBio(fontSize: 15), 90 | Padding( 91 | padding: const EdgeInsets.only( 92 | bottom: 5.0, 93 | top: 3.0, 94 | ), 95 | child: Row( 96 | mainAxisAlignment: MainAxisAlignment.center, 97 | children: [ 98 | if (data[0] != '') 99 | Image.asset( 100 | currentTheme.currentTheme == ThemeMode.dark 101 | ? 'assets/contact_me/constant/location-dark.png' 102 | : 'assets/contact_me/constant/location.png', 103 | scale: 4) 104 | else 105 | const Center(), 106 | CustomText( 107 | text: ' ${data[0]}', 108 | fontSize: 18, 109 | color: Theme.of(context).primaryColorLight), 110 | ], 111 | ), 112 | ), 113 | Padding( 114 | padding: const EdgeInsets.only( 115 | bottom: 10.0, 116 | top: 5.0, 117 | ), 118 | child: data[1] != '' 119 | ? CustomText( 120 | text: 'Open for opportunities: ${data[1]}', 121 | fontSize: 18, 122 | color: Theme.of(context).primaryColorLight) 123 | : const Center(), 124 | ), 125 | Padding( 126 | padding: const EdgeInsets.only(bottom: 10.0), 127 | child: SocialMediaBar( 128 | height: height, 129 | ), 130 | ), 131 | ], 132 | ), 133 | ); 134 | } else { 135 | return Column( 136 | mainAxisAlignment: MainAxisAlignment.center, 137 | children: [ 138 | Row( 139 | crossAxisAlignment: CrossAxisAlignment.start, 140 | mainAxisAlignment: MainAxisAlignment.spaceAround, 141 | children: [ 142 | SizedBox( 143 | width: width / 2, 144 | child: Column( 145 | crossAxisAlignment: CrossAxisAlignment.start, 146 | children: [ 147 | CustomText( 148 | text: 'Reach Out to me!', 149 | fontSize: 35, 150 | color: Theme.of(context).primaryColorLight), 151 | Padding( 152 | padding: const EdgeInsets.symmetric(vertical: 8.0), 153 | child: CustomText( 154 | text: 155 | 'DISCUSS A PROJECT OR JUST WANT TO SAY HI? MY INBOX IS OPEN FOR ALL.', 156 | fontSize: 18, 157 | color: Theme.of(context) 158 | .primaryColorLight 159 | .withOpacity(0.7)), 160 | ), 161 | MyBio(fontSize: 15), 162 | Padding( 163 | padding: const EdgeInsets.symmetric(vertical: 10.0), 164 | child: Row( 165 | children: [ 166 | if (data[0] != '') 167 | Image.asset( 168 | currentTheme.currentTheme == 169 | ThemeMode.dark 170 | ? 'assets/contact_me/constant/location-dark.png' 171 | : 'assets/contact_me/constant/location.png', 172 | scale: 4) 173 | else 174 | const Center(), 175 | CustomText( 176 | text: ' ${data[0]}', 177 | fontSize: 18, 178 | color: Theme.of(context).primaryColorLight), 179 | ], 180 | ), 181 | ), 182 | if (data[1] != '') 183 | CustomText( 184 | text: 'Open for opportunities: ${data[1]}', 185 | fontSize: 18, 186 | color: Theme.of(context).primaryColorLight) 187 | else 188 | const Center(), 189 | ], 190 | ), 191 | ), 192 | Column( 193 | mainAxisAlignment: MainAxisAlignment.center, 194 | children: [ 195 | Container( 196 | decoration: BoxDecoration( 197 | shape: BoxShape.circle, 198 | border: Border.all( 199 | width: 7, 200 | color: CustomTheme.darkTheme.cardColor, 201 | )), 202 | child: imageWidget(2.5)), 203 | SocialMediaBar( 204 | height: height, 205 | ), 206 | ], 207 | ), 208 | ], 209 | ), 210 | ], 211 | ); 212 | } 213 | }), 214 | Padding( 215 | padding: const EdgeInsets.only(bottom: 3.0), 216 | child: Column( 217 | children: [ 218 | TextButton( 219 | onPressed: () => htmlOpenLink(getNameAndLink[1]), 220 | child: CustomText( 221 | text: 'Made with ❤️ by ${getNameAndLink[0]}', 222 | fontSize: 10, 223 | color: Theme.of(context).primaryColorLight), 224 | ), 225 | TextButton( 226 | onPressed: () => htmlOpenLink( 227 | 'https://github.com/danger-ahead/flutter_dev_folio'), 228 | child: CustomText( 229 | text: 'Theme by flutter_dev_folio', 230 | fontSize: 10, 231 | color: Theme.of(context).primaryColorLight), 232 | ) 233 | ], 234 | ), 235 | ), 236 | ], 237 | ); 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | analyzer: 2 | strong-mode: 3 | implicit-casts: false 4 | implicit-dynamic: true 5 | errors: 6 | # treat missing required parameters as a warning (not a hint) 7 | missing_required_param: warning 8 | # treat missing returns as a warning (not a hint) 9 | missing_return: warning 10 | # allow having TODO comments in the code 11 | todo: ignore 12 | # allow self-reference to deprecated members (we do this because otherwise we have 13 | # to annotate every member in every test, assert, etc, when we deprecate something) 14 | deprecated_member_use_from_same_package: ignore 15 | # TODO(ianh): https://github.com/flutter/flutter/issues/74381 16 | # Clean up existing unnecessary imports, and remove line to ignore. 17 | unnecessary_import: ignore 18 | # Turned off until null-safe rollout is complete. 19 | unnecessary_null_comparison: ignore 20 | exclude: 21 | - "bin/cache/**" 22 | # Ignore protoc generated files 23 | - "dev/conductor/lib/proto/*" 24 | 25 | linter: 26 | rules: 27 | # these rules are documented on and in the same order as 28 | # the Dart Lint rules page to make maintenance easier 29 | # https://github.com/dart-lang/linter/blob/master/example/all.yaml 30 | # - always_declare_return_types 31 | # - always_put_control_body_on_new_line 32 | # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219 33 | - always_require_non_null_named_parameters 34 | # - always_specify_types 35 | # - always_use_package_imports # we do this commonly 36 | - annotate_overrides 37 | # - avoid_annotating_with_dynamic # conflicts with always_specify_types 38 | - avoid_bool_literals_in_conditional_expressions 39 | # - avoid_catches_without_on_clauses # blocked on https://github.com/dart-lang/linter/issues/3023 40 | # - avoid_catching_errors # blocked on https://github.com/dart-lang/linter/issues/3023 41 | - avoid_classes_with_only_static_members 42 | - avoid_double_and_int_checks 43 | # - avoid_dynamic_calls 44 | - avoid_empty_else 45 | - avoid_equals_and_hash_code_on_mutable_classes 46 | - avoid_escaping_inner_quotes 47 | - avoid_field_initializers_in_const_classes 48 | - avoid_function_literals_in_foreach_calls 49 | - avoid_implementing_value_types 50 | - avoid_init_to_null 51 | - avoid_js_rounded_ints 52 | # - avoid_multiple_declarations_per_line # seems to be a stylistic choice we don't subscribe to 53 | - avoid_null_checks_in_equality_operators 54 | # - avoid_positional_boolean_parameters # would have been nice to enable this but by now there's too many places that break it 55 | - avoid_print 56 | # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) 57 | - avoid_redundant_argument_values 58 | - avoid_relative_lib_imports 59 | - avoid_renaming_method_parameters 60 | - avoid_return_types_on_setters 61 | # - avoid_returning_null # still violated by some pre-nnbd code that we haven't yet migrated 62 | - avoid_returning_null_for_future 63 | - avoid_returning_null_for_void 64 | # - avoid_returning_this # there are enough valid reasons to return `this` that this lint ends up with too many false positives 65 | - avoid_setters_without_getters 66 | - avoid_shadowing_type_parameters 67 | - avoid_single_cascade_in_expression_statements 68 | - avoid_slow_async_io 69 | - avoid_type_to_string 70 | - avoid_types_as_parameter_names 71 | # - avoid_types_on_closure_parameters # conflicts with always_specify_types 72 | - avoid_unnecessary_containers 73 | - avoid_unused_constructor_parameters 74 | - avoid_void_async 75 | # - avoid_web_libraries_in_flutter # we use web libraries in web-specific code, and our tests prevent us from using them elsewhere 76 | - await_only_futures 77 | - camel_case_extensions 78 | - camel_case_types 79 | - cancel_subscriptions 80 | # - cascade_invocations # doesn't match the typical style of this repo 81 | # - cast_nullable_to_non_nullable 82 | # - close_sinks # not reliable enough 83 | # - comment_references # blocked on https://github.com/dart-lang/linter/issues/1142 84 | # - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204 85 | - control_flow_in_finally 86 | # - curly_braces_in_flow_control_structures # not required by flutter style 87 | - depend_on_referenced_packages 88 | - deprecated_consistency 89 | # - diagnostic_describe_all_properties # enabled only at the framework level (packages/flutter/lib) 90 | - directives_ordering 91 | # - do_not_use_environment # there are appropriate times to use the environment, especially in our tests and build logic 92 | - empty_catches 93 | - empty_constructor_bodies 94 | - empty_statements 95 | - eol_at_end_of_file 96 | - exhaustive_cases 97 | - file_names 98 | - flutter_style_todos 99 | - hash_and_equals 100 | - implementation_imports 101 | # - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811 102 | - iterable_contains_unrelated_type 103 | # - join_return_with_assignment # not required by flutter style 104 | - leading_newlines_in_multiline_strings 105 | - library_names 106 | - library_prefixes 107 | # - library_private_types_in_public_api 108 | # - lines_longer_than_80_chars # not required by flutter style 109 | - list_remove_unrelated_type 110 | # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/linter/issues/453 111 | - missing_whitespace_between_adjacent_strings 112 | - no_adjacent_strings_in_list 113 | - no_default_cases 114 | - no_duplicate_case_values 115 | - no_logic_in_create_state 116 | # - no_runtimeType_toString # ok in tests; we enable this only in packages/ 117 | - non_constant_identifier_names 118 | - noop_primitive_operations 119 | - null_check_on_nullable_type_parameter 120 | - null_closures 121 | # - omit_local_variable_types # opposite of always_specify_types 122 | # - one_member_abstracts # too many false positives 123 | - only_throw_errors # this does get disabled in a few places where we have legacy code that uses strings et al 124 | - overridden_fields 125 | - package_api_docs 126 | - package_names 127 | - package_prefixed_library_names 128 | # - parameter_assignments # we do this commonly 129 | - prefer_adjacent_string_concatenation 130 | - prefer_asserts_in_initializer_lists 131 | # - prefer_asserts_with_message # not required by flutter style 132 | - prefer_collection_literals 133 | - prefer_conditional_assignment 134 | - prefer_const_constructors 135 | - prefer_const_constructors_in_immutables 136 | - prefer_const_declarations 137 | - prefer_const_literals_to_create_immutables 138 | # - prefer_constructors_over_static_methods # far too many false positives 139 | - prefer_contains 140 | # - prefer_double_quotes # opposite of prefer_single_quotes 141 | - prefer_equal_for_default_values 142 | # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods 143 | - prefer_final_fields 144 | - prefer_final_in_for_each 145 | - prefer_final_locals 146 | # - prefer_final_parameters # we should enable this one day when it can be auto-fixed (https://github.com/dart-lang/linter/issues/3104), see also parameter_assignments 147 | - prefer_for_elements_to_map_fromIterable 148 | - prefer_foreach 149 | - prefer_function_declarations_over_variables 150 | - prefer_generic_function_type_aliases 151 | - prefer_if_elements_to_conditional_expressions 152 | - prefer_if_null_operators 153 | - prefer_initializing_formals 154 | - prefer_inlined_adds 155 | # - prefer_int_literals # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#use-double-literals-for-double-constants 156 | - prefer_interpolation_to_compose_strings 157 | - prefer_is_empty 158 | - prefer_is_not_empty 159 | - prefer_is_not_operator 160 | - prefer_iterable_whereType 161 | # - prefer_mixin # Has false positives, see https://github.com/dart-lang/linter/issues/3018 162 | - prefer_null_aware_operators 163 | # - prefer_null_aware_method_calls # "call()" is confusing to people new to the language since it's not documented anywhere 164 | - prefer_relative_imports 165 | - prefer_single_quotes 166 | - prefer_spread_collections 167 | # - prefer_typing_uninitialized_variables 168 | - prefer_void_to_null 169 | - provide_deprecation_message 170 | # - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml 171 | - recursive_getters 172 | # - require_trailing_commas # blocked on https://github.com/dart-lang/sdk/issues/47441 173 | - sized_box_for_whitespace 174 | - slash_for_doc_comments 175 | - sort_child_properties_last 176 | - sort_constructors_first 177 | # - sort_pub_dependencies # prevents separating pinned transitive dependencies 178 | - sort_unnamed_constructors_first 179 | - test_types_in_equals 180 | - throw_in_finally 181 | - tighten_type_of_initializing_formals 182 | # - type_annotate_public_apis # subset of always_specify_types 183 | - type_init_formals 184 | # - unawaited_futures # too many false positives, especially with the way AnimationController works 185 | - unnecessary_await_in_return 186 | - unnecessary_brace_in_string_interps 187 | - unnecessary_const 188 | - unnecessary_constructor_name 189 | # - unnecessary_final # conflicts with prefer_final_locals 190 | - unnecessary_getters_setters 191 | # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498 192 | - unnecessary_new 193 | - unnecessary_null_aware_assignments 194 | - unnecessary_null_checks 195 | - unnecessary_null_in_if_null_operators 196 | - unnecessary_nullable_for_final_variable_declarations 197 | - unnecessary_overrides 198 | - unnecessary_parenthesis 199 | # - unnecessary_raw_strings # what's "necessary" is a matter of opinion; consistency across strings can help readability more than this lint 200 | - unnecessary_statements 201 | - unnecessary_string_escapes 202 | - unnecessary_string_interpolations 203 | - unnecessary_this 204 | - unrelated_type_equality_checks 205 | # - unsafe_html 206 | - use_build_context_synchronously 207 | - use_full_hex_values_for_flutter_colors 208 | - use_function_type_syntax_for_parameters 209 | # - use_if_null_to_convert_nulls_to_bools # blocked on https://github.com/dart-lang/sdk/issues/47436 210 | - use_is_even_rather_than_modulo 211 | - use_key_in_widget_constructors 212 | - use_late_for_private_fields_and_variables 213 | - use_named_constants 214 | - use_raw_strings 215 | - use_rethrow_when_possible 216 | - use_setters_to_change_properties 217 | # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182 218 | - use_test_throws_matchers 219 | # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review 220 | - valid_regexps 221 | - void_checks --------------------------------------------------------------------------------