├── .gitignore
├── LICENSE
├── README.md
├── dots_clock
├── .metadata
├── .vscode
│ └── settings.json
├── LICENSE
├── README.md
├── android
│ ├── .gitignore
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── dots_clock
│ │ │ │ │ └── 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
│ └── settings.gradle
├── assets
│ └── fonts
│ │ ├── OFL.txt
│ │ └── Poppins-Bold.ttf
├── ios
│ ├── .gitignore
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.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
│ │ ├── Info.plist
│ │ └── Runner-Bridging-Header.h
├── lib
│ ├── main.dart
│ ├── models
│ │ └── dots_clock_style.dart
│ └── widgets
│ │ ├── dots_clock.dart
│ │ └── dots_painter.dart
├── pubspec.lock
└── pubspec.yaml
├── flutter_clock_helper
├── .metadata
├── CHANGELOG.md
├── README.md
├── customizer.png
├── lib
│ ├── customizer.dart
│ └── model.dart
└── pubspec.yaml
└── images
├── blobs.jpg
├── cellular_noise.jpg
├── cubic_noise.jpg
├── dark.jpg
├── dots_clock_standard.gif
├── gooey.jpg
├── simplex_noise.jpg
├── standard.jpg
├── value_noise.jpg
└── white_noise.jpg
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/# Miscellaneous
24 | *.class
25 | *.log
26 | *.pyc
27 | *.swp
28 | .DS_Store
29 | .atom/
30 | .buildlog/
31 | .history
32 | .svn/
33 |
34 | # IntelliJ related
35 | *.iml
36 | *.ipr
37 | *.iws
38 | .idea/
39 |
40 | # The .vscode folder contains launch configuration and tasks you configure in
41 | # VS Code which you may wish to be included in version control, so this line
42 | # is commented out by default.
43 | #.vscode/
44 |
45 | # Flutter/Dart/Pub related
46 | **/doc/api/
47 | .dart_tool/
48 | .flutter-plugins
49 | .packages
50 | .pub-cache/
51 | .pub/
52 | /build/
53 |
54 | # Web related
55 | lib/generated_plugin_registrant.dart
56 |
57 | # Other items since we are using a global .gitignore.
58 | **/.dart_tool
59 | **/.pubspec.lock
60 | **/.flutter-plugins
61 | **/.packages
62 | **/.pub-cache/
63 | **/.pub/
64 | **/build/
65 |
66 | # Remove pubspec.lock for libraries
67 | flutter_clock_helper/pubspec.lock
68 |
69 | # Other items grabbed from flutter/flutter repo
70 | flutter_*.png
71 | linked_*.ds
72 | unlinked.ds
73 | unlinked_spec.ds
74 |
75 | # Android related
76 | **/android/**/gradle-wrapper.jar
77 | **/android/.gradle
78 | **/android/captures/
79 | **/android/gradlew
80 | **/android/gradlew.bat
81 | **/android/local.properties
82 | **/android/**/GeneratedPluginRegistrant.java
83 | **/android/key.properties
84 | *.jks
85 |
86 | # iOS/XCode related
87 | **/ios/**/*.mode1v3
88 | **/ios/**/*.mode2v3
89 | **/ios/**/*.moved-aside
90 | **/ios/**/*.pbxuser
91 | **/ios/**/*.perspectivev3
92 | **/ios/**/*sync/
93 | **/ios/**/.sconsign.dblite
94 | **/ios/**/.tags*
95 | **/ios/**/.vagrant/
96 | **/ios/**/DerivedData/
97 | **/ios/**/Icon?
98 | **/ios/**/Pods/
99 | **/ios/**/.symlinks/
100 | **/ios/**/profile
101 | **/ios/**/xcuserdata
102 | **/ios/.generated/
103 | **/ios/Flutter/App.framework
104 | **/ios/Flutter/Flutter.framework
105 | **/ios/Flutter/Flutter.podspec
106 | **/ios/Flutter/Generated.xcconfig
107 | **/ios/Flutter/app.flx
108 | **/ios/Flutter/app.zip
109 | **/ios/Flutter/flutter_assets/
110 | **/ios/Flutter/flutter_export_environment.sh
111 | **/ios/ServiceDefinitions.json
112 | **/ios/Runner/GeneratedPluginRegistrant.*
113 |
114 | # Exceptions to above rules.
115 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
116 | Pub related
117 | **/doc/api/
118 | .dart_tool/
119 | .flutter-plugins
120 | .flutter-plugins-dependencies
121 | .packages
122 | .pub-cache/
123 | .pub/
124 | /build/
125 |
126 | # Web related
127 | lib/generated_plugin_registrant.dart
128 |
129 | # Exceptions to above rules.
130 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
131 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2019 The Chromium Authors. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without modification,
4 | are permitted provided that the following conditions are met:
5 |
6 | * Redistributions of source code must retain the above copyright
7 | notice, this list of conditions and the following disclaimer.
8 | * Redistributions in binary form must reproduce the above
9 | copyright notice, this list of conditions and the following
10 | disclaimer in the documentation and/or other materials provided
11 | with the distribution.
12 | * Neither the name of Google Inc. nor the names of its
13 | contributors may be used to endorse or promote products derived
14 | from this software without specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Dots Clock
4 |
5 | Dots Clock is a digital clock written in Flutter, Dart. It was developed for the [Flutter Clock challenge](https://flutter.dev/clock).
6 |
7 | # Table of Contents
8 | - [Clock Variations](#clock-variations)
9 | - [Design Philosophy](#design-philosophy)
10 | * [Goals](#goals)
11 | * [Implementation](#implementation)
12 | - [Final Thoughts](#final-thoughts)
13 |
14 |
15 | # Clock Variations
16 |
17 | | Variation | Screenshot | Motion Design |
18 | |--------------|------------------------------|---------------------------------------|
19 | |Standard | |[Youtube](https://youtu.be/Tpy14bsTklk)|
20 | |Blobs | |[Youtube](https://youtu.be/lfHU84U6yCs)|
21 | |Gooey | |[Youtube](https://youtu.be/QuXPebSS1Ko)|
22 | |Cellular Noise||[Youtube](https://youtu.be/BO_C2CW6tDc)|
23 | |Cubic Noise | |[Youtube](https://youtu.be/V2TbrsmReXg)|
24 | |Simplex Noise | |[Youtube](https://youtu.be/nMR9yyPnXDM)|
25 | |Value Noise | |[Youtube](https://youtu.be/NWtwxKwSCDw)|
26 | |White Noise | |[Youtube](https://youtu.be/Cx_ia3M_JdU)|
27 |
28 |
29 | # Design Philosophy
30 |
31 | ## Goals
32 |
33 | The clock is meant to simulate a **living, breathing entity** that, while displaying time information, is also an **interesting and soothing experience** to look at. It should interest the viewer and spark just enough intrigue to still disappear into the background of your living space. I would describe this attribute of the clock its "lava lampdness".
34 |
35 | ## Implementation
36 |
37 | With a grid of dots which vary in sizes through a noise function of choice, we make each dot appear as their own organism that pursues individual tasks. Each dot pulses with a sine wave function to simulate a **calming breathing pattern**. For the clock's standard variation we choose Perlin noise to size dots that are closer to each other similarly. So while they appear acting independantly, they also seem to work towards a common goal. A **collection of entities that together form a much larger functional one** makes for a compelling viewing experience where the viewer can observe each dot independantly to make out a pattern or take a step back to have a look at the bigger picture.
38 |
39 | While it needs to be interesting to look at when in focus, it also needs to disappear into the background when not needed to not intrude upon one's living space. For this purpose, the clock's **colors and shapes remain understated**, using only monocolor tones (which are slightly off-color) and circles to convey the experience. After all, the clock's static **image is only secondary and the motion design shall be the primary attraction**.
40 |
41 | For the font that displays the time, Poppins is a natural choice with its **bold and easy to recognize silhouette**. Since the dot grid reduces the resolution and detail level of the font, it couldn't have been one with complex or thin shapes otherwise it would be drowned out by the dots' animations. The fonts is masked onto the grid and scales up the dots that are contained in it. The transitions between different clock face states is smoothed out with the dots slowly scaling up or down to their new state to make it like look a whole **group of dots is consciously shifting their focus to display the next numbers** on the clock.
42 |
43 | # Final Thoughts
44 |
45 | Dots Clock is an exercise in **emergent motion design**. It was unknown to me how the final clock would look likte until it was actually built since the clock is modeled after realistic patterns and physics rules. The Perlin noise I employed is the same function that visual artists use to generate organic effects such as clouds, fire or landscape terrain. This connection to real-life helps it stand out as a force of nature rather than just a clock.
46 |
47 |
--------------------------------------------------------------------------------
/dots_clock/.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: 27321ebbad34b0a3fafe99fac037102196d655ff
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/dots_clock/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "editor.formatOnPaste": true
4 | }
--------------------------------------------------------------------------------
/dots_clock/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | MIT License
3 |
4 | Copyright (c) 2020 Tran Duy Khanh Steffen
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/dots_clock/README.md:
--------------------------------------------------------------------------------
1 | Refer to the top-level README for further information.
2 |
--------------------------------------------------------------------------------
/dots_clock/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
--------------------------------------------------------------------------------
/dots_clock/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 28
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 "com.example.dots_clock"
42 | minSdkVersion 16
43 | targetSdkVersion 28
44 | versionCode flutterVersionCode.toInteger()
45 | versionName flutterVersionName
46 | testInstrumentationRunner "androidx.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-jdk7:$kotlin_version"
64 | testImplementation 'junit:junit:4.12'
65 | androidTestImplementation 'androidx.test:runner:1.1.1'
66 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
67 | }
68 |
--------------------------------------------------------------------------------
/dots_clock/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/dots_clock/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
12 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/dots_clock/android/app/src/main/kotlin/com/example/dots_clock/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.dots_clock
2 |
3 | import androidx.annotation.NonNull;
4 | import io.flutter.embedding.android.FlutterActivity
5 | import io.flutter.embedding.engine.FlutterEngine
6 | import io.flutter.plugins.GeneratedPluginRegistrant
7 |
8 | class MainActivity: FlutterActivity() {
9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
10 | GeneratedPluginRegistrant.registerWith(flutterEngine);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/dots_clock/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/dots_clock/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dots_clock/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dots_clock/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dots_clock/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dots_clock/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/dots_clock/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/dots_clock/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/dots_clock/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/dots_clock/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 |
--------------------------------------------------------------------------------
/dots_clock/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-5.6.2-all.zip
7 |
--------------------------------------------------------------------------------
/dots_clock/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 |
--------------------------------------------------------------------------------
/dots_clock/assets/fonts/OFL.txt:
--------------------------------------------------------------------------------
1 | Copyright 2014-2017 Indian Type Foundry (info@indiantypefoundry.com)
2 |
3 | This Font Software is licensed under the SIL Open Font License, Version 1.1.
4 | This license is copied below, and is also available with a FAQ at:
5 | http://scripts.sil.org/OFL
6 |
7 |
8 | -----------------------------------------------------------
9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10 | -----------------------------------------------------------
11 |
12 | PREAMBLE
13 | The goals of the Open Font License (OFL) are to stimulate worldwide
14 | development of collaborative font projects, to support the font creation
15 | efforts of academic and linguistic communities, and to provide a free and
16 | open framework in which fonts may be shared and improved in partnership
17 | with others.
18 |
19 | The OFL allows the licensed fonts to be used, studied, modified and
20 | redistributed freely as long as they are not sold by themselves. The
21 | fonts, including any derivative works, can be bundled, embedded,
22 | redistributed and/or sold with any software provided that any reserved
23 | names are not used by derivative works. The fonts and derivatives,
24 | however, cannot be released under any other type of license. The
25 | requirement for fonts to remain under this license does not apply
26 | to any document created using the fonts or their derivatives.
27 |
28 | DEFINITIONS
29 | "Font Software" refers to the set of files released by the Copyright
30 | Holder(s) under this license and clearly marked as such. This may
31 | include source files, build scripts and documentation.
32 |
33 | "Reserved Font Name" refers to any names specified as such after the
34 | copyright statement(s).
35 |
36 | "Original Version" refers to the collection of Font Software components as
37 | distributed by the Copyright Holder(s).
38 |
39 | "Modified Version" refers to any derivative made by adding to, deleting,
40 | or substituting -- in part or in whole -- any of the components of the
41 | Original Version, by changing formats or by porting the Font Software to a
42 | new environment.
43 |
44 | "Author" refers to any designer, engineer, programmer, technical
45 | writer or other person who contributed to the Font Software.
46 |
47 | PERMISSION & CONDITIONS
48 | Permission is hereby granted, free of charge, to any person obtaining
49 | a copy of the Font Software, to use, study, copy, merge, embed, modify,
50 | redistribute, and sell modified and unmodified copies of the Font
51 | Software, subject to the following conditions:
52 |
53 | 1) Neither the Font Software nor any of its individual components,
54 | in Original or Modified Versions, may be sold by itself.
55 |
56 | 2) Original or Modified Versions of the Font Software may be bundled,
57 | redistributed and/or sold with any software, provided that each copy
58 | contains the above copyright notice and this license. These can be
59 | included either as stand-alone text files, human-readable headers or
60 | in the appropriate machine-readable metadata fields within text or
61 | binary files as long as those fields can be easily viewed by the user.
62 |
63 | 3) No Modified Version of the Font Software may use the Reserved Font
64 | Name(s) unless explicit written permission is granted by the corresponding
65 | Copyright Holder. This restriction only applies to the primary font name as
66 | presented to the users.
67 |
68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69 | Software shall not be used to promote, endorse or advertise any
70 | Modified Version, except to acknowledge the contribution(s) of the
71 | Copyright Holder(s) and the Author(s) or with their explicit written
72 | permission.
73 |
74 | 5) The Font Software, modified or unmodified, in part or in whole,
75 | must be distributed entirely under this license, and must not be
76 | distributed under any other license. The requirement for fonts to
77 | remain under this license does not apply to any document created
78 | using the Font Software.
79 |
80 | TERMINATION
81 | This license becomes null and void if any of the above conditions are
82 | not met.
83 |
84 | DISCLAIMER
85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93 | OTHER DEALINGS IN THE FONT SOFTWARE.
94 |
--------------------------------------------------------------------------------
/dots_clock/assets/fonts/Poppins-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/assets/fonts/Poppins-Bold.ttf
--------------------------------------------------------------------------------
/dots_clock/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/dots_clock/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 |
--------------------------------------------------------------------------------
/dots_clock/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/dots_clock/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/dots_clock/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
14 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
17 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
18 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
19 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
20 | /* End PBXBuildFile section */
21 |
22 | /* Begin PBXCopyFilesBuildPhase section */
23 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
24 | isa = PBXCopyFilesBuildPhase;
25 | buildActionMask = 2147483647;
26 | dstPath = "";
27 | dstSubfolderSpec = 10;
28 | files = (
29 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
30 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
31 | );
32 | name = "Embed Frameworks";
33 | runOnlyForDeploymentPostprocessing = 0;
34 | };
35 | /* End PBXCopyFilesBuildPhase section */
36 |
37 | /* Begin PBXFileReference section */
38 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
39 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
40 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
41 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; };
42 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
43 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
44 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
45 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
46 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
47 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; };
48 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
49 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
50 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
51 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
52 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
53 | /* End PBXFileReference section */
54 |
55 | /* Begin PBXFrameworksBuildPhase section */
56 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
57 | isa = PBXFrameworksBuildPhase;
58 | buildActionMask = 2147483647;
59 | files = (
60 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
61 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
62 | );
63 | runOnlyForDeploymentPostprocessing = 0;
64 | };
65 | /* End PBXFrameworksBuildPhase section */
66 |
67 | /* Begin PBXGroup section */
68 | 9740EEB11CF90186004384FC /* Flutter */ = {
69 | isa = PBXGroup;
70 | children = (
71 | 3B80C3931E831B6300D905FE /* App.framework */,
72 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
73 | 9740EEBA1CF902C7004384FC /* Flutter.framework */,
74 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
75 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
76 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
77 | );
78 | name = Flutter;
79 | sourceTree = "";
80 | };
81 | 97C146E51CF9000F007C117D = {
82 | isa = PBXGroup;
83 | children = (
84 | 9740EEB11CF90186004384FC /* Flutter */,
85 | 97C146F01CF9000F007C117D /* Runner */,
86 | 97C146EF1CF9000F007C117D /* Products */,
87 | );
88 | sourceTree = "";
89 | };
90 | 97C146EF1CF9000F007C117D /* Products */ = {
91 | isa = PBXGroup;
92 | children = (
93 | 97C146EE1CF9000F007C117D /* Runner.app */,
94 | );
95 | name = Products;
96 | sourceTree = "";
97 | };
98 | 97C146F01CF9000F007C117D /* Runner */ = {
99 | isa = PBXGroup;
100 | children = (
101 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
102 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
103 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
104 | 97C147021CF9000F007C117D /* Info.plist */,
105 | 97C146F11CF9000F007C117D /* Supporting Files */,
106 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
107 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
108 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
109 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
110 | );
111 | path = Runner;
112 | sourceTree = "";
113 | };
114 | 97C146F11CF9000F007C117D /* Supporting Files */ = {
115 | isa = PBXGroup;
116 | children = (
117 | );
118 | name = "Supporting Files";
119 | sourceTree = "";
120 | };
121 | /* End PBXGroup section */
122 |
123 | /* Begin PBXNativeTarget section */
124 | 97C146ED1CF9000F007C117D /* Runner */ = {
125 | isa = PBXNativeTarget;
126 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
127 | buildPhases = (
128 | 9740EEB61CF901F6004384FC /* Run Script */,
129 | 97C146EA1CF9000F007C117D /* Sources */,
130 | 97C146EB1CF9000F007C117D /* Frameworks */,
131 | 97C146EC1CF9000F007C117D /* Resources */,
132 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
133 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
134 | );
135 | buildRules = (
136 | );
137 | dependencies = (
138 | );
139 | name = Runner;
140 | productName = Runner;
141 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
142 | productType = "com.apple.product-type.application";
143 | };
144 | /* End PBXNativeTarget section */
145 |
146 | /* Begin PBXProject section */
147 | 97C146E61CF9000F007C117D /* Project object */ = {
148 | isa = PBXProject;
149 | attributes = {
150 | LastUpgradeCheck = 1020;
151 | ORGANIZATIONNAME = "The Chromium Authors";
152 | TargetAttributes = {
153 | 97C146ED1CF9000F007C117D = {
154 | CreatedOnToolsVersion = 7.3.1;
155 | LastSwiftMigration = 1100;
156 | };
157 | };
158 | };
159 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
160 | compatibilityVersion = "Xcode 3.2";
161 | developmentRegion = en;
162 | hasScannedForEncodings = 0;
163 | knownRegions = (
164 | en,
165 | Base,
166 | );
167 | mainGroup = 97C146E51CF9000F007C117D;
168 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
169 | projectDirPath = "";
170 | projectRoot = "";
171 | targets = (
172 | 97C146ED1CF9000F007C117D /* Runner */,
173 | );
174 | };
175 | /* End PBXProject section */
176 |
177 | /* Begin PBXResourcesBuildPhase section */
178 | 97C146EC1CF9000F007C117D /* Resources */ = {
179 | isa = PBXResourcesBuildPhase;
180 | buildActionMask = 2147483647;
181 | files = (
182 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
183 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
184 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
185 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
186 | );
187 | runOnlyForDeploymentPostprocessing = 0;
188 | };
189 | /* End PBXResourcesBuildPhase section */
190 |
191 | /* Begin PBXShellScriptBuildPhase section */
192 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
193 | isa = PBXShellScriptBuildPhase;
194 | buildActionMask = 2147483647;
195 | files = (
196 | );
197 | inputPaths = (
198 | );
199 | name = "Thin Binary";
200 | outputPaths = (
201 | );
202 | runOnlyForDeploymentPostprocessing = 0;
203 | shellPath = /bin/sh;
204 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
205 | };
206 | 9740EEB61CF901F6004384FC /* Run Script */ = {
207 | isa = PBXShellScriptBuildPhase;
208 | buildActionMask = 2147483647;
209 | files = (
210 | );
211 | inputPaths = (
212 | );
213 | name = "Run Script";
214 | outputPaths = (
215 | );
216 | runOnlyForDeploymentPostprocessing = 0;
217 | shellPath = /bin/sh;
218 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
219 | };
220 | /* End PBXShellScriptBuildPhase section */
221 |
222 | /* Begin PBXSourcesBuildPhase section */
223 | 97C146EA1CF9000F007C117D /* Sources */ = {
224 | isa = PBXSourcesBuildPhase;
225 | buildActionMask = 2147483647;
226 | files = (
227 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
228 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
229 | );
230 | runOnlyForDeploymentPostprocessing = 0;
231 | };
232 | /* End PBXSourcesBuildPhase section */
233 |
234 | /* Begin PBXVariantGroup section */
235 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
236 | isa = PBXVariantGroup;
237 | children = (
238 | 97C146FB1CF9000F007C117D /* Base */,
239 | );
240 | name = Main.storyboard;
241 | sourceTree = "";
242 | };
243 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
244 | isa = PBXVariantGroup;
245 | children = (
246 | 97C147001CF9000F007C117D /* Base */,
247 | );
248 | name = LaunchScreen.storyboard;
249 | sourceTree = "";
250 | };
251 | /* End PBXVariantGroup section */
252 |
253 | /* Begin XCBuildConfiguration section */
254 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
255 | isa = XCBuildConfiguration;
256 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
257 | buildSettings = {
258 | ALWAYS_SEARCH_USER_PATHS = NO;
259 | CLANG_ANALYZER_NONNULL = YES;
260 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
261 | CLANG_CXX_LIBRARY = "libc++";
262 | CLANG_ENABLE_MODULES = YES;
263 | CLANG_ENABLE_OBJC_ARC = YES;
264 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
265 | CLANG_WARN_BOOL_CONVERSION = YES;
266 | CLANG_WARN_COMMA = YES;
267 | CLANG_WARN_CONSTANT_CONVERSION = YES;
268 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
269 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
270 | CLANG_WARN_EMPTY_BODY = YES;
271 | CLANG_WARN_ENUM_CONVERSION = YES;
272 | CLANG_WARN_INFINITE_RECURSION = YES;
273 | CLANG_WARN_INT_CONVERSION = YES;
274 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
275 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
276 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
277 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
278 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
279 | CLANG_WARN_STRICT_PROTOTYPES = YES;
280 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
281 | CLANG_WARN_UNREACHABLE_CODE = YES;
282 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
283 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
284 | COPY_PHASE_STRIP = NO;
285 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
286 | ENABLE_NS_ASSERTIONS = NO;
287 | ENABLE_STRICT_OBJC_MSGSEND = YES;
288 | GCC_C_LANGUAGE_STANDARD = gnu99;
289 | GCC_NO_COMMON_BLOCKS = YES;
290 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
291 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
292 | GCC_WARN_UNDECLARED_SELECTOR = YES;
293 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
294 | GCC_WARN_UNUSED_FUNCTION = YES;
295 | GCC_WARN_UNUSED_VARIABLE = YES;
296 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
297 | MTL_ENABLE_DEBUG_INFO = NO;
298 | SDKROOT = iphoneos;
299 | SUPPORTED_PLATFORMS = iphoneos;
300 | TARGETED_DEVICE_FAMILY = "1,2";
301 | VALIDATE_PRODUCT = YES;
302 | };
303 | name = Profile;
304 | };
305 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
306 | isa = XCBuildConfiguration;
307 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
308 | buildSettings = {
309 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
310 | CLANG_ENABLE_MODULES = YES;
311 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
312 | ENABLE_BITCODE = NO;
313 | FRAMEWORK_SEARCH_PATHS = (
314 | "$(inherited)",
315 | "$(PROJECT_DIR)/Flutter",
316 | );
317 | INFOPLIST_FILE = Runner/Info.plist;
318 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
319 | LIBRARY_SEARCH_PATHS = (
320 | "$(inherited)",
321 | "$(PROJECT_DIR)/Flutter",
322 | );
323 | PRODUCT_BUNDLE_IDENTIFIER = com.example.dotsClock;
324 | PRODUCT_NAME = "$(TARGET_NAME)";
325 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
326 | SWIFT_VERSION = 5.0;
327 | VERSIONING_SYSTEM = "apple-generic";
328 | };
329 | name = Profile;
330 | };
331 | 97C147031CF9000F007C117D /* Debug */ = {
332 | isa = XCBuildConfiguration;
333 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
334 | buildSettings = {
335 | ALWAYS_SEARCH_USER_PATHS = NO;
336 | CLANG_ANALYZER_NONNULL = YES;
337 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
338 | CLANG_CXX_LIBRARY = "libc++";
339 | CLANG_ENABLE_MODULES = YES;
340 | CLANG_ENABLE_OBJC_ARC = YES;
341 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
342 | CLANG_WARN_BOOL_CONVERSION = YES;
343 | CLANG_WARN_COMMA = YES;
344 | CLANG_WARN_CONSTANT_CONVERSION = YES;
345 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
346 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
347 | CLANG_WARN_EMPTY_BODY = YES;
348 | CLANG_WARN_ENUM_CONVERSION = YES;
349 | CLANG_WARN_INFINITE_RECURSION = YES;
350 | CLANG_WARN_INT_CONVERSION = YES;
351 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
352 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
353 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
354 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
355 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
356 | CLANG_WARN_STRICT_PROTOTYPES = YES;
357 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
358 | CLANG_WARN_UNREACHABLE_CODE = YES;
359 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
360 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
361 | COPY_PHASE_STRIP = NO;
362 | DEBUG_INFORMATION_FORMAT = dwarf;
363 | ENABLE_STRICT_OBJC_MSGSEND = YES;
364 | ENABLE_TESTABILITY = YES;
365 | GCC_C_LANGUAGE_STANDARD = gnu99;
366 | GCC_DYNAMIC_NO_PIC = NO;
367 | GCC_NO_COMMON_BLOCKS = YES;
368 | GCC_OPTIMIZATION_LEVEL = 0;
369 | GCC_PREPROCESSOR_DEFINITIONS = (
370 | "DEBUG=1",
371 | "$(inherited)",
372 | );
373 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
374 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
375 | GCC_WARN_UNDECLARED_SELECTOR = YES;
376 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
377 | GCC_WARN_UNUSED_FUNCTION = YES;
378 | GCC_WARN_UNUSED_VARIABLE = YES;
379 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
380 | MTL_ENABLE_DEBUG_INFO = YES;
381 | ONLY_ACTIVE_ARCH = YES;
382 | SDKROOT = iphoneos;
383 | TARGETED_DEVICE_FAMILY = "1,2";
384 | };
385 | name = Debug;
386 | };
387 | 97C147041CF9000F007C117D /* Release */ = {
388 | isa = XCBuildConfiguration;
389 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
390 | buildSettings = {
391 | ALWAYS_SEARCH_USER_PATHS = NO;
392 | CLANG_ANALYZER_NONNULL = YES;
393 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
394 | CLANG_CXX_LIBRARY = "libc++";
395 | CLANG_ENABLE_MODULES = YES;
396 | CLANG_ENABLE_OBJC_ARC = YES;
397 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
398 | CLANG_WARN_BOOL_CONVERSION = YES;
399 | CLANG_WARN_COMMA = YES;
400 | CLANG_WARN_CONSTANT_CONVERSION = YES;
401 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
402 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
403 | CLANG_WARN_EMPTY_BODY = YES;
404 | CLANG_WARN_ENUM_CONVERSION = YES;
405 | CLANG_WARN_INFINITE_RECURSION = YES;
406 | CLANG_WARN_INT_CONVERSION = YES;
407 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
408 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
409 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
410 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
411 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
412 | CLANG_WARN_STRICT_PROTOTYPES = YES;
413 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
414 | CLANG_WARN_UNREACHABLE_CODE = YES;
415 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
416 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
417 | COPY_PHASE_STRIP = NO;
418 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
419 | ENABLE_NS_ASSERTIONS = NO;
420 | ENABLE_STRICT_OBJC_MSGSEND = YES;
421 | GCC_C_LANGUAGE_STANDARD = gnu99;
422 | GCC_NO_COMMON_BLOCKS = YES;
423 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
424 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
425 | GCC_WARN_UNDECLARED_SELECTOR = YES;
426 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
427 | GCC_WARN_UNUSED_FUNCTION = YES;
428 | GCC_WARN_UNUSED_VARIABLE = YES;
429 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
430 | MTL_ENABLE_DEBUG_INFO = NO;
431 | SDKROOT = iphoneos;
432 | SUPPORTED_PLATFORMS = iphoneos;
433 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
434 | TARGETED_DEVICE_FAMILY = "1,2";
435 | VALIDATE_PRODUCT = YES;
436 | };
437 | name = Release;
438 | };
439 | 97C147061CF9000F007C117D /* Debug */ = {
440 | isa = XCBuildConfiguration;
441 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
442 | buildSettings = {
443 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
444 | CLANG_ENABLE_MODULES = YES;
445 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
446 | ENABLE_BITCODE = NO;
447 | FRAMEWORK_SEARCH_PATHS = (
448 | "$(inherited)",
449 | "$(PROJECT_DIR)/Flutter",
450 | );
451 | INFOPLIST_FILE = Runner/Info.plist;
452 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
453 | LIBRARY_SEARCH_PATHS = (
454 | "$(inherited)",
455 | "$(PROJECT_DIR)/Flutter",
456 | );
457 | PRODUCT_BUNDLE_IDENTIFIER = com.example.dotsClock;
458 | PRODUCT_NAME = "$(TARGET_NAME)";
459 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
460 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
461 | SWIFT_VERSION = 5.0;
462 | VERSIONING_SYSTEM = "apple-generic";
463 | };
464 | name = Debug;
465 | };
466 | 97C147071CF9000F007C117D /* Release */ = {
467 | isa = XCBuildConfiguration;
468 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
469 | buildSettings = {
470 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
471 | CLANG_ENABLE_MODULES = YES;
472 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
473 | ENABLE_BITCODE = NO;
474 | FRAMEWORK_SEARCH_PATHS = (
475 | "$(inherited)",
476 | "$(PROJECT_DIR)/Flutter",
477 | );
478 | INFOPLIST_FILE = Runner/Info.plist;
479 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
480 | LIBRARY_SEARCH_PATHS = (
481 | "$(inherited)",
482 | "$(PROJECT_DIR)/Flutter",
483 | );
484 | PRODUCT_BUNDLE_IDENTIFIER = com.example.dotsClock;
485 | PRODUCT_NAME = "$(TARGET_NAME)";
486 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
487 | SWIFT_VERSION = 5.0;
488 | VERSIONING_SYSTEM = "apple-generic";
489 | };
490 | name = Release;
491 | };
492 | /* End XCBuildConfiguration section */
493 |
494 | /* Begin XCConfigurationList section */
495 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
496 | isa = XCConfigurationList;
497 | buildConfigurations = (
498 | 97C147031CF9000F007C117D /* Debug */,
499 | 97C147041CF9000F007C117D /* Release */,
500 | 249021D3217E4FDB00AE95B9 /* Profile */,
501 | );
502 | defaultConfigurationIsVisible = 0;
503 | defaultConfigurationName = Release;
504 | };
505 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
506 | isa = XCConfigurationList;
507 | buildConfigurations = (
508 | 97C147061CF9000F007C117D /* Debug */,
509 | 97C147071CF9000F007C117D /* Release */,
510 | 249021D4217E4FDB00AE95B9 /* Profile */,
511 | );
512 | defaultConfigurationIsVisible = 0;
513 | defaultConfigurationName = Release;
514 | };
515 | /* End XCConfigurationList section */
516 | };
517 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
518 | }
519 |
--------------------------------------------------------------------------------
/dots_clock/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/dots_clock/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 |
--------------------------------------------------------------------------------
/dots_clock/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/dots_clock/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 |
--------------------------------------------------------------------------------
/dots_clock/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 |
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/dots_clock/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 |
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/dots_clock/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/dots_clock/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.
--------------------------------------------------------------------------------
/dots_clock/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 |
--------------------------------------------------------------------------------
/dots_clock/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 |
--------------------------------------------------------------------------------
/dots_clock/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 | dots_clock
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 |
--------------------------------------------------------------------------------
/dots_clock/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
--------------------------------------------------------------------------------
/dots_clock/lib/main.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | import 'dart:io';
6 |
7 | import 'package:dots_clock/models/dots_clock_style.dart';
8 | import 'package:dots_clock/widgets/dots_clock.dart';
9 | import 'package:flutter/foundation.dart';
10 | import 'package:flutter/material.dart';
11 | import 'package:flutter_clock_helper/customizer.dart';
12 | import 'package:flutter_clock_helper/model.dart';
13 |
14 | void main() {
15 | // A temporary measure until Platform supports web and TargetPlatform supports
16 | // macOS.
17 | if (!kIsWeb && Platform.isMacOS) {
18 | // TODO(gspencergoog): Update this when TargetPlatform includes macOS.
19 | // https://github.com/flutter/flutter/issues/31366
20 | // See https://github.com/flutter/flutter/wiki/Desktop-shells#target-platform-override.
21 | debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
22 | }
23 |
24 | // This creates a clock that enables you to customize it.
25 | //
26 | // The [ClockCustomizer] takes in a [ClockBuilder] that consists of:
27 | // - A clock widget (in this case, [DigitalClock])
28 | // - A model (provided to you by [ClockModel])
29 | // For more information, see the flutter_clock_helper package.
30 | //
31 | // Your job is to edit [DigitalClock], or replace it with your
32 | // own clock widget. (Look in digital_clock.dart for more details!)
33 | runApp(
34 | ClockCustomizer(
35 | (ClockModel model) => LayoutBuilder(
36 | builder: (context, constraints) => DotsClock(
37 | width: constraints.maxWidth,
38 | height: constraints.maxHeight,
39 | model: model,
40 | // For other clocks, replace DotsClockStyle with the
41 | // following ones or make your own clock and reload.
42 | //
43 | // DotsClockStyle.blobs(),
44 | // DotsClockStyle.cellularNoise(),
45 | // DotsClockStyle.cubicNoise(),
46 | // DotsClockStyle.gooey(),
47 | // DotsClockStyle.simplexNoise(),
48 | // DotsClockStyle.valueNoise(),
49 | // DotsClockStyle.whiteNoise()
50 | style: DotsClockStyle.standard().copyWith(
51 | // Use box constraint height dependant units for consistent sizing
52 | // on all displays since aspect ratio is always the same for the contest.
53 | dotSpacing: constraints.maxHeight * 0.017,
54 | dotBaseSize: 0.5,
55 | dotActiveScale: constraints.maxHeight * 0.013,
56 | brightBackgroundColor: Color(0xFFF4F4F4),
57 | darkBackgroundColor: Color(0xFF10151B),
58 | ),
59 | ),
60 | ),
61 | ),
62 | );
63 | }
64 |
--------------------------------------------------------------------------------
/dots_clock/lib/models/dots_clock_style.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Tran Duy Khanh Steffen. All rights reserved.
2 | // Use of this source code is governed by a MIT license that can be
3 | // found in the dots_clock/LICENSE file.
4 |
5 | import 'dart:math';
6 |
7 | import 'package:fast_noise/fast_noise.dart';
8 | import 'package:flutter/material.dart';
9 |
10 | class DotsClockStyle {
11 | /// Basic [DotsClockStyle] constructor.
12 | ///
13 | /// Some values need to have defaults or are required
14 | /// otherwise no clock can be displayed.
15 | const DotsClockStyle({
16 | @required this.dotSpacing,
17 | @required this.dotActiveScale,
18 | @required this.fontPath,
19 | @required this.charXPosCorrections,
20 | @required this.gridBuilder,
21 | this.dotBaseSize: 1.0,
22 | this.brightColor: Colors.black,
23 | this.darkColor: Colors.white,
24 | this.brightBackgroundColor: Colors.white,
25 | this.darkBackgroundColor: Colors.black,
26 | this.idleAnimationDuration: const Duration(milliseconds: 10000),
27 | this.transitionAnimationDuration: const Duration(milliseconds: 3500),
28 | this.fontSize: 0.4,
29 | this.fontSpacing: 1.0,
30 | this.middleSpacing: 0.0,
31 | this.xOffset: 0.0,
32 | this.yOffset: 0.0,
33 | this.shouldCenterVertically: true,
34 | this.shouldCenterHorizontally: false,
35 | }) : assert(dotSpacing != null),
36 | assert(dotActiveScale != null),
37 | assert(fontPath != null),
38 | assert(charXPosCorrections != null),
39 | assert(gridBuilder != null),
40 | assert(dotBaseSize != null),
41 | assert(brightColor != null),
42 | assert(darkColor != null),
43 | assert(brightBackgroundColor != null),
44 | assert(darkBackgroundColor != null),
45 | assert(charXPosCorrections != null),
46 | assert(idleAnimationDuration != null),
47 | assert(transitionAnimationDuration != null),
48 | assert(dotSpacing != null),
49 | assert(fontSize != null),
50 | assert(fontSpacing != null),
51 | assert(middleSpacing != null),
52 | assert(xOffset != null),
53 | assert(yOffset != null),
54 | assert(shouldCenterVertically != null),
55 | assert(shouldCenterHorizontally != null);
56 |
57 | /// Main color that constrasts with [brightBackgroundColor].
58 | ///
59 | /// Used for bright theme setting.
60 | final Color brightColor;
61 |
62 | /// Main color that constrasts with [darkBackgroundColor].
63 | ///
64 | /// Used for dark theme setting.
65 | final Color darkColor;
66 |
67 | /// Background color that constrasts with [brightColor].
68 | ///
69 | /// Used for bright theme setting.
70 | final Color brightBackgroundColor;
71 |
72 | /// Background color that constrasts with [darkColor].
73 | ///
74 | /// Used for dark theme setting.
75 | final Color darkBackgroundColor;
76 |
77 | // TODO: Refactor this to [Duration] type.
78 | /// Duration of 1 cycle of the dots' idle animations.
79 | final Duration idleAnimationDuration;
80 |
81 | /// Duration of 1 cycle of the dots' transition animations.
82 | final Duration transitionAnimationDuration;
83 |
84 | /// Space between each dot.
85 | ///
86 | /// The higher this value the more space there is between dots
87 | /// and less dots will be displayed.
88 | final double dotSpacing;
89 |
90 | /// Size of dots at the sine wave's peak value.
91 | final double dotBaseSize;
92 |
93 | /// Maximum scale multiplier of an active dot.
94 | final double dotActiveScale;
95 |
96 | /// Filepath for the font to be masked on the dots grid.
97 | final String fontPath;
98 |
99 | /// Size of the font as a percentage of the window height.
100 | final double fontSize;
101 |
102 | /// Size of the font spacing as a percentage of font's height.
103 | final double fontSpacing;
104 |
105 | /// Size of the middle spacing between hours/minutes as a percentage of the window's width.
106 | final double middleSpacing;
107 |
108 | /// X-position to offset the clock face [Path] with.
109 | ///
110 | /// Overwritten by [shouldCenterHorizontally] when true.
111 | final double xOffset;
112 |
113 | /// Y-position to offset the clock face [Path] with.
114 | ///
115 | /// Overwritten by [shouldCenterVertically] when true.
116 | final double yOffset;
117 |
118 | /// Centers the clock face [Path] vertically when true.
119 | final bool shouldCenterVertically;
120 |
121 | /// Centers the clock face [Path] horizontally when true.
122 | final bool shouldCenterHorizontally;
123 |
124 | /// Correctional values for the x-position of certain characters.
125 | ///
126 | /// Fonts may not be monospaced after converting them to [Path].
127 | /// Offsets the defined characters by a percentage of the font's
128 | /// height along the x-axis.
129 | final Map charXPosCorrections;
130 |
131 | /// Callback function to build initial 2D array of dot initial sizes.
132 | final Function(int rows, int columns) gridBuilder;
133 |
134 | /// Overrides existing [DotsClockStyle] with defined values.
135 | DotsClockStyle copyWith({
136 | Color brightColor,
137 | Color darkColor,
138 | Color brightBackgroundColor,
139 | Color darkBackgroundColor,
140 | Duration idleAnimationDuration,
141 | Duration transitionAnimationDuration,
142 | double dotSpacing,
143 | double dotBaseSize,
144 | double dotActiveScale,
145 | String fontPath,
146 | double fontSize,
147 | double fontSpacing,
148 | double middleSpacing,
149 | double xOffset,
150 | double yOffset,
151 | bool shouldCenterVertically,
152 | bool shouldCenterHorizontally,
153 | Map charXPosCorrections,
154 | Function(int rows, int columns) gridBuilder,
155 | }) {
156 | return DotsClockStyle(
157 | brightColor: brightColor ?? this.brightColor,
158 | darkColor: darkColor ?? this.darkColor,
159 | brightBackgroundColor:
160 | brightBackgroundColor ?? this.brightBackgroundColor,
161 | darkBackgroundColor: darkBackgroundColor ?? this.darkBackgroundColor,
162 | idleAnimationDuration:
163 | idleAnimationDuration ?? this.idleAnimationDuration,
164 | transitionAnimationDuration:
165 | transitionAnimationDuration ?? this.transitionAnimationDuration,
166 | dotSpacing: dotSpacing ?? this.dotSpacing,
167 | dotBaseSize: dotBaseSize ?? this.dotBaseSize,
168 | dotActiveScale: dotActiveScale ?? this.dotActiveScale,
169 | fontPath: fontPath ?? this.fontPath,
170 | gridBuilder: gridBuilder ?? this.gridBuilder,
171 | charXPosCorrections: charXPosCorrections ?? this.charXPosCorrections,
172 | fontSize: fontSize ?? this.fontSize,
173 | fontSpacing: fontSpacing ?? this.fontSpacing,
174 | middleSpacing: middleSpacing ?? this.middleSpacing,
175 | xOffset: xOffset ?? this.xOffset,
176 | yOffset: yOffset ?? this.yOffset,
177 | shouldCenterVertically:
178 | shouldCenterVertically ?? this.shouldCenterVertically,
179 | shouldCenterHorizontally:
180 | shouldCenterHorizontally ?? this.shouldCenterHorizontally,
181 | );
182 | }
183 |
184 | /// A standard [DotsClockStyle].
185 | factory DotsClockStyle.standard() {
186 | return DotsClockStyle(
187 | dotSpacing: 6.5,
188 | dotActiveScale: 3,
189 | fontPath: "assets/fonts/Poppins-Bold.ttf",
190 | fontSize: 0.4,
191 | fontSpacing: 0.9,
192 | middleSpacing: 0.05,
193 | shouldCenterHorizontally: true,
194 | charXPosCorrections: {
195 | "1": 0.175,
196 | "7": 0.1,
197 | },
198 | gridBuilder: (rows, columns) {
199 | PerlinNoise noise = PerlinNoise(
200 | octaves: 4,
201 | frequency: 0.35,
202 | );
203 | return List.generate(
204 | rows,
205 | (int row) => List.generate(
206 | columns,
207 | (int column) {
208 | double noiseValue =
209 | noise.getPerlin2(column.toDouble(), row.toDouble());
210 | double percentage = (noiseValue + sqrt1_2) / (2 * sqrt1_2);
211 | double value = percentage * 2 * pi;
212 | return value;
213 | },
214 | ),
215 | );
216 | },
217 | );
218 | }
219 |
220 | /// A [DotsClockStyle] with oversized dots.
221 | factory DotsClockStyle.blobs() {
222 | return DotsClockStyle(
223 | dotSpacing: 6.5,
224 | dotActiveScale: 6,
225 | fontPath: "assets/fonts/Poppins-Bold.ttf",
226 | fontSize: 0.4,
227 | fontSpacing: 0.9,
228 | middleSpacing: 0.05,
229 | shouldCenterHorizontally: true,
230 | charXPosCorrections: {
231 | "1": 0.175,
232 | "7": 0.1,
233 | },
234 | gridBuilder: (rows, columns) {
235 | PerlinNoise noise = PerlinNoise(
236 | octaves: 4,
237 | frequency: 0.35,
238 | );
239 | return List.generate(
240 | rows,
241 | (int row) => List.generate(
242 | columns,
243 | (int column) {
244 | double noiseValue =
245 | noise.getPerlin2(column.toDouble(), row.toDouble());
246 | double percentage = (noiseValue + sqrt1_2) / (2 * sqrt1_2);
247 | double value = percentage * 2 * pi;
248 | return value;
249 | },
250 | ),
251 | );
252 | },
253 | );
254 | }
255 |
256 | /// A [DotsClockStyle] with gooey animations.
257 | factory DotsClockStyle.gooey() {
258 | return DotsClockStyle(
259 | dotSpacing: 6.5,
260 | dotActiveScale: 3,
261 | fontPath: "assets/fonts/Poppins-Bold.ttf",
262 | fontSize: 0.4,
263 | fontSpacing: 0.9,
264 | middleSpacing: 0.05,
265 | shouldCenterHorizontally: true,
266 | charXPosCorrections: {
267 | "1": 0.175,
268 | "7": 0.1,
269 | },
270 | gridBuilder: (rows, columns) {
271 | PerlinNoise noise = PerlinNoise(
272 | octaves: 4,
273 | frequency: 0.1,
274 | );
275 | return List.generate(
276 | rows,
277 | (int row) => List.generate(
278 | columns,
279 | (int column) {
280 | double noiseValue =
281 | noise.getPerlin2(column.toDouble(), row.toDouble());
282 | double percentage = (noiseValue + sqrt1_2) / (2 * sqrt1_2);
283 | double value = percentage * 2 * pi;
284 | return value;
285 | },
286 | ),
287 | );
288 | },
289 | );
290 | }
291 |
292 | /// A [DotsClockStyle] using celluar noise.
293 | factory DotsClockStyle.cellularNoise() {
294 | return DotsClockStyle(
295 | dotSpacing: 6.5,
296 | dotActiveScale: 3,
297 | fontPath: "assets/fonts/Poppins-Bold.ttf",
298 | fontSize: 0.4,
299 | fontSpacing: 0.9,
300 | middleSpacing: 0.05,
301 | shouldCenterHorizontally: true,
302 | charXPosCorrections: {
303 | "1": 0.175,
304 | "7": 0.1,
305 | },
306 | gridBuilder: (rows, columns) {
307 | CellularNoise noise = CellularNoise(
308 | octaves: 3,
309 | frequency: 0.3,
310 | );
311 | return List.generate(
312 | rows,
313 | (int row) => List.generate(
314 | columns,
315 | (int column) {
316 | double noiseValue =
317 | noise.getCellular2(column.toDouble(), row.toDouble());
318 | double percentage = (noiseValue + sqrt1_2) / (2 * sqrt1_2);
319 | double value = percentage * 2 * pi;
320 | return value;
321 | },
322 | ),
323 | );
324 | },
325 | );
326 | }
327 |
328 | /// A [DotsClockStyle] using simplex noise.
329 | factory DotsClockStyle.simplexNoise() {
330 | return DotsClockStyle(
331 | dotSpacing: 6.5,
332 | dotActiveScale: 3,
333 | fontPath: "assets/fonts/Poppins-Bold.ttf",
334 | fontSize: 0.4,
335 | fontSpacing: 0.9,
336 | middleSpacing: 0.05,
337 | shouldCenterHorizontally: true,
338 | charXPosCorrections: {
339 | "1": 0.175,
340 | "7": 0.1,
341 | },
342 | gridBuilder: (rows, columns) {
343 | SimplexNoise noise = SimplexNoise(
344 | octaves: 4,
345 | frequency: 0.0075,
346 | );
347 | return List.generate(
348 | rows,
349 | (int row) => List.generate(
350 | columns,
351 | (int column) {
352 | double noiseValue =
353 | noise.getSimplex2(column.toDouble(), row.toDouble());
354 | double percentage = (noiseValue + sqrt1_2) / (2 * sqrt1_2);
355 | double value = percentage * 2 * pi;
356 | return value;
357 | },
358 | ),
359 | );
360 | },
361 | );
362 | }
363 |
364 | /// A [DotsClockStyle] using cubic noise.
365 | factory DotsClockStyle.cubicNoise() {
366 | return DotsClockStyle(
367 | dotSpacing: 6.5,
368 | dotActiveScale: 3,
369 | fontPath: "assets/fonts/Poppins-Bold.ttf",
370 | fontSize: 0.4,
371 | fontSpacing: 0.9,
372 | middleSpacing: 0.05,
373 | shouldCenterHorizontally: true,
374 | charXPosCorrections: {
375 | "1": 0.175,
376 | "7": 0.1,
377 | },
378 | gridBuilder: (rows, columns) {
379 | CubicNoise noise = CubicNoise(
380 | octaves: 3,
381 | frequency: 0.015,
382 | );
383 | return List.generate(
384 | rows,
385 | (int row) => List.generate(
386 | columns,
387 | (int column) {
388 | double noiseValue =
389 | noise.getCubic2(column.toDouble(), row.toDouble());
390 | double percentage = (noiseValue + sqrt1_2) / (2 * sqrt1_2);
391 | double value = percentage * 2 * pi;
392 | return value;
393 | },
394 | ),
395 | );
396 | },
397 | );
398 | }
399 |
400 | /// A [DotsClockStyle] using value noise.
401 | factory DotsClockStyle.valueNoise() {
402 | return DotsClockStyle(
403 | dotSpacing: 6.5,
404 | dotActiveScale: 3,
405 | fontPath: "assets/fonts/Poppins-Bold.ttf",
406 | fontSize: 0.4,
407 | fontSpacing: 0.9,
408 | middleSpacing: 0.05,
409 | shouldCenterHorizontally: true,
410 | charXPosCorrections: {
411 | "1": 0.175,
412 | "7": 0.1,
413 | },
414 | gridBuilder: (rows, columns) {
415 | ValueNoise noise = ValueNoise(
416 | octaves: 3,
417 | frequency: 0.015,
418 | );
419 | return List.generate(
420 | rows,
421 | (int row) => List.generate(
422 | columns,
423 | (int column) {
424 | double noiseValue =
425 | noise.getValue2(column.toDouble(), row.toDouble());
426 | double percentage = (noiseValue + sqrt1_2) / (2 * sqrt1_2);
427 | double value = percentage * 2 * pi;
428 | return value;
429 | },
430 | ),
431 | );
432 | },
433 | );
434 | }
435 |
436 | /// A [DotsClockStyle] using white noise.
437 | factory DotsClockStyle.whiteNoise() {
438 | return DotsClockStyle(
439 | dotSpacing: 6.5,
440 | dotActiveScale: 3,
441 | fontPath: "assets/fonts/Poppins-Bold.ttf",
442 | fontSize: 0.4,
443 | fontSpacing: 0.9,
444 | middleSpacing: 0.05,
445 | shouldCenterHorizontally: true,
446 | charXPosCorrections: {
447 | "1": 0.175,
448 | "7": 0.1,
449 | },
450 | gridBuilder: (rows, columns) {
451 | WhiteNoise noise = WhiteNoise();
452 | return List.generate(
453 | rows,
454 | (int row) => List.generate(
455 | columns,
456 | (int column) {
457 | double noiseValue = noise.getWhiteNoise2(column, row);
458 | double percentage = (noiseValue + sqrt1_2) / (2 * sqrt1_2);
459 | double value = percentage * 2 * pi;
460 | return value;
461 | },
462 | ),
463 | );
464 | },
465 | );
466 | }
467 | }
468 |
--------------------------------------------------------------------------------
/dots_clock/lib/widgets/dots_clock.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Tran Duy Khanh Steffen. All rights reserved.
2 | // Use of this source code is governed by a MIT license that can be
3 | // found in the dots_clock/LICENSE file.
4 |
5 | import 'dart:async';
6 | import 'dart:math';
7 |
8 | import 'package:dots_clock/models/dots_clock_style.dart';
9 | import 'package:dots_clock/widgets/dots_painter.dart';
10 | import 'package:flutter/material.dart';
11 | import 'package:flutter/services.dart';
12 | import 'package:flutter_clock_helper/model.dart';
13 | import 'package:intl/intl.dart';
14 | import 'package:text_to_path_maker/text_to_path_maker.dart';
15 |
16 | class DotsClock extends StatefulWidget {
17 | const DotsClock({
18 | @required this.model,
19 | @required this.style,
20 | @required this.width,
21 | @required this.height,
22 | });
23 |
24 | /// [ClockModel] to provide weather, temperature, location information.
25 | final ClockModel model;
26 |
27 | /// Data model that has the style specifications.
28 | final DotsClockStyle style;
29 |
30 | /// Width of the available render space.
31 | final double width;
32 |
33 | /// Height of the available render space.
34 | final double height;
35 |
36 | @override
37 | State createState() => DotsClockState();
38 | }
39 |
40 | class DotsClockState extends State with TickerProviderStateMixin {
41 | /// Current time.
42 | DateTime _dateTime = DateTime.now();
43 |
44 | /// [Timer] to update clock in an interval.
45 | Timer _timer;
46 |
47 | /// Font for the digital clock face.
48 | PMFont _targetFont;
49 |
50 | /// Current [Path] of the clock face's font.
51 | ///
52 | /// Used to compare active/inactive dots differences between
53 | /// clock updates and animate transitions for the dots.
54 | Path _currentPath;
55 |
56 | /// Previous [Path] of the clock face's font.
57 | ///
58 | /// Used to compare differences between clock ticks and
59 | /// animate transitions for the dots.
60 | Path _oldPath;
61 |
62 | /// 2D array containing the initial size values for each dot.
63 | List> _dotsGrid;
64 |
65 | /// [AnimationController] for the dot idle animations.
66 | AnimationController _dotPulseController;
67 |
68 | /// [Animation] values for the dot idle scaling animations.
69 | Animation _dotPulseAnimation;
70 |
71 | /// [AnimationController] for the dot transition animations.
72 | AnimationController _dotTransitionController;
73 |
74 | /// [Animation] values for the dot transition animations.
75 | Animation _dotTransitionAnimation;
76 |
77 | /// Number of rows based on [DotsClockStyle] and it's dot spacing.
78 | int _rows;
79 |
80 | /// Number of columns based on [DotsClockStyle] and it's dot spacing.
81 | int _columns;
82 |
83 | @override
84 | void initState() {
85 | super.initState();
86 | // Calculate number of columns, rows based on dot spacing.
87 | _rows = (widget.height / widget.style.dotSpacing).floor();
88 | _columns = (widget.width / widget.style.dotSpacing).floor();
89 |
90 | // Dot idle pulsing animation that scales the dots' sizes.
91 | //
92 | // Is set to repeat as it should always be animating.
93 | _dotPulseController = AnimationController(
94 | duration: widget.style.idleAnimationDuration,
95 | vsync: this,
96 | );
97 | _dotPulseAnimation = Tween(begin: 0.0, end: 2 * pi).animate(
98 | CurvedAnimation(
99 | curve: Curves.linear,
100 | parent: _dotPulseController,
101 | ),
102 | )..addListener(() => setState(() {}));
103 | _dotPulseController.repeat();
104 |
105 | // Dot transition animation between active/inactive state
106 | // by scaling them up or down to their correct size.
107 | //
108 | // Plays for each clock update.
109 | _dotTransitionController = AnimationController(
110 | duration: widget.style.transitionAnimationDuration,
111 | vsync: this,
112 | );
113 | _dotTransitionAnimation =
114 | Tween(begin: widget.style.dotActiveScale, end: 0.0).animate(
115 | CurvedAnimation(
116 | curve: Curves.linear,
117 | parent: _dotTransitionController,
118 | ),
119 | )..addListener(() => setState(() {}));
120 |
121 | widget.model.addListener(_updateModel);
122 |
123 | _loadFont().then((v) {
124 | _updatePath(_getFormattedTime());
125 | });
126 |
127 | _initDotsGrid();
128 | _updateTime();
129 | _updateModel();
130 | }
131 |
132 | @override
133 | void didUpdateWidget(DotsClock oldWidget) {
134 | super.didUpdateWidget(oldWidget);
135 | if (widget.model != oldWidget.model) {
136 | oldWidget.model.removeListener(_updateModel);
137 | widget.model.addListener(_updateModel);
138 | }
139 | _updatePath(_getFormattedTime());
140 | }
141 |
142 | @override
143 | void dispose() {
144 | _timer?.cancel();
145 | _dotPulseController.dispose();
146 | _dotTransitionController.dispose();
147 | super.dispose();
148 | }
149 |
150 | /// Update 3rd party information model.
151 | ///
152 | /// Currently unused.
153 | void _updateModel() {
154 | setState(() {
155 | // Cause the clock to rebuild when the model changes.
156 | });
157 | }
158 |
159 | /// Initialise dots grid via [DotsClockStyle] builder function.
160 | _initDotsGrid() {
161 | _dotsGrid = widget.style.gridBuilder(_rows, _columns);
162 | }
163 |
164 | /// Update current [_time] in a given interval and update clock face path.
165 | void _updateTime() {
166 | setState(() {
167 | _dateTime = DateTime.now();
168 | // Update once per minute. If you want to update every second, use the
169 | // following code.
170 | _timer = Timer(
171 | Duration(minutes: 1) -
172 | Duration(seconds: _dateTime.second) -
173 | Duration(milliseconds: _dateTime.millisecond),
174 | _updateTime,
175 | );
176 | // Update once per second, but make sure to do it at the beginning of each
177 | // new second, so that the clock is accurate.
178 | // _timer = Timer(
179 | // Duration(seconds: 1) - Duration(milliseconds: _dateTime.millisecond),
180 | // _updateTime,
181 | // );
182 |
183 | _updatePath(_getFormattedTime());
184 | });
185 | _dotTransitionController.reset();
186 | _dotTransitionController.forward();
187 | }
188 |
189 | /// Get the current formatted time.
190 | String _getFormattedTime() {
191 | final String hour =
192 | DateFormat(widget.model.is24HourFormat ? 'HH' : 'hh').format(_dateTime);
193 | final String minute = DateFormat('mm').format(_dateTime);
194 | return '$hour$minute';
195 | }
196 |
197 | /// Load the target font.
198 | Future _loadFont() async {
199 | ByteData data = await rootBundle.load(widget.style.fontPath);
200 | PMFontReader reader = PMFontReader();
201 | _targetFont = reader.parseTTFAsset(data);
202 | return reader.parseTTFAsset(data);
203 | }
204 |
205 | /// Update the clock face path.
206 | void _updatePath(String time) {
207 | _oldPath = _currentPath;
208 | _currentPath = _buildClockFacePath(time);
209 | }
210 |
211 | /// Calculate the next clock face path.
212 | Path _buildClockFacePath(String string) {
213 | if (_targetFont != null) {
214 | Path stringPath = Path();
215 |
216 | for (int i = 0; i < string.length; i++) {
217 | Path charPath =
218 | _targetFont.generatePathForCharacter(string.codeUnitAt(i));
219 |
220 | // PMTransform.moveAndScale scales by minus y-scale.
221 | //
222 | // Flip char path on y-axis because inital paths are reversed.
223 | charPath = PMTransform.moveAndScale(charPath, 0.0, 0.0, 1.0, 1.0);
224 |
225 | // Scale char path to defined font size.
226 | double targetHeight = widget.style.fontSize * widget.height;
227 | double yScaleFactor = targetHeight / charPath.getBounds().height;
228 | charPath = PMTransform.moveAndScale(
229 | charPath, 0.0, 0.0, yScaleFactor, -yScaleFactor);
230 |
231 | // Apply x-position corrections to make the font monospace.
232 | //
233 | // Some chars may overlap with other chars otherwise.
234 | charPath = widget.style.charXPosCorrections.containsKey(string[i])
235 | ? PMTransform.moveAndScale(
236 | charPath,
237 | widget.style.charXPosCorrections[string[i]] * targetHeight,
238 | 0.0,
239 | 1.0,
240 | -1.0,
241 | )
242 | : charPath;
243 |
244 | // Apply middle spacing based on char height.
245 | charPath = i >= string.length / 2
246 | ? PMTransform.moveAndScale(charPath,
247 | widget.width * widget.style.middleSpacing, 0.0, 1.0, -1.0)
248 | : charPath;
249 |
250 | // Position char path.
251 | charPath = PMTransform.moveAndScale(
252 | charPath,
253 | i * targetHeight * widget.style.fontSpacing +
254 | (widget.style.xOffset * widget.width),
255 | 0.0,
256 | 1.0,
257 | -1.0,
258 | );
259 |
260 | // Add char path to string path.
261 | stringPath.addPath(
262 | charPath,
263 | Offset(
264 | 0,
265 | 0,
266 | ),
267 | );
268 | }
269 |
270 | // Center string path horizontally.
271 | if (widget.style.shouldCenterHorizontally) {
272 | final double targetXPos =
273 | (widget.width / 2) - (stringPath.getBounds().width / 2);
274 | final double xTranslation = targetXPos - stringPath.getBounds().left;
275 | stringPath =
276 | PMTransform.moveAndScale(stringPath, xTranslation, 0.0, 1.0, -1.0);
277 | }
278 |
279 | // Center string path vertically.
280 | if (widget.style.shouldCenterVertically) {
281 | final double targetYPos =
282 | (widget.height / 2) - (stringPath.getBounds().height / 2);
283 | final double yTranslation = targetYPos - stringPath.getBounds().top;
284 | stringPath =
285 | PMTransform.moveAndScale(stringPath, 0.0, yTranslation, 1.0, -1.0);
286 | }
287 |
288 | return stringPath;
289 | } else {
290 | return Path();
291 | }
292 | }
293 |
294 | @override
295 | Widget build(BuildContext context) {
296 | return Container(
297 | color: Theme.of(context).brightness == Brightness.light
298 | ? widget.style.brightBackgroundColor
299 | : widget.style.darkBackgroundColor,
300 | child: ClipRect(
301 | child: CustomPaint(
302 | painter: DotsPainter(
303 | color: Theme.of(context).brightness == Brightness.light
304 | ? widget.style.brightColor
305 | : widget.style.darkColor,
306 | oldPath: _oldPath,
307 | currentPath: _currentPath,
308 | pulseValue: _dotPulseAnimation.value,
309 | grid: _dotsGrid,
310 | rows: _rows,
311 | columns: _columns,
312 | transitionValue: _dotTransitionAnimation.value,
313 | spacing: widget.style.dotSpacing,
314 | dotBaseSize: widget.style.dotBaseSize,
315 | dotActiveScale: widget.style.dotActiveScale,
316 | ),
317 | ),
318 | ),
319 | );
320 | }
321 | }
322 |
--------------------------------------------------------------------------------
/dots_clock/lib/widgets/dots_painter.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | /// [CustomPainter] that draws the clock face for [DotsClock].
6 | class DotsPainter extends CustomPainter {
7 | DotsPainter({
8 | this.oldPath,
9 | this.currentPath,
10 | @required this.color,
11 | @required this.grid,
12 | @required this.rows,
13 | @required this.columns,
14 | @required this.pulseValue,
15 | @required this.transitionValue,
16 | @required this.spacing,
17 | @required this.dotBaseSize,
18 | @required this.dotActiveScale,
19 | });
20 |
21 | /// Previous [Path] of the clock face's font.
22 | ///
23 | /// Used to compare differences between clock updates and
24 | /// animate transitions for the dots.
25 | final Path oldPath;
26 |
27 | /// Current [Path] of the clock face's font.
28 | ///
29 | /// Used to compare differences between clock updates and
30 | /// animate transitions for the dots.
31 | final Path currentPath;
32 |
33 | /// [Color] with which to draw the dots.
34 | final Color color;
35 |
36 | /// 2D array containing the initial size values for each dot.
37 | final List> grid;
38 |
39 | /// Number of rows to paint.
40 | final int rows;
41 |
42 | /// Number of columns to paint.
43 | final int columns;
44 |
45 | /// Current idle scale animation value to add onto each dot's size.
46 | final double pulseValue;
47 |
48 | /// Current transition animation value to add onto some dot's size.
49 | final double transitionValue;
50 |
51 | /// Spacing between rows and columns of dots.
52 | ///
53 | /// The higher this value the more space there is between dots
54 | /// and less dots will be displayed.
55 | final double spacing;
56 |
57 | /// Size of dots at the sine wave's peak value.
58 | final double dotBaseSize;
59 |
60 | /// Maximum scale multiplier of an active dot.
61 | final double dotActiveScale;
62 |
63 | @override
64 | void paint(Canvas canvas, Size size) {
65 | for (int i = 0; i < rows; i++) {
66 | for (int j = 0; j < columns; j++) {
67 | Offset offset = Offset(
68 | j * spacing + (spacing / 2),
69 | i * spacing + (spacing / 2),
70 | );
71 |
72 | // Calculate the dot's current size by adding idle animation value
73 | // onto initial size and then applying sine function.
74 | double radius = sin(grid[i][j] + pulseValue) * dotBaseSize;
75 |
76 | // Paint dots differently based on their state:
77 | if (oldPath != null && currentPath != null) {
78 | // Dot is at active -> inactive state (transition scale down animation)
79 | if (oldPath.contains(offset) && !currentPath.contains(offset)) {
80 | radius = (radius * transitionValue.clamp(1, dotActiveScale)).abs();
81 | }
82 |
83 | // Dot is at inactive -> active state (transition scale up animation)
84 | if (!oldPath.contains(offset) && currentPath.contains(offset)) {
85 | radius = (radius * (dotActiveScale - transitionValue)).abs();
86 | }
87 |
88 | // Dot is at inactive state (idle at base scale)
89 | if (!oldPath.contains(offset) && !currentPath.contains(offset)) {
90 | radius = radius;
91 | }
92 |
93 | // Dot is at active state (idle at activeScale)
94 | if (oldPath.contains(offset) && currentPath.contains(offset)) {
95 | radius = (radius * dotActiveScale).abs();
96 | }
97 | }
98 |
99 | canvas.drawOval(
100 | Rect.fromCircle(center: offset, radius: radius),
101 | Paint()..color = color,
102 | );
103 | }
104 | }
105 | }
106 |
107 | @override
108 | bool shouldRepaint(DotsPainter oldDelegate) {
109 | return oldDelegate.oldPath != oldPath ||
110 | oldDelegate.currentPath != currentPath ||
111 | oldDelegate.color != color ||
112 | oldDelegate.grid != grid ||
113 | oldDelegate.rows != rows ||
114 | oldDelegate.columns != columns ||
115 | oldDelegate.pulseValue != pulseValue ||
116 | oldDelegate.transitionValue != transitionValue ||
117 | oldDelegate.spacing != spacing ||
118 | oldDelegate.dotActiveScale != dotActiveScale;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/dots_clock/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | archive:
5 | dependency: transitive
6 | description:
7 | name: archive
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "2.0.11"
11 | args:
12 | dependency: transitive
13 | description:
14 | name: args
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "1.5.2"
18 | async:
19 | dependency: transitive
20 | description:
21 | name: async
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "2.4.0"
25 | boolean_selector:
26 | dependency: transitive
27 | description:
28 | name: boolean_selector
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.0.5"
32 | charcode:
33 | dependency: transitive
34 | description:
35 | name: charcode
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.1.2"
39 | collection:
40 | dependency: transitive
41 | description:
42 | name: collection
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "1.14.11"
46 | convert:
47 | dependency: transitive
48 | description:
49 | name: convert
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "2.1.1"
53 | crypto:
54 | dependency: transitive
55 | description:
56 | name: crypto
57 | url: "https://pub.dartlang.org"
58 | source: hosted
59 | version: "2.1.3"
60 | cupertino_icons:
61 | dependency: "direct main"
62 | description:
63 | name: cupertino_icons
64 | url: "https://pub.dartlang.org"
65 | source: hosted
66 | version: "0.1.3"
67 | fast_noise:
68 | dependency: "direct main"
69 | description:
70 | name: fast_noise
71 | url: "https://pub.dartlang.org"
72 | source: hosted
73 | version: "0.1.3+1"
74 | fixnum:
75 | dependency: transitive
76 | description:
77 | name: fixnum
78 | url: "https://pub.dartlang.org"
79 | source: hosted
80 | version: "0.10.11"
81 | flutter:
82 | dependency: "direct main"
83 | description: flutter
84 | source: sdk
85 | version: "0.0.0"
86 | flutter_clock_helper:
87 | dependency: "direct main"
88 | description:
89 | path: "..\\flutter_clock_helper"
90 | relative: true
91 | source: path
92 | version: "1.0.0+1"
93 | flutter_test:
94 | dependency: "direct dev"
95 | description: flutter
96 | source: sdk
97 | version: "0.0.0"
98 | image:
99 | dependency: transitive
100 | description:
101 | name: image
102 | url: "https://pub.dartlang.org"
103 | source: hosted
104 | version: "2.1.4"
105 | intl:
106 | dependency: transitive
107 | description:
108 | name: intl
109 | url: "https://pub.dartlang.org"
110 | source: hosted
111 | version: "0.16.1"
112 | matcher:
113 | dependency: transitive
114 | description:
115 | name: matcher
116 | url: "https://pub.dartlang.org"
117 | source: hosted
118 | version: "0.12.6"
119 | meta:
120 | dependency: transitive
121 | description:
122 | name: meta
123 | url: "https://pub.dartlang.org"
124 | source: hosted
125 | version: "1.1.8"
126 | path:
127 | dependency: transitive
128 | description:
129 | name: path
130 | url: "https://pub.dartlang.org"
131 | source: hosted
132 | version: "1.6.4"
133 | pedantic:
134 | dependency: transitive
135 | description:
136 | name: pedantic
137 | url: "https://pub.dartlang.org"
138 | source: hosted
139 | version: "1.8.0+1"
140 | petitparser:
141 | dependency: transitive
142 | description:
143 | name: petitparser
144 | url: "https://pub.dartlang.org"
145 | source: hosted
146 | version: "2.4.0"
147 | quiver:
148 | dependency: transitive
149 | description:
150 | name: quiver
151 | url: "https://pub.dartlang.org"
152 | source: hosted
153 | version: "2.0.5"
154 | sky_engine:
155 | dependency: transitive
156 | description: flutter
157 | source: sdk
158 | version: "0.0.99"
159 | source_span:
160 | dependency: transitive
161 | description:
162 | name: source_span
163 | url: "https://pub.dartlang.org"
164 | source: hosted
165 | version: "1.5.5"
166 | stack_trace:
167 | dependency: transitive
168 | description:
169 | name: stack_trace
170 | url: "https://pub.dartlang.org"
171 | source: hosted
172 | version: "1.9.3"
173 | stream_channel:
174 | dependency: transitive
175 | description:
176 | name: stream_channel
177 | url: "https://pub.dartlang.org"
178 | source: hosted
179 | version: "2.0.0"
180 | string_scanner:
181 | dependency: transitive
182 | description:
183 | name: string_scanner
184 | url: "https://pub.dartlang.org"
185 | source: hosted
186 | version: "1.0.5"
187 | term_glyph:
188 | dependency: transitive
189 | description:
190 | name: term_glyph
191 | url: "https://pub.dartlang.org"
192 | source: hosted
193 | version: "1.1.0"
194 | test_api:
195 | dependency: transitive
196 | description:
197 | name: test_api
198 | url: "https://pub.dartlang.org"
199 | source: hosted
200 | version: "0.2.11"
201 | text_to_path_maker:
202 | dependency: "direct main"
203 | description:
204 | name: text_to_path_maker
205 | url: "https://pub.dartlang.org"
206 | source: hosted
207 | version: "0.5.7"
208 | typed_data:
209 | dependency: transitive
210 | description:
211 | name: typed_data
212 | url: "https://pub.dartlang.org"
213 | source: hosted
214 | version: "1.1.6"
215 | vector_math:
216 | dependency: transitive
217 | description:
218 | name: vector_math
219 | url: "https://pub.dartlang.org"
220 | source: hosted
221 | version: "2.0.8"
222 | xml:
223 | dependency: transitive
224 | description:
225 | name: xml
226 | url: "https://pub.dartlang.org"
227 | source: hosted
228 | version: "3.5.0"
229 | sdks:
230 | dart: ">=2.5.0 <3.0.0"
231 |
--------------------------------------------------------------------------------
/dots_clock/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: dots_clock
2 | description: Digital clock.
3 | version: 1.0.0+1
4 |
5 | environment:
6 | sdk: ">=2.1.0 <3.0.0"
7 |
8 | dependencies:
9 | flutter:
10 | sdk: flutter
11 | flutter_clock_helper:
12 | path: ../flutter_clock_helper
13 | text_to_path_maker: ^0.5.7
14 | fast_noise: ^0.1.3+1
15 |
16 | dev_dependencies:
17 | flutter_test:
18 | sdk: flutter
19 |
20 | flutter:
21 | uses-material-design: true
22 | fonts:
23 | - family: Poppins Bold
24 | fonts:
25 | - asset: assets/fonts/Poppins-Bold.ttf
26 |
--------------------------------------------------------------------------------
/flutter_clock_helper/.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: 9bd02a1787bd264fde13a445a900ca28d08e3cef
8 | channel: master
9 |
10 | project_type: package
11 |
--------------------------------------------------------------------------------
/flutter_clock_helper/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [0.0.1] - TODO: Add release date.
2 |
3 | * TODO: Describe initial release.
4 |
--------------------------------------------------------------------------------
/flutter_clock_helper/README.md:
--------------------------------------------------------------------------------
1 | # Flutter Clock Helper
2 |
3 | This package provides scaffolding code for the clock in the Flutter Clock contest.
4 |
5 | Contestants: Do not edit this code.
6 |
7 |
8 | ## Model
9 | Provides data that can change in the clock. Look in model.dart for more details.
10 |
11 | * Time format (12- or 24-hour)
12 | * Location
13 | * Temperature
14 | * Temperature high
15 | * Temperature low
16 | * Temperature unit
17 | * Weather unit
18 |
19 |
20 | ## Clock Customizer
21 | Provides customizations for your clock (based on the model).
22 | You can change the behavior of your clock based on these customizations.
23 |
24 |
25 |
26 | To use inside your app's `main.dart`:
27 |
28 | ```
29 | runApp(ClockCustomizer((ClockModel model) => AnalogClock(model)));
30 | ```
31 |
32 | For more information, see the code inside [lib/](lib).
33 | For a full example, see the [Analog Clock](../analog_clock) or [Digital Clock](../digital_clock) in this GitHub repo.
34 |
--------------------------------------------------------------------------------
/flutter_clock_helper/customizer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/flutter_clock_helper/customizer.png
--------------------------------------------------------------------------------
/flutter_clock_helper/lib/customizer.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | import 'package:flutter/material.dart';
6 |
7 | import 'model.dart';
8 |
9 | /// Returns a clock [Widget] with [ClockModel].
10 | ///
11 | /// Example:
12 | /// final myClockBuilder = (ClockModel model) => AnalogClock(model);
13 | ///
14 | /// Contestants: Do not edit this.
15 | typedef Widget ClockBuilder(ClockModel model);
16 |
17 | /// Wrapper for clock widget to allow for customizations.
18 | ///
19 | /// Puts the clock in landscape orientation with an aspect ratio of 5:3.
20 | /// Provides a drawer where users can customize the data that is sent to the
21 | /// clock. To show/hide the drawer, double-tap the clock.
22 | ///
23 | /// To use the [ClockCustomizer], pass your clock into it, using a ClockBuilder.
24 | ///
25 | /// ```
26 | /// final myClockBuilder = (ClockModel model) => AnalogClock(model);
27 | /// return ClockCustomizer(myClockBuilder);
28 | /// ```
29 | /// Contestants: Do not edit this.
30 | class ClockCustomizer extends StatefulWidget {
31 | const ClockCustomizer(this._clock);
32 |
33 | /// The clock widget with [ClockModel], to update and display.
34 | final ClockBuilder _clock;
35 |
36 | @override
37 | _ClockCustomizerState createState() => _ClockCustomizerState();
38 | }
39 |
40 | class _ClockCustomizerState extends State {
41 | final _model = ClockModel();
42 | ThemeMode _themeMode = ThemeMode.light;
43 | bool _configButtonShown = false;
44 |
45 | @override
46 | void initState() {
47 | super.initState();
48 | _model.addListener(_handleModelChange);
49 | }
50 |
51 | @override
52 | void dispose() {
53 | _model.removeListener(_handleModelChange);
54 | _model.dispose();
55 | super.dispose();
56 | }
57 |
58 | void _handleModelChange() => setState(() {});
59 |
60 | Widget _enumMenu(
61 | String label, T value, List items, ValueChanged onChanged) {
62 | return InputDecorator(
63 | decoration: InputDecoration(
64 | labelText: label,
65 | ),
66 | child: DropdownButtonHideUnderline(
67 | child: DropdownButton(
68 | value: value,
69 | isDense: true,
70 | onChanged: onChanged,
71 | items: items.map((T item) {
72 | return DropdownMenuItem(
73 | value: item,
74 | child: Text(enumToString(item)),
75 | );
76 | }).toList(),
77 | ),
78 | ),
79 | );
80 | }
81 |
82 | Widget _switch(String label, bool value, ValueChanged onChanged) {
83 | return Row(
84 | children: [
85 | Expanded(child: Text(label)),
86 | Switch(
87 | value: value,
88 | onChanged: onChanged,
89 | ),
90 | ],
91 | );
92 | }
93 |
94 | Widget _textField(
95 | String currentValue, String label, ValueChanged onChanged) {
96 | return TextField(
97 | decoration: InputDecoration(
98 | hintText: currentValue,
99 | helperText: label,
100 | ),
101 | onChanged: onChanged,
102 | );
103 | }
104 |
105 | Widget _configDrawer(BuildContext context) {
106 | return SafeArea(
107 | child: Drawer(
108 | child: Padding(
109 | padding: const EdgeInsets.all(16.0),
110 | child: SingleChildScrollView(
111 | child: Column(
112 | children: [
113 | _textField(_model.location, 'Location', (String location) {
114 | setState(() {
115 | _model.location = location;
116 | });
117 | }),
118 | _textField(_model.temperature.toString(), 'Temperature',
119 | (String temperature) {
120 | setState(() {
121 | _model.temperature = double.parse(temperature);
122 | });
123 | }),
124 | _enumMenu('Theme', _themeMode,
125 | ThemeMode.values.toList()..remove(ThemeMode.system),
126 | (ThemeMode mode) {
127 | setState(() {
128 | _themeMode = mode;
129 | });
130 | }),
131 | _switch('24-hour format', _model.is24HourFormat, (bool value) {
132 | setState(() {
133 | _model.is24HourFormat = value;
134 | });
135 | }),
136 | _enumMenu(
137 | 'Weather', _model.weatherCondition, WeatherCondition.values,
138 | (WeatherCondition condition) {
139 | setState(() {
140 | _model.weatherCondition = condition;
141 | });
142 | }),
143 | _enumMenu('Units', _model.unit, TemperatureUnit.values,
144 | (TemperatureUnit unit) {
145 | setState(() {
146 | _model.unit = unit;
147 | });
148 | }),
149 | ],
150 | ),
151 | ),
152 | ),
153 | ),
154 | );
155 | }
156 |
157 | Widget _configButton() {
158 | return Builder(
159 | builder: (BuildContext context) {
160 | return IconButton(
161 | icon: Icon(Icons.settings),
162 | tooltip: 'Configure clock',
163 | onPressed: () {
164 | Scaffold.of(context).openEndDrawer();
165 | setState(() {
166 | _configButtonShown = false;
167 | });
168 | },
169 | );
170 | },
171 | );
172 | }
173 |
174 | @override
175 | Widget build(BuildContext context) {
176 | final clock = Center(
177 | child: AspectRatio(
178 | aspectRatio: 5 / 3,
179 | child: Container(
180 | decoration: BoxDecoration(
181 | border: Border.all(
182 | width: 2,
183 | color: Theme.of(context).unselectedWidgetColor,
184 | ),
185 | ),
186 | child: widget._clock(_model),
187 | ),
188 | ),
189 | );
190 |
191 | return MaterialApp(
192 | theme: ThemeData.light(),
193 | darkTheme: ThemeData.dark(),
194 | themeMode: _themeMode,
195 | debugShowCheckedModeBanner: false,
196 | home: Scaffold(
197 | resizeToAvoidBottomPadding: false,
198 | endDrawer: _configDrawer(context),
199 | body: SafeArea(
200 | child: GestureDetector(
201 | behavior: HitTestBehavior.opaque,
202 | onTap: () {
203 | setState(() {
204 | _configButtonShown = !_configButtonShown;
205 | });
206 | },
207 | child: Stack(
208 | children: [
209 | clock,
210 | if (_configButtonShown)
211 | Positioned(
212 | top: 0,
213 | right: 0,
214 | child: Opacity(
215 | opacity: 0.7,
216 | child: _configButton(),
217 | ),
218 | ),
219 | ],
220 | ),
221 | ),
222 | ),
223 | ),
224 | );
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/flutter_clock_helper/lib/model.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2019 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | import 'package:flutter/foundation.dart';
6 | import 'package:flutter/material.dart';
7 |
8 | /// This is the model that contains the customization options for the clock.
9 | ///
10 | /// It is a [ChangeNotifier], so use [ChangeNotifier.addListener] to listen to
11 | /// changes to the model. Be sure to call [ChangeNotifier.removeListener] in
12 | /// your `dispose` method.
13 | ///
14 | /// Contestants: Do not edit this.
15 | class ClockModel extends ChangeNotifier {
16 | get is24HourFormat => _is24HourFormat;
17 | bool _is24HourFormat = true;
18 | set is24HourFormat(bool is24HourFormat) {
19 | if (_is24HourFormat != is24HourFormat) {
20 | _is24HourFormat = is24HourFormat;
21 | notifyListeners();
22 | }
23 | }
24 |
25 | /// Current location String, for example 'Mountain View, CA'.
26 | get location => _location;
27 | String _location = 'Mountain View, CA';
28 | set location(String location) {
29 | if (location != _location) {
30 | _location = location;
31 | notifyListeners();
32 | }
33 | }
34 |
35 | /// Current temperature string, for example '22°C'.
36 | get temperature => _convertFromCelsius(_temperature);
37 | // Stored in degrees celsius, and converted based on the current unit setting
38 | num _temperature = 22.0;
39 | set temperature(num temperature) {
40 | temperature = _convertToCelsius(temperature);
41 | if (temperature != _temperature) {
42 | _temperature = temperature;
43 | _low = _temperature - 3.0;
44 | _high = _temperature + 4.0;
45 | notifyListeners();
46 | }
47 | }
48 |
49 | /// Daily high temperature, for example '26'.
50 | get high => _convertFromCelsius(_high);
51 | // Stored in degrees celsius, and converted based on the current unit setting
52 | num _high = 26.0;
53 | set high(num high) {
54 | high = _convertToCelsius(high);
55 | if (high != _high) {
56 | _high = high;
57 | notifyListeners();
58 | }
59 | }
60 |
61 | /// Daily low temperature, for example '19'.
62 | get low => _convertFromCelsius(_low);
63 | num _low = 19.0;
64 | set low(num low) {
65 | low = _convertToCelsius(low);
66 | if (low != _low) {
67 | _low = low;
68 | notifyListeners();
69 | }
70 | }
71 |
72 | /// Weather condition text for the current weather, for example 'cloudy'.
73 | WeatherCondition get weatherCondition => _weatherCondition;
74 | WeatherCondition _weatherCondition = WeatherCondition.sunny;
75 | set weatherCondition(WeatherCondition weatherCondition) {
76 | if (weatherCondition != _weatherCondition) {
77 | _weatherCondition = weatherCondition;
78 | notifyListeners();
79 | }
80 | }
81 |
82 | /// [WeatherCondition] value without the enum type.
83 | String get weatherString => enumToString(weatherCondition);
84 |
85 | /// Temperature unit, for example 'celsius'.
86 | TemperatureUnit get unit => _unit;
87 | TemperatureUnit _unit = TemperatureUnit.celsius;
88 | set unit(TemperatureUnit unit) {
89 | if (unit != _unit) {
90 | _unit = unit;
91 | notifyListeners();
92 | }
93 | }
94 |
95 | /// Temperature with unit of measurement.
96 | String get temperatureString {
97 | return '${temperature.toStringAsFixed(1)}$unitString';
98 | }
99 |
100 | /// Temperature high with unit of measurement.
101 | String get highString {
102 | return '${high.toStringAsFixed(1)}$unitString';
103 | }
104 |
105 | /// Temperature low with unit of measurement.
106 | String get lowString {
107 | return '${low.toStringAsFixed(1)}$unitString';
108 | }
109 |
110 | /// Temperature unit of measurement with degrees.
111 | String get unitString {
112 | switch (unit) {
113 | case TemperatureUnit.fahrenheit:
114 | return '°F';
115 | case TemperatureUnit.celsius:
116 | default:
117 | return '°C';
118 | }
119 | }
120 |
121 | num _convertFromCelsius(num degreesCelsius) {
122 | switch (unit) {
123 | case TemperatureUnit.fahrenheit:
124 | return 32.0 + degreesCelsius * 9.0 / 5.0;
125 | case TemperatureUnit.celsius:
126 | default:
127 | return degreesCelsius;
128 | break;
129 | }
130 | }
131 |
132 | num _convertToCelsius(num degrees) {
133 | switch (unit) {
134 | case TemperatureUnit.fahrenheit:
135 | return (degrees - 32.0) * 5.0 / 9.0;
136 | case TemperatureUnit.celsius:
137 | default:
138 | return degrees;
139 | break;
140 | }
141 | }
142 | }
143 |
144 | /// Weather condition in English.
145 | enum WeatherCondition {
146 | cloudy,
147 | foggy,
148 | rainy,
149 | snowy,
150 | sunny,
151 | thunderstorm,
152 | windy,
153 | }
154 |
155 | /// Temperature unit of measurement.
156 | enum TemperatureUnit {
157 | celsius,
158 | fahrenheit,
159 | }
160 |
161 | /// Removes the enum type and returns the value as a String.
162 | String enumToString(Object e) => e.toString().split('.').last;
163 |
--------------------------------------------------------------------------------
/flutter_clock_helper/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_clock_helper
2 | description: Helper classes for Flutter Clock contest.
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 | intl: "^0.16.0"
13 |
14 | cupertino_icons: ^0.1.2
15 |
16 | dev_dependencies:
17 | flutter_test:
18 | sdk: flutter
19 |
20 | flutter:
21 | uses-material-design: true
22 |
--------------------------------------------------------------------------------
/images/blobs.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/images/blobs.jpg
--------------------------------------------------------------------------------
/images/cellular_noise.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/images/cellular_noise.jpg
--------------------------------------------------------------------------------
/images/cubic_noise.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/images/cubic_noise.jpg
--------------------------------------------------------------------------------
/images/dark.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/images/dark.jpg
--------------------------------------------------------------------------------
/images/dots_clock_standard.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/images/dots_clock_standard.gif
--------------------------------------------------------------------------------
/images/gooey.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/images/gooey.jpg
--------------------------------------------------------------------------------
/images/simplex_noise.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/images/simplex_noise.jpg
--------------------------------------------------------------------------------
/images/standard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/images/standard.jpg
--------------------------------------------------------------------------------
/images/value_noise.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/images/value_noise.jpg
--------------------------------------------------------------------------------
/images/white_noise.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kainsteffen/dots-clock/6bc83ff6d6b813d6a221f5639f716d31d7dbf4d2/images/white_noise.jpg
--------------------------------------------------------------------------------