├── .gitignore
├── .metadata
├── README.md
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── weather_app_flutter
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable-v21
│ │ │ └── launch_background.xml
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
└── city_list.json
├── data
├── screenshot.jpg
├── screenshot_config_json.png
└── test.json
├── images
├── placeholder.png
├── sunrise.png
└── sunset.png
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ └── Icon-App-83.5x83.5@2x.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
├── lib
├── config
│ ├── build_config.dart
│ └── env_config.dart
├── core
│ ├── app_colors.dart
│ ├── app_utils.dart
│ └── text_style.dart
├── main.dart
├── network
│ ├── WeatherApi.dart
│ ├── WeatherApiImpl.dart
│ ├── api_interceptor.dart
│ └── dio_client.dart
└── ui
│ └── home
│ ├── model
│ ├── City.dart
│ ├── weather_data.dart
│ └── weather_response.dart
│ ├── view
│ └── HomePage.dart
│ └── widget
│ ├── Item_sun_time.dart
│ ├── input_section.dart
│ ├── item_weather_property.dart
│ ├── sun_time.dart
│ ├── temperature_section.dart
│ ├── weather_data_output.dart
│ └── weather_property.dart
├── pubspec.lock
├── pubspec.yaml
├── test
└── widget_test.dart
└── web
├── favicon.png
├── icons
├── Icon-192.png
└── Icon-512.png
├── index.html
└── manifest.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Web related
35 | lib/generated_plugin_registrant.dart
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
43 | # Android related
44 | **/android/**/gradle-wrapper.jar
45 | **/android/.gradle
46 | **/android/captures/
47 | **/android/gradlew
48 | **/android/gradlew.bat
49 | **/android/local.properties
50 | **/android/**/GeneratedPluginRegistrant.java
51 |
52 | # iOS/XCode related
53 | **/ios/**/*.mode1v3
54 | **/ios/**/*.mode2v3
55 | **/ios/**/*.moved-aside
56 | **/ios/**/*.pbxuser
57 | **/ios/**/*.perspectivev3
58 | **/ios/**/*sync/
59 | **/ios/**/.sconsign.dblite
60 | **/ios/**/.tags*
61 | **/ios/**/.vagrant/
62 | **/ios/**/DerivedData/
63 | **/ios/**/Icon?
64 | **/ios/**/Pods/
65 | **/ios/**/.symlinks/
66 | **/ios/**/profile
67 | **/ios/**/xcuserdata
68 | **/ios/.generated/
69 | **/ios/Flutter/App.framework
70 | **/ios/Flutter/Flutter.framework
71 | **/ios/Flutter/Generated.xcconfig
72 | **/ios/Flutter/app.flx
73 | **/ios/Flutter/app.zip
74 | **/ios/Flutter/flutter_assets/
75 | **/ios/ServiceDefinitions.json
76 | **/ios/Runner/GeneratedPluginRegistrant.*
77 |
78 | ### Android ###
79 | # Built application files
80 | *.apk
81 | *.aar
82 | *.ap_
83 | *.aab
84 |
85 | # Files for the ART/Dalvik VM
86 | *.dex
87 |
88 | # Generated files
89 | bin/
90 | gen/
91 | out/
92 | # Uncomment the following line in case you need and you don't have the release build type files in your app
93 | # release/
94 |
95 | # Gradle files
96 | .gradle/
97 | build/
98 |
99 | # Local configuration file (sdk path, etc)
100 | local.properties
101 |
102 | # Custom file and directory
103 | /assets/config.json
--------------------------------------------------------------------------------
/.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: 1d9032c7e1d867f071f2277eb1673e8f9b0274e3
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Basic Flutter (Android + iOS) App (Dart + Dio) - Weather App
2 |
3 | This is a very beginning friendly project of Flutter. A simple weather forecast App using Open Weather Map API.
4 | I have used `StatefulWidget` for state management. For network calls I used the popular Flutter package `Dio`.
5 |
6 |
7 |
8 | ### Prerequisite
9 | Basic understanding of Dart programming language. Have to familiar with REST API and network calls with HTTP protocol.
10 |
11 | ### Project Description
12 | We will develop a weather forecast Android Application with Flutter. The UI will be as like as above screenshot. There is a `DropdownButton` with some `City` name. After selection a city, user need to hit the `View Weather` button. Then App will send request to Open Weather web API and show the weather information in the UI.
13 |
14 | ### Open Weather API
15 | We will use [Open Weather Map API](https://openweathermap.org/api) for collecting weather information. To get the real weather information of a city, you need to sign up and get your own `APP ID`. Otherwise you can test the API with their sample `BASE URL` and sample `APP ID` without creating account.
16 |
17 | ### Project Setup
18 | Clone the project and open it using Android Studio. Then create a file `config.json` inside `assets` folder. Add `baseUrl` and `appId` JSON field inside the parent JSON object.
19 |
20 |
21 |
22 | #### Use Sample API without creating account
23 | Add below lines at your `config.json` file. Then run the project. You'll get dummy or static API response from Open Weather API.
24 | ```
25 | {
26 | "baseUrl": "https://samples.openweathermap.org/data/2.5",
27 | "appId": "b6907d289e10d714a6e88b30761fae22"
28 | }
29 | ```
30 | #### Use Real APP ID after sign up and activation of your APP ID
31 | After Sign up at the website collect your own `APP ID` from their [API Keys page](https://home.openweathermap.org/api_keys). Then add your `APP ID` in `config.json` file like below.
32 | ```
33 | {
34 | "baseUrl": "http://api.openweathermap.org/data/2.5",
35 | "appId": ""
36 | }
37 | ```
38 | The BASE URL and APP ID will be fetched from `main.dart` file and will be stored it in our local configuration file.
39 |
40 | **Note:** The free version of Open Weather API allows maximum 60 API calls per minute.
41 | ### Run the project
42 | Run `flutter pub get` to sync the packages. Then run the app to your real device or emulator.
43 | ### Disclaimer
44 | This is my first project in Flutter. So there are lots of things to improve. It is not guaranteed about the best practices and Flutter convention in this project. Please don't use this project as a reference or as a boilerplate of your other project. For the sake of simplicity, I avoided to use Bloc, GetX etc. Next time I'll create different repositories for them.
45 | Feel free to create issues for improvement.Thanks.
46 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | compileSdkVersion 30
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | defaultConfig {
36 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
37 | applicationId "com.example.weather_app_flutter"
38 | minSdkVersion 16
39 | targetSdkVersion 30
40 | versionCode flutterVersionCode.toInteger()
41 | versionName flutterVersionName
42 | }
43 |
44 | buildTypes {
45 | release {
46 | // TODO: Add your own signing config for the release build.
47 | // Signing with the debug keys for now, so `flutter run --release` works.
48 | signingConfig signingConfigs.debug
49 | }
50 | }
51 | }
52 |
53 | flutter {
54 | source '../..'
55 | }
56 |
57 | dependencies {
58 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
59 | }
60 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
9 |
16 |
20 |
23 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
38 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/weather_app_flutter/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.weather_app_flutter
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity : FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:4.1.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | project.evaluationDependsOn(':app')
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
7 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/assets/city_list.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 1185241,
4 | "name": "Dhaka",
5 | "country": "BD"
6 | },
7 | {
8 | "id": 1336135,
9 | "name": "Khulna",
10 | "country": "BD"
11 | },
12 | {
13 | "id": 1337200,
14 | "name": "Chittagong",
15 | "country": "BD"
16 | },
17 | {
18 | "id": 1336134,
19 | "name": "Coxs Bazar",
20 | "country": "BD"
21 | },
22 | {
23 | "id": 1185128,
24 | "name": "Rajshahi",
25 | "country": "BD"
26 | },
27 | {
28 | "id": 1336137,
29 | "name": "Barisal",
30 | "country": "BD"
31 | },
32 | {
33 | "id": 1185099,
34 | "name": "Sylhet",
35 | "country": "BD"
36 | },
37 | {
38 | "id": 1185188,
39 | "name": "Rangpur",
40 | "country": "BD"
41 | },
42 | {
43 | "id": 5056033,
44 | "name": "London",
45 | "country": "US"
46 | },
47 | {
48 | "id": 1275004,
49 | "name": "Kolkata",
50 | "country": "IN"
51 | },
52 | {
53 | "id": 108410,
54 | "name": "Riyadh",
55 | "country": "SA"
56 | },
57 | {
58 | "id": 292968,
59 | "name": "Abu Dhabi",
60 | "country": "AE"
61 | },
62 | {
63 | "id": 5128638,
64 | "name": "New York",
65 | "country": "US"
66 | },
67 | {
68 | "id": 1850147,
69 | "name": "Tokyo",
70 | "country": "JP"
71 | },
72 | {
73 | "id": 1176615,
74 | "name": "Islamabad",
75 | "country": "PK"
76 | },
77 | {
78 | "id": 1261481,
79 | "name": "New Delhi",
80 | "country": "IN"
81 | }
82 | ]
--------------------------------------------------------------------------------
/data/screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/data/screenshot.jpg
--------------------------------------------------------------------------------
/data/screenshot_config_json.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/data/screenshot_config_json.png
--------------------------------------------------------------------------------
/data/test.json:
--------------------------------------------------------------------------------
1 | {"status":"Success","statusCode":200,"data":{"userList":[{"id":"7f141043-104b-4b61-a9b6-95941aed2292","name":"John Doe","profilePictureUrl":"https:\/\/picsum.photos\/id\/12\/300\/300","dateOfBirth":"2021-08-17T08:39:04.1665352+00:00","relation":"Father","isAeonUser":true},{"id":"7f141043-104b-4b61-a9b6-95941aed2292","name":"John Doe","profilePictureUrl":"https:\/\/picsum.photos\/id\/12\/300\/300","dateOfBirth":"2021-08-17T08:39:04.1665352+00:00","relation":"Father","isAeonUser":false},{"id":"7f141043-104b-4b61-a9b6-95941aed2292","name":"John Doe","profilePictureUrl":"https:\/\/picsum.photos\/id\/12\/300\/300","dateOfBirth":"2021-08-17T08:39:04.1665352+00:00","relation":"Father","isAeonUser":true}],"pageNumber":1,"pageSize":10,"total":20},"message":"Successful","errors":null}
2 |
--------------------------------------------------------------------------------
/images/placeholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/images/placeholder.png
--------------------------------------------------------------------------------
/images/sunrise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/images/sunrise.png
--------------------------------------------------------------------------------
/images/sunset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/images/sunset.png
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/ephemeral/
22 | Flutter/app.flx
23 | Flutter/app.zip
24 | Flutter/flutter_assets/
25 | Flutter/flutter_export_environment.sh
26 | ServiceDefinitions.json
27 | Runner/GeneratedPluginRegistrant.*
28 |
29 | # Exceptions to above rules.
30 | !default.mode1v3
31 | !default.mode2v3
32 | !default.pbxuser
33 | !default.perspectivev3
34 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
16 | /* End PBXBuildFile section */
17 |
18 | /* Begin PBXCopyFilesBuildPhase section */
19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
20 | isa = PBXCopyFilesBuildPhase;
21 | buildActionMask = 2147483647;
22 | dstPath = "";
23 | dstSubfolderSpec = 10;
24 | files = (
25 | );
26 | name = "Embed Frameworks";
27 | runOnlyForDeploymentPostprocessing = 0;
28 | };
29 | /* End PBXCopyFilesBuildPhase section */
30 |
31 | /* Begin PBXFileReference section */
32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
45 | /* End PBXFileReference section */
46 |
47 | /* Begin PBXFrameworksBuildPhase section */
48 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
49 | isa = PBXFrameworksBuildPhase;
50 | buildActionMask = 2147483647;
51 | files = (
52 | );
53 | runOnlyForDeploymentPostprocessing = 0;
54 | };
55 | /* End PBXFrameworksBuildPhase section */
56 |
57 | /* Begin PBXGroup section */
58 | 9740EEB11CF90186004384FC /* Flutter */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
65 | );
66 | name = Flutter;
67 | sourceTree = "";
68 | };
69 | 97C146E51CF9000F007C117D = {
70 | isa = PBXGroup;
71 | children = (
72 | 9740EEB11CF90186004384FC /* Flutter */,
73 | 97C146F01CF9000F007C117D /* Runner */,
74 | 97C146EF1CF9000F007C117D /* Products */,
75 | );
76 | sourceTree = "";
77 | };
78 | 97C146EF1CF9000F007C117D /* Products */ = {
79 | isa = PBXGroup;
80 | children = (
81 | 97C146EE1CF9000F007C117D /* Runner.app */,
82 | );
83 | name = Products;
84 | sourceTree = "";
85 | };
86 | 97C146F01CF9000F007C117D /* Runner */ = {
87 | isa = PBXGroup;
88 | children = (
89 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
92 | 97C147021CF9000F007C117D /* Info.plist */,
93 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
94 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
95 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
96 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
97 | );
98 | path = Runner;
99 | sourceTree = "";
100 | };
101 | /* End PBXGroup section */
102 |
103 | /* Begin PBXNativeTarget section */
104 | 97C146ED1CF9000F007C117D /* Runner */ = {
105 | isa = PBXNativeTarget;
106 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
107 | buildPhases = (
108 | 9740EEB61CF901F6004384FC /* Run Script */,
109 | 97C146EA1CF9000F007C117D /* Sources */,
110 | 97C146EB1CF9000F007C117D /* Frameworks */,
111 | 97C146EC1CF9000F007C117D /* Resources */,
112 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
113 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
114 | );
115 | buildRules = (
116 | );
117 | dependencies = (
118 | );
119 | name = Runner;
120 | productName = Runner;
121 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
122 | productType = "com.apple.product-type.application";
123 | };
124 | /* End PBXNativeTarget section */
125 |
126 | /* Begin PBXProject section */
127 | 97C146E61CF9000F007C117D /* Project object */ = {
128 | isa = PBXProject;
129 | attributes = {
130 | LastUpgradeCheck = 1020;
131 | ORGANIZATIONNAME = "";
132 | TargetAttributes = {
133 | 97C146ED1CF9000F007C117D = {
134 | CreatedOnToolsVersion = 7.3.1;
135 | LastSwiftMigration = 1100;
136 | };
137 | };
138 | };
139 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
140 | compatibilityVersion = "Xcode 9.3";
141 | developmentRegion = en;
142 | hasScannedForEncodings = 0;
143 | knownRegions = (
144 | en,
145 | Base,
146 | );
147 | mainGroup = 97C146E51CF9000F007C117D;
148 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
149 | projectDirPath = "";
150 | projectRoot = "";
151 | targets = (
152 | 97C146ED1CF9000F007C117D /* Runner */,
153 | );
154 | };
155 | /* End PBXProject section */
156 |
157 | /* Begin PBXResourcesBuildPhase section */
158 | 97C146EC1CF9000F007C117D /* Resources */ = {
159 | isa = PBXResourcesBuildPhase;
160 | buildActionMask = 2147483647;
161 | files = (
162 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
163 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
164 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
165 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
166 | );
167 | runOnlyForDeploymentPostprocessing = 0;
168 | };
169 | /* End PBXResourcesBuildPhase section */
170 |
171 | /* Begin PBXShellScriptBuildPhase section */
172 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
173 | isa = PBXShellScriptBuildPhase;
174 | buildActionMask = 2147483647;
175 | files = (
176 | );
177 | inputPaths = (
178 | );
179 | name = "Thin Binary";
180 | outputPaths = (
181 | );
182 | runOnlyForDeploymentPostprocessing = 0;
183 | shellPath = /bin/sh;
184 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
185 | };
186 | 9740EEB61CF901F6004384FC /* Run Script */ = {
187 | isa = PBXShellScriptBuildPhase;
188 | buildActionMask = 2147483647;
189 | files = (
190 | );
191 | inputPaths = (
192 | );
193 | name = "Run Script";
194 | outputPaths = (
195 | );
196 | runOnlyForDeploymentPostprocessing = 0;
197 | shellPath = /bin/sh;
198 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
199 | };
200 | /* End PBXShellScriptBuildPhase section */
201 |
202 | /* Begin PBXSourcesBuildPhase section */
203 | 97C146EA1CF9000F007C117D /* Sources */ = {
204 | isa = PBXSourcesBuildPhase;
205 | buildActionMask = 2147483647;
206 | files = (
207 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
208 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
209 | );
210 | runOnlyForDeploymentPostprocessing = 0;
211 | };
212 | /* End PBXSourcesBuildPhase section */
213 |
214 | /* Begin PBXVariantGroup section */
215 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
216 | isa = PBXVariantGroup;
217 | children = (
218 | 97C146FB1CF9000F007C117D /* Base */,
219 | );
220 | name = Main.storyboard;
221 | sourceTree = "";
222 | };
223 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
224 | isa = PBXVariantGroup;
225 | children = (
226 | 97C147001CF9000F007C117D /* Base */,
227 | );
228 | name = LaunchScreen.storyboard;
229 | sourceTree = "";
230 | };
231 | /* End PBXVariantGroup section */
232 |
233 | /* Begin XCBuildConfiguration section */
234 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
235 | isa = XCBuildConfiguration;
236 | buildSettings = {
237 | ALWAYS_SEARCH_USER_PATHS = NO;
238 | CLANG_ANALYZER_NONNULL = YES;
239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
240 | CLANG_CXX_LIBRARY = "libc++";
241 | CLANG_ENABLE_MODULES = YES;
242 | CLANG_ENABLE_OBJC_ARC = YES;
243 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
244 | CLANG_WARN_BOOL_CONVERSION = YES;
245 | CLANG_WARN_COMMA = YES;
246 | CLANG_WARN_CONSTANT_CONVERSION = YES;
247 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
249 | CLANG_WARN_EMPTY_BODY = YES;
250 | CLANG_WARN_ENUM_CONVERSION = YES;
251 | CLANG_WARN_INFINITE_RECURSION = YES;
252 | CLANG_WARN_INT_CONVERSION = YES;
253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
254 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
258 | CLANG_WARN_STRICT_PROTOTYPES = YES;
259 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
260 | CLANG_WARN_UNREACHABLE_CODE = YES;
261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
263 | COPY_PHASE_STRIP = NO;
264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
265 | ENABLE_NS_ASSERTIONS = NO;
266 | ENABLE_STRICT_OBJC_MSGSEND = YES;
267 | GCC_C_LANGUAGE_STANDARD = gnu99;
268 | GCC_NO_COMMON_BLOCKS = YES;
269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
271 | GCC_WARN_UNDECLARED_SELECTOR = YES;
272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
273 | GCC_WARN_UNUSED_FUNCTION = YES;
274 | GCC_WARN_UNUSED_VARIABLE = YES;
275 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
276 | MTL_ENABLE_DEBUG_INFO = NO;
277 | SDKROOT = iphoneos;
278 | SUPPORTED_PLATFORMS = iphoneos;
279 | TARGETED_DEVICE_FAMILY = "1,2";
280 | VALIDATE_PRODUCT = YES;
281 | };
282 | name = Profile;
283 | };
284 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
285 | isa = XCBuildConfiguration;
286 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
287 | buildSettings = {
288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
289 | CLANG_ENABLE_MODULES = YES;
290 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
291 | ENABLE_BITCODE = NO;
292 | INFOPLIST_FILE = Runner/Info.plist;
293 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
294 | PRODUCT_BUNDLE_IDENTIFIER = com.example.weatherAppFlutter;
295 | PRODUCT_NAME = "$(TARGET_NAME)";
296 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
297 | SWIFT_VERSION = 5.0;
298 | VERSIONING_SYSTEM = "apple-generic";
299 | };
300 | name = Profile;
301 | };
302 | 97C147031CF9000F007C117D /* Debug */ = {
303 | isa = XCBuildConfiguration;
304 | buildSettings = {
305 | ALWAYS_SEARCH_USER_PATHS = NO;
306 | CLANG_ANALYZER_NONNULL = YES;
307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
308 | CLANG_CXX_LIBRARY = "libc++";
309 | CLANG_ENABLE_MODULES = YES;
310 | CLANG_ENABLE_OBJC_ARC = YES;
311 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
312 | CLANG_WARN_BOOL_CONVERSION = YES;
313 | CLANG_WARN_COMMA = YES;
314 | CLANG_WARN_CONSTANT_CONVERSION = YES;
315 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
316 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
317 | CLANG_WARN_EMPTY_BODY = YES;
318 | CLANG_WARN_ENUM_CONVERSION = YES;
319 | CLANG_WARN_INFINITE_RECURSION = YES;
320 | CLANG_WARN_INT_CONVERSION = YES;
321 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
322 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
323 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
324 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
325 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
326 | CLANG_WARN_STRICT_PROTOTYPES = YES;
327 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
328 | CLANG_WARN_UNREACHABLE_CODE = YES;
329 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
330 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
331 | COPY_PHASE_STRIP = NO;
332 | DEBUG_INFORMATION_FORMAT = dwarf;
333 | ENABLE_STRICT_OBJC_MSGSEND = YES;
334 | ENABLE_TESTABILITY = YES;
335 | GCC_C_LANGUAGE_STANDARD = gnu99;
336 | GCC_DYNAMIC_NO_PIC = NO;
337 | GCC_NO_COMMON_BLOCKS = YES;
338 | GCC_OPTIMIZATION_LEVEL = 0;
339 | GCC_PREPROCESSOR_DEFINITIONS = (
340 | "DEBUG=1",
341 | "$(inherited)",
342 | );
343 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
344 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
345 | GCC_WARN_UNDECLARED_SELECTOR = YES;
346 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
347 | GCC_WARN_UNUSED_FUNCTION = YES;
348 | GCC_WARN_UNUSED_VARIABLE = YES;
349 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
350 | MTL_ENABLE_DEBUG_INFO = YES;
351 | ONLY_ACTIVE_ARCH = YES;
352 | SDKROOT = iphoneos;
353 | TARGETED_DEVICE_FAMILY = "1,2";
354 | };
355 | name = Debug;
356 | };
357 | 97C147041CF9000F007C117D /* Release */ = {
358 | isa = XCBuildConfiguration;
359 | buildSettings = {
360 | ALWAYS_SEARCH_USER_PATHS = NO;
361 | CLANG_ANALYZER_NONNULL = YES;
362 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
363 | CLANG_CXX_LIBRARY = "libc++";
364 | CLANG_ENABLE_MODULES = YES;
365 | CLANG_ENABLE_OBJC_ARC = YES;
366 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
367 | CLANG_WARN_BOOL_CONVERSION = YES;
368 | CLANG_WARN_COMMA = YES;
369 | CLANG_WARN_CONSTANT_CONVERSION = YES;
370 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
371 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
372 | CLANG_WARN_EMPTY_BODY = YES;
373 | CLANG_WARN_ENUM_CONVERSION = YES;
374 | CLANG_WARN_INFINITE_RECURSION = YES;
375 | CLANG_WARN_INT_CONVERSION = YES;
376 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
377 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
378 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
379 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
380 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
381 | CLANG_WARN_STRICT_PROTOTYPES = YES;
382 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
383 | CLANG_WARN_UNREACHABLE_CODE = YES;
384 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
385 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
386 | COPY_PHASE_STRIP = NO;
387 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
388 | ENABLE_NS_ASSERTIONS = NO;
389 | ENABLE_STRICT_OBJC_MSGSEND = YES;
390 | GCC_C_LANGUAGE_STANDARD = gnu99;
391 | GCC_NO_COMMON_BLOCKS = YES;
392 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
393 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
394 | GCC_WARN_UNDECLARED_SELECTOR = YES;
395 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
396 | GCC_WARN_UNUSED_FUNCTION = YES;
397 | GCC_WARN_UNUSED_VARIABLE = YES;
398 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
399 | MTL_ENABLE_DEBUG_INFO = NO;
400 | SDKROOT = iphoneos;
401 | SUPPORTED_PLATFORMS = iphoneos;
402 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
403 | TARGETED_DEVICE_FAMILY = "1,2";
404 | VALIDATE_PRODUCT = YES;
405 | };
406 | name = Release;
407 | };
408 | 97C147061CF9000F007C117D /* Debug */ = {
409 | isa = XCBuildConfiguration;
410 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
411 | buildSettings = {
412 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
413 | CLANG_ENABLE_MODULES = YES;
414 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
415 | ENABLE_BITCODE = NO;
416 | INFOPLIST_FILE = Runner/Info.plist;
417 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
418 | PRODUCT_BUNDLE_IDENTIFIER = com.example.weatherAppFlutter;
419 | PRODUCT_NAME = "$(TARGET_NAME)";
420 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
421 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
422 | SWIFT_VERSION = 5.0;
423 | VERSIONING_SYSTEM = "apple-generic";
424 | };
425 | name = Debug;
426 | };
427 | 97C147071CF9000F007C117D /* Release */ = {
428 | isa = XCBuildConfiguration;
429 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
430 | buildSettings = {
431 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
432 | CLANG_ENABLE_MODULES = YES;
433 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
434 | ENABLE_BITCODE = NO;
435 | INFOPLIST_FILE = Runner/Info.plist;
436 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
437 | PRODUCT_BUNDLE_IDENTIFIER = com.example.weatherAppFlutter;
438 | PRODUCT_NAME = "$(TARGET_NAME)";
439 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
440 | SWIFT_VERSION = 5.0;
441 | VERSIONING_SYSTEM = "apple-generic";
442 | };
443 | name = Release;
444 | };
445 | /* End XCBuildConfiguration section */
446 |
447 | /* Begin XCConfigurationList section */
448 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
449 | isa = XCConfigurationList;
450 | buildConfigurations = (
451 | 97C147031CF9000F007C117D /* Debug */,
452 | 97C147041CF9000F007C117D /* Release */,
453 | 249021D3217E4FDB00AE95B9 /* Profile */,
454 | );
455 | defaultConfigurationIsVisible = 0;
456 | defaultConfigurationName = Release;
457 | };
458 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
459 | isa = XCConfigurationList;
460 | buildConfigurations = (
461 | 97C147061CF9000F007C117D /* Debug */,
462 | 97C147071CF9000F007C117D /* Release */,
463 | 249021D4217E4FDB00AE95B9 /* Profile */,
464 | );
465 | defaultConfigurationIsVisible = 0;
466 | defaultConfigurationName = Release;
467 | };
468 | /* End XCConfigurationList section */
469 | };
470 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
471 | }
472 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "size": "20x20",
5 | "idiom": "iphone",
6 | "filename": "Icon-App-20x20@2x.png",
7 | "scale": "2x"
8 | },
9 | {
10 | "size": "20x20",
11 | "idiom": "iphone",
12 | "filename": "Icon-App-20x20@3x.png",
13 | "scale": "3x"
14 | },
15 | {
16 | "size": "29x29",
17 | "idiom": "iphone",
18 | "filename": "Icon-App-29x29@1x.png",
19 | "scale": "1x"
20 | },
21 | {
22 | "size": "29x29",
23 | "idiom": "iphone",
24 | "filename": "Icon-App-29x29@2x.png",
25 | "scale": "2x"
26 | },
27 | {
28 | "size": "29x29",
29 | "idiom": "iphone",
30 | "filename": "Icon-App-29x29@3x.png",
31 | "scale": "3x"
32 | },
33 | {
34 | "size": "40x40",
35 | "idiom": "iphone",
36 | "filename": "Icon-App-40x40@2x.png",
37 | "scale": "2x"
38 | },
39 | {
40 | "size": "40x40",
41 | "idiom": "iphone",
42 | "filename": "Icon-App-40x40@3x.png",
43 | "scale": "3x"
44 | },
45 | {
46 | "size": "60x60",
47 | "idiom": "iphone",
48 | "filename": "Icon-App-60x60@2x.png",
49 | "scale": "2x"
50 | },
51 | {
52 | "size": "60x60",
53 | "idiom": "iphone",
54 | "filename": "Icon-App-60x60@3x.png",
55 | "scale": "3x"
56 | },
57 | {
58 | "size": "20x20",
59 | "idiom": "ipad",
60 | "filename": "Icon-App-20x20@1x.png",
61 | "scale": "1x"
62 | },
63 | {
64 | "size": "20x20",
65 | "idiom": "ipad",
66 | "filename": "Icon-App-20x20@2x.png",
67 | "scale": "2x"
68 | },
69 | {
70 | "size": "29x29",
71 | "idiom": "ipad",
72 | "filename": "Icon-App-29x29@1x.png",
73 | "scale": "1x"
74 | },
75 | {
76 | "size": "29x29",
77 | "idiom": "ipad",
78 | "filename": "Icon-App-29x29@2x.png",
79 | "scale": "2x"
80 | },
81 | {
82 | "size": "40x40",
83 | "idiom": "ipad",
84 | "filename": "Icon-App-40x40@1x.png",
85 | "scale": "1x"
86 | },
87 | {
88 | "size": "40x40",
89 | "idiom": "ipad",
90 | "filename": "Icon-App-40x40@2x.png",
91 | "scale": "2x"
92 | },
93 | {
94 | "size": "76x76",
95 | "idiom": "ipad",
96 | "filename": "Icon-App-76x76@1x.png",
97 | "scale": "1x"
98 | },
99 | {
100 | "size": "76x76",
101 | "idiom": "ipad",
102 | "filename": "Icon-App-76x76@2x.png",
103 | "scale": "2x"
104 | },
105 | {
106 | "size": "83.5x83.5",
107 | "idiom": "ipad",
108 | "filename": "Icon-App-83.5x83.5@2x.png",
109 | "scale": "2x"
110 | },
111 | {
112 | "size": "1024x1024",
113 | "idiom": "ios-marketing",
114 | "filename": "Icon-App-1024x1024@1x.png",
115 | "scale": "1x"
116 | }
117 | ],
118 | "info": {
119 | "version": 1,
120 | "author": "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "idiom": "universal",
5 | "filename": "LaunchImage.png",
6 | "scale": "1x"
7 | },
8 | {
9 | "idiom": "universal",
10 | "filename": "LaunchImage@2x.png",
11 | "scale": "2x"
12 | },
13 | {
14 | "idiom": "universal",
15 | "filename": "LaunchImage@3x.png",
16 | "scale": "3x"
17 | }
18 | ],
19 | "info": {
20 | "version": 1,
21 | "author": "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | Weather Forecast
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/lib/config/build_config.dart:
--------------------------------------------------------------------------------
1 | import 'package:weather_app_flutter/config/env_config.dart';
2 |
3 | class BuildConfig {
4 | late final EnvConfig config;
5 | bool _lock = false;
6 |
7 | static final BuildConfig instance = BuildConfig._internal();
8 |
9 | BuildConfig._internal();
10 |
11 | factory BuildConfig.instantiate({
12 | required EnvConfig envConfig,
13 | }) {
14 | if (instance._lock) return instance;
15 |
16 | instance.config = envConfig;
17 | instance._lock = true;
18 |
19 | return instance;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lib/config/env_config.dart:
--------------------------------------------------------------------------------
1 | import 'package:logger/logger.dart';
2 |
3 | class EnvConfig {
4 | final String baseUrl;
5 | final String appId;
6 | late final Logger logger;
7 |
8 | EnvConfig({
9 | required this.baseUrl,
10 | required this.appId,
11 | }) {
12 | logger = Logger(
13 | printer: PrettyPrinter(
14 | colors: true,
15 | printEmojis: true,
16 | printTime: false,
17 | ),
18 | );
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/core/app_colors.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 | import 'package:flutter/material.dart';
3 |
4 | abstract class AppColors {
5 | static const Color colorPrimary = Colors.teal;
6 | static const Color colorAccent = Color(0xFFFF5722);
7 |
8 | static const Color textLabelColor = Color(0xFF616161);
9 | static const Color textValueColor = Colors.black;
10 | }
--------------------------------------------------------------------------------
/lib/core/app_utils.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:intl/intl.dart';
4 |
5 | String unixTimestampToDateTimeString(int? timestamp) {
6 | if (timestamp == null) return '--/--';
7 | var date = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
8 | var formattedDate = DateFormat('dd MMM, yyyy - hh:mm a').format(date);
9 | return formattedDate;
10 | }
11 |
12 | String unixTimestampToTimeString(int? timestamp) {
13 | if (timestamp == null) return '--/--';
14 | var date = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
15 | var formattedDate = DateFormat('hh:mm a').format(date);
16 | return formattedDate;
17 | }
18 |
19 | int kelvinToCelsius(double? temperature) {
20 | if (temperature == null) return 0;
21 |
22 | return (temperature - 273.15).toInt();
23 | }
24 |
25 | enum SnackBarType { MESSAGE, ERROR }
26 |
27 | showSnackBar(BuildContext context, String message,
28 | {SnackBarType type = SnackBarType.MESSAGE}) {
29 | Color backgroundColor =
30 | type == SnackBarType.MESSAGE ? Colors.black87 : Colors.red;
31 |
32 | final snackBar = SnackBar(
33 | backgroundColor: backgroundColor,
34 | content: Text(message),
35 | action: SnackBarAction(
36 | label: 'OK',
37 | onPressed: () {
38 | // Some code to undo the change.
39 | },
40 | ),
41 | );
42 |
43 | // Find the ScaffoldMessenger in the widget tree
44 | // and use it to show a SnackBar.
45 | ScaffoldMessenger.of(context).showSnackBar(snackBar);
46 | }
47 |
--------------------------------------------------------------------------------
/lib/core/text_style.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:weather_app_flutter/core/app_colors.dart';
3 |
4 | const extraLargeTitleTextStyle = TextStyle(
5 | fontSize: 80,
6 | fontWeight: FontWeight.w400,
7 | color: Colors.teal,
8 | );
9 |
10 | const titleTextStyle = TextStyle(color: Colors.teal, fontSize: 20);
11 |
12 | const labelTextStyle = TextStyle(
13 | fontSize: 16,
14 | fontWeight: FontWeight.normal,
15 | color: AppColors.textLabelColor,
16 | );
17 |
18 | const valueTextStyle = TextStyle(
19 | fontSize: 16,
20 | fontWeight: FontWeight.normal,
21 | color: AppColors.textValueColor,
22 | );
23 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter/services.dart';
5 | import 'package:logger/logger.dart';
6 | import 'package:weather_app_flutter/config/build_config.dart';
7 | import 'package:weather_app_flutter/config/env_config.dart';
8 |
9 | import 'ui/home/view/HomePage.dart';
10 |
11 | Future main() async {
12 | var logger = Logger();
13 | WidgetsFlutterBinding.ensureInitialized();
14 | try {
15 | EnvConfig config = await getConfig();
16 | BuildConfig.instantiate(envConfig: config);
17 | runApp(MyApp());
18 | } catch (e) {
19 | logger.e(e);
20 | }
21 | }
22 |
23 | class MyApp extends StatelessWidget {
24 | final String appTitle = 'Weather Forecast - Flutter';
25 |
26 | @override
27 | Widget build(BuildContext context) {
28 | return MaterialApp(
29 | title: appTitle,
30 | theme: ThemeData(primarySwatch: Colors.teal),
31 | home: HomePage(title: appTitle),
32 | debugShowCheckedModeBanner: false,
33 | );
34 | }
35 | }
36 |
37 | Future getConfig() async {
38 | var logger = Logger();
39 | try {
40 | String configString = await rootBundle.loadString('assets/config.json');
41 | final configJson = await json.decode(configString) as Map;
42 |
43 | String baseUrl = configJson['baseUrl'];
44 | String appId = configJson['appId'];
45 |
46 | if(baseUrl.isEmpty || appId.isEmpty)
47 | logger.e('Base URL and AppID should not empty. '
48 | 'Please follow the guideline for configuring this project.\n'
49 | 'Guideline: https://github.com/hasancse91/weather_app_flutter');
50 |
51 | return EnvConfig(
52 | baseUrl: baseUrl,
53 | appId: appId,
54 | );
55 | } catch (e) {
56 | throw Exception('$e\nLocal configuration NOT found. '
57 | 'Please follow the guideline for configuring this project.\n'
58 | 'Guideline: https://github.com/hasancse91/weather_app_flutter');
59 | }
60 | }
--------------------------------------------------------------------------------
/lib/network/WeatherApi.dart:
--------------------------------------------------------------------------------
1 | import 'package:weather_app_flutter/ui/home/model/weather_data.dart';
2 |
3 | abstract class WeatherApi {
4 | Future? getWeatherInfo(int? cityId);
5 | }
6 |
--------------------------------------------------------------------------------
/lib/network/WeatherApiImpl.dart:
--------------------------------------------------------------------------------
1 | import 'package:weather_app_flutter/config/build_config.dart';
2 | import 'package:weather_app_flutter/network/WeatherApi.dart';
3 | import 'package:weather_app_flutter/network/dio_client.dart';
4 | import 'package:weather_app_flutter/ui/home/model/weather_data.dart';
5 | import 'package:weather_app_flutter/ui/home/model/weather_response.dart';
6 |
7 | class WeatherApiImpl extends WeatherApi {
8 | var logger = BuildConfig.instance.config.logger;
9 |
10 | @override
11 | Future? getWeatherInfo(int? cityId) {
12 | return _getWeather(cityId);
13 | }
14 |
15 | Future _getWeather(int? cityId) async {
16 | try {
17 | var dioClient = DioClient().client;
18 | var response = await dioClient.get(
19 | '/weather',
20 | queryParameters: {'id': cityId},
21 | );
22 |
23 | logger.i("Response body JSON:\n$response");
24 |
25 | WeatherResponse weatherResponse = WeatherResponse.fromJson(response.data);
26 | WeatherData weatherData = weatherResponse.toWeatherData();
27 | return weatherData;
28 | } catch (e) {
29 | throw e;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/network/api_interceptor.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:pretty_dio_logger/pretty_dio_logger.dart';
3 | import 'package:weather_app_flutter/config/build_config.dart';
4 |
5 | List getInterceptors() {
6 | return [
7 | _getPrettyLoggerInterceptor(),
8 | _getAppIdQueryParameterInterceptor(),
9 | ];
10 | }
11 |
12 | PrettyDioLogger _getPrettyLoggerInterceptor() {
13 | return PrettyDioLogger(requestHeader: true, responseHeader: true);
14 | }
15 |
16 | Interceptor _getAppIdQueryParameterInterceptor() {
17 | var interceptor = InterceptorsWrapper(onRequest: (options, handler) {
18 | options.queryParameters.addAll(
19 | {'appid': BuildConfig.instance.config.appId},
20 | );
21 |
22 | return handler.next(options);
23 | });
24 |
25 | return interceptor;
26 | }
27 |
--------------------------------------------------------------------------------
/lib/network/dio_client.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:weather_app_flutter/config/build_config.dart';
3 | import 'package:weather_app_flutter/network/api_interceptor.dart';
4 |
5 | class DioClient {
6 | static final DioClient _dioClient = DioClient._internal();
7 | late Dio _dio;
8 |
9 | factory DioClient() {
10 | return _dioClient;
11 | }
12 |
13 | Dio get client => _dio;
14 |
15 | DioClient._internal() {
16 | var options = BaseOptions(
17 | baseUrl: BuildConfig.instance.config.baseUrl,
18 | connectTimeout: 5000,
19 | receiveTimeout: 3000,
20 | );
21 |
22 | _dio = Dio(options);
23 | _dio.interceptors.addAll(getInterceptors());
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/ui/home/model/City.dart:
--------------------------------------------------------------------------------
1 | class City {
2 | int id;
3 | String name;
4 | String countryCode;
5 |
6 | City(this.id, this.name, this.countryCode);
7 |
8 | City.fromJson(Map json)
9 | : id = json['id'],
10 | name = json['name'],
11 | countryCode = json['country'];
12 |
13 | Map toJson() => {
14 | 'id': id,
15 | 'name': name,
16 | 'country': countryCode,
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/lib/ui/home/model/weather_data.dart:
--------------------------------------------------------------------------------
1 | class WeatherData {
2 | String dateTime;
3 | String temperature;
4 | String cityAndCountry;
5 | String weatherConditionIconUrl;
6 | String weatherConditionIconDescription;
7 | String humidity;
8 | String pressure;
9 | String visibility;
10 | String sunrise;
11 | String sunset;
12 |
13 | WeatherData({
14 | required this.dateTime,
15 | required this.temperature,
16 | required this.cityAndCountry,
17 | required this.weatherConditionIconUrl,
18 | required this.weatherConditionIconDescription,
19 | required this.humidity,
20 | required this.pressure,
21 | required this.visibility,
22 | required this.sunrise,
23 | required this.sunset,
24 | });
25 | }
26 |
--------------------------------------------------------------------------------
/lib/ui/home/model/weather_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:weather_app_flutter/core/app_utils.dart';
2 | import 'package:weather_app_flutter/ui/home/model/weather_data.dart';
3 |
4 | /// This code is generated by JsonToDart plugin.
5 | /// Plugin homepage: https://plugins.jetbrains.com/plugin/12562-jsontodart-json-to-dart-/
6 | class WeatherResponse {
7 | Coord? coord;
8 | List? weather;
9 | String? base;
10 | Main? main;
11 | int? visibility;
12 | Wind? wind;
13 | Clouds? clouds;
14 | int? dt;
15 | Sys? sys;
16 | int? timezone;
17 | int? id;
18 | String? name;
19 | int? cod;
20 |
21 | WeatherResponse(
22 | {this.coord,
23 | this.weather,
24 | this.base,
25 | this.main,
26 | this.visibility,
27 | this.wind,
28 | this.clouds,
29 | this.dt,
30 | this.sys,
31 | this.timezone,
32 | this.id,
33 | this.name,
34 | this.cod});
35 |
36 | WeatherResponse.fromJson(dynamic json) {
37 | coord = json["coord"] != null ? Coord.fromJson(json["coord"]) : null;
38 | if (json["weather"] != null) {
39 | weather = [];
40 | json["weather"].forEach((v) {
41 | weather?.add(Weather.fromJson(v));
42 | });
43 | }
44 | base = json["base"];
45 | main = json["main"] != null ? Main.fromJson(json["main"]) : null;
46 | visibility = json["visibility"];
47 | wind = json["wind"] != null ? Wind.fromJson(json["wind"]) : null;
48 | clouds = json["clouds"] != null ? Clouds.fromJson(json["clouds"]) : null;
49 | dt = json["dt"];
50 | sys = json["sys"] != null ? Sys.fromJson(json["sys"]) : null;
51 | timezone = json["timezone"];
52 | id = json["id"];
53 | name = json["name"];
54 | cod = json["cod"];
55 | }
56 |
57 | Map toJson() {
58 | var map = {};
59 | if (coord != null) {
60 | map["coord"] = coord?.toJson();
61 | }
62 | if (weather != null) {
63 | map["weather"] = weather?.map((v) => v.toJson()).toList();
64 | }
65 | map["base"] = base;
66 | if (main != null) {
67 | map["main"] = main?.toJson();
68 | }
69 | map["visibility"] = visibility;
70 | if (wind != null) {
71 | map["wind"] = wind?.toJson();
72 | }
73 | if (clouds != null) {
74 | map["clouds"] = clouds?.toJson();
75 | }
76 | map["dt"] = dt;
77 | if (sys != null) {
78 | map["sys"] = sys?.toJson();
79 | }
80 | map["timezone"] = timezone;
81 | map["id"] = id;
82 | map["name"] = name;
83 | map["cod"] = cod;
84 | return map;
85 | }
86 |
87 | WeatherData toWeatherData() {
88 | return WeatherData(
89 | dateTime: unixTimestampToDateTimeString(dt),
90 | temperature: kelvinToCelsius(main!.temp).toString(),
91 | cityAndCountry: "$name, ${sys!.country}",
92 | weatherConditionIconUrl:
93 | "http://openweathermap.org/img/w/${weather![0].icon}.png",
94 | weatherConditionIconDescription: weather![0].description ?? '',
95 | humidity: "${main!.humidity}%",
96 | pressure: "${main!.pressure} mBar",
97 | visibility: "${visibility! / 1000.0} KM",
98 | sunrise: unixTimestampToTimeString(sys!.sunrise),
99 | sunset: unixTimestampToTimeString(sys!.sunset));
100 | }
101 | }
102 |
103 | class Sys {
104 | int? type;
105 | int? id;
106 | String? country;
107 | int? sunrise;
108 | int? sunset;
109 |
110 | Sys({this.type, this.id, this.country, this.sunrise, this.sunset});
111 |
112 | Sys.fromJson(dynamic json) {
113 | type = json["type"];
114 | id = json["id"];
115 | country = json["country"];
116 | sunrise = json["sunrise"];
117 | sunset = json["sunset"];
118 | }
119 |
120 | Map toJson() {
121 | var map = {};
122 | map["type"] = type;
123 | map["id"] = id;
124 | map["country"] = country;
125 | map["sunrise"] = sunrise;
126 | map["sunset"] = sunset;
127 | return map;
128 | }
129 | }
130 |
131 | class Clouds {
132 | int? all;
133 |
134 | Clouds({this.all});
135 |
136 | Clouds.fromJson(dynamic json) {
137 | all = json["all"];
138 | }
139 |
140 | Map toJson() {
141 | var map = {};
142 | map["all"] = all;
143 | return map;
144 | }
145 | }
146 |
147 | class Wind {
148 | num? speed;
149 | int? deg;
150 | double? gust;
151 |
152 | Wind({this.speed, this.deg, this.gust});
153 |
154 | Wind.fromJson(dynamic json) {
155 | speed = json["speed"];
156 | deg = json["deg"];
157 | gust = json["gust"];
158 | }
159 |
160 | Map toJson() {
161 | var map = {};
162 | map["speed"] = speed;
163 | map["deg"] = deg;
164 | map["gust"] = gust;
165 | return map;
166 | }
167 | }
168 |
169 | class Main {
170 | double? temp;
171 | double? feelsLike;
172 | double? tempMin;
173 | double? tempMax;
174 | int? pressure;
175 | int? humidity;
176 | int? seaLevel;
177 | int? grndLevel;
178 |
179 | Main(
180 | {this.temp,
181 | this.feelsLike,
182 | this.tempMin,
183 | this.tempMax,
184 | this.pressure,
185 | this.humidity,
186 | this.seaLevel,
187 | this.grndLevel});
188 |
189 | Main.fromJson(dynamic json) {
190 | temp = json["temp"];
191 | feelsLike = json["feels_like"];
192 | tempMin = json["temp_min"];
193 | tempMax = json["temp_max"];
194 | pressure = json["pressure"];
195 | humidity = json["humidity"];
196 | seaLevel = json["sea_level"];
197 | grndLevel = json["grnd_level"];
198 | }
199 |
200 | Map toJson() {
201 | var map = {};
202 | map["temp"] = temp;
203 | map["feels_like"] = feelsLike;
204 | map["temp_min"] = tempMin;
205 | map["temp_max"] = tempMax;
206 | map["pressure"] = pressure;
207 | map["humidity"] = humidity;
208 | map["sea_level"] = seaLevel;
209 | map["grnd_level"] = grndLevel;
210 | return map;
211 | }
212 | }
213 |
214 | class Weather {
215 | int? id;
216 | String? main;
217 | String? description;
218 | String? icon;
219 |
220 | Weather({this.id, this.main, this.description, this.icon});
221 |
222 | Weather.fromJson(dynamic json) {
223 | id = json["id"];
224 | main = json["main"];
225 | description = json["description"];
226 | icon = json["icon"];
227 | }
228 |
229 | Map toJson() {
230 | var map = {};
231 | map["id"] = id;
232 | map["main"] = main;
233 | map["description"] = description;
234 | map["icon"] = icon;
235 | return map;
236 | }
237 | }
238 |
239 | class Coord {
240 | double? lon;
241 | double? lat;
242 |
243 | Coord({this.lon, this.lat});
244 |
245 | Coord.fromJson(dynamic json) {
246 | lon = json["lon"];
247 | lat = json["lat"];
248 | }
249 |
250 | Map toJson() {
251 | var map = {};
252 | map["lon"] = lon;
253 | map["lat"] = lat;
254 | return map;
255 | }
256 | }
257 |
--------------------------------------------------------------------------------
/lib/ui/home/view/HomePage.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter/services.dart';
5 | import 'package:flutter/widgets.dart';
6 | import 'package:weather_app_flutter/config/build_config.dart';
7 | import 'package:weather_app_flutter/core/app_utils.dart';
8 | import 'package:weather_app_flutter/network/WeatherApi.dart';
9 | import 'package:weather_app_flutter/network/WeatherApiImpl.dart';
10 | import 'package:weather_app_flutter/ui/home/model/City.dart';
11 | import 'package:weather_app_flutter/ui/home/model/weather_data.dart';
12 | import 'package:weather_app_flutter/ui/home/widget/weather_data_output.dart';
13 |
14 | class HomePage extends StatefulWidget {
15 | final String title;
16 |
17 | HomePage({Key? key, required this.title}) : super(key: key);
18 |
19 | @override
20 | _HomePageState createState() => _HomePageState();
21 | }
22 |
23 | class _HomePageState extends State {
24 | final logger = BuildConfig.instance.config.logger;
25 | List cityList = [];
26 | City? selectedCity;
27 | bool isWeatherDataLoaded = false;
28 | WeatherData? weather;
29 | late WeatherApi weatherApi;
30 |
31 | @override
32 | void initState() {
33 | super.initState();
34 | readCityList();
35 | weatherApi = WeatherApiImpl();
36 | }
37 |
38 | @override
39 | Widget build(BuildContext context) {
40 | return Scaffold(
41 | appBar: AppBar(
42 | title: Text(widget.title),
43 | ),
44 | body: Container(
45 | margin: EdgeInsets.all(20.0),
46 | child: Column(
47 | crossAxisAlignment: CrossAxisAlignment.start,
48 | children: [
49 | _getInputSection(),
50 | if (isWeatherDataLoaded) WeatherDataOutput(weather: weather!),
51 | ],
52 | ),
53 | ),
54 | );
55 | }
56 |
57 | _getInputSection() {
58 | return Container(
59 | margin: EdgeInsets.only(bottom: 16.0),
60 | child: Row(
61 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
62 | children: [
63 | _getCityDropdown(),
64 | ElevatedButton(onPressed: showWeather, child: Text('VIEW WEATHER')),
65 | ],
66 | ));
67 | }
68 |
69 | DropdownButton _getCityDropdown() {
70 | return DropdownButton(
71 | value: selectedCity,
72 | onChanged: (City? newCity) {
73 | setState(() {
74 | if (newCity != null) selectedCity = newCity;
75 | isWeatherDataLoaded = false;
76 | });
77 | },
78 | items: cityList.map((City city) {
79 | return DropdownMenuItem(value: city, child: Text(city.name));
80 | }).toList(),
81 | );
82 | }
83 |
84 | void readCityList() async {
85 | String response = await rootBundle.loadString('assets/city_list.json');
86 | final data = await json.decode(response) as List;
87 | setState(() {
88 | cityList = data.map((city) => City.fromJson(city)).toList();
89 | selectedCity = cityList[0];
90 | });
91 | }
92 |
93 | showWeather() async {
94 | try {
95 | var weatherTemp = await weatherApi.getWeatherInfo(selectedCity?.id);
96 | setState(() {
97 | weather = weatherTemp;
98 | isWeatherDataLoaded = true;
99 | });
100 | } catch (e) {
101 | showSnackBar(context, e.toString(), type: SnackBarType.ERROR);
102 | logger.e(e);
103 | }
104 | }
105 | }
--------------------------------------------------------------------------------
/lib/ui/home/widget/Item_sun_time.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:weather_app_flutter/core/text_style.dart';
3 |
4 | class ItemSunTime extends StatelessWidget {
5 | final String label;
6 | final String value;
7 | final String imagePath;
8 |
9 | const ItemSunTime({
10 | Key? key,
11 | required this.label,
12 | required this.value,
13 | required this.imagePath,
14 | }) : super(key: key);
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return Column(
19 | children: [
20 | Text(label, style: labelTextStyle),
21 | Container(
22 | child: Image.asset(
23 | imagePath,
24 | width: 100,
25 | height: 100,
26 | ),
27 | margin: EdgeInsets.only(top: 12.0, bottom: 12.0),
28 | ),
29 | Text(value, style: valueTextStyle),
30 | ],
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lib/ui/home/widget/input_section.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:weather_app_flutter/ui/home/model/City.dart';
3 |
4 | class InputSection extends StatefulWidget {
5 | final List cityList;
6 | final Function(int) onTap;
7 |
8 | const InputSection({Key? key, required this.cityList, required this.onTap})
9 | : super(key: key);
10 |
11 | @override
12 | _InputSectionState createState() =>
13 | _InputSectionState(cityList: cityList, onTap: onTap);
14 | }
15 |
16 | class _InputSectionState extends State {
17 | final List cityList;
18 | final Function(int) onTap;
19 | City? selectedCity;
20 |
21 | _InputSectionState({required this.cityList, required this.onTap});
22 |
23 | @override
24 | Widget build(BuildContext context) {
25 | if (cityList.isNotEmpty) selectedCity = cityList[0];
26 |
27 | return Container(
28 | margin: EdgeInsets.only(bottom: 16.0),
29 | child: Row(
30 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
31 | children: [
32 | _getCityDropdown(),
33 | ElevatedButton(
34 | onPressed: onTap(selectedCity!.id),
35 | child: Text('VIEW WEATHER'),
36 | ),
37 | ],
38 | ));
39 | }
40 |
41 | DropdownButton _getCityDropdown() {
42 | return DropdownButton(
43 | value: selectedCity,
44 | onChanged: (City? newCity) {
45 | setState(() {
46 | if (newCity != null) selectedCity = newCity;
47 | });
48 | },
49 | items: cityList.map((City city) {
50 | return DropdownMenuItem(
51 | value: city,
52 | child: Text(city.name),
53 | );
54 | }).toList(),
55 | );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/lib/ui/home/widget/item_weather_property.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:weather_app_flutter/core/text_style.dart';
3 |
4 | class ItemWeatherProperty extends StatelessWidget {
5 | final String label;
6 | final String value;
7 |
8 | const ItemWeatherProperty({
9 | Key? key,
10 | required this.label,
11 | required this.value,
12 | }) : super(key: key);
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return Padding(
17 | padding: const EdgeInsets.only(top: 4, bottom: 4),
18 | child: Row(children: [
19 | Text(label, style: labelTextStyle),
20 | SizedBox(width: 24),
21 | Text(value, style: valueTextStyle),
22 | ]),
23 | );
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/ui/home/widget/sun_time.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:weather_app_flutter/ui/home/widget/Item_sun_time.dart';
3 |
4 | class SunTime extends StatelessWidget {
5 | final String sunrise;
6 | final String sunset;
7 |
8 | const SunTime({
9 | Key? key,
10 | required this.sunrise,
11 | required this.sunset,
12 | }) : super(key: key);
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return Row(
17 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
18 | children: [
19 | ItemSunTime(
20 | label: "Sunrise",
21 | value: sunrise,
22 | imagePath: 'images/sunrise.png',
23 | ),
24 | ItemSunTime(
25 | label: "Sunset",
26 | value: sunset,
27 | imagePath: 'images/sunset.png',
28 | ),
29 | ],
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/ui/home/widget/temperature_section.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:weather_app_flutter/core/text_style.dart';
3 |
4 | class TemperatureSection extends StatelessWidget {
5 | final String dateTime;
6 | final String temperature;
7 | final String iconUrl;
8 | final String description;
9 | final String cityAndCountry;
10 |
11 | const TemperatureSection({
12 | Key? key,
13 | required this.dateTime,
14 | required this.temperature,
15 | required this.iconUrl,
16 | required this.description,
17 | required this.cityAndCountry,
18 | }) : super(key: key);
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | return Column(
23 | crossAxisAlignment: CrossAxisAlignment.start,
24 | children: [
25 | Text(dateTime, style: valueTextStyle),
26 | _getTemperatureRow(),
27 | Text(cityAndCountry, style: titleTextStyle)
28 | ],
29 | );
30 | }
31 |
32 | _getTemperatureRow() {
33 | return Row(
34 | children: [
35 | Text(temperature, style: extraLargeTitleTextStyle),
36 | Text('°C', style: TextStyle(fontSize: 35, color: Colors.teal)),
37 | Spacer(),
38 | Column(
39 | mainAxisAlignment: MainAxisAlignment.center,
40 | crossAxisAlignment: CrossAxisAlignment.center,
41 | children: [
42 | // Image.network(iconUrl, width: 60, height: 60),
43 | FadeInImage(
44 | width: 60,
45 | height: 60,
46 | image: NetworkImage(iconUrl),
47 | placeholder: AssetImage("images/placeholder.png"),
48 | imageErrorBuilder: (context, error, stackTrace) {
49 | return Icon(Icons.error);
50 | },
51 | fit: BoxFit.fitWidth,
52 | ),
53 | Text(description),
54 | ],
55 | )
56 | ],
57 | );
58 | }
59 | }
--------------------------------------------------------------------------------
/lib/ui/home/widget/weather_data_output.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:weather_app_flutter/ui/home/model/weather_data.dart';
3 | import 'package:weather_app_flutter/ui/home/widget/sun_time.dart';
4 | import 'package:weather_app_flutter/ui/home/widget/temperature_section.dart';
5 | import 'package:weather_app_flutter/ui/home/widget/weather_property.dart';
6 |
7 | class WeatherDataOutput extends StatelessWidget {
8 | final WeatherData weather;
9 |
10 | const WeatherDataOutput({Key? key, required this.weather}) : super(key: key);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return Expanded(
15 | child: Column(
16 | children: [
17 | TemperatureSection(
18 | dateTime: weather.dateTime,
19 | temperature: weather.temperature,
20 | iconUrl: weather.weatherConditionIconUrl,
21 | description: weather.weatherConditionIconDescription,
22 | cityAndCountry: weather.cityAndCountry,
23 | ),
24 | SizedBox(height: 16),
25 | WeatherProperty(
26 | humidity: weather.humidity,
27 | pressure: weather.pressure,
28 | visibility: weather.visibility,
29 | ),
30 | Spacer(),
31 | SunTime(sunrise: weather.sunrise, sunset: weather.sunset),
32 | SizedBox(height: 10)
33 | ],
34 | ),
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/ui/home/widget/weather_property.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:weather_app_flutter/ui/home/widget/item_weather_property.dart';
3 |
4 | class WeatherProperty extends StatelessWidget {
5 | final String humidity;
6 | final String pressure;
7 | final String visibility;
8 |
9 | const WeatherProperty({
10 | Key? key,
11 | required this.humidity,
12 | required this.pressure,
13 | required this.visibility,
14 | }) : super(key: key);
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return Column(
19 | children: [
20 | ItemWeatherProperty(label: "Humidity", value: humidity),
21 | ItemWeatherProperty(label: "Pressure", value: pressure),
22 | ItemWeatherProperty(label: "Visibility", value: visibility)
23 | ],
24 | );
25 | }
26 | }
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | characters:
5 | dependency: transitive
6 | description:
7 | name: characters
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "1.1.0"
11 | charcode:
12 | dependency: transitive
13 | description:
14 | name: charcode
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "1.2.0"
18 | clock:
19 | dependency: transitive
20 | description:
21 | name: clock
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "1.1.0"
25 | collection:
26 | dependency: transitive
27 | description:
28 | name: collection
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.15.0"
32 | cupertino_icons:
33 | dependency: "direct main"
34 | description:
35 | name: cupertino_icons
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.0.3"
39 | dio:
40 | dependency: "direct main"
41 | description:
42 | name: dio
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "4.0.0"
46 | flutter:
47 | dependency: "direct main"
48 | description: flutter
49 | source: sdk
50 | version: "0.0.0"
51 | http_parser:
52 | dependency: transitive
53 | description:
54 | name: http_parser
55 | url: "https://pub.dartlang.org"
56 | source: hosted
57 | version: "4.0.0"
58 | intl:
59 | dependency: "direct main"
60 | description:
61 | name: intl
62 | url: "https://pub.dartlang.org"
63 | source: hosted
64 | version: "0.17.0"
65 | logger:
66 | dependency: "direct dev"
67 | description:
68 | name: logger
69 | url: "https://pub.dartlang.org"
70 | source: hosted
71 | version: "1.0.0"
72 | meta:
73 | dependency: transitive
74 | description:
75 | name: meta
76 | url: "https://pub.dartlang.org"
77 | source: hosted
78 | version: "1.3.0"
79 | path:
80 | dependency: transitive
81 | description:
82 | name: path
83 | url: "https://pub.dartlang.org"
84 | source: hosted
85 | version: "1.8.0"
86 | pretty_dio_logger:
87 | dependency: "direct dev"
88 | description:
89 | name: pretty_dio_logger
90 | url: "https://pub.dartlang.org"
91 | source: hosted
92 | version: "1.2.0-beta-1"
93 | sky_engine:
94 | dependency: transitive
95 | description: flutter
96 | source: sdk
97 | version: "0.0.99"
98 | source_span:
99 | dependency: transitive
100 | description:
101 | name: source_span
102 | url: "https://pub.dartlang.org"
103 | source: hosted
104 | version: "1.8.1"
105 | string_scanner:
106 | dependency: transitive
107 | description:
108 | name: string_scanner
109 | url: "https://pub.dartlang.org"
110 | source: hosted
111 | version: "1.1.0"
112 | term_glyph:
113 | dependency: transitive
114 | description:
115 | name: term_glyph
116 | url: "https://pub.dartlang.org"
117 | source: hosted
118 | version: "1.2.0"
119 | typed_data:
120 | dependency: transitive
121 | description:
122 | name: typed_data
123 | url: "https://pub.dartlang.org"
124 | source: hosted
125 | version: "1.3.0"
126 | vector_math:
127 | dependency: transitive
128 | description:
129 | name: vector_math
130 | url: "https://pub.dartlang.org"
131 | source: hosted
132 | version: "2.1.0"
133 | sdks:
134 | dart: ">=2.12.0 <3.0.0"
135 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: weather_app_flutter
2 | description: A weather forecast flutter App
3 | version: 1.0.0+1
4 |
5 | environment:
6 | sdk: '>=2.12.0 <3.0.0'
7 |
8 | dependencies:
9 | flutter:
10 | sdk: flutter
11 | dio: ^4.0.0
12 | cupertino_icons: ^1.0.2
13 | intl: ^0.17.0
14 |
15 | dev_dependencies:
16 | pretty_dio_logger: ^1.1.1
17 | logger: ^1.0.0
18 |
19 | flutter:
20 | uses-material-design: true
21 | assets:
22 | - images/
23 | - assets/
24 |
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:weather_app_flutter/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/web/favicon.png
--------------------------------------------------------------------------------
/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hasancse91/weather_app_flutter/2ae0303f2ec7941c341ea2c4bfd3c6055eec588b/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | weather_app_flutter
27 |
28 |
29 |
30 |
33 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "weather_app_flutter",
3 | "short_name": "weather_app_flutter",
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 |
--------------------------------------------------------------------------------