diff --git a/.metadata b/.metadata index 0f055bf..56bfc2c 100644 --- a/.metadata +++ b/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: ffb2ecea5223acdd139a5039be2f9c796962833d + revision: f4abaa0735eba4dfd8f33f73363911d63931fe03 channel: stable project_type: app diff --git a/README.md b/README.md index 9152445..29253f7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# Flutter Course Code +# bottom_navigation_bar + +A new Flutter project. ## Getting Started diff --git a/android/.gitignore b/android/.gitignore index 6f56801..0a741cb 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -9,5 +9,3 @@ GeneratedPluginRegistrant.java # Remember to never publicly share your keystore. # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app key.properties -**/*.keystore -**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle index 617083c..5d441f8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -28,22 +28,13 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { compileSdkVersion 30 - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - sourceSets { main.java.srcDirs += 'src/main/kotlin' } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.contacts_01" + applicationId "com.example.bottom_navigation_bar" minSdkVersion 16 targetSdkVersion 30 versionCode flutterVersionCode.toInteger() diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 47d7ea9..c0d80f0 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.example.bottom_navigation_bar"> diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 609e8ad..44fbb2d 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + package="com.example.bottom_navigation_bar"> + package="com.example.bottom_navigation_bar"> diff --git a/android/build.gradle b/android/build.gradle index ed45c65..9b6ed06 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -2,7 +2,7 @@ buildscript { ext.kotlin_version = '1.3.50' repositories { google() - mavenCentral() + jcenter() } dependencies { @@ -14,7 +14,7 @@ buildscript { allprojects { repositories { google() - mavenCentral() + jcenter() } } diff --git a/images/m-cloudy.png b/images/m-cloudy.png new file mode 100644 index 0000000..fa0b07d Binary files /dev/null and b/images/m-cloudy.png differ diff --git a/images/rainy.jpg b/images/rainy.jpg new file mode 100644 index 0000000..3a1fc0b Binary files /dev/null and b/images/rainy.jpg differ diff --git a/images/sun.png b/images/sun.png new file mode 100644 index 0000000..aad8882 Binary files /dev/null and b/images/sun.png differ diff --git a/images/unnamed.jpg b/images/unnamed.jpg new file mode 100644 index 0000000..e0d6ba5 Binary files /dev/null and b/images/unnamed.jpg differ diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 8d4492f..9367d48 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 8.0 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 5d430f2..c9b0529 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -291,7 +291,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.example.contacts01; + PRODUCT_BUNDLE_IDENTIFIER = com.example.bottomNavigationBar; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -415,7 +415,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.example.contacts01; + PRODUCT_BUNDLE_IDENTIFIER = com.example.bottomNavigationBar; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -434,7 +434,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.example.contacts01; + PRODUCT_BUNDLE_IDENTIFIER = com.example.bottomNavigationBar; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index e2eed25..672e2e9 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -11,7 +11,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - contacts_01 + bottom_navigation_bar CFBundlePackageType APPL CFBundleShortVersionString diff --git a/lib/Task_1/home_screen.dart b/lib/Task_1/home_screen.dart new file mode 100644 index 0000000..534cdd9 --- /dev/null +++ b/lib/Task_1/home_screen.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart'; +import 'instagram_ui.dart'; + +class HomeScreen extends StatelessWidget { + const HomeScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.black, + child: SingleChildScrollView( + child: Column( + children: [ + ...postContent.map((val) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: CircleAvatar( + backgroundImage: NetworkImage(val.userImage), + ), + ), + Text( + val.userName, + style: const TextStyle(color: Colors.white), + ) + ], + ), + Image.network( + val.postImage, + height: 300, + width: double.infinity, + fit: BoxFit.cover, + ), + Row( + children: [ + IconButton( + onPressed: () {}, + icon: const Icon(Icons.favorite_outline), + color: Colors.white, + iconSize: 45, + ), + IconButton( + onPressed: () {}, + icon: const Icon(Icons.location_on_outlined), + color: Colors.white, + iconSize: 45, + ), + Expanded( + child: Container(), + ), + IconButton( + onPressed: () {}, + icon: const Icon(Icons.more_vert), + color: Colors.white, + iconSize: 45, + ), + ], + ), + Padding( + padding: const EdgeInsets.fromLTRB(10.0, 0.0, 0.0, 16.0), + child: Text( + '${val.likes} Likes', + style: const TextStyle( + color: Colors.white, + fontSize: 25, + fontWeight: FontWeight.w800), + ), + ), + ], + ); + }).toList(), + ], + ), + ), + ); + } +} diff --git a/lib/Task_1/instagram_ui.dart b/lib/Task_1/instagram_ui.dart new file mode 100644 index 0000000..7f055b7 --- /dev/null +++ b/lib/Task_1/instagram_ui.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; +import 'home_screen.dart'; +import 'posts.dart'; + +void main() => runApp(const InstagramUiApp()); + +class InstagramUiApp extends StatelessWidget { + const InstagramUiApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + title: 'instagram', + home: MyHomePage(), + ); + } +} + +final List postContent = [ + Posts( + postImage: + 'https://images.pexels.com/photos/1254913/pexels-photo-1254913.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500', + userImage: + 'data:image/jpeg;base64,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', + likes: '${130}', + userName: 'fh_5am'), + Posts( + postImage: + 'https://images.pexels.com/photos/1544923/pexels-photo-1544923.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500', + userImage: + 'https://images.unsplash.com/flagged/photo-1570612861542-284f4c12e75f?ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8cGVyc29ufGVufDB8fDB8fA%3D%3D&ixlib=rb-1.2.1&w=1000&q=80', + likes: '${304}', + userName: '11_qr'), + Posts( + postImage: + 'https://images.pexels.com/photos/1544947/pexels-photo-1544947.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500', + userImage: + 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8cGVyc29ufGVufDB8fDB8fA%3D%3D&ixlib=rb-1.2.1&w=1000&q=80', + likes: '${212}', + userName: 'etoi12'), + Posts( + postImage: + 'https://images.pexels.com/photos/1544942/pexels-photo-1544942.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500', + userImage: + 'https://t4.ftcdn.net/jpg/03/83/25/83/360_F_383258331_D8imaEMl8Q3lf7EKU2Pi78Cn0R7KkW9o.jpg', + likes: '${148}', + userName: 'nane01'), +]; + +class MyHomePage extends StatefulWidget { + const MyHomePage({Key? key}) : super(key: key); + + @override + _MyHomePageState createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + int _selectedIndex = 0; + + void _onItemTapped(int index) { + setState(() { + _selectedIndex = index; + }); + } + + static late List _pages; + _MyHomePageState() { + _pages = const [ + HomeScreen(), + Center( + child: Text( + 'No Notifications Yet', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + ), + Center( + child: Text( + 'Your Profile', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + ), + Center( + child: Text( + 'No Messages Yet', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + ), + ]; + } + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('instagram'), + actions: [ + IconButton(onPressed: () {}, icon: const Icon(Icons.message_outlined)) + ], + backgroundColor: Colors.black87, + ), + body: _pages[_selectedIndex], + bottomNavigationBar: BottomNavigationBar( + backgroundColor: Colors.black87, + unselectedItemColor: Colors.white, + selectedItemColor: Colors.white70, + items: const [ + BottomNavigationBarItem( + backgroundColor: Colors.black87, + icon: Icon( + Icons.home_outlined, + ), + activeIcon: Icon(Icons.home), + label: 'Home', + ), + BottomNavigationBarItem( + backgroundColor: Colors.black87, + icon: Icon( + Icons.favorite_outline, + ), + activeIcon: Icon(Icons.favorite), + label: 'Notifications', + ), + BottomNavigationBarItem( + backgroundColor: Colors.black87, + icon: Icon( + Icons.person_outline, + ), + activeIcon: Icon(Icons.person), + label: 'Profile', + ), + ], + currentIndex: _selectedIndex, + onTap: _onItemTapped, + ), + ); + } +} diff --git a/lib/Task_1/posts.dart b/lib/Task_1/posts.dart new file mode 100644 index 0000000..f0d1b62 --- /dev/null +++ b/lib/Task_1/posts.dart @@ -0,0 +1,10 @@ +class Posts { + String postImage, userImage, userName, likes; + + Posts({ + required this.postImage, + required this.userImage, + required this.userName, + required this.likes, + }); +} diff --git a/lib/Task_2/new_note_page.dart b/lib/Task_2/new_note_page.dart new file mode 100644 index 0000000..3f97df8 --- /dev/null +++ b/lib/Task_2/new_note_page.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'note_model.dart'; + +class NewNotePage extends StatefulWidget { + const NewNotePage(this.noteModel, {Key? key}) : super(key: key); + final NoteModel noteModel; + + @override + _NewNotePageState createState() => _NewNotePageState(); +} + +class _NewNotePageState extends State { + final _controller = TextEditingController(); + + @override + void initState() { + _controller.text = widget.noteModel.content; + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('New Note'), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: _controller, + onChanged: (str) { + widget.noteModel.content = str; + }, + decoration: const InputDecoration( + labelText: 'Type your note here', + labelStyle: TextStyle(color: Colors.grey, fontSize: 20.0), + // border: InputBorder.none, + ), + maxLines: null, + style: const TextStyle(fontSize: 30.0, fontWeight: FontWeight.w500), + autofocus: true, + keyboardType: TextInputType.multiline, + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Icon(Icons.check), + ), + ); + } +} diff --git a/lib/Task_2/note_app.dart b/lib/Task_2/note_app.dart new file mode 100644 index 0000000..70f4445 --- /dev/null +++ b/lib/Task_2/note_app.dart @@ -0,0 +1,166 @@ +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'note_model.dart'; +import 'new_note_page.dart'; + +class NoteApp extends StatelessWidget { + const NoteApp({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Notes App', + theme: ThemeData( + primarySwatch: Colors.amber, + ), + home: const MyHomePage(title: 'Notes App'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({Key? key, required this.title}) : super(key: key); + + final String title; + + @override + _MyHomePageState createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + List notes = []; + + //I used getData function to get data from SharedPreferences + //and I also used it for removing a specific note from notesList + Future getData({String? get}) async { + final prefs = await SharedPreferences.getInstance(); + setState(() { + var notesList = prefs.getStringList('noteContent'); + if (notesList != null) + // ignore: curly_braces_in_flow_control_structures + for (int i = 0; i < notesList.length; i++) { + //here is the check for get data from SharedPreferences + //if it is false it will execute the else statement which will remove a note + if (get == 'get') { + notes.add(NoteModel(notesList[i])); + } else { + notes.removeWhere((element) => element == NoteModel(notesList[i])); + } + } + }); + } + + @override + void initState() { + super.initState(); + getData( + get: + 'get'); //I passed 'get' to the getData so it will know I want to get data not to remove note + } + + //I used removeNote function to remove a specific note from notesList + void removeNote(NoteModel note) { + setState(() { + notes.remove(note); + getData(); //I passed nothig to the function so it will know I want to remove data not to get data + setData(); //I called setData here to save tha data after removing a note + }); + } + + //I used openNewNote function for editing an existing note and for open and editing a new note + void openNewNote({NoteModel? noteModel}) { + NoteModel _note = noteModel ?? NoteModel(''); + Navigator.of(context) + .push(MaterialPageRoute(builder: (context) => NewNotePage(_note))) + .then((_) { + setState( + () { + if (noteModel == null) { + if (_note.content.isNotEmpty) notes.add(_note); + } + }, + ); + setData(); //I called setData function to save data after adding and editing a note + }); + } + + //this function is to set a data and save it + Future setData() async { + final prefs = await SharedPreferences.getInstance(); + prefs.setStringList('noteContent', notes.map((e) => e.content).toList()); + } + + Widget noteItemView(NoteModel note) { + return Card( + child: InkWell( + onTap: () { + openNewNote(noteModel: note); + }, + child: Padding( + padding: const EdgeInsets.all(30.0), + child: Row( + children: [ + Expanded( + child: Text( + note.content, + maxLines: 1, + overflow: TextOverflow.ellipsis, + softWrap: true, + style: const TextStyle(fontSize: 30.0), + ), + ), + Expanded(child: Container()), + IconButton( + onPressed: () => removeNote(note), + icon: const Icon( + Icons.remove_circle_outline, + color: Colors.red, + )), + ], + ), + ), + ), + ); + } + + Widget buildNotesList() { + return ListView.builder( + itemBuilder: (_context, index) => noteItemView(notes[index]), + itemCount: notes.length, + ); + } + + @override + Widget build(BuildContext context) { + return DefaultTabController( + length: 2, + child: Scaffold( + appBar: AppBar( + title: Text(widget.title), + bottom: const TabBar( + tabs: [ + Tab( + icon: Icon(Icons.home), + ), + Tab( + icon: Icon(Icons.star), + ), + ], + ), + ), + body: TabBarView(children: [ + buildNotesList(), + const Center( + child: Text( + 'No Favorites Yet', + style: TextStyle(fontSize: 30.0, color: Colors.grey), + )) + ]), + floatingActionButton: FloatingActionButton( + onPressed: openNewNote, + tooltip: 'Add new note', + child: const Icon(Icons.add), + ), + ), + ); + } +} diff --git a/lib/Task_2/note_model.dart b/lib/Task_2/note_model.dart new file mode 100644 index 0000000..43194c5 --- /dev/null +++ b/lib/Task_2/note_model.dart @@ -0,0 +1,4 @@ +class NoteModel { + NoteModel(this.content); + String content; +} diff --git a/lib/Task_3/Api/weather_api.dart b/lib/Task_3/Api/weather_api.dart new file mode 100644 index 0000000..819e105 --- /dev/null +++ b/lib/Task_3/Api/weather_api.dart @@ -0,0 +1,72 @@ +// ignore_for_file: avoid_print,, prefer_typing_uninitialized_variables + +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:http/http.dart' as http; +import 'package:tuple/tuple.dart'; + +import '../Models/weather_model.dart'; + +// Future fechWeather() async { +// var apiUrl = Uri.parse( +// "https://api.weatherapi.com/v1/forecast.json?key=34758bbdd2e44d47821102523211810&q=Baghdad&days=7&aqi=no&alerts=no"); +// var response = await http.get(apiUrl); + +// print(response.statusCode); +// if (response.statusCode == 200) { +// try { +// var wether = Weather.fromJson(jsonDecode(response.body)); +// print(wether); + +// return wether; +// } catch (e) { +// return throw Exception("Json parse error"); +// } +// } else { +// throw Exception('network connection failed'); +// } +// } +class WetherApi with ChangeNotifier { + final String name; + WetherApi({ + required this.name, + }); + Future> fetchWeatherDaily( + {String name = 'Baghdad'}) async { + var response; + try { + var apiUrl = Uri.parse( + "https://api.weatherapi.com/v1/forecast.json?key=34758bbdd2e44d47821102523211810&q=$name&days=7&aqi=no&alerts=no"); + response = await http.get(apiUrl); + var dailay = Weather.fromJson(jsonDecode(response.body)); + print(response.statusCode); + print(dailay); + notifyListeners(); + return Tuple2(null, dailay); + } catch (e) { + if (response?.statusCode == 200) { + print('response code1: $e'); + return Tuple2( + ErrorResponse( + 'There is currently a problem. Please try again later', + response?.statusCode ?? -1), + null); + } + print('response code2: ${response?.statusCode}'); + return Tuple2( + ErrorResponse( + 'Please make sure you are connected to the internet', -1), + null); + } + } + + @override + notifyListeners(); +} + +class ErrorResponse { + ErrorResponse(this.message, this.statusCode); + String message; + int statusCode; +} diff --git a/lib/Task_3/Models/weather_model.dart b/lib/Task_3/Models/weather_model.dart new file mode 100644 index 0000000..ca474aa --- /dev/null +++ b/lib/Task_3/Models/weather_model.dart @@ -0,0 +1,316 @@ +// ignore_for_file: prefer_typing_uninitialized_variables + +class Weather { + Weather({ + required this.location, + required this.current, + required this.forecast, + }); + late final Location location; + late final Current current; + late final Forecast forecast; + + Weather.fromJson(Map json) { + location = Location.fromJson(json['location']); + current = Current.fromJson(json['current']); + forecast = Forecast.fromJson(json['forecast']); + } + + Map toJson() { + final _data = {}; + _data['location'] = location.toJson(); + _data['current'] = current.toJson(); + _data['forecast'] = forecast.toJson(); + return _data; + } +} + +class Location { + Location({ + required this.name, + required this.region, + required this.country, + required this.lat, + required this.lon, + required this.tzId, + required this.localtimeEpoch, + required this.localtime, + }); + late final name; + late final region; + late final country; + late final lat; + late final lon; + late final tzId; + late final localtimeEpoch; + late final localtime; + + Location.fromJson(Map json) { + name = json['name']; + region = json['region']; + country = json['country']; + lat = json['lat']; + lon = json['lon']; + tzId = json['tz_id']; + localtimeEpoch = json['localtime_epoch']; + localtime = json['localtime']; + } + + Map toJson() { + final _data = {}; + _data['name'] = name; + _data['region'] = region; + _data['country'] = country; + _data['lat'] = lat; + _data['lon'] = lon; + _data['tz_id'] = tzId; + _data['localtime_epoch'] = localtimeEpoch; + _data['localtime'] = localtime; + return _data; + } +} + +class Current { + Current({ + required this.lastUpdated, + required this.tempC, + required this.isDay, + required this.condition, + required this.humidity, + required this.cloud, + required this.feelslikeC, + required this.uv, + }); + late final lastUpdated; + late final tempC; + late final isDay; + late final condition; + late final humidity; + late final cloud; + late final feelslikeC; + late final uv; + + Current.fromJson(Map json) { + lastUpdated = json['last_updated']; + tempC = json['temp_c']; + isDay = json['is_day']; + condition = Condition.fromJson(json['condition']); + humidity = json['humidity']; + cloud = json['cloud']; + feelslikeC = json['feelslike_c']; + uv = json['uv']; + } + + Map toJson() { + final _data = {}; + _data['last_updated'] = lastUpdated; + _data['temp_c'] = tempC; + _data['is_day'] = isDay; + _data['condition'] = condition.toJson(); + _data['humidity'] = humidity; + _data['cloud'] = cloud; + _data['feelslike_c'] = feelslikeC; + _data['uv'] = uv; + return _data; + } +} + +class Condition { + Condition({ + required this.text, + required this.icon, + required this.code, + }); + late final text; + late final icon; + late final code; + + Condition.fromJson(Map json) { + text = json['text']; + icon = json['icon']; + code = json['code']; + } + + Map toJson() { + final _data = {}; + _data['text'] = text; + _data['icon'] = icon; + _data['code'] = code; + return _data; + } +} + +class Forecast { + Forecast({ + required this.forecastday, + }); + late final forecastday; + + Forecast.fromJson(Map json) { + forecastday = List.from(json['forecastday']) + .map((e) => Forecastday.fromJson(e)) + .toList(); + } + + Map toJson() { + final _data = {}; + _data['forecastday'] = forecastday.map((e) => e.toJson()).toList(); + return _data; + } +} + +class Forecastday { + Forecastday({ + required this.date, + required this.day, + required this.astro, + required this.hour, + }); + late final date; + late final day; + late final astro; + late final hour; + + Forecastday.fromJson(Map json) { + date = json['date']; + day = Day.fromJson(json['day']); + astro = Astro.fromJson(json['astro']); + hour = List.from(json['hour']).map((e) => Hour.fromJson(e)).toList(); + } + + Map toJson() { + final _data = {}; + _data['date'] = date; + _data['day'] = day.toJson(); + _data['astro'] = astro.toJson(); + _data['hour'] = hour.map((e) => e.toJson()).toList(); + return _data; + } +} + +class Day { + Day({ + required this.maxtempC, + required this.mintempC, + required this.avgtempC, + required this.dailyWillItRain, + required this.dailyChanceOfRain, + required this.dailyWillItSnow, + required this.dailyChanceOfSnow, + required this.condition, + }); + late final maxtempC; + late final mintempC; + late final avgtempC; + late final dailyWillItRain; + late final dailyChanceOfRain; + late final dailyWillItSnow; + late final dailyChanceOfSnow; + late final condition; + + Day.fromJson(Map json) { + maxtempC = json['maxtemp_c']; + mintempC = json['mintemp_c']; + avgtempC = json['avgtemp_c']; + dailyWillItRain = json['daily_will_it_rain']; + dailyChanceOfRain = json['daily_chance_of_rain']; + dailyWillItSnow = json['daily_will_it_snow']; + dailyChanceOfSnow = json['daily_chance_of_snow']; + condition = Condition.fromJson(json['condition']); + } + + Map toJson() { + final _data = {}; + _data['maxtemp_c'] = maxtempC; + _data['mintemp_c'] = mintempC; + _data['avgtemp_c'] = avgtempC; + _data['daily_will_it_rain'] = dailyWillItRain; + _data['daily_chance_of_rain'] = dailyChanceOfRain; + _data['daily_will_it_snow'] = dailyWillItSnow; + _data['daily_chance_of_snow'] = dailyChanceOfSnow; + _data['condition'] = condition.toJson(); + return _data; + } +} + +class Astro { + Astro({ + required this.sunrise, + required this.sunset, + required this.moonrise, + required this.moonset, + required this.moonPhase, + }); + late final sunrise; + late final sunset; + late final moonrise; + late final moonset; + late final moonPhase; + + Astro.fromJson(Map json) { + sunrise = json['sunrise']; + sunset = json['sunset']; + moonrise = json['moonrise']; + moonset = json['moonset']; + moonPhase = json['moon_phase']; + } + + Map toJson() { + final _data = {}; + _data['sunrise'] = sunrise; + _data['sunset'] = sunset; + _data['moonrise'] = moonrise; + _data['moonset'] = moonset; + _data['moon_phase'] = moonPhase; + return _data; + } +} + +class Hour { + Hour({ + required this.time, + required this.tempC, + required this.isDay, + required this.condition, + required this.humidity, + required this.cloud, + required this.feelslikeC, + required this.chanceOfRain, + required this.chanceOfSnow, + }); + late final time; + late final tempC; + late final isDay; + late final condition; + late final humidity; + late final cloud; + late final feelslikeC; + late final chanceOfRain; + late final chanceOfSnow; + + Hour.fromJson(Map json) { + time = json['time']; + tempC = json['temp_c']; + isDay = json['is_day']; + condition = Condition.fromJson(json['condition']); + humidity = json['humidity']; + cloud = json['cloud']; + feelslikeC = json['feelslike_c']; + chanceOfRain = json['chance_of_rain']; + chanceOfSnow = json['chance_of_snow']; + } + + Map toJson() { + final _data = {}; + _data['time'] = time; + _data['temp_c'] = tempC; + _data['is_day'] = isDay; + _data['condition'] = condition.toJson(); + _data['humidity'] = humidity; + _data['cloud'] = cloud; + _data['feelslike_c'] = feelslikeC; + _data['chance_of_rain'] = chanceOfRain; + _data['chance_of_snow'] = chanceOfSnow; + return _data; + } +} diff --git a/lib/Task_3/Provider/my_provider.dart b/lib/Task_3/Provider/my_provider.dart new file mode 100644 index 0000000..70778f0 --- /dev/null +++ b/lib/Task_3/Provider/my_provider.dart @@ -0,0 +1,8 @@ +// import 'package:flutter/material.dart'; +// import '/Api/weather_api.dart'; + +// class MyProvider with ChangeNotifier { +// WetherApi wether = WetherApi(); +// snapshot.data!.item2!.location.country; + +// } diff --git a/lib/Task_3/Screens/loding_screen.dart b/lib/Task_3/Screens/loding_screen.dart new file mode 100644 index 0000000..cb5e6df --- /dev/null +++ b/lib/Task_3/Screens/loding_screen.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +class LoadingScreen extends StatelessWidget { + const LoadingScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + height: double.infinity, + width: double.maxFinite, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.bottomRight, + end: Alignment.topLeft, + colors: [ + Colors.blue, + Colors.black, + ], + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + CircularProgressIndicator(), + SizedBox( + height: 20, + ), + ], + ), + ); + } +} diff --git a/lib/Task_3/Screens/my_home_page.dart b/lib/Task_3/Screens/my_home_page.dart new file mode 100644 index 0000000..c56de40 --- /dev/null +++ b/lib/Task_3/Screens/my_home_page.dart @@ -0,0 +1,292 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:tuple/tuple.dart'; +import '../Api/weather_api.dart'; +import '../Models/weather_model.dart'; +import '../Widgets/my_app_bar.dart'; +import 'package:weather_icons/weather_icons.dart'; + +import '../Widgets/current_condition_card.dart'; +import 'loding_screen.dart'; + +class MyHomePage extends StatefulWidget { + final String title; + + const MyHomePage({ + Key? key, + required this.title, + }) : super(key: key); + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + var n = 0; + + @override + Widget build(BuildContext context) { + WetherApi wether = WetherApi(name: 'Baghdad'); + debugPrint('build run this many times: ${n++}'); + + return Scaffold( + body: FutureBuilder>( + future: wether.fetchWeatherDaily(), + builder: (context, + AsyncSnapshot> snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const LoadingScreen(); + } else { + if (snapshot.data?.item1 != null) { + return SafeArea( + child: Container( + height: double.infinity, + width: double.maxFinite, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.bottomRight, + end: Alignment.topLeft, + colors: [ + Colors.blue, + Colors.black, + ], + ), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + snapshot.data!.item1!.message, + style: const TextStyle( + color: Colors.white, fontSize: 20), + textAlign: TextAlign.center, + ), + const SizedBox( + height: 10, + ), + ElevatedButton( + onPressed: () { + setState(() {}); + }, + child: const Text('Try Again')) + ], + ), + ), + ), + ); + } else { + var myCountry = snapshot.data!.item2!.location.country; + var myCity = snapshot.data!.item2!.location.name; + var conditionIcon = + snapshot.data!.item2!.current.condition.icon.toString(); + var conditionTemp = + ((snapshot.data!.item2!.current.tempC)).toString(); + var conditionText = + snapshot.data!.item2!.current.condition.text.toString(); + var localTime = snapshot.data!.item2!.location.localtime + .toString() + .split(' '); + return SafeArea( + child: Scaffold( + appBar: MyAppBar( + city: myCity, + country: myCountry, + ), + body: Container( + width: double.maxFinite, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.bottomRight, + end: Alignment.topLeft, + colors: [ + Colors.blue, + Colors.black, + ], + ), + ), + child: ListView( + children: [ + CurrentCondition( + conditionIcon: conditionIcon, + conditionTemp: conditionTemp, + conditionText: conditionText, + time: localTime, + ), + const Text( + 'Today', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 35, + fontWeight: FontWeight.bold), + ), + Padding( + padding: const EdgeInsets.all(4.0), + child: Stack( + children: [ + Container( + width: double.infinity, + height: 250, + decoration: BoxDecoration( + color: Colors.black54, + borderRadius: BorderRadius.circular(4.0)), + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.only( + right: 15, top: 20, left: 10), + child: Column( + children: [ + Text( + DateFormat('hh:mm').format( + DateTime.parse(snapshot + .data! + .item2! + .forecast + .forecastday[0] + .hour[index] + .time)), + style: const TextStyle( + color: Colors.white, + fontSize: 20), + ), + const SizedBox( + height: 10, + ), + Image.network( + "https:${snapshot.data!.item2!.forecast.forecastday[0].hour[index].condition.icon}"), + Row( + children: [ + const BoxedIcon( + WeatherIcons.humidity, + color: Colors.white, + ), + const SizedBox( + width: 10, + ), + Text( + "${snapshot.data!.item2!.forecast.forecastday[0].hour[index].chanceOfRain.toString()}%", + style: const TextStyle( + color: Colors.white, + fontSize: 20), + ), + ], + ), + const SizedBox( + height: 25, + ), + Text( + '${snapshot.data!.item2!.forecast.forecastday[0].hour[index].tempC.toString()}º', + style: const TextStyle( + color: Colors.white, + fontSize: 20), + ), + ], + ), + ); + }, + itemCount: snapshot.data!.item2!.forecast + .forecastday[0].hour.length, + ), + ), + ], + ), + ), + const Text( + 'Daily', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 35, + fontWeight: FontWeight.bold), + ), + Padding( + padding: const EdgeInsets.all(4.0), + child: Stack(children: [ + Container( + width: double.infinity, + height: 300, + decoration: BoxDecoration( + color: Colors.black54, + borderRadius: BorderRadius.circular(4.0)), + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.only( + right: 75, top: 20, left: 10), + child: Column( + children: [ + Text( + DateFormat.E().format(DateTime.parse( + snapshot.data!.item2!.forecast + .forecastday[index].date)), + style: const TextStyle( + color: Colors.white, fontSize: 20), + ), + const SizedBox( + height: 10, + ), + Image.network( + "https:${snapshot.data!.item2!.forecast.forecastday[index].day.condition.icon}"), + Row( + children: [ + const BoxedIcon( + WeatherIcons.humidity, + color: Colors.white, + ), + const SizedBox( + width: 10, + ), + Text( + "${snapshot.data!.item2!.forecast.forecastday[index].day.dailyChanceOfRain.toString()}%", + style: const TextStyle( + color: Colors.white, + fontSize: 20), + ), + ], + ), + const SizedBox( + height: 20, + ), + Text( + '${snapshot.data!.item2!.forecast.forecastday[index].day.maxtempC.toString()} ºMax', + style: const TextStyle( + color: Colors.white, fontSize: 20), + ), + const BoxedIcon( + WeatherIcons.direction_up_right, + color: Colors.white, + ), + Text( + '${snapshot.data!.item2!.forecast.forecastday[index].day.mintempC.toString()} ºMin', + style: const TextStyle( + color: Colors.white, fontSize: 20), + ), + ], + ), + ); + }, + itemCount: snapshot + .data!.item2!.forecast.forecastday.length, + ), + ), + ]), + ), + const SizedBox( + height: 20, + ) + ], + ), + ), + )); + } + } + }, + ), + ); + } +} diff --git a/lib/Task_3/Widgets/current_condition_card.dart b/lib/Task_3/Widgets/current_condition_card.dart new file mode 100644 index 0000000..e550c04 --- /dev/null +++ b/lib/Task_3/Widgets/current_condition_card.dart @@ -0,0 +1,86 @@ +// ignore_for_file: prefer_typing_uninitialized_variables + +import 'package:flutter/material.dart'; + +class CurrentCondition extends StatelessWidget { + final conditionIcon; + final conditionTemp; + final conditionText; + final time; + const CurrentCondition({ + Key? key, + required this.conditionIcon, + required this.conditionTemp, + required this.time, + required this.conditionText, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + const Text( + 'Current', + style: TextStyle( + color: Colors.white, fontSize: 35, fontWeight: FontWeight.bold), + ), + Card( + elevation: 1, + color: Colors.black54, + child: Padding( + padding: const EdgeInsets.only(top: 10, right: 20), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + '${time[0]}', + style: + const TextStyle(color: Colors.white, fontSize: 24.0), + ), + ], + ), + const SizedBox(height: 10), + const Text( + 'Current Temp', + style: TextStyle(color: Colors.white, fontSize: 24.0), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '$conditionTempº', + style: const TextStyle( + color: Colors.white, + fontSize: 45, + fontWeight: FontWeight.bold), + ), + // const BoxedIcon( + // WeatherIcons.celsius, + // color: Colors.white, + // size: 45.0, + // ), + ], + ), + Row( + children: [ + Image.network( + "https:$conditionIcon", + scale: 1, + ), + Text('$conditionText', + style: const TextStyle( + color: Colors.white, + fontSize: 35, + fontWeight: FontWeight.bold)) + ], + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/Task_3/Widgets/my_app_bar.dart b/lib/Task_3/Widgets/my_app_bar.dart new file mode 100644 index 0000000..f13c430 --- /dev/null +++ b/lib/Task_3/Widgets/my_app_bar.dart @@ -0,0 +1,43 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:flutter/material.dart'; + +import 'text_box.dart'; + +class MyAppBar extends StatelessWidget implements PreferredSizeWidget { + final String country, city; + const MyAppBar({Key? key, required this.country, required this.city}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return AppBar( + elevation: 1, + title: TextBox(), + actions: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + children: [ + Text( + '$country, $city', + style: const TextStyle( + color: Colors.white, + fontSize: 20, + fontWeight: FontWeight.bold), + ), + SizedBox( + width: 8.0, + ) + ], + ), + ], + ), + ], + ); + } + + @override + Size get preferredSize => Size.fromHeight(kToolbarHeight); +} diff --git a/lib/Task_3/Widgets/text_box.dart b/lib/Task_3/Widgets/text_box.dart new file mode 100644 index 0000000..c16de69 --- /dev/null +++ b/lib/Task_3/Widgets/text_box.dart @@ -0,0 +1,36 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:flutter/material.dart'; +import '../Api/weather_api.dart'; + +class TextBox extends StatefulWidget { + const TextBox({Key? key}) : super(key: key); + + @override + State createState() => _TextBoxState(); +} + +class _TextBoxState extends State { + @override + Widget build(BuildContext context) { + var _controller = TextEditingController(); + return Container( + // decoration: BoxDecoration(borderRadius: BorderRadius.circular(6.0)), + alignment: Alignment.centerLeft, + color: Colors.blue[100], + child: TextField( + textAlign: TextAlign.left, + decoration: InputDecoration( + hintText: 'Search', + prefixIcon: Icon(Icons.search), + ), + controller: _controller, + cursorHeight: 6.0, + onSubmitted: (cityName) { + WetherApi(name: cityName).fetchWeatherDaily(); + setState(() {}); + }, + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index 2c084ed..5f0ffcb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,255 +1,45 @@ -import 'package:flutter/material.dart'; -import 'dart:math' as math; -void main() { - runApp(const MyApp()); -} - -class Contact { - String image; - String name; - String mobileNumber; - DateTime date; - bool isIncoming; - - Contact(this.image, this.name, this.mobileNumber, this.date, this.isIncoming); -} - -class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter Demo 2', - theme: ThemeData( - primarySwatch: Colors.blue, - ), - debugShowCheckedModeBanner: false, - home: const MyHomePage(title: 'Contacts App'), - ); - } -} - -class MyHomePage extends StatefulWidget { - const MyHomePage({Key? key, required this.title}) : super(key: key); - - final String title; - - @override - State createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _selectedIndex = 2; - static const TextStyle optionStyle = - TextStyle(fontSize: 30, fontWeight: FontWeight.bold); - static late List _pages; - - _MyHomePageState() { - _pages = [ - buildContactsList(), - buildFavoritesGridView(), - // Text('hello'), - Text( - 'Index 2: School', - style: optionStyle, - ), - ]; - } - - void _onItemTapped(int index) { - setState(() { - _selectedIndex = index; - }); - } - - var contacts = [ - Contact( - 'https://i.pravatar.cc/300', - 'Ahmed', - '71766137347', - DateTime.now().add( - const Duration(seconds: 3), - ), - true, - ), - Contact( - 'https://i.pravatar.cc/301', - 'Ali', - '71766137347', - DateTime.now().add( - const Duration(days: 1), - ), - false, - ), - Contact( - 'https://i.pravatar.cc/302', - 'Kamal', - '71766137347', - DateTime.now().add( - const Duration(days: 3), - ), - true, - ), - Contact( - 'https://i.pravatar.cc/303', - 'Mohammad', - '71766137347', - DateTime.now().add( - const Duration(days: 5), - ), - true, - ), - Contact( - 'https://i.pravatar.cc/304', - 'Mohammad', - '71766137347', - DateTime.now().add( - const Duration(days: 5), - ), - false, - ), - Contact( - 'https://i.pravatar.cc/305', - 'Hussein', - '71766137347', - DateTime.now().add( - const Duration(days: 6), - ), - false, - ), - Contact( - 'https://i.pravatar.cc/306', - 'Aboud', - '71766137347', - DateTime.now().add( - const Duration(days: 7), - ), - false, - ), - Contact( - 'https://i.pravatar.cc/307', - 'Osama', - '71766137347', - DateTime.now().add( - const Duration(days: 6), - ), - false, - ), - ]; - - Widget buildFavoritesGridView() { - return Column( - children: [ - Text('Favorites'), - Divider(thickness: 4,), - Expanded( - child: GridView.count( - crossAxisCount: 3, - children: List.generate(5, (index) { - var personColor = Color((math.Random().nextDouble() * 0xFFFFFF).toInt()) - .withOpacity(1.0); - return Center( - child: Container( - width: 120, - height: 120, - child: Text( - contacts[index].name[0], - style: TextStyle(fontSize: 40), - ), - alignment: Alignment.center, - decoration: - BoxDecoration(shape: BoxShape.circle, color: personColor), - ), - ); - }), - ), - ), - ], - ); - } - - Widget buildContactItem(Contact _contact) { - return Card( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - CircleAvatar( - backgroundImage: NetworkImage(_contact.image), - ), - Padding( - padding: const EdgeInsets.all(16), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - _contact.name, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - Text(_contact.mobileNumber), - ], - ), - ), - Text(_contact.date.toIso8601String().split('T').first), - Expanded( - child: Container(), - ), - if (_contact.isIncoming) - Icon( - Icons.arrow_downward, - color: Colors.red, - ) - else - Icon( - Icons.arrow_upward, - color: Colors.green, - ) - ], - ), - ), - ); - } - - Widget buildContactsList() { - return ListView.builder( - itemBuilder: (_context, index) { - return buildContactItem(contacts[index]); - }, - itemCount: contacts.length, - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Center( - child: _pages[_selectedIndex], - ), - bottomNavigationBar: BottomNavigationBar( - items: const [ - BottomNavigationBarItem( - icon: Icon(Icons.home), - label: 'Recent', - ), - BottomNavigationBarItem( - icon: Icon(Icons.favorite), - label: 'Favorites', - ), - BottomNavigationBarItem( - icon: Icon(Icons.access_time_outlined), - label: 'School', - activeIcon: Icon(Icons.access_time_filled) - ), - ], - currentIndex: _selectedIndex, - selectedItemColor: Colors.amber[800], - onTap: _onItemTapped, - ), - ); - } -} +//Task 1 and 2: +// import 'package:flutter/material.dart'; +// import 'Task_1/instagram_ui.dart'; +// import 'Task_2/note_app.dart'; + +// void main() { +// runApp(const NoteApp()); +// } + +//Task 3: +// ignore_for_file: prefer_const_constructors + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import './Task_3/Api/weather_api.dart'; +import './Task_3/Screens/my_home_page.dart'; +import 'Task_3/Api/weather_api.dart'; +import 'Task_3/Screens/my_home_page.dart'; +// import 'package:provider/provider.dart'; +// import 'Provider/my_provider.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Weather App', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + debugShowCheckedModeBanner: false, + home: ChangeNotifierProvider( + create: (BuildContext context) => WetherApi(name: 'Baghdad'), + child: const MyHomePage(title: 'Weather App'), + lazy: true, + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 750761f..859b440 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.1" + version: "2.8.2" boolean_selector: dependency: transitive description: @@ -21,7 +21,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: @@ -57,6 +57,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.2" flutter: dependency: "direct main" description: flutter @@ -74,6 +88,46 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + get: + dependency: "direct main" + description: + name: get + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.8" + http: + dependency: "direct main" + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.4" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + intl: + dependency: "direct main" + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.3" lints: dependency: transitive description: @@ -87,7 +141,7 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.11" meta: dependency: transitive description: @@ -95,6 +149,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.7.0" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" path: dependency: transitive description: @@ -102,6 +163,104 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.1" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1+1" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" sky_engine: dependency: transitive description: flutter @@ -148,7 +307,14 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.2" + version: "0.4.3" + tuple: + dependency: "direct main" + description: + name: tuple + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" typed_data: dependency: transitive description: @@ -162,6 +328,28 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" + weather_icons: + dependency: "direct main" + description: + name: weather_icons + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.9" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=2.14.0 <3.0.0" + flutter: ">=2.5.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1c93cc7..b157245 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,8 +1,8 @@ -name: contacts_01 -description: A new Flutter project. +name: flutter_course_tasks +description: A project that contains my tasks solution. # The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. +# pub.dev using `pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev # The following defines the version and build number for your application. @@ -20,47 +20,39 @@ version: 1.0.0+1 environment: sdk: ">=2.12.0 <3.0.0" -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. dependencies: flutter: sdk: flutter - + provider: ^6.0.1 + get: ^4.3.8 + shared_preferences: ^2.0.7 + http: ^0.13.3 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 + tuple: ^2.0.0 + intl: ^0.17.0 + weather_icons: ^3.0.0 dev_dependencies: + flutter_lints: ^1.0.4 flutter_test: sdk: flutter - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^1.0.0 - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec # The following section is specific to Flutter. flutter: - # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg + assets: + - images/ # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware. diff --git a/test/widget_test.dart b/test/widget_test.dart index 5f578bd..c801bc0 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -5,15 +5,17 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. +import 'package:flutter_course_tasks/Task_3/Screens/my_home_page.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:contacts_01/main.dart'; - void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); + await tester.pumpWidget(const MyHomePage( + title: 'Weather App', + )); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget); diff --git a/web/index.html b/web/index.html index d2606e7..dbe6d6b 100644 --- a/web/index.html +++ b/web/index.html @@ -10,11 +10,8 @@ For more details: * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base - - This is a placeholder for base href that will be replaced by the value of - the `--base-href` argument provided to `flutter build`. --> - + @@ -23,10 +20,10 @@ - + - contacts_01 + bottom_navigation_bar @@ -67,7 +64,7 @@ if (!reg.active && (reg.installing || reg.waiting)) { // No active web worker and we have installed or are installing // one for the first time. Simply wait for it to activate. - waitForActivation(reg.installing || reg.waiting); + waitForActivation(reg.installing ?? reg.waiting); } else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) { // When the app updates the serviceWorkerVersion changes, so we // need to ask the service worker to update. diff --git a/web/manifest.json b/web/manifest.json index 9631a79..47e0e60 100644 --- a/web/manifest.json +++ b/web/manifest.json @@ -1,6 +1,6 @@ { - "name": "contacts_01", - "short_name": "contacts_01", + "name": "bottom_navigation_bar", + "short_name": "bottom_navigation_bar", "start_url": ".", "display": "standalone", "background_color": "#0175C2", @@ -18,18 +18,6 @@ "src": "icons/Icon-512.png", "sizes": "512x512", "type": "image/png" - }, - { - "src": "icons/Icon-maskable-192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "icons/Icon-maskable-512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" } ] }