diff --git a/assets/hacktoberfest.png b/assets/hacktoberfest.png new file mode 100644 index 0000000..5a6d3e6 Binary files /dev/null and b/assets/hacktoberfest.png differ diff --git a/lib/home_page.dart b/lib/home_page.dart index 437adba..3b490e6 100644 --- a/lib/home_page.dart +++ b/lib/home_page.dart @@ -9,6 +9,7 @@ import 'package:opso/opso_timeline.dart'; import 'package:opso/programs%20screen/girl_script.dart'; import 'package:opso/programs%20screen/google_season_of_docs_screen.dart'; import 'package:opso/programs%20screen/google_summer_of_code_screen.dart'; +import 'package:opso/programs%20screen/hacktoberfest_screen.dart'; import 'package:opso/programs%20screen/linux_foundation.dart'; import 'package:opso/programs%20screen/major_league_hacking_fellowship.dart'; import 'package:opso/programs%20screen/open_summer_of_code.dart'; @@ -100,6 +101,10 @@ class _HomePageState extends State { Program( title: 'Linux Foundation', imageAssetPath: 'assets/linux_foundation_logo.png', + ), + Program( + title: 'Hacktoberfest', + imageAssetPath: 'assets/hacktoberfest.png', ), Program( title: 'Outreachy', @@ -406,6 +411,12 @@ class _HomePageState extends State { case 'Summer of Bitcoin': Navigator.pushNamed(context, "/summer_of_bitcoin"); + + + case 'Hacktoberfest': + Navigator.push(context, + MaterialPageRoute(builder: (context) => const Hacktoberfest())); + case 'Open Summer of Code': @@ -506,6 +517,10 @@ class ProgramSearchDelegate extends SearchDelegate { Program( title: 'Summer of Bitcoin', imageAssetPath: 'assets/summer_of_bitcoin_logo.png', + ), + Program( + title: 'Hacktoberfest', + imageAssetPath: 'assets/hacktoberfest.png', ), Program( title: 'Linux Foundation', @@ -655,6 +670,15 @@ class ProgramSearchDelegate extends SearchDelegate { ), ); break; + + case 'Hacktoberfest': + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const Hacktoberfest(), + ), + ); + break; case 'Linux Foundation': @@ -679,5 +703,4 @@ class Program { required this.title, required this.imageAssetPath, }); -} - +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 80c7f89..dc5d285 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:opso/landing_page.dart'; import 'package:opso/programs%20screen/girl_script.dart'; import 'package:opso/programs%20screen/google_season_of_docs_screen.dart'; import 'package:opso/programs%20screen/google_summer_of_code_screen.dart'; +import 'package:opso/programs%20screen/hacktoberfest_screen.dart'; import 'package:opso/programs%20screen/linux_foundation.dart'; import 'package:opso/programs%20screen/major_league_hacking_fellowship.dart'; import 'package:opso/programs%20screen/open_summer_of_code.dart'; @@ -50,6 +51,7 @@ class OpSoApp extends StatelessWidget { "/google_season_of_docs": (context) => GoogleSeasonOfDocsScreen(), "/summer_of_bitcoin": (context) => const SummerOfBitcoin(), + "/hacktoberfest_screen": (context) => const Hacktoberfest(), "/open_summer_of_code": (context) => const OpenSummerOfCode(), "/outreachy": (context) => const OutreachyScreen(), "/major_league_hacking_fellowship": (context) => @@ -71,4 +73,4 @@ class OpSoApp extends StatelessWidget { ); }); } -} +} \ No newline at end of file diff --git a/lib/programs screen/hacktoberfest_screen.dart b/lib/programs screen/hacktoberfest_screen.dart new file mode 100644 index 0000000..230b49b --- /dev/null +++ b/lib/programs screen/hacktoberfest_screen.dart @@ -0,0 +1,403 @@ +import 'package:flutter/material.dart'; +import 'package:opso/modals/book_mark_model.dart'; +import 'package:timeline_tile/timeline_tile.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class Hacktoberfest extends StatefulWidget { + const Hacktoberfest({super.key}); + + @override + State createState() => _HacktoberfestState(); +} + +class _HacktoberfestState extends State { + bool isBookmarked = true; + String currectPage = "/Hacktoberfest"; + String currentProject = "Hacktoberfest"; + + @override + void initState() { + super.initState(); + _checkBookmarkStatus(); + } + + Future _checkBookmarkStatus() async { + bool bookmarkStatus = await HandleBookmark.isBookmarked(currentProject); + setState(() { + isBookmarked = bookmarkStatus; + }); + } + + Future _refresh() async { + setState(() {}); + } + + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + double gap = screenWidth * 0.05; + double pad = screenWidth * 0.04; + double titleSize = screenWidth * 0.05; + double contentSize = screenWidth * 0.04; + return RefreshIndicator( + onRefresh: _refresh, + child: Scaffold( + appBar: AppBar( + title: const Text('Hacktoberfest'), + actions: [ + IconButton( + icon: (isBookmarked) + ? const Icon(Icons.bookmark_add_rounded) + : const Icon(Icons.bookmark_add_outlined), + onPressed: () { + setState(() { + isBookmarked = !isBookmarked; + }); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + isBookmarked ? 'Bookmark added' : 'Bookmark removed'), + duration: const Duration(seconds: 2), + ), + ); + if (isBookmarked) { + print("Adding"); + HandleBookmark.addBookmark(currentProject, currectPage); + } else { + print("Deleting"); + HandleBookmark.deleteBookmark(currentProject); + } + }, + ) + ], + ), + body: SingleChildScrollView( + padding: EdgeInsets.all(pad), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.symmetric(vertical: pad), + child: Text( + 'Celebrate Open Source and Grow Your Skills with Hacktoberfest!', + style: TextStyle( + fontSize: titleSize, fontWeight: FontWeight.bold, color: Colors.white), + ), + ), + Padding( + padding: EdgeInsets.symmetric(vertical: pad), + child: Text( + 'Hacktoberfest is an annual event in October, organized by DigitalOcean and GitHub, to promote open-source contributions. Participants submit pull requests to GitHub repositories, fostering community, learning, and collaboration among developers worldwide.', + style: TextStyle( + fontSize: contentSize, + color: Colors.white, + ), + ), + ), + Row( + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.orange, + foregroundColor: Colors.black, + ), + onPressed: () async { + await _launchUrl("https://hacktoberfest.com/"); + }, + child: const Text("Website")), + SizedBox(width: gap), + ElevatedButton( + onPressed: () async { + await _launchUrl( + "https://hacktoberfest.com/about/"); + }, + child: const Text("Learn More")), + ], + ), + SizedBox(height: gap), + Padding( + padding: EdgeInsets.symmetric(vertical: pad), + child: Text( + 'How to find issues in Hacktoberfest', + style: TextStyle( + fontSize: titleSize, fontWeight: FontWeight.bold, color: Colors.white), + ), + ), + Padding( + padding: EdgeInsets.symmetric(vertical: pad), + child: RichText( + text: TextSpan( + style: TextStyle( + fontSize: contentSize, + color: Colors.white, + height: 1.5, // Adjusts line spacing + ), + children: [ + TextSpan( + text: '1. ', + style: TextStyle(fontWeight: FontWeight.bold), + ), + TextSpan( + text: 'First, go to GitHub.\n', + ), + TextSpan( + text: '2. ', + style: TextStyle(fontWeight: FontWeight.bold), + ), + TextSpan( + text: 'Click on "Issues."\n', + ), + TextSpan( + text: '3. ', + style: TextStyle(fontWeight: FontWeight.bold), + ), + TextSpan( + text: 'Use the filter: is:open is:issue archived:false label:hacktoberfest\n', + ), + TextSpan( + text: '4. ', + style: TextStyle(fontWeight: FontWeight.bold), + ), + TextSpan( + text: 'Solve issues and make your contributions.', + ), + ], + ), + ), + ), + + Padding( + padding: EdgeInsets.symmetric(vertical: pad), + child: Text( + 'For Maintainers', + style: TextStyle( + fontSize: titleSize, fontWeight: FontWeight.bold, color: Colors.white), + ), + ), + Padding( + padding: EdgeInsets.symmetric(vertical: pad), + child: Text( + 'Prepare your project for contributions by following these best practices:\n\n' + '1. Add the “hacktoberfest” topic to your repository to opt-in to Hacktoberfest and indicate you’re looking for contributions.\n\n' + '2. Apply the “hacktoberfest” label to issues you want contributors to help with in your GitHub or GitLab project.\n\n' + '3. Add a CONTRIBUTING.md file with contribution guidelines to your repository.\n\n' + '4. Choose issues that have a well-defined scope and are self-contained.\n\n' + '5. Adopt a code of conduct to create a greater sense of inclusion and community for contributors.\n\n' + '6. Be ready to review pull/merge requests, accepting those that are valid by merging them, leaving an overall approving review, or by adding the “hacktoberfest-accepted” label.\n\n' + '7. Reject any spammy requests you receive by labeling them as “spam,” and any other invalid contributions by closing them or labeling them as “invalid.”', + style: TextStyle( + fontSize: contentSize, + color: Colors.white, + height: 1.5, // Adjusts line spacing + ), + ), + ), + SizedBox(height: gap), + _buildTimeline(), + SizedBox(height: gap), + Center( + child: ElevatedButton( + onPressed: () { + _launchUrl('https://hacktoberfest.com/participation/#faq'); + }, + child: const Text('Read the FAQ'), + ), + ), + ], + ), + ), + ), + ); + } + + Widget _buildTrackTile(String title, String description, VoidCallback onTap) { + return InkWell( + onTap: onTap, + child: Card( + surfaceTintColor: Colors.orange, + elevation: 4.0, + margin: const EdgeInsets.symmetric(vertical: 10.0), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.orange)), + const SizedBox(height: 8), + Text(description), + ], + ), + ), + ), + ); + } + + Widget _buildTimelineItem( + {required String time, + required String title, + required String description}) { + return TimelineTile( + alignment: TimelineAlign.start, + isFirst: true, + indicatorStyle: const IndicatorStyle( + width: 40.0, + color: Colors.orange, + padding: EdgeInsets.all(8.0), + ), + endChild: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + time, + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 8.0), + Text( + title, + style: const TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 4.0), + Text(description), + ], + ), + ), + ); + } +} + + Widget _buildTimeline() { + return Column( + children: [ + _buildTimelineItem( + time: 'October 1, 2024', + title: 'Hacktoberfest Starts', + description: 'The event kicks off and repositories start receiving contributions.', + ), + _buildTimelineItem( + time: 'October 31, 2024', + title: 'Hacktoberfest Ends', + description: 'The event concludes and final contributions are counted.', + ), + ], + ); + } + + + + Widget _buildTimelineItem( + {required String time, + required String title, + required String description}) { + return TimelineTile( + alignment: TimelineAlign.start, + isFirst: true, + indicatorStyle: const IndicatorStyle( + width: 40.0, + color: Colors.orange, + padding: EdgeInsets.all(8.0), + ), + endChild: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + time, + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 8.0), + Text( + title, + style: const TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 4.0), + Text(description), + ], + ), + ), + ); + } + + +class TrackDetailsScreen extends StatelessWidget { + final String title, description; + final String? url; + + const TrackDetailsScreen( + {super.key, required this.title, required this.description, this.url}); + + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + double gap = screenWidth * 0.05; + double pad = screenWidth * 0.04; + double titleSize = screenWidth * 0.05; + double contentSize = screenWidth * 0.04; + return Scaffold( + appBar: AppBar( + title: Text(title), + ), + body: SingleChildScrollView( + padding: EdgeInsets.all(pad), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.symmetric(vertical: pad), + child: Text( + title, + style: + TextStyle(fontSize: titleSize, fontWeight: FontWeight.bold, color: Colors.white), + ), + ), + SizedBox(height: gap), + Padding( + padding: EdgeInsets.symmetric(vertical: pad), + child: Text( + description, + style: TextStyle( + fontSize: contentSize, + color: Colors.white, + ), + ), + ), + SizedBox(height: gap), + (url != null && url!.isNotEmpty) + ? Center( + child: ElevatedButton( + onPressed: () { + _launchUrl(url!); + }, + child: const Text('Explore More'), + ), + ) + : Container(), + ], + ), + ), + ); + } +} + +Future _launchUrl(String url) async { + final Uri uri = Uri.parse(url); + if (!await launchUrl(uri)) { + throw 'Could not launch $url'; + } +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index dc98038..1ed692f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -268,26 +268,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.0" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "2.0.1" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "2.0.1" lints: dependency: transitive description: @@ -316,10 +316,10 @@ packages: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.11.0" multi_select_flutter: dependency: "direct main" description: @@ -497,10 +497,10 @@ packages: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.6.1" timeline_tile: dependency: "direct main" description: @@ -617,10 +617,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "13.0.0" web: dependency: transitive description: @@ -663,4 +663,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.3.3 <4.0.0" - flutter: ">=3.19.0" + flutter: ">=3.19.0" \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 65d4ace..3d8ae6d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -92,6 +92,7 @@ flutter: - assets/splash screen.png - assets/github_swag.png - assets/sokde.png + - assets/hacktoberfest.png - assets/xyz_domain.png - assets/participation_certificate.png - assets/coding_ninja_swag.png