├── .gitignore
├── LICENSE
├── README.md
├── slider_menu
├── .idea
│ ├── libraries
│ │ └── Flutter_Plugins.xml
│ ├── modules.xml
│ ├── ui_challenge_flutter.iml
│ ├── vcs.xml
│ └── workspace.xml
├── .metadata
├── analysis_options.yaml
├── android
│ ├── .project
│ ├── .settings
│ │ └── org.eclipse.buildship.core.prefs
│ ├── app
│ │ ├── .classpath
│ │ ├── .project
│ │ ├── .settings
│ │ │ └── org.eclipse.buildship.core.prefs
│ │ ├── build.gradle
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── gen
│ │ │ └── cz
│ │ │ │ └── stepanzalis
│ │ │ │ └── uichallenges
│ │ │ │ ├── BuildConfig.java
│ │ │ │ ├── Manifest.java
│ │ │ │ └── R.java
│ │ │ ├── kotlin
│ │ │ └── cz
│ │ │ │ └── stepanzalis
│ │ │ │ └── uichallenges
│ │ │ │ └── MainActivity.kt
│ │ │ └── res
│ │ │ ├── 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
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ └── settings.gradle
├── assets
│ ├── fonts
│ │ └── Roboto-Medium.ttf
│ └── images
│ │ ├── avatars
│ │ ├── avatar1.png
│ │ ├── avatar2.png
│ │ ├── avatar3.png
│ │ ├── avatar4.png
│ │ ├── avatar5.png
│ │ ├── avatar6.png
│ │ ├── avatar7.png
│ │ └── user_image.png
│ │ ├── ic_back.png
│ │ ├── ic_calendar.png
│ │ ├── ic_inbox.png
│ │ ├── ic_projects_done.png
│ │ ├── ic_projects_todo.png
│ │ ├── ic_tag.png
│ │ ├── ic_trash.png
│ │ ├── ic_user.png
│ │ └── ic_user_menu.png
├── images
│ ├── app.gif
│ ├── closed_menu.png
│ └── open_menu.png
├── ios
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ └── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── 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
│ ├── io
│ │ ├── data
│ │ │ ├── menu_data.dart
│ │ │ ├── person.dart
│ │ │ └── persons_data.dart
│ │ └── menu_provider.dart
│ ├── main.dart
│ ├── menu
│ │ ├── animated_screen.dart
│ │ ├── menu_item.dart
│ │ └── menu_screen.dart
│ ├── menu_holder.dart
│ ├── project
│ │ ├── item_person.dart
│ │ └── project_screen.dart
│ └── theme
│ │ └── text_styles.dart
├── pubspec.lock
└── pubspec.yaml
├── temp_slider
├── .gitignore
├── .metadata
├── README.md
├── Screenshot 2019-01-11 at 14.25.20.png
├── analysis_options.yaml
├── android
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── temperatureoval
│ │ │ │ └── MainActivity.java
│ │ │ └── res
│ │ │ ├── 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
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ └── settings.gradle
├── assets
│ └── ic_ac.png
├── ios
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ └── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── Runner
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── 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
│ │ └── main.m
├── lib
│ ├── colors.dart
│ ├── main.dart
│ ├── type_enum.dart
│ └── widgets
│ │ ├── central_temp.dart
│ │ ├── icon_slider.dart
│ │ ├── icon_text.dart
│ │ ├── painters
│ │ └── ruler_painter.dart
│ │ ├── round_button.dart
│ │ └── ruler.dart
├── pubspec.yaml
├── screenshot.png
└── test
│ └── widget_test.dart
└── vpn_app
├── README.md
├── android
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── io
│ │ │ │ └── flutter
│ │ │ │ └── plugins
│ │ │ │ └── GeneratedPluginRegistrant.java
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── stepanzalis
│ │ │ │ └── vpn_app
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── 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
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── local.properties
├── settings.gradle
└── vpn_app_android.iml
├── assets
├── fonts
│ ├── SF-Pro-Display-Bold.otf
│ ├── SF-Pro-Display-Medium.otf
│ ├── SF-Pro-Display-Regular.otf
│ └── SF-Pro-Display-Semibold.otf
└── images
│ ├── arrow.svg
│ ├── check_arrow.svg
│ ├── down_arrow.svg
│ ├── flags
│ ├── australia.svg
│ ├── automatic.svg
│ ├── india.svg
│ ├── russia.svg
│ ├── singapore.svg
│ ├── sweden.svg
│ ├── uk.svg
│ └── us.svg
│ ├── hamburger.svg
│ └── onboarding.png
├── ios
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ ├── Generated.xcconfig
│ └── Release.xcconfig
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ └── contents.xcworkspacedata
└── 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
│ ├── GeneratedPluginRegistrant.h
│ ├── GeneratedPluginRegistrant.m
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
├── lib
├── io
│ └── models
│ │ ├── connection_model.dart
│ │ ├── server_model.dart
│ │ ├── vpn_server.dart
│ │ └── welcome_model.dart
├── main.dart
├── ui
│ ├── screens
│ │ ├── home
│ │ │ ├── drawer_layout.dart
│ │ │ ├── home_page_screen.dart
│ │ │ ├── main_page_container.dart
│ │ │ └── widgets
│ │ │ │ ├── connection_info_widget.dart
│ │ │ │ ├── connection_state_circle_widget.dart
│ │ │ │ ├── item_country_server_widget.dart
│ │ │ │ ├── rounded_checkbox_widget.dart
│ │ │ │ ├── server_container_widget.dart
│ │ │ │ └── stroke_circle_widget.dart
│ │ └── welcome
│ │ │ ├── welcome_screen.dart
│ │ │ └── widgets
│ │ │ ├── circle_dot.dart
│ │ │ └── intro_widget.dart
│ └── widgets
│ │ └── rounded_button_widget.dart
└── util
│ ├── colors.dart
│ ├── dimens.dart
│ ├── router.dart
│ ├── status_bar.dart
│ ├── string.dart
│ └── theme.dart
├── pubspec.yaml
├── screenshots
└── screenshot1.png
└── test
├── connection_model_tests.dart
├── server_model_tests.dart
├── string_utils_test.dart
├── welcome_model_tests.dart
└── widget_tests.dart
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | .DS_Store
6 | /.idea
7 | *.rawproto
8 | *.jar
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Štěpán Záliš
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UI Flutter challenges
2 |
3 | This repository consists of weekly UI challenges from designers at www.dribbble.com.
4 | If anyone wants to see his design live, feel free to send it to: stepan.zalis@gmail.com.
5 |
6 | [](https://codemagic.io/apps/5c0770552e0492001c5c5782/5c0770552e0492001c5c5781/latest_build)
7 |
8 | Thanks! :v:
9 |
10 | ## Flutter is :blue_heart:
11 |
12 | Feel free to comment and contribute!
13 |
14 |
15 | ### 1. Slide navigation
16 | Design was taken from [Roman Bova](https://dribbble.com/shots/3925867-Activity-Feed-Daily-UI-047-Freebie). Nice and clean slide animation.
17 |
18 |
19 |
20 | ### 2. Thermostat
21 | The goal was to implement the behaviour of scrollable ruler to change a temperature (using a CustomPainter).
22 |
23 |
24 |
25 | ### 3. VPN
26 | Design was taken from freebie [project365](https://project365.design/2018/10/05/day-278-vpn-mobile-app-ui-kit-sketch-freebie/)
27 |
28 |
29 |
--------------------------------------------------------------------------------
/slider_menu/.idea/libraries/Flutter_Plugins.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/slider_menu/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/slider_menu/.idea/ui_challenge_flutter.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/slider_menu/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/slider_menu/.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: d954ae6850a06ea461d5595cef424e278ed9f17f
8 | channel: dev
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/slider_menu/android/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | android
4 | Project android created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.buildship.core.gradleprojectbuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.buildship.core.gradleprojectnature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/slider_menu/android/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | connection.project.dir=
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/slider_menu/android/app/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/slider_menu/android/app/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | app
4 | Project app created by Buildship.
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.buildship.core.gradleprojectbuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.buildship.core.gradleprojectnature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/slider_menu/android/app/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | connection.project.dir=..
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/slider_menu/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 27
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | lintOptions {
36 | disable 'InvalidPackage'
37 | }
38 |
39 | defaultConfig {
40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
41 | applicationId "cz.stepanzalis.uichallenges"
42 | minSdkVersion 16
43 | targetSdkVersion 27
44 | versionCode flutterVersionCode.toInteger()
45 | versionName flutterVersionName
46 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
47 | }
48 |
49 | buildTypes {
50 | release {
51 | // TODO: Add your own signing config for the release build.
52 | // Signing with the debug keys for now, so `flutter run --release` works.
53 | signingConfig signingConfigs.debug
54 | }
55 | }
56 | }
57 |
58 | flutter {
59 | source '../..'
60 | }
61 |
62 | dependencies {
63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
64 | testImplementation 'junit:junit:4.12'
65 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
66 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
67 | }
68 |
--------------------------------------------------------------------------------
/slider_menu/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
15 |
19 |
26 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/slider_menu/android/app/src/main/gen/cz/stepanzalis/uichallenges/BuildConfig.java:
--------------------------------------------------------------------------------
1 | /*___Generated_by_IDEA___*/
2 |
3 | package cz.stepanzalis.uichallenges;
4 |
5 | /* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
6 | public final class BuildConfig {
7 | public final static boolean DEBUG = Boolean.parseBoolean(null);
8 | }
--------------------------------------------------------------------------------
/slider_menu/android/app/src/main/gen/cz/stepanzalis/uichallenges/Manifest.java:
--------------------------------------------------------------------------------
1 | /*___Generated_by_IDEA___*/
2 |
3 | package cz.stepanzalis.uichallenges;
4 |
5 | /* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
6 | public final class Manifest {
7 | }
--------------------------------------------------------------------------------
/slider_menu/android/app/src/main/gen/cz/stepanzalis/uichallenges/R.java:
--------------------------------------------------------------------------------
1 | /*___Generated_by_IDEA___*/
2 |
3 | package cz.stepanzalis.uichallenges;
4 |
5 | /* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
6 | public final class R {
7 | }
--------------------------------------------------------------------------------
/slider_menu/android/app/src/main/kotlin/cz/stepanzalis/uichallenges/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package cz.stepanzalis.uichallenges
2 |
3 | import android.os.Bundle
4 |
5 | import io.flutter.app.FlutterActivity
6 | import io.flutter.plugins.GeneratedPluginRegistrant
7 |
8 | class MainActivity(): FlutterActivity() {
9 | override fun onCreate(savedInstanceState: Bundle?) {
10 | super.onCreate(savedInstanceState)
11 | GeneratedPluginRegistrant.registerWith(this)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/slider_menu/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/slider_menu/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/slider_menu/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/slider_menu/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/slider_menu/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/slider_menu/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/slider_menu/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/slider_menu/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.2.30'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.1.2'
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 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/slider_menu/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
--------------------------------------------------------------------------------
/slider_menu/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-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/slider_menu/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/slider_menu/assets/fonts/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/fonts/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/slider_menu/assets/images/avatars/avatar1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/avatars/avatar1.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/avatars/avatar2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/avatars/avatar2.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/avatars/avatar3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/avatars/avatar3.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/avatars/avatar4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/avatars/avatar4.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/avatars/avatar5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/avatars/avatar5.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/avatars/avatar6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/avatars/avatar6.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/avatars/avatar7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/avatars/avatar7.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/avatars/user_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/avatars/user_image.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/ic_back.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/ic_calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/ic_calendar.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/ic_inbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/ic_inbox.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/ic_projects_done.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/ic_projects_done.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/ic_projects_todo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/ic_projects_todo.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/ic_tag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/ic_tag.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/ic_trash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/ic_trash.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/ic_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/ic_user.png
--------------------------------------------------------------------------------
/slider_menu/assets/images/ic_user_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/assets/images/ic_user_menu.png
--------------------------------------------------------------------------------
/slider_menu/images/app.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/images/app.gif
--------------------------------------------------------------------------------
/slider_menu/images/closed_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/images/closed_menu.png
--------------------------------------------------------------------------------
/slider_menu/images/open_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/images/open_menu.png
--------------------------------------------------------------------------------
/slider_menu/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 |
--------------------------------------------------------------------------------
/slider_menu/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/slider_menu/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/slider_menu/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/slider_menu/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
56 |
58 |
64 |
65 |
66 |
67 |
68 |
69 |
75 |
77 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/slider_menu/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/slider_menu/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildSystemType
6 | Original
7 |
8 |
9 |
--------------------------------------------------------------------------------
/slider_menu/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: [UIApplicationLaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/slider_menu/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 |
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/slider_menu/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 |
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/slider_menu/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/slider_menu/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.
--------------------------------------------------------------------------------
/slider_menu/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 |
--------------------------------------------------------------------------------
/slider_menu/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 |
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ui_challenges
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 |
--------------------------------------------------------------------------------
/slider_menu/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
--------------------------------------------------------------------------------
/slider_menu/lib/io/data/menu_data.dart:
--------------------------------------------------------------------------------
1 | import 'package:ui_challenges/menu/menu_item.dart';
2 |
3 | class MenuData {
4 |
5 | final menu = [
6 | ItemMenu(path: 'assets/images/ic_inbox.png', name: 'Inbox'),
7 | ItemMenu(path: 'assets/images/ic_calendar.png', name: 'Calendar'),
8 | ItemMenu(path: 'assets/images/ic_projects_done.png', name: 'Projects'),
9 | ItemMenu(path: 'assets/images/ic_user.png', name: 'Crew'),
10 | ItemMenu(path: 'assets/images/ic_tag.png', name: 'Tags'),
11 | ItemMenu(path: '', name: ''),
12 | ItemMenu(path: 'assets/images/ic_projects_todo.png', name: 'Projects'),
13 | ];
14 | }
15 |
--------------------------------------------------------------------------------
/slider_menu/lib/io/data/person.dart:
--------------------------------------------------------------------------------
1 | class Person {
2 |
3 | String name;
4 | String imagePath;
5 | String time;
6 | String task;
7 | String state;
8 |
9 | Person(this.name, this.imagePath, this.time, this.state, this.task);
10 |
11 |
12 | }
--------------------------------------------------------------------------------
/slider_menu/lib/io/data/persons_data.dart:
--------------------------------------------------------------------------------
1 | import 'package:ui_challenges/io/data/person.dart';
2 |
3 | class PersonsData {
4 |
5 | final persons = [
6 | Person('Christian Nelson', 'assets/images/avatars/avatar1.png',
7 | '17 min ago', 'completed', 'Task name'),
8 | Person('Martha Ford', 'assets/images/avatars/avatar2.png', '21 min ago',
9 | 'completed', 'Test'),
10 | Person('Gladys Lawrance', 'assets/images/avatars/avatar3.png', '34 min ago',
11 | 'completed', 'Users'),
12 | Person('Carl Fletcher', 'assets/images/avatars/avatar4.png', '35 min ago',
13 | 'completed', 'Bussiness'),
14 | Person('Dave Roberts', 'assets/images/avatars/avatar5.png', '47 min ago',
15 | 'completed', 'HR rel'),
16 | Person('Hailey Waever', 'assets/images/avatars/avatar6.png', '59 min ago',
17 | 'completed', 'Task to contribute'),
18 | Person('Super Admin', 'assets/images/avatars/avatar7.png', '2 h ago',
19 | 'completed', 'Admin')
20 | ];
21 |
22 | }
--------------------------------------------------------------------------------
/slider_menu/lib/io/menu_provider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class MenuProvider with ChangeNotifier {
4 |
5 | bool _open = false;
6 | int _selectedId = 0;
7 |
8 | bool get isOpen => _open;
9 | int get getSelected => _selectedId;
10 |
11 | changeSelectedPage(selected) {
12 | _selectedId = selected;
13 | debugPrint(selected.toString());
14 | }
15 |
16 | toggleMenuPanel() {
17 | _open = !_open;
18 | notifyListeners();
19 | }
20 | }
--------------------------------------------------------------------------------
/slider_menu/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ui_challenges/io/menu_provider.dart';
3 | import 'package:ui_challenges/menu_holder.dart';
4 | import 'package:provider/provider.dart';
5 |
6 | void main() => runApp(MenuApp(key: ValueKey('menuApp')));
7 |
8 | class MenuApp extends StatelessWidget {
9 |
10 | const MenuApp({Key key}) : super(key: key);
11 |
12 | @override
13 | Widget build(BuildContext context) => MaterialApp(
14 | debugShowCheckedModeBanner: false,
15 | theme: Theme.of(context).copyWith(
16 | primaryColor: Colors.white,
17 | accentIconTheme: Theme.of(context).accentIconTheme.copyWith(
18 | color: Colors.white
19 | )
20 | ),
21 | home: ChangeNotifierProvider(
22 | builder: (_) => MenuProvider(),
23 | child: MenuHolder())
24 | );
25 | }
--------------------------------------------------------------------------------
/slider_menu/lib/menu/animated_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:provider/provider.dart';
4 | import 'package:ui_challenges/io/menu_provider.dart';
5 | import 'package:ui_challenges/theme/text_styles.dart';
6 |
7 | class AnimatedScreen extends StatefulWidget {
8 |
9 | const AnimatedScreen({@required this.appBarTitle, @required this.body});
10 |
11 | final String appBarTitle;
12 | final Widget body;
13 |
14 | @override
15 | _AnimatedScreenState createState() => _AnimatedScreenState();
16 | }
17 |
18 | class _AnimatedScreenState extends State with SingleTickerProviderStateMixin {
19 |
20 | AnimationController _animationController;
21 | Animation _tween;
22 |
23 | @override
24 | Widget build(BuildContext context) {
25 | final openPercent = Interval(0.0, 0.8, curve: Curves.easeOut).transform(_tween.value);
26 |
27 | final slideAmount = 255.0 * openPercent;
28 | final contentScale = 1 - (0.35 * openPercent);
29 |
30 | return Consumer(
31 | builder: (context, model, child) {
32 |
33 | if (model.isOpen) _animationController.reverse();
34 | else _animationController.forward();
35 |
36 | return Transform(
37 | transform: Matrix4.translationValues(slideAmount, 0.0, 0.0)..scale(contentScale, contentScale),
38 | alignment: Alignment.centerLeft,
39 | child: Container(
40 | decoration: BoxDecoration(
41 | boxShadow: [
42 | new BoxShadow(
43 | color: Colors.blue[100],
44 | offset: Offset(0.0, 3.0),
45 | blurRadius: 50.0,
46 | spreadRadius: 1.0,
47 | ),
48 | ],
49 | ),
50 | child: Scaffold(appBar: getAppBar(widget.appBarTitle, model), body: widget.body)));
51 | });
52 | }
53 |
54 | Widget getAppBar(String appBarText, MenuProvider model) => AppBar(
55 | title: Text(appBarText, style: MyTextTheme().getLightSmallGrey().copyWith(fontSize: 20.0)),
56 | leading: IconButton(
57 | icon: Icon(CupertinoIcons.back, color: Colors.grey[400], size: 25.0),
58 | onPressed: () {
59 | model.isOpen ? _animationController.reverse() : _animationController.forward();
60 | model.toggleMenuPanel();
61 | }),
62 | elevation: 0.0,
63 | actions: [
64 | IconButton(
65 | icon: Image(image: AssetImage('assets/images/ic_trash.png'), width: 25, height: 25),
66 | onPressed: () {},
67 | )
68 | ],
69 | );
70 |
71 | @override
72 | void initState() {
73 | _animationController = AnimationController(
74 | duration: Duration(milliseconds: 500),
75 | vsync: this,
76 | )..addListener(() {
77 | setState(() {});
78 | });
79 |
80 | _tween = Tween(begin: 0.0, end: 1.0).animate(_animationController);
81 | super.initState();
82 | }
83 |
84 | @override
85 | void dispose() {
86 | _animationController.dispose();
87 | super.dispose();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/slider_menu/lib/menu/menu_item.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ui_challenges/theme/text_styles.dart';
3 |
4 | class ItemMenu extends StatelessWidget {
5 |
6 | final String path;
7 | final String name;
8 |
9 | const ItemMenu({@required this.path, @required this.name});
10 |
11 | @override
12 | Widget build(BuildContext context) => Padding(
13 | padding: const EdgeInsets.only(left: 30.0, top: 10.0, bottom: 10.0),
14 | child: Container(
15 | height: 55,
16 | child: Row(
17 | crossAxisAlignment: CrossAxisAlignment.center,
18 | mainAxisAlignment: MainAxisAlignment.start,
19 | textBaseline: TextBaseline.alphabetic,
20 | children: [
21 | Image.asset(path, width: 25, height: 25, color: Colors.grey[400]),
22 | SizedBox(width: 20.0),
23 | Text(name,
24 | style: MyTextTheme()
25 | .getLightSmallGrey()
26 | .copyWith(fontSize: 22.0, fontWeight: FontWeight.w700))
27 | ],
28 | ),
29 | ),
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/slider_menu/lib/menu/menu_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ui_challenges/io/data/menu_data.dart';
3 | import 'package:ui_challenges/menu/menu_item.dart';
4 | import 'package:ui_challenges/theme/text_styles.dart';
5 |
6 | class MenuScreen extends StatefulWidget {
7 |
8 | MenuScreen(this.tap);
9 |
10 | Function(int) tap;
11 |
12 | @override
13 | _MenuScreenState createState() => _MenuScreenState();
14 | }
15 |
16 | class _MenuScreenState extends State {
17 | final data = MenuData().menu;
18 |
19 | @override
20 | Widget build(BuildContext context) => Scaffold(
21 | backgroundColor: Colors.white,
22 | body: SafeArea(
23 | child: Padding(
24 | padding: const EdgeInsets.only(top: 40.0),
25 | child: Column(
26 | children: [
27 | _AvatarListTile(),
28 | SizedBox(height: 20),
29 | Expanded(
30 | child: ListView.builder(
31 | itemCount: data.length,
32 | itemBuilder: (context, index) {
33 | final model = data[index];
34 | return GestureDetector(
35 | onTap: () => widget.tap(index),
36 | child: model.path.isEmpty ? _Divider() : ItemMenu(path: model.path, name: model.name));
37 | },
38 | )),
39 | ],
40 | ),
41 | )));
42 | }
43 |
44 | class _Divider extends StatelessWidget {
45 | const _Divider();
46 |
47 | @override
48 | Widget build(BuildContext context) => Padding(
49 | padding: const EdgeInsets.only(left: 30.0, top: 15, bottom: 15),
50 | child: Container(
51 | height: 2.0,
52 | color: Colors.grey[300],
53 | ),
54 | );
55 | }
56 |
57 | class _AvatarListTile extends StatelessWidget {
58 | const _AvatarListTile();
59 |
60 | @override
61 | Widget build(BuildContext context) => ListTile(
62 | leading:
63 | CircleAvatar(radius: 25.0, child: Image.asset('assets/images/avatars/user_image.png', fit: BoxFit.contain)),
64 | title: Text('Roman Bova', style: MyTextTheme().getGrey().copyWith(fontSize: 24, fontWeight: FontWeight.w600)),
65 | subtitle: Text('UI/UX Designer',
66 | style: MyTextTheme().getSmallBlue().copyWith(fontSize: 20, fontWeight: FontWeight.w400)));
67 | }
68 |
--------------------------------------------------------------------------------
/slider_menu/lib/menu_holder.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:provider/provider.dart';
3 | import 'package:ui_challenges/io/menu_provider.dart';
4 | import 'package:ui_challenges/menu/animated_screen.dart';
5 | import 'package:ui_challenges/menu/menu_screen.dart';
6 | import 'package:ui_challenges/project/project_screen.dart';
7 |
8 | class MenuHolder extends StatefulWidget {
9 | const MenuHolder();
10 |
11 | @override
12 | _MenuHolderState createState() => _MenuHolderState();
13 | }
14 |
15 | class _MenuHolderState extends State {
16 |
17 | Widget currentScreen = AnimatedScreen(appBarTitle: 'Project', body: ProjectScreen());
18 |
19 | @override
20 | Widget build(BuildContext context) => Container(
21 | color: Colors.white,
22 | child: Stack(
23 | children: [
24 | MenuScreen((selectedId) => {
25 | Provider.of(context, listen: false).changeSelectedPage(selectedId),
26 | Provider.of(context, listen: false).toggleMenuPanel()
27 | }),
28 | currentScreen
29 | ],
30 | ),
31 | );
32 | }
33 |
--------------------------------------------------------------------------------
/slider_menu/lib/project/item_person.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:ui_challenges/io/data/person.dart';
3 | import 'package:ui_challenges/theme/text_styles.dart';
4 |
5 | class ItemPerson extends StatelessWidget {
6 | ItemPerson(this.person);
7 |
8 | final Person person;
9 | final MyTextTheme textTheme = MyTextTheme();
10 |
11 | @override
12 | Widget build(BuildContext context) => PersonListTile(person, textTheme);
13 | }
14 |
15 | class PersonListTile extends ListTile {
16 |
17 | final Person person;
18 | final MyTextTheme textTheme;
19 | const PersonListTile(this.person, this.textTheme);
20 |
21 | @override
22 | Widget build(BuildContext context) => Padding(
23 | padding: const EdgeInsets.only(left: 20.0),
24 | child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [
25 | _AvatarWidget(person.imagePath, 40.0),
26 | SizedBox(width: 20),
27 | Expanded(
28 | child: Column(
29 | crossAxisAlignment: CrossAxisAlignment.start,
30 | children: [_FirstRowInPerson(person, textTheme), _SecondRowInPerson(person, textTheme)])),
31 | ]),
32 | );
33 | }
34 |
35 |
36 | class _AvatarWidget extends StatelessWidget {
37 |
38 | final String path;
39 | final double radius;
40 |
41 | const _AvatarWidget(this.path, this.radius)
42 | : assert(path != null),
43 | assert(radius != null);
44 |
45 | @override
46 | Widget build(BuildContext context) => Material(
47 | shape: CircleBorder(),
48 | color: Colors.transparent,
49 | shadowColor: Colors.transparent,
50 | child: Image.asset(path, width: radius, height: radius));
51 | }
52 |
53 | class _FirstRowInPerson extends StatelessWidget {
54 | final Person person;
55 | final MyTextTheme textTheme;
56 |
57 | const _FirstRowInPerson(this.person, this.textTheme)
58 | : assert(person != null),
59 | assert(textTheme != null);
60 |
61 | @override
62 | Widget build(BuildContext context) => Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
63 | Text(person.name, style: textTheme.getGrey()),
64 | Padding(
65 | padding: EdgeInsets.only(right: 10.0),
66 | child: Text(person.time,
67 | style: textTheme.getLightSmallGrey().copyWith(fontSize: 17.0, fontWeight: FontWeight.w600)))
68 | ]);
69 | }
70 |
71 | class _SecondRowInPerson extends StatelessWidget {
72 | final Person person;
73 | final MyTextTheme textTheme;
74 |
75 | const _SecondRowInPerson(this.person, this.textTheme)
76 | : assert(person != null),
77 | assert(textTheme != null);
78 |
79 | @override
80 | Widget build(BuildContext context) => Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
81 | Text(person.state, style: textTheme.getLightSmallGrey()),
82 | SizedBox(width: 15.0),
83 | Text(person.task, style: textTheme.getSmallBlue())
84 | ]);
85 | }
86 |
--------------------------------------------------------------------------------
/slider_menu/lib/project/project_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:ui_challenges/io/data/persons_data.dart';
4 | import 'package:ui_challenges/project/item_person.dart';
5 | import 'package:ui_challenges/theme/text_styles.dart';
6 |
7 | class ProjectScreen extends StatelessWidget {
8 |
9 | PersonsData data;
10 |
11 | ProjectScreen() {
12 | data = PersonsData();
13 | }
14 |
15 | @override
16 | Widget build(BuildContext context) => _ActivityListView(data);
17 | }
18 |
19 | class _ActivityListView extends StatelessWidget {
20 |
21 | final PersonsData data;
22 | const _ActivityListView(this.data);
23 |
24 | @override
25 | Widget build(BuildContext context) => Container(
26 | color: Colors.white,
27 | child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
28 | Padding(
29 | padding: EdgeInsets.only(left: 20.0, top: 20.0),
30 | child: Text("Activity Feed",
31 | style: MyTextTheme().getSmallBlue().copyWith(fontWeight: FontWeight.bold, fontSize: 25))),
32 | Expanded(
33 | child: ListView.builder(
34 | padding: EdgeInsets.only(top: 20),
35 | itemCount: data.persons.length,
36 | itemBuilder: (context, int index) =>
37 | Padding(padding: EdgeInsets.only(top: 20.0, bottom: 20.0), child: ItemPerson(data.persons[index]))))
38 | ]));
39 | }
40 |
--------------------------------------------------------------------------------
/slider_menu/lib/theme/text_styles.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class MyTextTheme {
4 |
5 | const MyTextTheme();
6 |
7 | TextStyle getSmallBlue() {
8 | return _getSmallFont(Colors.blue);
9 | }
10 |
11 | TextStyle getBigBlue() {
12 | return getSmallBlue().copyWith(fontSize: 25, fontWeight: FontWeight.bold);
13 | }
14 |
15 | TextStyle getLightSmallGrey() {
16 | return _getSmallFont(Colors.grey[400]);
17 | }
18 |
19 | TextStyle getGrey() {
20 | return TextStyle(fontSize: 22.0, color: Colors.blueGrey[300], fontWeight: FontWeight.w600);
21 | }
22 |
23 | _getSmallFont(Color color) {
24 | return TextStyle(fontSize: 15.0, color: color);
25 | }
26 |
27 |
28 | }
--------------------------------------------------------------------------------
/slider_menu/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: ui_challenges
2 | description: UI Challenges Flutter
3 |
4 | version: 1.0.0+1
5 |
6 | environment:
7 | sdk: ">=2.2.3 <3.0.0"
8 |
9 | dependencies:
10 | flutter:
11 | sdk: flutter
12 |
13 | # State management
14 | provider: ^3.0.0+1
15 |
16 | cupertino_icons: ^0.1.2
17 |
18 | dev_dependencies:
19 | flutter_test:
20 | sdk: flutter
21 |
22 | flutter:
23 | uses-material-design: true
24 |
25 | assets:
26 | - assets/images/avatars/avatar1.png
27 | - assets/images/avatars/avatar2.png
28 | - assets/images/avatars/avatar3.png
29 | - assets/images/avatars/avatar4.png
30 | - assets/images/avatars/avatar5.png
31 | - assets/images/avatars/avatar6.png
32 | - assets/images/avatars/avatar7.png
33 | - assets/images/avatars/user_image.png
34 |
35 | - assets/images/ic_user.png
36 | - assets/images/ic_back.png
37 | - assets/images/ic_trash.png
38 |
39 | - assets/images/ic_inbox.png
40 | - assets/images/ic_projects_todo.png
41 | - assets/images/ic_projects_done.png
42 | - assets/images/ic_calendar.png
43 | - assets/images/ic_tag.png
44 |
45 |
46 | fonts:
47 | - family: Roboto
48 | fonts:
49 | - asset: assets/fonts/Roboto-Medium.ttf
50 |
51 |
--------------------------------------------------------------------------------
/temp_slider/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.lock
4 | *.log
5 | *.pyc
6 | *.swp
7 | .DS_Store
8 | .atom/
9 | .buildlog/
10 | .history
11 | .svn/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # Visual Studio Code related
20 | .vscode/
21 |
22 | # Flutter/Dart/Pub related
23 | **/doc/api/
24 | .dart_tool/
25 | .flutter-plugins
26 | .packages
27 | .pub-cache/
28 | .pub/
29 | build/
30 |
31 | # Android related
32 | **/android/**/gradle-wrapper.jar
33 | **/android/.gradle
34 | **/android/captures/
35 | **/android/gradlew
36 | **/android/gradlew.bat
37 | **/android/local.properties
38 | **/android/**/GeneratedPluginRegistrant.java
39 |
40 | # iOS/XCode related
41 | **/ios/**/*.mode1v3
42 | **/ios/**/*.mode2v3
43 | **/ios/**/*.moved-aside
44 | **/ios/**/*.pbxuser
45 | **/ios/**/*.perspectivev3
46 | **/ios/**/*sync/
47 | **/ios/**/.sconsign.dblite
48 | **/ios/**/.tags*
49 | **/ios/**/.vagrant/
50 | **/ios/**/DerivedData/
51 | **/ios/**/Icon?
52 | **/ios/**/Pods/
53 | **/ios/**/.symlinks/
54 | **/ios/**/profile
55 | **/ios/**/xcuserdata
56 | **/ios/.generated/
57 | **/ios/Flutter/App.framework
58 | **/ios/Flutter/Flutter.framework
59 | **/ios/Flutter/Generated.xcconfig
60 | **/ios/Flutter/app.flx
61 | **/ios/Flutter/app.zip
62 | **/ios/Flutter/flutter_assets/
63 | **/ios/ServiceDefinitions.json
64 | **/ios/Runner/GeneratedPluginRegistrant.*
65 |
66 | # Exceptions to above rules.
67 | !**/ios/**/default.mode1v3
68 | !**/ios/**/default.mode2v3
69 | !**/ios/**/default.pbxuser
70 | !**/ios/**/default.perspectivev3
71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
72 |
--------------------------------------------------------------------------------
/temp_slider/.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: 1407091bfb5bb535630d4d596541817737da8412
8 | channel: dev
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/temp_slider/README.md:
--------------------------------------------------------------------------------
1 | # Smart Home App
2 |
3 | Original design from https://dribbble.com/shakuro
4 | Project page: https://dribbble.com/shots/5534531-Smart-Home-App-Thermostat
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/temp_slider/Screenshot 2019-01-11 at 14.25.20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/Screenshot 2019-01-11 at 14.25.20.png
--------------------------------------------------------------------------------
/temp_slider/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 from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
26 |
27 | android {
28 | compileSdkVersion 27
29 |
30 | lintOptions {
31 | disable 'InvalidPackage'
32 | }
33 |
34 | defaultConfig {
35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
36 | applicationId "com.example.temperatureoval"
37 | minSdkVersion 16
38 | targetSdkVersion 27
39 | versionCode flutterVersionCode.toInteger()
40 | versionName flutterVersionName
41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
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 | testImplementation 'junit:junit:4.12'
59 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
61 | }
62 |
--------------------------------------------------------------------------------
/temp_slider/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
15 |
19 |
26 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/temp_slider/android/app/src/main/java/com/example/temperatureoval/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.temperatureoval;
2 |
3 | import android.os.Bundle;
4 | import io.flutter.app.FlutterActivity;
5 | import io.flutter.plugins.GeneratedPluginRegistrant;
6 |
7 | public class MainActivity extends FlutterActivity {
8 | @Override
9 | protected void onCreate(Bundle savedInstanceState) {
10 | super.onCreate(savedInstanceState);
11 | GeneratedPluginRegistrant.registerWith(this);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/temp_slider/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/temp_slider/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/temp_slider/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/temp_slider/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/temp_slider/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/temp_slider/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/temp_slider/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/temp_slider/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.2.1'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | google()
15 | jcenter()
16 | }
17 | }
18 |
19 | rootProject.buildDir = '../build'
20 | subprojects {
21 | project.buildDir = "${rootProject.buildDir}/${project.name}"
22 | }
23 | subprojects {
24 | project.evaluationDependsOn(':app')
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/temp_slider/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
--------------------------------------------------------------------------------
/temp_slider/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-4.10.2-all.zip
7 |
--------------------------------------------------------------------------------
/temp_slider/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/temp_slider/assets/ic_ac.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/assets/ic_ac.png
--------------------------------------------------------------------------------
/temp_slider/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 |
--------------------------------------------------------------------------------
/temp_slider/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/temp_slider/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/temp_slider/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/temp_slider/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
56 |
58 |
64 |
65 |
66 |
67 |
68 |
69 |
75 |
77 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/temp_slider/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/temp_slider/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/temp_slider/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildSystemType
6 | Original
7 |
8 |
9 |
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : FlutterAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #include "AppDelegate.h"
2 | #include "GeneratedPluginRegistrant.h"
3 |
4 | @implementation AppDelegate
5 |
6 | - (BOOL)application:(UIApplication *)application
7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
8 | [GeneratedPluginRegistrant registerWithRegistry:self];
9 | // Override point for customization after application launch.
10 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
11 | }
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/temp_slider/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 |
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/temp_slider/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 |
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/temp_slider/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.
--------------------------------------------------------------------------------
/temp_slider/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 |
--------------------------------------------------------------------------------
/temp_slider/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 |
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | temperature_oval
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 |
--------------------------------------------------------------------------------
/temp_slider/ios/Runner/main.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char* argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/temp_slider/lib/colors.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 |
4 | Color pinkColor = Color.fromARGB(255, 224, 0, 71);
5 | Color greyColor = Color.fromARGB(255, 76, 75, 75);
6 | Color backgroundColor = Color.fromARGB(255, 19, 17, 20);
7 | Color rulerColor = Color.fromARGB(220, 76, 75, 75);
8 |
--------------------------------------------------------------------------------
/temp_slider/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:temperature_oval/type_enum.dart';
3 | import 'package:temperature_oval/widgets/central_temp.dart';
4 | import 'package:temperature_oval/widgets/icon_slider.dart';
5 | import 'package:temperature_oval/widgets/icon_text.dart';
6 | import 'package:temperature_oval/widgets/round_button.dart';
7 | import 'package:temperature_oval/widgets/ruler.dart';
8 | import 'colors.dart';
9 |
10 | void main() => runApp(MyApp());
11 |
12 | class MyApp extends StatelessWidget {
13 | @override
14 | Widget build(BuildContext context) => MaterialApp(
15 | debugShowCheckedModeBanner: false,
16 | home: HomePage(),
17 | );
18 | }
19 |
20 | class HomePage extends StatefulWidget {
21 | const HomePage({Key key}) : super(key: key);
22 |
23 | @override
24 | HomePageState createState() => new HomePageState();
25 | }
26 |
27 | class HomePageState extends State {
28 | double value = 3;
29 | num temp = 77;
30 | List sampleData = [];
31 |
32 | @override
33 | Widget build(BuildContext context) => Scaffold(
34 | appBar: AppBar(
35 | elevation: 0,
36 | backgroundColor: backgroundColor,
37 | leading: Icon(Icons.arrow_back),
38 | ),
39 | body: Container(
40 | color: backgroundColor,
41 | width: MediaQuery.of(context).size.width,
42 | height: MediaQuery.of(context).size.height,
43 | child: SafeArea(
44 | child: Stack(
45 | children: [
46 | Positioned(
47 | top: MediaQuery.of(context).size.height / 4,
48 | left: 0,
49 | child: CentralTemp(temperature: temp.toString())),
50 | Positioned(top: 30, left: MediaQuery.of(context).size.width / 1.3, child: RulerWidget(size: MediaQuery.of(context).size, function: setTemp)),
51 | Positioned(
52 | left: 30,
53 | top: MediaQuery.of(context).size.height / 1.9,
54 | child: IconTextWidget(
55 | icon: Icons.alarm,
56 | text: 'Set smart schedule',
57 | type: IconText.greyIconPinkText)),
58 | Positioned(
59 | left: 30,
60 | top: MediaQuery.of(context).size.height / 1.7,
61 | child:
62 | Container(height: 80, child: Row(children: sampleData))),
63 | Positioned(
64 | left: 30,
65 | top: MediaQuery.of(context).size.height / 1.4,
66 | child: IconSlider()),
67 | Positioned(
68 | child: Align(
69 | alignment: FractionalOffset.bottomCenter,
70 | child: IconTextWidget(
71 | icon: Icons.power_settings_new,
72 | text: 'Hold to turn off',
73 | type: IconText.pinkIconGreyText)))
74 | ],
75 | ),
76 | ),
77 | ));
78 |
79 | setTemp(temp) {
80 | setState(() {
81 | this.temp = temp.round();
82 | });
83 | }
84 |
85 | @override
86 | void initState() {
87 | sampleData.add(RoundButton(icon: Icons.ac_unit));
88 | sampleData.add(SizedBox(width: 15));
89 | sampleData.add(RoundButton(icon: Icons.place));
90 | sampleData.add(SizedBox(width: 15));
91 | sampleData.add(RoundButton(icon: Icons.wb_sunny));
92 |
93 | super.initState();
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/temp_slider/lib/type_enum.dart:
--------------------------------------------------------------------------------
1 |
2 | enum IconText {
3 | pinkIconGreyText, greyIconPinkText
4 | }
5 |
--------------------------------------------------------------------------------
/temp_slider/lib/widgets/central_temp.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class CentralTemp extends StatelessWidget {
4 |
5 | const CentralTemp({Key key, this.temperature}) : super(key: key);
6 |
7 | // actul temperature number
8 | final temperature;
9 |
10 | @override
11 | Widget build(BuildContext context) => Padding(
12 | padding: const EdgeInsets.only(left: 20.0),
13 | child: Column(
14 | mainAxisAlignment: MainAxisAlignment.start,
15 | crossAxisAlignment: CrossAxisAlignment.start,
16 | mainAxisSize: MainAxisSize.min,
17 | children: [
18 | Text('TEMPERATURE, °F',
19 | style: TextStyle(fontSize: 13, color: Colors.white)),
20 | Text(temperature,
21 | style: TextStyle(fontSize: 160, color: Colors.white, height: 0.85)),
22 | ],
23 | ),
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/temp_slider/lib/widgets/icon_slider.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:temperature_oval/colors.dart';
5 |
6 | class IconSlider extends StatefulWidget {
7 | const IconSlider({
8 | Key key,
9 | }) : super(key: key);
10 |
11 | @override
12 | IconSliderState createState() => new IconSliderState();
13 | }
14 |
15 | class IconSliderState extends State with TickerProviderStateMixin {
16 | var sliderValue = 3.0;
17 |
18 | AnimationController _animationController;
19 |
20 | @override
21 | Widget build(BuildContext context) => Row(
22 | mainAxisAlignment: MainAxisAlignment.center,
23 | crossAxisAlignment: CrossAxisAlignment.center,
24 | children: [
25 | Container(
26 | child: AnimatedBuilder(
27 | animation: _animationController,
28 | child: ImageIcon(AssetImage('assets/ic_ac.png'),
29 | color: greyColor, size: 20.0),
30 | builder: (context, widget) => Transform.rotate(
31 | angle: _animationController.value * pi, child: widget),
32 | ),
33 | ),
34 | Container(
35 | width: MediaQuery.of(context).size.width / 1.3,
36 | child: Slider(
37 | value: sliderValue,
38 | min: 0,
39 | max: 10,
40 | onChanged: (double newValue) {
41 | setState(() {
42 | sliderValue = newValue;
43 | _animationController.forward();
44 |
45 | _animationController.addStatusListener((status) {
46 | if (status == AnimationStatus.completed) {
47 | _animationController.value = 0;
48 | }
49 | });
50 | });
51 | },
52 | activeColor: pinkColor,
53 | inactiveColor: greyColor),
54 | )
55 | ],
56 | );
57 |
58 | @override
59 | void initState() {
60 | _animationController = new AnimationController(
61 | duration: const Duration(milliseconds: 800),
62 | vsync: this,
63 | )..addListener(() {
64 | setState(() {});
65 | });
66 |
67 | super.initState();
68 | }
69 |
70 | @override
71 | void dispose() {
72 | _animationController.dispose();
73 | super.dispose();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/temp_slider/lib/widgets/icon_text.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:temperature_oval/colors.dart';
3 | import 'package:temperature_oval/type_enum.dart';
4 |
5 | class IconTextWidget extends StatelessWidget {
6 |
7 | const IconTextWidget({Key key, this.icon, this.text, this.type})
8 | : super(key: key);
9 |
10 | final icon;
11 | final text;
12 | final type;
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | final iconColor = type == IconText.greyIconPinkText ? greyColor : pinkColor;
17 | final textColor = type == IconText.greyIconPinkText ? pinkColor : greyColor;
18 |
19 | return Row(mainAxisAlignment: MainAxisAlignment.center, children: [
20 | Icon(icon, color: iconColor),
21 | SizedBox(width: 7),
22 | Text(text, style: TextStyle(fontSize: 13, color: textColor))
23 | ]);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/temp_slider/lib/widgets/painters/ruler_painter.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:temperature_oval/colors.dart';
5 |
6 | class RulerPainter extends CustomPainter {
7 | final smallLength = 25.0;
8 | final longLength = 15.0;
9 | final numberOfLines = 200;
10 |
11 | final strokeWidth = 1.0;
12 |
13 | final Paint rulerPaint;
14 |
15 | RulerPainter({Key key, this.scrollLen}) : rulerPaint = new Paint() {
16 | rulerPaint.color = rulerColor;
17 | }
18 |
19 | final double scrollLen;
20 |
21 | @override
22 | void paint(Canvas canvas, Size size) {
23 | var tickMarkLength;
24 | final angle = 2 * pi / numberOfLines;
25 |
26 | final radius = size.width;
27 | canvas.save();
28 |
29 | final circlePaint = Paint()
30 | ..style = PaintingStyle.stroke
31 | ..strokeWidth = 5.0
32 | ..color = pinkColor;
33 |
34 | final shadow = Paint()
35 | ..style = PaintingStyle.stroke
36 | ..strokeWidth = 10.0
37 | ..color = pinkColor
38 | ..maskFilter = MaskFilter.blur(BlurStyle.normal, 90);
39 |
40 | // pink border around ruler
41 | canvas.drawCircle(new Offset(radius, radius), radius + 8, circlePaint);
42 | canvas.drawCircle(new Offset(radius, radius), radius + 8, shadow);
43 |
44 | // drawing
45 | canvas.translate(radius, radius);
46 |
47 | for (var i = 0; i < numberOfLines; i++) {
48 | tickMarkLength = i % 5 == 0 ? smallLength : longLength;
49 | rulerPaint.strokeWidth = strokeWidth;
50 | canvas.drawLine(new Offset(0.0, -radius),
51 | new Offset(0.0, -radius + tickMarkLength), rulerPaint);
52 |
53 | canvas.rotate(angle);
54 | }
55 | canvas.restore();
56 | }
57 |
58 | @override
59 | bool shouldRepaint(RulerPainter oldDelegate) => true;
60 | }
61 |
--------------------------------------------------------------------------------
/temp_slider/lib/widgets/round_button.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:temperature_oval/colors.dart';
3 |
4 | class RoundButton extends StatefulWidget {
5 | RoundButton({Key key, this.icon}) : super(key: key);
6 |
7 | final icon;
8 | bool tapped = false;
9 |
10 | @override
11 | _RoundButtonState createState() => _RoundButtonState();
12 | }
13 |
14 | class _RoundButtonState extends State {
15 | @override
16 | Widget build(BuildContext context) => GestureDetector(
17 | onTap: handleSelected,
18 | child: Material(
19 | color: Colors.transparent,
20 | child: Container(
21 | decoration: BoxDecoration(
22 | border: Border.all(
23 | color: widget.tapped ? pinkColor : greyColor, width: 2.0),
24 | color: widget.tapped ? pinkColor : Colors.transparent,
25 | shape: BoxShape.circle,
26 | ),
27 | child: Padding(
28 | padding: EdgeInsets.all(15.0),
29 | child: Icon(
30 | widget.icon,
31 | size: 25.0,
32 | color: widget.tapped ? Colors.white : greyColor,
33 | ),
34 | ),
35 | ),
36 | ));
37 |
38 | handleSelected() {
39 | setState(() {
40 | widget.tapped = !widget.tapped;
41 | });
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/temp_slider/lib/widgets/ruler.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:temperature_oval/widgets/painters/ruler_painter.dart';
3 |
4 | class RulerWidget extends StatefulWidget {
5 |
6 | RulerWidget({
7 | Key key,
8 | this.size,
9 | this.function,
10 | }) : super(key: key);
11 |
12 | Size size;
13 | Function(double) function;
14 |
15 | @override
16 | RulerWidgetState createState() => new RulerWidgetState();
17 | }
18 |
19 | class RulerWidgetState extends State {
20 | double _y = 0;
21 | double _len = 0;
22 |
23 | GlobalKey keyPaint = GlobalKey();
24 |
25 | @override
26 | Widget build(BuildContext context) => GestureDetector(
27 | onVerticalDragStart: (detail) {
28 | _y = detail.globalPosition.dy;
29 | },
30 | onVerticalDragUpdate: (detail) {
31 | setState(() {
32 | _len += detail.globalPosition.dy - _y;
33 | _y = detail.globalPosition.dy;
34 | widget.function(_len);
35 | });
36 | },
37 | child: Transform(
38 | transform: Matrix4.rotationZ(_len / 10),
39 | alignment: FractionalOffset.centerRight,
40 | child: Container(
41 | height: 400,
42 | width: 200,
43 | child: CustomPaint(
44 | willChange: true,
45 | painter: RulerPainter(scrollLen: _len),
46 | ),
47 | ),
48 | ),
49 | );
50 | }
51 |
--------------------------------------------------------------------------------
/temp_slider/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: temperature_oval
2 | description: A new Flutter project.
3 |
4 | # The following defines the version and build number for your application.
5 | # A version number is three numbers separated by dots, like 1.2.43
6 | # followed by an optional build number separated by a +.
7 | # Both the version and the builder number may be overridden in flutter
8 | # build by specifying --build-name and --build-number, respectively.
9 | # Read more about versioning at semver.org.
10 | version: 1.0.0+1
11 |
12 | environment:
13 | sdk: ">=2.1.0 <3.0.0"
14 |
15 | dependencies:
16 | flutter:
17 | sdk: flutter
18 |
19 | # The following adds the Cupertino Icons font to your application.
20 | # Use with the CupertinoIcons class for iOS style icons.
21 | cupertino_icons: ^0.1.2
22 |
23 | dev_dependencies:
24 | flutter_test:
25 | sdk: flutter
26 |
27 |
28 | # For information on the generic Dart part of this file, see the
29 | # following page: https://www.dartlang.org/tools/pub/pubspec
30 |
31 | # The following section is specific to Flutter.
32 | flutter:
33 |
34 | # The following line ensures that the Material Icons font is
35 | # included with your application, so that you can use the icons in
36 | # the material Icons class.
37 | uses-material-design: true
38 |
39 | # To add assets to your application, add an assets section, like this:
40 | assets:
41 | - assets/ic_ac.png
42 |
43 |
44 | # An image asset can refer to one or more resolution-specific "variants", see
45 | # https://flutter.io/assets-and-images/#resolution-aware.
46 |
47 | # For details regarding adding assets from package dependencies, see
48 | # https://flutter.io/assets-and-images/#from-packages
49 |
50 | # To add custom fonts to your application, add a fonts section here,
51 | # in this "flutter" section. Each entry in this list should have a
52 | # "family" key with the font family name, and a "fonts" key with a
53 | # list giving the asset and other descriptors for the font. For
54 | # example:
55 | # fonts:
56 | # - family: Schyler
57 | # fonts:
58 | # - asset: fonts/Schyler-Regular.ttf
59 | # - asset: fonts/Schyler-Italic.ttf
60 | # style: italic
61 | # - family: Trajan Pro
62 | # fonts:
63 | # - asset: fonts/TrajanPro.ttf
64 | # - asset: fonts/TrajanPro_Bold.ttf
65 | # weight: 700
66 | #
67 | # For details regarding fonts from package dependencies,
68 | # see https://flutter.io/custom-fonts/#from-packages
69 |
--------------------------------------------------------------------------------
/temp_slider/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/temp_slider/screenshot.png
--------------------------------------------------------------------------------
/temp_slider/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:temperature_oval/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 |
--------------------------------------------------------------------------------
/vpn_app/README.md:
--------------------------------------------------------------------------------
1 | # 📶 VPN App
2 |
3 | Flutter UI challenge (3.)
4 |
5 | ### State Managment
6 | - Provider
7 |
8 | ### Dependencies
9 | - flutter_svg
10 |
--------------------------------------------------------------------------------
/vpn_app/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
4 |
5 | android {
6 | compileSdkVersion 28
7 |
8 | sourceSets {
9 | main.java.srcDirs += 'src/main/kotlin'
10 | }
11 |
12 | lintOptions {
13 | disable 'InvalidPackage'
14 | }
15 |
16 | defaultConfig {
17 | applicationId "com.stepanzalis.vpn_app"
18 | minSdkVersion 19
19 | targetSdkVersion 28
20 | versionCode 1
21 | versionName "0.0.1"
22 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
23 | }
24 |
25 | buildTypes {
26 | release {
27 | // TODO: Add your own signing config for the release build.
28 | // Signing with the debug keys for now, so `flutter run --release` works.
29 | signingConfig signingConfigs.debug
30 | }
31 | }
32 | }
33 |
34 | flutter {
35 | source '../..'
36 | }
37 |
38 | dependencies {
39 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
40 | testImplementation 'junit:junit:4.12'
41 | androidTestImplementation 'androidx.test:runner:1.1.1'
42 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
43 | }
44 |
--------------------------------------------------------------------------------
/vpn_app/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/vpn_app/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
9 |
13 |
20 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/vpn_app/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java:
--------------------------------------------------------------------------------
1 | package io.flutter.plugins;
2 |
3 | import io.flutter.plugin.common.PluginRegistry;
4 |
5 | /**
6 | * Generated file. Do not edit.
7 | */
8 | public final class GeneratedPluginRegistrant {
9 | public static void registerWith(PluginRegistry registry) {
10 | if (alreadyRegisteredWith(registry)) {
11 | return;
12 | }
13 | }
14 |
15 | private static boolean alreadyRegisteredWith(PluginRegistry registry) {
16 | final String key = GeneratedPluginRegistrant.class.getCanonicalName();
17 | if (registry.hasPlugin(key)) {
18 | return true;
19 | }
20 | registry.registrarFor(key);
21 | return false;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/vpn_app/android/app/src/main/kotlin/com/stepanzalis/vpn_app/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.stepanzalis.vpn_app
2 |
3 | import android.os.Bundle
4 |
5 | import io.flutter.app.FlutterActivity
6 | import io.flutter.plugins.GeneratedPluginRegistrant
7 |
8 | class MainActivity: FlutterActivity() {
9 | override fun onCreate(savedInstanceState: Bundle?) {
10 | super.onCreate(savedInstanceState)
11 | GeneratedPluginRegistrant.registerWith(this)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/vpn_app/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/vpn_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/vpn_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/vpn_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/vpn_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/vpn_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/vpn_app/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/vpn_app/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/vpn_app/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.2.71'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.2.1'
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 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/vpn_app/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 |
--------------------------------------------------------------------------------
/vpn_app/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
6 |
--------------------------------------------------------------------------------
/vpn_app/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/vpn_app/android/local.properties:
--------------------------------------------------------------------------------
1 | sdk.dir=/Users/stepanzalis/Library/Android/sdk
2 | flutter.sdk=/Users/stepanzalis/flutter
3 | flutter.buildMode=release
4 | flutter.versionName=1.0.0
5 | flutter.versionCode=1
--------------------------------------------------------------------------------
/vpn_app/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/vpn_app/android/vpn_app_android.iml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/vpn_app/assets/fonts/SF-Pro-Display-Bold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/assets/fonts/SF-Pro-Display-Bold.otf
--------------------------------------------------------------------------------
/vpn_app/assets/fonts/SF-Pro-Display-Medium.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/assets/fonts/SF-Pro-Display-Medium.otf
--------------------------------------------------------------------------------
/vpn_app/assets/fonts/SF-Pro-Display-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/assets/fonts/SF-Pro-Display-Regular.otf
--------------------------------------------------------------------------------
/vpn_app/assets/fonts/SF-Pro-Display-Semibold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/assets/fonts/SF-Pro-Display-Semibold.otf
--------------------------------------------------------------------------------
/vpn_app/assets/images/arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/vpn_app/assets/images/check_arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/vpn_app/assets/images/down_arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/vpn_app/assets/images/flags/australia.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/vpn_app/assets/images/flags/automatic.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/vpn_app/assets/images/flags/india.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/vpn_app/assets/images/flags/russia.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/vpn_app/assets/images/flags/singapore.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/vpn_app/assets/images/flags/sweden.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/vpn_app/assets/images/flags/uk.svg:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/vpn_app/assets/images/flags/us.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/vpn_app/assets/images/hamburger.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/vpn_app/assets/images/onboarding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/assets/images/onboarding.png
--------------------------------------------------------------------------------
/vpn_app/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 |
--------------------------------------------------------------------------------
/vpn_app/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/vpn_app/ios/Flutter/Generated.xcconfig:
--------------------------------------------------------------------------------
1 | // This is a generated file; do not edit or check into version control.
2 | FLUTTER_ROOT=/Users/stepanzalis/flutter
3 | FLUTTER_APPLICATION_PATH=/Users/stepanzalis/Desktop/vpn_app
4 | FLUTTER_TARGET=lib/main.dart
5 | FLUTTER_BUILD_DIR=build
6 | SYMROOT=${SOURCE_ROOT}/../build/ios
7 | FLUTTER_FRAMEWORK_DIR=/Users/stepanzalis/flutter/bin/cache/artifacts/engine/ios
8 | FLUTTER_BUILD_NAME=1.0.0
9 | FLUTTER_BUILD_NUMBER=1
10 |
--------------------------------------------------------------------------------
/vpn_app/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/vpn_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/vpn_app/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 |
--------------------------------------------------------------------------------
/vpn_app/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/vpn_app/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 |
--------------------------------------------------------------------------------
/vpn_app/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 |
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/vpn_app/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 |
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/vpn_app/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.
--------------------------------------------------------------------------------
/vpn_app/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 |
--------------------------------------------------------------------------------
/vpn_app/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 |
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/GeneratedPluginRegistrant.h:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | #ifndef GeneratedPluginRegistrant_h
6 | #define GeneratedPluginRegistrant_h
7 |
8 | #import
9 |
10 | @interface GeneratedPluginRegistrant : NSObject
11 | + (void)registerWithRegistry:(NSObject*)registry;
12 | @end
13 |
14 | #endif /* GeneratedPluginRegistrant_h */
15 |
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/GeneratedPluginRegistrant.m:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | #import "GeneratedPluginRegistrant.h"
6 |
7 | @implementation GeneratedPluginRegistrant
8 |
9 | + (void)registerWithRegistry:(NSObject*)registry {
10 | }
11 |
12 | @end
13 |
--------------------------------------------------------------------------------
/vpn_app/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 | vpn_app
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 |
--------------------------------------------------------------------------------
/vpn_app/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
--------------------------------------------------------------------------------
/vpn_app/lib/io/models/connection_model.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/cupertino.dart';
3 |
4 | class ConnectionModel with ChangeNotifier {
5 |
6 | bool _connected = false;
7 | bool get isConnected => _connected;
8 |
9 | String get connectionStateTitle => isConnected ? 'CONNECTED' : 'DISCONNECTED';
10 | String get buttonTitle => isConnected ? 'DISCONNECT' : 'CONNECT NOW';
11 |
12 | void changeConnectionState() {
13 | _connected = !_connected;
14 | notifyListeners();
15 | }
16 | }
--------------------------------------------------------------------------------
/vpn_app/lib/io/models/server_model.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/cupertino.dart';
3 | import 'package:vpn_app/io/models/vpn_server.dart';
4 |
5 | class ServerModel with ChangeNotifier {
6 |
7 | VpnServer _selectedServer = servers[1];
8 |
9 | int get selectedIndex => _selectedServer.index;
10 | VpnServer get selectedServer => _selectedServer;
11 |
12 | void changeServer(int index) {
13 | if (index < 0 || index > servers.length - 1) return null;
14 |
15 | _selectedServer = servers[index];
16 | notifyListeners();
17 | }
18 |
19 | static final servers = [
20 | VpnServer('Automatic', 'us.svg', 0),
21 | VpnServer('New York, NY', 'us.svg', 1),
22 | VpnServer('London', 'uk.svg', 2),
23 | VpnServer('Moscow', 'russia.svg', 3),
24 | VpnServer('Stockholm', 'sweden.svg', 4),
25 | VpnServer('Melbourne', 'australia.svg', 5),
26 | VpnServer('New Deplhi', 'india.svg', 6),
27 | VpnServer('Singapore', 'india.svg', 7),
28 | ];
29 | }
--------------------------------------------------------------------------------
/vpn_app/lib/io/models/vpn_server.dart:
--------------------------------------------------------------------------------
1 | class VpnServer {
2 |
3 | final String stateName;
4 | final String flagAssetName;
5 | final int index;
6 |
7 | VpnServer(this.stateName, this.flagAssetName, this.index)
8 | : assert(stateName != null || stateName.isNotEmpty, 'Country name should not be empty'),
9 | assert(flagAssetName != null, 'Flag resource should not be null');
10 | }
11 |
--------------------------------------------------------------------------------
/vpn_app/lib/io/models/welcome_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:vpn_app/ui/screens/welcome/widgets/intro_widget.dart';
3 |
4 | class WelcomeModel with ChangeNotifier {
5 |
6 | int _currentIndex = 0;
7 | int get currentIndex => _currentIndex;
8 |
9 | List get widgets => _introWidgetList;
10 | int get widgetLength => widgets.length;
11 |
12 | bool get lastPage => _currentIndex == widgetLength - 1;
13 |
14 | void changeCurrentIndex(int index) {
15 | if (index < 0 || index > widgetLength - 1) return null;
16 |
17 | _currentIndex = index;
18 | notifyListeners();
19 | }
20 |
21 | final List _introWidgetList = [
22 | IntroWidget(
23 | title: 'Secured, forever.',
24 | imageRes: 'assets/images/onboarding.png',
25 | description:
26 | 'Curabitur lobortis id lorem id bibendum. Ut id consectetur magna. Quisque volutpat augue enim, pulvinar lobortis.'),
27 | IntroWidget(
28 | title: 'Secured, forever.',
29 | imageRes: 'assets/images/onboarding.png',
30 | description:
31 | 'Curabitur lobortis id lorem id bibendum. Ut id consectetur magna. Quisque volutpat augue enim, pulvinar lobortis.'),
32 | IntroWidget(
33 | title: 'Secured, forever.',
34 | imageRes: 'assets/images/onboarding.png',
35 | description:
36 | 'Curabitur lobortis id lorem id bibendum. Ut id consectetur magna. Quisque volutpat augue enim, pulvinar lobortis.'),
37 | ];
38 | }
39 |
--------------------------------------------------------------------------------
/vpn_app/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:provider/provider.dart';
3 | import 'package:vpn_app/io/models/connection_model.dart';
4 | import 'package:vpn_app/io/models/welcome_model.dart';
5 | import 'package:vpn_app/io/models/server_model.dart';
6 | import 'package:vpn_app/ui/screens/home/home_page_screen.dart';
7 | import 'package:vpn_app/util/router.dart';
8 | import 'package:vpn_app/util/status_bar.dart';
9 | import 'package:vpn_app/util/theme.dart';
10 |
11 | Future main() async {
12 | setPreferredOrientations();
13 | setStatusBarColor();
14 | runApp(VpnApp());
15 | }
16 |
17 | class VpnApp extends StatelessWidget {
18 |
19 | @override
20 | Widget build(BuildContext context) => MultiProvider(
21 | providers: [
22 | ChangeNotifierProvider(builder: (context) => WelcomeModel()),
23 | ChangeNotifierProvider(builder: (context) => ConnectionModel()),
24 | ChangeNotifierProvider(builder: (context) => ServerModel()),
25 | ],
26 | child: Directionality(
27 | textDirection: TextDirection.ltr,
28 | child: MaterialApp(
29 | title: 'VPN',
30 | debugShowCheckedModeBanner: false,
31 | theme: appTheme,
32 | onGenerateRoute: Router.generateRoute,
33 | home: HomeScreen(),
34 | ),
35 | ),
36 | );
37 | }
38 |
--------------------------------------------------------------------------------
/vpn_app/lib/ui/screens/home/drawer_layout.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class DrawerLayout extends StatelessWidget {
4 |
5 | const DrawerLayout();
6 |
7 | @override
8 | Widget build(BuildContext context) => Drawer(
9 | child: Container(
10 | color: Colors.white,
11 | child: Center(
12 | child: Text('Implement me', style: Theme.of(context).textTheme.body2),
13 | ),
14 | ),
15 | );
16 | }
--------------------------------------------------------------------------------
/vpn_app/lib/ui/screens/home/home_page_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_svg/svg.dart';
3 | import 'package:vpn_app/ui/screens/home/drawer_layout.dart';
4 | import 'package:vpn_app/ui/screens/home/main_page_container.dart';
5 |
6 | class HomeScreen extends StatelessWidget {
7 |
8 | const HomeScreen();
9 |
10 | @override
11 | Widget build(BuildContext context) => SafeArea(
12 | child: Scaffold(
13 | appBar: AppBar(
14 | elevation: 0,
15 | backgroundColor: Theme.of(context).backgroundColor,
16 | leading: Builder(
17 | builder: (context) => IconButton(
18 | icon: SvgPicture.asset('assets/images/hamburger.svg'),
19 | onPressed: () => Scaffold.of(context).openDrawer(),
20 | ),
21 | ),
22 | centerTitle: true,
23 | title: Text(
24 | 'VPN',
25 | style: Theme.of(context).textTheme.title,
26 | ),
27 | ),
28 | drawer: DrawerLayout(),
29 | body: MainPageContainer()),
30 | );
31 | }
--------------------------------------------------------------------------------
/vpn_app/lib/ui/screens/home/main_page_container.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:provider/provider.dart';
3 | import 'package:vpn_app/io/models/connection_model.dart';
4 | import 'package:vpn_app/io/models/server_model.dart';
5 | import 'package:vpn_app/io/models/vpn_server.dart';
6 | import 'package:vpn_app/ui/screens/home/widgets/connection_info_widget.dart';
7 | import 'package:vpn_app/ui/screens/home/widgets/connection_state_circle_widget.dart';
8 | import 'package:vpn_app/ui/screens/home/widgets/server_container_widget.dart';
9 | import 'package:vpn_app/ui/widgets/rounded_button_widget.dart';
10 | import 'package:vpn_app/util/dimens.dart';
11 |
12 | class MainPageContainer extends StatelessWidget {
13 | const MainPageContainer();
14 |
15 | @override
16 | Widget build(BuildContext context) => Container(
17 | width: double.infinity,
18 | height: double.infinity,
19 | color: Theme.of(context).backgroundColor,
20 | child: Stack(
21 | alignment: Alignment.center,
22 | children: [
23 | Column(
24 | mainAxisSize: MainAxisSize.min,
25 | mainAxisAlignment: MainAxisAlignment.center,
26 | crossAxisAlignment: CrossAxisAlignment.center,
27 | children: [
28 | _ConnectionStateInfo(),
29 | SizedBox(height: separatorHeight),
30 | _ConnectionStateCircle(),
31 | SizedBox(height: separatorHeight),
32 | _ConnectionButton(),
33 | ],
34 | ),
35 | _ServerBottomContainer()
36 | ],
37 | ),
38 | );
39 | }
40 |
41 | class _ConnectionStateCircle extends StatelessWidget {
42 | const _ConnectionStateCircle();
43 |
44 | @override
45 | Widget build(BuildContext context) => Consumer(
46 | builder: (context, model, child) => ConnectionStateCircleWidget(
47 | circleSize: connectionCircleSize,
48 | connected: model.isConnected,
49 | ),
50 | );
51 | }
52 |
53 | class _ConnectionButton extends StatelessWidget {
54 | const _ConnectionButton();
55 |
56 | @override
57 | Widget build(BuildContext context) => Consumer(
58 | builder: (context, model, child) => RoundedButton(
59 | title: model.buttonTitle,
60 | filled: model.isConnected,
61 | onTap: () => model.changeConnectionState(),
62 | ),
63 | );
64 | }
65 |
66 | class _ConnectionStateInfo extends StatelessWidget {
67 | const _ConnectionStateInfo();
68 |
69 | @override
70 | Widget build(BuildContext context) => Consumer(
71 | builder: (context, model, child) => ConnectionStateInfo(
72 | title: model.connectionStateTitle,
73 | connected: model.isConnected,
74 | ),
75 | );
76 | }
77 |
78 | class _ServerBottomContainer extends StatelessWidget {
79 | const _ServerBottomContainer();
80 |
81 | @override
82 | Widget build(BuildContext context) {
83 | final VpnServer selectedServer = Provider.of(context).selectedServer;
84 |
85 | return Align(
86 | alignment: Alignment.bottomCenter,
87 | child: ServerContainer(chosenServer: selectedServer),
88 | );
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/vpn_app/lib/ui/screens/home/widgets/connection_info_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:vpn_app/util/colors.dart';
3 | import 'package:vpn_app/util/dimens.dart';
4 | import 'package:vpn_app/util/string.dart';
5 |
6 | class ConnectionStateInfo extends StatelessWidget {
7 |
8 | final String title;
9 | final bool connected;
10 |
11 | const ConnectionStateInfo({@required this.title, @required this.connected});
12 |
13 | @override
14 | Widget build(BuildContext context) => Material(
15 | elevation: 8,
16 | shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
17 | child: Container(
18 | height: connectionStateHeight,
19 | width: connectionStateWidth,
20 | decoration: BoxDecoration(
21 | color: Colors.white,
22 | borderRadius: BorderRadius.circular(30.0),
23 | ),
24 | child: Row(
25 | mainAxisSize: MainAxisSize.min,
26 | mainAxisAlignment: MainAxisAlignment.center,
27 | crossAxisAlignment: CrossAxisAlignment.center,
28 | children: [
29 | Text(capitalize(title.toLowerCase()), style: Theme.of(context).textTheme.overline),
30 | SizedBox(width: 10),
31 | _ConnectionIcon(connected: connected),
32 | ],
33 | ),
34 | ),
35 | );
36 | }
37 |
38 | class _ConnectionIcon extends StatelessWidget {
39 | final double size = 10;
40 | final bool connected;
41 |
42 | const _ConnectionIcon({@required this.connected});
43 |
44 | @override
45 | Widget build(BuildContext context) => Container(
46 | width: size,
47 | height: size,
48 | decoration: BoxDecoration(
49 | color: connected ? connectedStateColor : disconnectedStateColor,
50 | shape: BoxShape.circle,
51 | ),
52 | );
53 | }
54 |
--------------------------------------------------------------------------------
/vpn_app/lib/ui/screens/home/widgets/connection_state_circle_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_svg/flutter_svg.dart';
4 | import 'package:vpn_app/ui/screens/home/widgets/stroke_circle_widget.dart';
5 | import 'package:vpn_app/util/colors.dart';
6 | import 'package:vpn_app/util/dimens.dart';
7 |
8 | class ConnectionStateCircleWidget extends StatelessWidget {
9 | final double circleSize;
10 | final bool connected;
11 |
12 | const ConnectionStateCircleWidget({this.circleSize = 200, @required this.connected})
13 | : assert(circleSize >= 0, '$ConnectionStateCircleWidget must be bigger then zero');
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | final Color outerCircleColor = connected ? primaryColor : outerDisconnectedColor;
18 | final Color innerCircleColor = connected ? innerConnectedColor : innerDisconnectedColor;
19 |
20 | return Stack(
21 | alignment: Alignment.center,
22 | children: [
23 | StrokedCircle(circleSize: circleSize, color: outerCircleColor),
24 | StrokedCircle(circleSize: outerCircleSize, color: innerCircleColor),
25 | _InnerIconCircle(circleSize: innerCircleSize, connected: connected),
26 | ],
27 | );
28 | }
29 | }
30 |
31 | class _IconWidget extends StatelessWidget {
32 | final String imagePath;
33 | final double size;
34 |
35 | const _IconWidget({@required this.imagePath, this.size = 30, Key key}) : super(key: key);
36 |
37 | @override
38 | Widget build(BuildContext context) => SvgPicture.asset(
39 | imagePath,
40 | width: size,
41 | height: size,
42 | );
43 | }
44 |
45 | class _InnerIconCircle extends StatelessWidget {
46 | final bool connected;
47 | final double circleSize;
48 |
49 | _InnerIconCircle({@required this.connected, this.circleSize = 160});
50 |
51 | @override
52 | Widget build(BuildContext context) {
53 | final List gradientColors = connected ? connectedGradientColors : disconnectedGradientColors;
54 | final CrossFadeState currentFadeState = connected ? CrossFadeState.showSecond : CrossFadeState.showFirst;
55 |
56 | return Container(
57 | width: circleSize,
58 | height: circleSize,
59 | decoration: BoxDecoration(
60 | shape: BoxShape.circle,
61 | gradient: LinearGradient(
62 | begin: Alignment.bottomLeft,
63 | end: Alignment.topRight,
64 | colors: gradientColors,
65 | ),
66 | ),
67 | child: Center(
68 | child: AnimatedCrossFade(
69 | duration: Duration(milliseconds: 300),
70 | firstChild: _IconWidget(imagePath: 'assets/images/arrow.svg', key: UniqueKey()),
71 | secondChild: _IconWidget(imagePath: 'assets/images/check_arrow.svg', key: UniqueKey()),
72 | crossFadeState: currentFadeState,
73 | ),
74 | ),
75 | );
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/vpn_app/lib/ui/screens/home/widgets/item_country_server_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_svg/flutter_svg.dart';
3 | import 'package:vpn_app/io/models/vpn_server.dart';
4 | import 'package:vpn_app/ui/screens/home/widgets/rounded_checkbox_widget.dart';
5 | import 'package:vpn_app/util/dimens.dart';
6 |
7 | class CountryServerItem extends StatelessWidget {
8 | final VpnServer server;
9 | final bool selected;
10 |
11 | const CountryServerItem({@required this.server, this.selected});
12 |
13 | @override
14 | Widget build(BuildContext context) => Container(
15 | width: double.infinity,
16 | height: itemStateFlagHeight,
17 | color: Theme.of(context).backgroundColor,
18 | child: Row(
19 | mainAxisSize: MainAxisSize.max,
20 | crossAxisAlignment: CrossAxisAlignment.center,
21 | children: [
22 | Expanded(
23 | flex: 2,
24 | child: SvgPicture.asset('assets/images/flags/${server.flagAssetName}'),
25 | ),
26 | Expanded(
27 | flex: 5,
28 | child: Text(
29 | '${server.stateName}',
30 | style: Theme.of(context).textTheme.body1.copyWith(fontSize: 18),
31 | ),
32 | ),
33 | Expanded(
34 | flex: 3,
35 | child: RoundedCheckbox(checked: selected),
36 | )
37 | ],
38 | ),
39 | );
40 | }
41 |
--------------------------------------------------------------------------------
/vpn_app/lib/ui/screens/home/widgets/rounded_checkbox_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:vpn_app/util/colors.dart';
3 | import 'package:vpn_app/util/dimens.dart';
4 |
5 | class RoundedCheckbox extends StatelessWidget {
6 | final double size;
7 | final bool checked;
8 |
9 | const RoundedCheckbox({@required this.checked, this.size});
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | final Color color = checked ? primaryColor : Colors.white;
14 | final Color borderColor = checked ? primaryColor : strokeCheckBoxColor;
15 |
16 | return Container(
17 | width: size ?? checkBoxHeight,
18 | height: size ?? checkBoxHeight,
19 | decoration: BoxDecoration(
20 | border: Border.all(color: borderColor, width: 1),
21 | color: color,
22 | shape: BoxShape.circle,
23 | ),
24 | child: checked
25 | ? Icon(
26 | Icons.check,
27 | size: 15,
28 | color: Colors.white,
29 | )
30 | : null,
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/vpn_app/lib/ui/screens/home/widgets/server_container_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_svg/flutter_svg.dart';
3 | import 'package:provider/provider.dart';
4 | import 'package:vpn_app/io/models/server_model.dart';
5 | import 'package:vpn_app/io/models/vpn_server.dart';
6 | import 'package:vpn_app/ui/screens/home/widgets/item_country_server_widget.dart';
7 | import 'package:vpn_app/util/colors.dart';
8 |
9 | class ServerContainer extends StatelessWidget {
10 |
11 | final VpnServer chosenServer;
12 | const ServerContainer({@required this.chosenServer});
13 |
14 | @override
15 | Widget build(BuildContext context) => GestureDetector(
16 | onTap: () => _openServerList(context),
17 | child: _ContainerHolder(
18 | child: Consumer(
19 | builder: (context, model, child) => Row(
20 | mainAxisAlignment: MainAxisAlignment.center,
21 | crossAxisAlignment: CrossAxisAlignment.center,
22 | children: [
23 | SvgPicture.asset('assets/images/flags/${chosenServer.flagAssetName}', width: 20, height: 20),
24 | SizedBox(width: 15),
25 | Text(
26 | '${chosenServer.stateName}',
27 | style: Theme.of(context).textTheme.body1.copyWith(color: primaryTextColor),
28 | ),
29 | SizedBox(width: 10),
30 | child,
31 | ],
32 | ),
33 | child: SvgPicture.asset('assets/images/down_arrow.svg', width: 8, height: 8),
34 | ),
35 | ),
36 | );
37 | }
38 |
39 | _openServerList(context) {
40 | final List servers = ServerModel.servers;
41 |
42 | showModalBottomSheet(
43 | backgroundColor: Theme.of(context).backgroundColor,
44 | context: context,
45 | builder: (context) => Consumer(
46 | builder: (context, model, child) => Container(
47 | margin: EdgeInsets.only(top: 20),
48 | child: Column(
49 | children: [
50 | child,
51 | SizedBox(height: 20),
52 | Expanded(
53 | child: ListView.builder(
54 | itemCount: servers.length,
55 | itemBuilder: (context, index) => GestureDetector(
56 | onTap: () {
57 | model.changeServer(index);
58 | Navigator.of(context).pop();
59 | },
60 | child: CountryServerItem(
61 | server: servers[index],
62 | selected: model.selectedIndex == index,
63 | ),
64 | ),
65 | ),
66 | ),
67 | ],
68 | ),
69 | ),
70 | child: Center(child: Text('Pick your server', style: Theme.of(context).textTheme.overline)),
71 | ),
72 | );
73 | }
74 |
75 | class _ContainerHolder extends StatelessWidget {
76 |
77 | final Widget child;
78 | const _ContainerHolder({@required this.child});
79 |
80 | @override
81 | Widget build(BuildContext context) => Container(
82 | height: 70,
83 | decoration: BoxDecoration(
84 | color: Colors.white,
85 | boxShadow: [
86 | BoxShadow(
87 | color: Colors.grey[300],
88 | blurRadius: 5.0,
89 | ),
90 | ],
91 | ),
92 | child: child,
93 | );
94 | }
95 |
--------------------------------------------------------------------------------
/vpn_app/lib/ui/screens/home/widgets/stroke_circle_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:vpn_app/util/dimens.dart';
3 |
4 | class StrokedCircle extends StatelessWidget {
5 | final Color color;
6 | final double circleSize;
7 |
8 | StrokedCircle({@required this.color, this.circleSize = 100, Key key}) : super(key: key);
9 |
10 | @override
11 | Widget build(BuildContext context) => Container(
12 | width: circleSize,
13 | height: circleSize,
14 | decoration: BoxDecoration(
15 | shape: BoxShape.circle,
16 | color: color,
17 | ),
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/vpn_app/lib/ui/screens/welcome/welcome_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:provider/provider.dart';
3 | import 'package:vpn_app/io/models/welcome_model.dart';
4 | import 'package:vpn_app/ui/screens/welcome/widgets/circle_dot.dart';
5 | import 'package:vpn_app/ui/widgets/rounded_button_widget.dart';
6 | import 'package:vpn_app/util/router.dart';
7 |
8 | class WelcomeScreen extends StatelessWidget {
9 | @override
10 | Widget build(BuildContext context) => SafeArea(
11 | child: Scaffold(
12 | body: Container(
13 | child: Stack(
14 | children: [
15 | _OnboardingPageView(),
16 | _PageCircleBar(),
17 | _GetStartedButton(),
18 | ],
19 | ),
20 | ),
21 | ),
22 | );
23 | }
24 |
25 | class _OnboardingPageView extends StatelessWidget {
26 |
27 | const _OnboardingPageView();
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | final model = Provider.of(context, listen: false);
32 |
33 | return PageView.builder(
34 | physics: ClampingScrollPhysics(),
35 | onPageChanged: (index) => _onPageChanged(index, model),
36 | itemCount: model.widgetLength,
37 | itemBuilder: (context, index) => model.widgets[index]);
38 | }
39 |
40 | _onPageChanged(index, WelcomeModel model) => model.changeCurrentIndex(index);
41 | }
42 |
43 | class _PageCircleBar extends StatelessWidget {
44 |
45 | const _PageCircleBar();
46 |
47 | @override
48 | Widget build(BuildContext context) => Consumer(
49 | builder: (context, model, child) => Padding(
50 | padding: const EdgeInsets.only(bottom: 110.0),
51 | child: Align(
52 | alignment: Alignment.bottomCenter,
53 | child: Container(
54 | color: Theme.of(context).backgroundColor,
55 | child: Row(
56 | mainAxisSize: MainAxisSize.min,
57 | mainAxisAlignment: MainAxisAlignment.center,
58 | children: [
59 | for (int i = 0; i < model.widgetLength; i++) ...[
60 | CircleDot(selected: i == model.currentIndex, key: UniqueKey())
61 | ]
62 | ],
63 | ),
64 | ),
65 | ),
66 | ),
67 | );
68 | }
69 |
70 | class _GetStartedButton extends StatelessWidget {
71 |
72 | const _GetStartedButton();
73 |
74 | @override
75 | Widget build(BuildContext context) {
76 | final WelcomeModel model = Provider.of(context);
77 | final double opacity = model.lastPage ? 1 : 0;
78 |
79 | return AnimatedOpacity(
80 | opacity: opacity,
81 | duration: Duration(milliseconds: 200),
82 | curve: Curves.easeIn,
83 | child: Align(
84 | alignment: Alignment.bottomCenter,
85 | child: Padding(
86 | padding: EdgeInsets.only(bottom: 30),
87 | child: RoundedButton(
88 | title: 'GET STARTED',
89 | onTap: () => Navigator.of(context).pushNamed(Router.HOME_PAGE),
90 | ),
91 | ),
92 | ),
93 | );
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/vpn_app/lib/ui/screens/welcome/widgets/circle_dot.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:vpn_app/util/colors.dart';
3 |
4 | class CircleDot extends StatelessWidget {
5 | final bool selected;
6 |
7 | CircleDot({@required this.selected, Key key}) : super(key: key);
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | final double size = selected ? 10 : 8;
12 | final Color color = selected ? unselectedGrey : selectedGrey;
13 |
14 | return AnimatedContainer(
15 | margin: EdgeInsets.symmetric(horizontal: 5),
16 | width: size,
17 | height: size,
18 | duration: Duration(milliseconds: 200),
19 | decoration: BoxDecoration(
20 | color: color,
21 | shape: BoxShape.circle,
22 | ),
23 | );
24 | }
25 | }
--------------------------------------------------------------------------------
/vpn_app/lib/ui/screens/welcome/widgets/intro_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class IntroWidget extends StatelessWidget {
4 |
5 | final String title;
6 | final String description;
7 | final String imageRes;
8 |
9 | IntroWidget({@required this.title, @required this.description, this.imageRes, Key key}) : super(key: key);
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return Container(
14 | color: Theme.of(context).backgroundColor,
15 | child: Column(
16 | crossAxisAlignment: CrossAxisAlignment.center,
17 | children: [
18 | SizedBox(height: 50),
19 | Image.asset(imageRes, scale: 1.2),
20 | SizedBox(height: 20),
21 | Text(title, style: Theme.of(context).textTheme.headline),
22 | Padding(
23 | padding: EdgeInsets.fromLTRB(30, 10, 30, 0),
24 | child: Text(description, style: Theme.of(context).textTheme.overline, textAlign: TextAlign.center))
25 | ],
26 | ));
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/vpn_app/lib/ui/widgets/rounded_button_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:vpn_app/util/colors.dart';
3 | import 'package:vpn_app/util/dimens.dart';
4 |
5 | class RoundedButton extends StatelessWidget {
6 |
7 | final String title;
8 | final bool filled;
9 | final Function onTap;
10 |
11 | const RoundedButton({@required this.title, this.filled = true, this.onTap});
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | final Color backgroundColor = filled ? primaryColor : Colors.white;
16 | final Color borderSideColor = filled ? primaryColor : disconnectedButtonColor;
17 |
18 | return MaterialButton(
19 | height: primaryButtonHeight,
20 | padding: EdgeInsets.only(left: 40, right: 40),
21 | color: backgroundColor,
22 | onPressed: onTap,
23 | elevation: 2,
24 | child: Text(
25 | title,
26 | style: filled
27 | ? Theme.of(context).textTheme.button
28 | : Theme.of(context).textTheme.button.copyWith(color: disconnectedTextColor),
29 | ),
30 | shape: RoundedRectangleBorder(
31 | side: BorderSide(color: borderSideColor),
32 | borderRadius: BorderRadius.circular(40),
33 | ),
34 | );
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/vpn_app/lib/util/colors.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// General
4 | const Color backgroundColor = Colors.white;
5 | const Color primaryColor = Color(0xFF0094fc);
6 |
7 | const Color primaryTextColor = Color(0xFF011f3f);
8 | const Color secondaryTextColor = Color(0xFF8b959a);
9 |
10 | const Color selectedGrey = Color(0x48919ba0);
11 | const Color unselectedGrey = Color(0xFF919ba0);
12 |
13 | /// widgets
14 | final Color strokeCheckBoxColor = Colors.grey[300];
15 |
16 | // connection state button
17 | const Color connectedStateColor = Color(0xFF5ed40a);
18 | const Color disconnectedStateColor = Color(0xFFcecece);
19 |
20 | // connection button
21 | const Color disconnectedButtonColor = Color(0xFF5B5B5B);
22 | const Color disconnectedTextColor = Color(0xFF011F3F);
23 |
24 | // circle widget
25 | const outerDisconnectedColor = Color(0xFF53585C);
26 | const innerConnectedColor = Color(0xFF0260B1);
27 | const innerDisconnectedColor = Color(0xFF777B7F);
28 |
29 | const List connectedGradientColors = [
30 | Color(0xFF2861ff),
31 | Color(0xFF25b5ff),
32 | ];
33 |
34 | const List disconnectedGradientColors = [
35 | Color(0xFFc2cded),
36 | Color(0xFFa2a3a4),
37 | ];
38 |
39 |
--------------------------------------------------------------------------------
/vpn_app/lib/util/dimens.dart:
--------------------------------------------------------------------------------
1 |
2 | // widgets sizes
3 | const double connectionCircleSize = 200;
4 | const double outerCircleSize = 180;
5 | const double innerCircleSize = 160;
6 |
7 | const double connectionStateHeight = 45;
8 | const double connectionStateWidth = 160;
9 | const double checkBoxHeight = 22;
10 | const double itemStateFlagHeight = 50;
11 |
12 | // buttons
13 | const double primaryButtonHeight = 50;
14 |
15 | // separator (others)
16 | const double separatorHeight = 30;
17 | const double strokeWidth = 10;
18 |
19 |
--------------------------------------------------------------------------------
/vpn_app/lib/util/router.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:vpn_app/ui/screens/home/home_page_screen.dart';
3 | import 'package:vpn_app/ui/screens/welcome/welcome_screen.dart';
4 |
5 | class Router {
6 |
7 | static const HOME_PAGE = "/home";
8 | static const DEFAULT = "/";
9 |
10 | static Route generateRoute(RouteSettings settings) {
11 | switch (settings.name) {
12 | case DEFAULT:
13 | return MaterialPageRoute(builder: (_) => WelcomeScreen());
14 | case HOME_PAGE:
15 | return MaterialPageRoute(builder: (_) => HomeScreen());
16 | default:
17 | return MaterialPageRoute(
18 | builder: (_) => Scaffold(body: Center(child: Text('No route defined for ${settings.name}'))));
19 | }
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/vpn_app/lib/util/status_bar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 |
4 | void setStatusBarColor() {
5 | SystemChrome.setSystemUIOverlayStyle(
6 | SystemUiOverlayStyle(
7 | statusBarIconBrightness: Brightness.dark,
8 | systemNavigationBarColor: Colors.white,
9 | statusBarColor: Colors.white,
10 | ),
11 | );
12 | }
13 |
14 | Future setPreferredOrientations() async {
15 | await SystemChrome.setPreferredOrientations(
16 | [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown],
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/vpn_app/lib/util/string.dart:
--------------------------------------------------------------------------------
1 | String capitalize(String s) => s[0].toUpperCase() + s.substring(1);
2 |
--------------------------------------------------------------------------------
/vpn_app/lib/util/theme.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:vpn_app/util/colors.dart';
3 |
4 | var appTheme = ThemeData(
5 | brightness: Brightness.light,
6 | backgroundColor: backgroundColor,
7 | primaryColor: primaryColor,
8 | fontFamily: 'SF-Pro-Display-Medium',
9 | buttonTheme: ButtonThemeData(
10 | buttonColor: primaryColor
11 | ),
12 | textTheme: TextTheme(
13 | title: TextStyle(color: primaryTextColor, fontSize: 20.0), // App bar
14 | headline: TextStyle(color: primaryTextColor, fontSize: 20.0, fontFamily: 'SF-Pro-Display', fontWeight: FontWeight.w800), // Onboarding title
15 | body1: TextStyle(color: primaryTextColor, fontSize: 18.0, fontFamily: 'SF-Pro-Display-Regular'), // regular text
16 | overline: TextStyle(color: secondaryTextColor, fontSize: 14.0, letterSpacing: 0), // description text
17 | button: TextStyle(color: Colors.white, fontSize: 14.0, fontWeight: FontWeight.bold, fontFamily: 'SF-Pro-Display-Bold',letterSpacing: 1),
18 | ),
19 | );
20 |
--------------------------------------------------------------------------------
/vpn_app/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: vpn_app
2 | description: Flutter UI challenge
3 |
4 | version: 1.0.0+1
5 |
6 | environment:
7 | sdk: ">=2.2.2 <3.0.0"
8 |
9 | dependencies:
10 | flutter:
11 | sdk: flutter
12 | cupertino_icons: ^0.1.2
13 | provider: ^3.1.0
14 | flutter_svg: ^0.14.0
15 |
16 | dev_dependencies:
17 | test:
18 | flutter_test:
19 | sdk: flutter
20 |
21 | flutter:
22 | uses-material-design: true
23 |
24 |
25 | assets:
26 | - assets/images/
27 | - assets/images/flags/
28 |
29 | fonts:
30 | - family: SF-Pro-Display
31 | fonts:
32 | - asset: assets/fonts/SF-Pro-Display-Bold.otf
33 | - asset: assets/fonts/SF-Pro-Display-Medium.otf
34 | - asset: assets/fonts/SF-Pro-Display-Regular.otf
35 | - asset: assets/fonts/SF-Pro-Display-Semibold.otf
36 |
37 |
--------------------------------------------------------------------------------
/vpn_app/screenshots/screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stepanzalis/ui_challenge_flutter/08c1574abf715f45ff9ff888732ae4617a762a18/vpn_app/screenshots/screenshot1.png
--------------------------------------------------------------------------------
/vpn_app/test/connection_model_tests.dart:
--------------------------------------------------------------------------------
1 | import 'package:test/test.dart';
2 | import 'package:vpn_app/io/models/connection_model.dart';
3 |
4 | void main() {
5 | group('Connection tests', () {
6 |
7 | test('connection state should ba false when init', () {
8 | final ConnectionModel model = ConnectionModel();
9 | expect(model.isConnected, false);
10 | });
11 |
12 | test('connection state must be changed when method to change is call', () {
13 | final ConnectionModel model = ConnectionModel();
14 | model.changeConnectionState();
15 | expect(model.isConnected, true);
16 | });
17 |
18 | test('connection state must be changed when method to change is call', () {
19 | final ConnectionModel model = ConnectionModel();
20 | model.changeConnectionState();
21 | expect(model.isConnected, true);
22 | });
23 | });
24 | }
--------------------------------------------------------------------------------
/vpn_app/test/server_model_tests.dart:
--------------------------------------------------------------------------------
1 | import 'package:test/test.dart';
2 | import 'package:vpn_app/io/models/server_model.dart';
3 |
4 | void main() {
5 | group('Server tests', () {
6 |
7 | test('server with index 1 should be selected at init', () {
8 | final ServerModel model = ServerModel();
9 | expect(model.selectedIndex, 1);
10 | });
11 |
12 | test('index of selected server should be changed when method is call', () {
13 | final ServerModel model = ServerModel();
14 | final int valueToTest = 10;
15 |
16 | model.changeServer(valueToTest);
17 | expect(model.selectedIndex, 1);
18 | });
19 | });
20 | }
--------------------------------------------------------------------------------
/vpn_app/test/string_utils_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:test/test.dart';
2 | import 'package:vpn_app/util/string.dart';
3 |
4 | void main() {
5 | test('capitalize function should return string with first letter uppercased', () {
6 |
7 | final String normalText = "test";
8 | final String upperCasedText = capitalize(normalText);
9 |
10 | expect(upperCasedText, "Test");
11 | });
12 | }
--------------------------------------------------------------------------------
/vpn_app/test/welcome_model_tests.dart:
--------------------------------------------------------------------------------
1 | import 'package:test/test.dart';
2 | import 'package:vpn_app/io/models/welcome_model.dart';
3 |
4 | void main() {
5 | group('Welcome tests', () {
6 |
7 | test('current index should be 0 at start', () {
8 | final WelcomeModel model = WelcomeModel();
9 | expect(model.currentIndex, 0);
10 | });
11 |
12 | test('vvalid value should be changed', () {
13 | final WelcomeModel model = WelcomeModel();
14 | final int valueToTest = 2;
15 |
16 | model.changeCurrentIndex(valueToTest);
17 | expect(model.currentIndex, valueToTest);
18 | });
19 |
20 | test('intro widgets length should be the same as length of the widget array', () {
21 | final WelcomeModel model = WelcomeModel();
22 |
23 | final int expectedLength = model.widgets.length;
24 | expect(model.widgetLength, expectedLength);
25 | });
26 |
27 | test('Last page should reflect array size minus one', () {
28 | final WelcomeModel model = WelcomeModel();
29 |
30 | final int lastPageIndex = model.widgetLength - 1;
31 | model.changeCurrentIndex(lastPageIndex);
32 | expect(model.currentIndex, lastPageIndex);
33 | });
34 |
35 | test('Change index to non existing value does not do anything', () {
36 | final WelcomeModel model = WelcomeModel();
37 |
38 | final int highRandomValue = model.widgetLength + 1000;
39 | model.changeCurrentIndex(highRandomValue);
40 | expect(model.currentIndex, 0);
41 | });
42 |
43 | test('Change index to non to negative value does not do anything', () {
44 | final WelcomeModel model = WelcomeModel();
45 |
46 | final int negativeValue = -1;
47 | model.changeCurrentIndex(negativeValue);
48 | expect(model.currentIndex, 0);
49 | });
50 | });
51 | }
52 |
--------------------------------------------------------------------------------
/vpn_app/test/widget_tests.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_test/flutter_test.dart';
2 |
3 | import 'package:vpn_app/main.dart';
4 |
5 | void main() {
6 | testWidgets('smoke test', (WidgetTester tester) async {
7 | await tester.pumpWidget(VpnApp());
8 | });
9 | }
10 |
--------------------------------------------------------------------------------