├── .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 | ![](images/dots_clock_standard.gif) 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 |![](images/standard.jpg) |[Youtube](https://youtu.be/Tpy14bsTklk)| 20 | |Blobs |![](images/blobs.jpg) |[Youtube](https://youtu.be/lfHU84U6yCs)| 21 | |Gooey |![](images/gooey.jpg) |[Youtube](https://youtu.be/QuXPebSS1Ko)| 22 | |Cellular Noise|![](images/cellular_noise.jpg)|[Youtube](https://youtu.be/BO_C2CW6tDc)| 23 | |Cubic Noise |![](images/cubic_noise.jpg) |[Youtube](https://youtu.be/V2TbrsmReXg)| 24 | |Simplex Noise |![](images/simplex_noise.jpg) |[Youtube](https://youtu.be/nMR9yyPnXDM)| 25 | |Value Noise |![](images/value_noise.jpg) |[Youtube](https://youtu.be/NWtwxKwSCDw)| 26 | |White Noise |![](images/white_noise.jpg) |[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 --------------------------------------------------------------------------------