├── city_clock ├── Lo-Fi_clock.png ├── assets │ ├── digits │ │ ├── colon.png │ │ ├── hour1-0.png │ │ ├── hour1-1.png │ │ ├── hour1-2.png │ │ ├── hour2-0.png │ │ ├── hour2-1.png │ │ ├── hour2-2.png │ │ ├── hour2-3.png │ │ ├── hour2-4.png │ │ ├── hour2-5.png │ │ ├── hour2-6.png │ │ ├── hour2-7.png │ │ ├── hour2-8.png │ │ ├── hour2-9.png │ │ ├── minute1-0.png │ │ ├── minute1-1.png │ │ ├── minute1-2.png │ │ ├── minute1-3.png │ │ ├── minute1-4.png │ │ ├── minute1-5.png │ │ ├── minute1-6.png │ │ ├── minute1-7.png │ │ ├── minute1-8.png │ │ ├── minute1-9.png │ │ ├── minute2-0.png │ │ ├── minute2-1.png │ │ ├── minute2-2.png │ │ ├── minute2-3.png │ │ ├── minute2-4.png │ │ ├── minute2-5.png │ │ ├── minute2-6.png │ │ ├── minute2-7.png │ │ ├── minute2-8.png │ │ └── minute2-9.png │ ├── images │ │ ├── clouds-0.png │ │ ├── clouds-1.png │ │ ├── signs │ │ │ └── sign_night.png │ │ ├── skies │ │ │ └── sky_night.png │ │ ├── streets │ │ │ └── street_night.png │ │ ├── city_back │ │ │ └── city_back_night.png │ │ └── city_front │ │ │ └── city_front_night.png │ ├── sprites │ │ ├── spritesheet.png │ │ └── spritesheet.json │ ├── fonts │ │ ├── PressStart2P-Regular.ttf │ │ └── OFL.txt │ └── cfg │ │ └── app_settings.json ├── .metadata ├── .vscode │ └── launch.json ├── .gitignore ├── lib │ ├── utils │ │ └── assets_loader.dart │ ├── environment │ │ ├── scene_layers.dart │ │ ├── scene.dart │ │ └── weather.dart │ ├── main.dart │ └── clock │ │ ├── clock.dart │ │ └── clock_text.dart ├── test │ └── widget_test.dart ├── pubspec.yaml └── pubspec.lock ├── flutter_clock_helper ├── CHANGELOG.md ├── customizer.png ├── .metadata ├── pubspec.yaml ├── README.md └── lib │ ├── model.dart │ └── customizer.dart ├── README.md └── LICENSE /city_clock/Lo-Fi_clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/Lo-Fi_clock.png -------------------------------------------------------------------------------- /flutter_clock_helper/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.0.1] - TODO: Add release date. 2 | 3 | * TODO: Describe initial release. 4 | -------------------------------------------------------------------------------- /city_clock/assets/digits/colon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/colon.png -------------------------------------------------------------------------------- /flutter_clock_helper/customizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/flutter_clock_helper/customizer.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour1-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour1-0.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour1-1.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour1-2.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour2-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour2-0.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour2-1.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour2-2.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour2-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour2-3.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour2-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour2-4.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour2-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour2-5.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour2-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour2-6.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour2-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour2-7.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour2-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour2-8.png -------------------------------------------------------------------------------- /city_clock/assets/digits/hour2-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/hour2-9.png -------------------------------------------------------------------------------- /city_clock/assets/images/clouds-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/images/clouds-0.png -------------------------------------------------------------------------------- /city_clock/assets/images/clouds-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/images/clouds-1.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute1-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute1-0.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute1-1.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute1-2.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute1-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute1-3.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute1-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute1-4.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute1-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute1-5.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute1-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute1-6.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute1-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute1-7.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute1-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute1-8.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute1-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute1-9.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute2-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute2-0.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute2-1.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute2-2.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute2-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute2-3.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute2-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute2-4.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute2-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute2-5.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute2-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute2-6.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute2-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute2-7.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute2-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute2-8.png -------------------------------------------------------------------------------- /city_clock/assets/digits/minute2-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/digits/minute2-9.png -------------------------------------------------------------------------------- /city_clock/assets/sprites/spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/sprites/spritesheet.png -------------------------------------------------------------------------------- /city_clock/assets/images/signs/sign_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/images/signs/sign_night.png -------------------------------------------------------------------------------- /city_clock/assets/images/skies/sky_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/images/skies/sky_night.png -------------------------------------------------------------------------------- /city_clock/assets/fonts/PressStart2P-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/fonts/PressStart2P-Regular.ttf -------------------------------------------------------------------------------- /city_clock/assets/images/streets/street_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/images/streets/street_night.png -------------------------------------------------------------------------------- /city_clock/assets/images/city_back/city_back_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/images/city_back/city_back_night.png -------------------------------------------------------------------------------- /city_clock/assets/images/city_front/city_front_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosliwmichael/flutter_clock/HEAD/city_clock/assets/images/city_front/city_front_night.png -------------------------------------------------------------------------------- /city_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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /city_clock/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Flutter", 9 | "request": "launch", 10 | "type": "dart" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /city_clock/assets/sprites/spritesheet.json: -------------------------------------------------------------------------------- 1 | { 2 | "frames": [ 3 | { 4 | "filename": "rain_drop.png", 5 | "frame": { 6 | "x": 1, 7 | "y": 1, 8 | "w": 27, 9 | "h": 45 10 | }, 11 | "rotated": false, 12 | "trimmed": false, 13 | "spriteSourceSize": { 14 | "x": 0, 15 | "y": 0, 16 | "w": 27, 17 | "h": 45 18 | }, 19 | "sourceSize": { 20 | "w": 27, 21 | "h": 45 22 | }, 23 | "pivot": {"x":0.0,"y":0.0} 24 | } 25 | ], 26 | "meta": { 27 | "app": "http://www.codeandweb.com/texturepacker", 28 | "version": "1.0", 29 | "image": "spritesheet.png", 30 | "format": "RGBA8888", 31 | "size": { 32 | "w": 29, 33 | "h": 47 34 | }, 35 | "scale": "1" 36 | } 37 | } -------------------------------------------------------------------------------- /city_clock/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | /build/ 32 | 33 | # Web related 34 | lib/generated_plugin_registrant.dart 35 | 36 | # Exceptions to above rules. 37 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 38 | -------------------------------------------------------------------------------- /city_clock/lib/utils/assets_loader.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:spritewidget/spritewidget.dart'; 3 | import 'package:global_configuration/global_configuration.dart'; 4 | 5 | Future loadSpriteSheet() async { 6 | ImageMap _imageMap = new ImageMap(rootBundle); 7 | await _imageMap.loadImage(GlobalConfiguration().getString("spriteSheet")); 8 | 9 | String json = await rootBundle 10 | .loadString(GlobalConfiguration().getString("spriteSheetJson")); 11 | SpriteSheet _spriteSheet = new SpriteSheet( 12 | _imageMap[GlobalConfiguration().getString("spriteSheet")], json); 13 | 14 | assert(_spriteSheet.image != null); 15 | return _spriteSheet; 16 | } 17 | 18 | Future loadWeatherImages() async { 19 | ImageMap _imageMap = new ImageMap(rootBundle); 20 | await _imageMap.load([ 21 | 'assets/images/clouds-0.png', 22 | 'assets/images/clouds-1.png', 23 | ]); 24 | return _imageMap; 25 | } 26 | -------------------------------------------------------------------------------- /city_clock/lib/environment/scene_layers.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:global_configuration/global_configuration.dart'; 3 | 4 | Widget loadSky() { 5 | return Image( 6 | image: AssetImage(GlobalConfiguration().getString("skyNight")), 7 | fit: BoxFit.fitWidth, 8 | ); 9 | } 10 | 11 | Widget loadCityBack() { 12 | return Image( 13 | image: AssetImage(GlobalConfiguration().getString("cityBackNight")), 14 | fit: BoxFit.fitWidth, 15 | ); 16 | } 17 | 18 | Widget loadCityFront() { 19 | return Image( 20 | image: AssetImage(GlobalConfiguration().getString("cityFrontNight")), 21 | fit: BoxFit.fitWidth, 22 | ); 23 | } 24 | 25 | Widget loadStreet() { 26 | return Image( 27 | image: AssetImage(GlobalConfiguration().getString("streetNight")), 28 | fit: BoxFit.fitWidth, 29 | ); 30 | } 31 | 32 | Widget loadSign() { 33 | return Image( 34 | image: AssetImage(GlobalConfiguration().getString("signNight")), 35 | fit: BoxFit.fitWidth, 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lofi-clock 2 |

3 | 4 |

5 | 6 | This project is an entry for the [flutter clock challenge](https://flutter.dev/clock) hosted by Google for Lenovo Smart clock, 2020. 7 | Our preferred testing enviornment was an Android emulator. The app works best on a 5:3 screen that has a resolution of 800x480 pixels in landscape mode. 8 | 9 | We made a clock face that borrows influence from Lofi music videos. Unfortunately, due to unexpected power cut, our graphic designer is unable to finish animations in time. Not to worry, we plan on finishing the project post competition and judging. 10 | 11 | We would REALLY encourage feedback on this project, whether you are the judge, or a fellow flutter developer. We basically jumped in with no prior flutter expereince, hence can use advice on how to properly refactor the app! :) 12 | - 13 | Code Contributors- 14 | 15 | -[Michael Wilson](https://github.com/nosliwmichael), 16 | 17 | -[Nishant Grover](https://github.com/nishantg95) 18 | -------------------------------------------------------------------------------- /city_clock/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | void main() { 12 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 13 | // Build our app and trigger a frame. 14 | 15 | // Verify that our counter starts at 0. 16 | expect(find.text('0'), findsOneWidget); 17 | expect(find.text('1'), findsNothing); 18 | 19 | // Tap the '+' icon and trigger a frame. 20 | await tester.tap(find.byIcon(Icons.add)); 21 | await tester.pump(); 22 | 23 | // Verify that our counter has incremented. 24 | expect(find.text('0'), findsNothing); 25 | expect(find.text('1'), findsOneWidget); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /city_clock/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:city_clock/environment/scene.dart'; 2 | import 'package:city_clock/utils/assets_loader.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | import 'package:flutter_clock_helper/customizer.dart'; 6 | import 'package:flutter_clock_helper/model.dart'; 7 | import 'package:spritewidget/spritewidget.dart'; 8 | import 'package:global_configuration/global_configuration.dart'; 9 | 10 | void main() async { 11 | // Enable widget binding before runApp is called so we can load assets 12 | WidgetsFlutterBinding.ensureInitialized(); 13 | // Hide nav/status bars 14 | SystemChrome.setEnabledSystemUIOverlays([]); 15 | 16 | await GlobalConfiguration().loadFromAsset("app_settings"); 17 | 18 | // Contains scene/environment assets 19 | ImageMap images = await loadWeatherImages(); 20 | // Contains sprite/animation assets 21 | SpriteSheet spriteSheet = await loadSpriteSheet(); 22 | 23 | // Start app with ClockCustomizer widget 24 | runApp( 25 | ClockCustomizer((ClockModel model) => Scene(model, images, spriteSheet))); 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Michael Wilson, Nishant Grover, Oscar Serna 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /city_clock/lib/environment/scene.dart: -------------------------------------------------------------------------------- 1 | import 'package:city_clock/clock/clock.dart'; 2 | import 'package:city_clock/environment/scene_layers.dart'; 3 | import 'package:city_clock/environment/weather.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_clock_helper/model.dart'; 6 | import 'package:spritewidget/spritewidget.dart'; 7 | 8 | class Scene extends StatelessWidget { 9 | final ClockModel model; 10 | final ImageMap images; 11 | final SpriteSheet spriteSheet; 12 | Scene(this.model, this.images, this.spriteSheet); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | List sceneWidgets = new List(); 17 | sceneWidgets.add(loadSky()); 18 | //Add clouds 19 | if (model.weatherString == 'cloudy' || 20 | model.weatherString == 'foggy' || 21 | model.weatherString == 'rainy' || 22 | model.weatherString == 'thunderstorm' || 23 | model.weatherString == 'snowy') { 24 | sceneWidgets.add(SpriteWidget(CloudyWeather(images))); 25 | } 26 | sceneWidgets.add(loadCityBack()); 27 | sceneWidgets.add(loadCityFront()); 28 | //Add rain 29 | if (model.weatherString == 'rainy' || 30 | model.weatherString == 'thunderstorm') { 31 | sceneWidgets.add(SpriteWidget(RainyWeather(spriteSheet))); 32 | } 33 | sceneWidgets.add(loadStreet()); 34 | sceneWidgets.add(loadSign()); 35 | sceneWidgets.add(Clock(model, images)); 36 | return Stack(children: sceneWidgets, fit: StackFit.expand); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /city_clock/lib/clock/clock.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:city_clock/clock/clock_text.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:spritewidget/spritewidget.dart'; 5 | import 'package:flutter_clock_helper/model.dart'; 6 | 7 | class Clock extends StatefulWidget { 8 | Clock(this.model, this.images); 9 | 10 | final ClockModel model; 11 | final ImageMap images; 12 | 13 | @override 14 | _ClockState createState() => _ClockState(); 15 | } 16 | 17 | class _ClockState extends State { 18 | DateTime _dateTime = DateTime.now(); 19 | Timer _timer; 20 | 21 | @override 22 | void initState() { 23 | super.initState(); 24 | widget.model.addListener(_updateModel); 25 | _updateTime(); 26 | _updateModel(); 27 | } 28 | 29 | @override 30 | void dispose() { 31 | _timer?.cancel(); 32 | widget.model.removeListener(_updateModel); 33 | widget.model.dispose(); 34 | super.dispose(); 35 | } 36 | 37 | void _updateModel() { 38 | setState(() {}); 39 | } 40 | 41 | void _updateTime() { 42 | setState(() { 43 | this._dateTime = DateTime.now(); 44 | this._timer = Timer( 45 | // Duration(minutes: 1) - 46 | Duration(milliseconds: 500) - 47 | Duration(milliseconds: _dateTime.millisecond), 48 | _updateTime, 49 | ); 50 | }); 51 | } 52 | 53 | @override 54 | Widget build(BuildContext context) { 55 | return Container( 56 | child: Stack(fit: StackFit.expand, children: [ 57 | ClockText(widget.model, _dateTime), 58 | ]), 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /city_clock/assets/cfg/app_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "spriteSheet": "assets/sprites/spritesheet.png", 3 | "spriteSheetJson": "assets/sprites/spritesheet.json", 4 | "cloud0": "assets/images/clouds-0.png", 5 | "cloud1": "assets/images/clouds-1.png", 6 | 7 | "cityBackNight": "assets/images/city_back/city_back_night.png", 8 | "cityFrontNight": "assets/images/city_front/city_front_night.png", 9 | "streetNight": "assets/images/streets/street_night.png", 10 | "skyNight": "assets/images/skies/sky_night.png", 11 | "signNight": "assets/images/signs/sign_night.png", 12 | 13 | "colon": "assets/digits/colon.png", 14 | "hour1-0": "assets/digits/hour1-0.png", 15 | "hour1-1": "assets/digits/hour1-1.png", 16 | "hour1-2": "assets/digits/hour1-2.png", 17 | "hour2-0": "assets/digits/hour2-0.png", 18 | "hour2-1": "assets/digits/hour2-1.png", 19 | "hour2-2": "assets/digits/hour2-2.png", 20 | "hour2-3": "assets/digits/hour2-3.png", 21 | "hour2-4": "assets/digits/hour2-4.png", 22 | "hour2-5": "assets/digits/hour2-5.png", 23 | "hour2-6": "assets/digits/hour2-6.png", 24 | "hour2-7": "assets/digits/hour2-7.png", 25 | "hour2-8": "assets/digits/hour2-8.png", 26 | "hour2-9": "assets/digits/hour2-9.png", 27 | "minute1-0": "assets/digits/minute1-0.png", 28 | "minute1-1": "assets/digits/minute1-1.png", 29 | "minute1-2": "assets/digits/minute1-2.png", 30 | "minute1-3": "assets/digits/minute1-3.png", 31 | "minute1-4": "assets/digits/minute1-4.png", 32 | "minute1-5": "assets/digits/minute1-5.png", 33 | "minute1-6": "assets/digits/minute1-6.png", 34 | "minute2-0": "assets/digits/minute2-0.png", 35 | "minute2-1": "assets/digits/minute2-1.png", 36 | "minute2-2": "assets/digits/minute2-2.png", 37 | "minute2-3": "assets/digits/minute2-3.png", 38 | "minute2-4": "assets/digits/minute2-4.png", 39 | "minute2-5": "assets/digits/minute2-5.png", 40 | "minute2-6": "assets/digits/minute2-6.png", 41 | "minute2-7": "assets/digits/minute2-7.png", 42 | "minute2-8": "assets/digits/minute2-8.png", 43 | "minute2-9": "assets/digits/minute2-9.png" 44 | } -------------------------------------------------------------------------------- /city_clock/lib/clock/clock_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_clock_helper/model.dart'; 3 | import 'package:intl/intl.dart'; 4 | import 'package:global_configuration/global_configuration.dart'; 5 | 6 | class ClockText extends StatelessWidget { 7 | final ClockModel model; 8 | final DateTime dateTime; 9 | final fontStyle = TextStyle( 10 | fontFamily: 'Pixel_Text', 11 | fontSize: 20, 12 | fontWeight: FontWeight.bold, 13 | color: Color.fromARGB(255, 14, 62, 110), 14 | ); 15 | final _hour1, _hour2, _minute1, _minute2; 16 | ClockText(this.model, this.dateTime) 17 | : _hour1 = 18 | DateFormat(model.is24HourFormat ? 'HH' : 'hh').format(dateTime)[0], 19 | _hour2 = 20 | DateFormat(model.is24HourFormat ? 'HH' : 'hh').format(dateTime)[1], 21 | _minute1 = DateFormat('mm').format(dateTime)[0], 22 | _minute2 = DateFormat('mm').format(dateTime)[1]; 23 | 24 | Widget loadTimeImages() { 25 | Image image; 26 | List timeList = new List(); 27 | //Fetch and add Hour1 image 28 | image = Image( 29 | image: AssetImage(GlobalConfiguration().getString("hour1-$_hour1")), 30 | fit: BoxFit.fitWidth, 31 | ); 32 | timeList.add(image); 33 | 34 | //Fetch and add Hour2 image 35 | image = Image( 36 | image: AssetImage(GlobalConfiguration().getString('hour2-$_hour2')), 37 | fit: BoxFit.fitWidth, 38 | ); 39 | timeList.add(image); 40 | 41 | //Fetch and add ":" image 42 | image = Image( 43 | image: AssetImage(GlobalConfiguration().getString('colon')), 44 | fit: BoxFit.fitWidth, 45 | ); 46 | timeList.add(image); 47 | 48 | //Fetch and add Minute1 image 49 | image = Image( 50 | image: AssetImage(GlobalConfiguration().getString('minute1-$_minute1')), 51 | fit: BoxFit.fitWidth, 52 | ); 53 | timeList.add(image); 54 | 55 | //Fetch and add Minute2 image 56 | image = Image( 57 | image: AssetImage(GlobalConfiguration().getString('minute2-$_minute2')), 58 | fit: BoxFit.fitWidth, 59 | ); 60 | timeList.add(image); 61 | 62 | return Stack(children: timeList, fit: StackFit.expand); 63 | } 64 | 65 | @override 66 | Widget build(BuildContext context) { 67 | return loadTimeImages(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /city_clock/assets/fonts/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright 2012 The Press Start 2P Project Authors (cody@zone38.net), with Reserved Font Name "Press Start 2P". 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 | -------------------------------------------------------------------------------- /city_clock/lib/environment/weather.dart: -------------------------------------------------------------------------------- 1 | // For the different weathers we are displaying different gradient backgrounds, 2 | // these are the colors for top and bottom. 3 | import 'dart:ui' as ui; 4 | 5 | import 'package:flutter/material.dart'; 6 | import 'package:spritewidget/spritewidget.dart'; 7 | 8 | class CloudyWeather extends NodeWithSize { 9 | CloudyWeather(this.images) : super(const Size(800, 480)) { 10 | _cloudsSharp = new CloudLayer( 11 | image: images['assets/images/clouds-0.png'], 12 | rotated: false, 13 | dark: false, 14 | loopTime: 50.0); 15 | addChild(_cloudsSharp); 16 | 17 | _cloudsDark = new CloudLayer( 18 | image: images['assets/images/clouds-1.png'], 19 | rotated: true, 20 | dark: true, 21 | loopTime: 75.0); 22 | addChild(_cloudsDark); 23 | 24 | _cloudsSoft = new CloudLayer( 25 | image: images['assets/images/clouds-1.png'], 26 | rotated: false, 27 | dark: false, 28 | loopTime: 100.0); 29 | addChild(_cloudsSoft); 30 | } 31 | 32 | ImageMap images; 33 | CloudLayer _cloudsSharp; 34 | CloudLayer _cloudsSoft; 35 | CloudLayer _cloudsDark; 36 | } 37 | 38 | class RainyWeather extends NodeWithSize { 39 | RainyWeather(this.spriteSheet) : super(const Size(800, 480)) { 40 | _rain = new Rain(spriteSheet['rain_drop.png']); 41 | _rain.active = true; 42 | addChild(_rain); 43 | } 44 | SpriteSheet spriteSheet; 45 | Rain _rain; 46 | } 47 | 48 | // Draws and animates a cloud layer using two sprites. 49 | class CloudLayer extends Node { 50 | CloudLayer({ui.Image image, bool dark, bool rotated, double loopTime}) { 51 | // Creates and positions the two cloud sprites. 52 | _sprites.add(_createSprite(image, dark, rotated)); 53 | _sprites[0].position = const Offset(1024.0, 1024.0); 54 | _sprites[0].opacity = 1.0; 55 | addChild(_sprites[0]); 56 | 57 | _sprites.add(_createSprite(image, dark, rotated)); 58 | _sprites[1].position = const Offset(3072.0, 1024.0); 59 | addChild(_sprites[1]); 60 | 61 | // Animates the clouds across the screen. 62 | motions.run(new MotionRepeatForever(new MotionTween( 63 | (a) => position = a, 64 | Offset.zero, 65 | const Offset(-2048.0, 0.0), 66 | loopTime))); 67 | } 68 | 69 | List _sprites = []; 70 | 71 | Sprite _createSprite(ui.Image image, bool dark, bool rotated) { 72 | Sprite sprite = new Sprite.fromImage(image); 73 | 74 | if (rotated) sprite.scaleX = -1.0; 75 | 76 | if (dark) { 77 | sprite.colorOverlay = const Color(0xff000000); 78 | sprite.opacity = 0.0; 79 | } 80 | 81 | return sprite; 82 | } 83 | 84 | set active(bool active) { 85 | // Toggle visibility of the cloud layer 86 | double opacity; 87 | if (active) 88 | opacity = 1.0; 89 | else 90 | opacity = 0.0; 91 | 92 | for (Sprite sprite in _sprites) { 93 | sprite.motions.stopAll(); 94 | sprite.motions.run(new MotionTween( 95 | (a) => sprite.opacity = a, sprite.opacity, opacity, 1.0)); 96 | } 97 | } 98 | } 99 | 100 | // Rain layer. Uses three layers of particle systems, to create a parallax 101 | // rain effect. 102 | class Rain extends Node { 103 | Rain(this.spriteTexture) { 104 | _addParticles(4.0); 105 | _addParticles(4.5); 106 | _addParticles(5.0); 107 | _addParticles(5.5); 108 | } 109 | 110 | SpriteTexture spriteTexture; 111 | 112 | List _particles = []; 113 | 114 | void _addParticles(double distance) { 115 | ParticleSystem particles = new ParticleSystem(spriteTexture, 116 | transferMode: BlendMode.srcATop, 117 | posVar: const Offset(1300.0, 0.0), 118 | direction: 85.0, 119 | directionVar: 0.0, 120 | speed: 1000.0 / distance, 121 | speedVar: 100.0 / distance, 122 | startSize: 0.6 / distance, 123 | startSizeVar: 0.2 / distance, 124 | endSize: 1.2 / distance, 125 | endSizeVar: 0.2 / distance, 126 | life: 1.0 * distance, 127 | lifeVar: 1.0 * distance); 128 | particles.position = const Offset(1024.0, -200.0); 129 | particles.rotation = 10.0; 130 | particles.opacity = 0.0; 131 | 132 | _particles.add(particles); 133 | addChild(particles); 134 | } 135 | 136 | set active(bool active) { 137 | motions.stopAll(); 138 | for (ParticleSystem system in _particles) { 139 | if (active) { 140 | motions.run(new MotionTween( 141 | (a) => system.opacity = a, system.opacity, 1.0, 2.0)); 142 | } else { 143 | motions.run(new MotionTween( 144 | (a) => system.opacity = a, system.opacity, 0.0, 0.5)); 145 | } 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /city_clock/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: city_clock 2 | description: A new Flutter project. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 1.0.0+1 15 | 16 | environment: 17 | sdk: ">=2.1.0 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 22 | 23 | spritewidget: 24 | 25 | marquee: ^1.3.1 26 | 27 | flutter_clock_helper: 28 | path: ../flutter_clock_helper 29 | 30 | # The following adds the Cupertino Icons font to your application. 31 | # Use with the CupertinoIcons class for iOS style icons. 32 | cupertino_icons: ^0.1.2 33 | 34 | global_configuration: ^1.4.0 35 | 36 | dev_dependencies: 37 | flutter_test: 38 | sdk: flutter 39 | 40 | 41 | # For information on the generic Dart part of this file, see the 42 | # following page: https://dart.dev/tools/pub/pubspec 43 | 44 | # The following section is specific to Flutter. 45 | flutter: 46 | 47 | # The following line ensures that the Material Icons font is 48 | # included with your application, so that you can use the icons in 49 | # the material Icons class. 50 | uses-material-design: true 51 | 52 | # To add assets to your application, add an assets section, like this: 53 | # assets: 54 | # - images/a_dot_burr.jpeg 55 | # - images/a_dot_ham.jpeg 56 | assets: 57 | # Config 58 | - assets/cfg/ 59 | # Sprites 60 | - assets/sprites/spritesheet.png 61 | - assets/sprites/spritesheet.json 62 | # Images 63 | - assets/clouds-0.png 64 | - assets/clouds-1.png 65 | # Load city backdrops 66 | - assets/images/city_back/city_back_night.png 67 | # Load city foregrounds 68 | - assets/images/city_front/city_front_night.png 69 | # Load streets 70 | - assets/images/streets/street_night.png 71 | # Load skies 72 | - assets/images/skies/sky_night.png 73 | # Load signs 74 | - assets/images/signs/sign_night.png 75 | # Time Digits 76 | - assets/digits/colon.png 77 | - assets/digits/hour1-0.png 78 | - assets/digits/hour1-1.png 79 | - assets/digits/hour1-2.png 80 | - assets/digits/hour2-0.png 81 | - assets/digits/hour2-1.png 82 | - assets/digits/hour2-2.png 83 | - assets/digits/hour2-3.png 84 | - assets/digits/hour2-4.png 85 | - assets/digits/hour2-5.png 86 | - assets/digits/hour2-6.png 87 | - assets/digits/hour2-7.png 88 | - assets/digits/hour2-8.png 89 | - assets/digits/hour2-9.png 90 | - assets/digits/minute1-0.png 91 | - assets/digits/minute1-1.png 92 | - assets/digits/minute1-2.png 93 | - assets/digits/minute1-3.png 94 | - assets/digits/minute1-4.png 95 | - assets/digits/minute1-5.png 96 | - assets/digits/minute1-6.png 97 | - assets/digits/minute2-0.png 98 | - assets/digits/minute2-1.png 99 | - assets/digits/minute2-2.png 100 | - assets/digits/minute2-3.png 101 | - assets/digits/minute2-4.png 102 | - assets/digits/minute2-5.png 103 | - assets/digits/minute2-6.png 104 | - assets/digits/minute2-7.png 105 | - assets/digits/minute2-8.png 106 | - assets/digits/minute2-9.png 107 | 108 | # An image asset can refer to one or more resolution-specific variants, see 109 | # https://flutter.dev/assets-and-images/#resolution-aware. 110 | 111 | # For details regarding adding assets from package dependencies, see 112 | # https://flutter.dev/assets-and-images/#from-packages 113 | 114 | # To add custom fonts to your application, add a fonts section here, 115 | # in this "flutter" section. Each entry in this list should have a 116 | # "family" key with the font family name, and a "fonts" key with a 117 | # list giving the asset and other descriptors for the font. For 118 | # example: 119 | # fonts: 120 | # - family: Schyler 121 | # fonts: 122 | # - asset: fonts/Schyler-Regular.ttf 123 | # - asset: fonts/Schyler-Italic.ttf 124 | # style: italic 125 | # - family: Trajan Pro 126 | # fonts: 127 | # - asset: fonts/TrajanPro.ttf 128 | # - asset: fonts/TrajanPro_Bold.ttf 129 | # weight: 700 130 | # 131 | fonts: 132 | - family: Pixel_Text 133 | fonts: 134 | - asset: assets/fonts/PressStart2P-Regular.ttf 135 | # For details regarding fonts from package dependencies, 136 | # see https://flutter.dev/custom-fonts/#from-packages 137 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /city_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 | flutter: 68 | dependency: "direct main" 69 | description: flutter 70 | source: sdk 71 | version: "0.0.0" 72 | flutter_clock_helper: 73 | dependency: "direct main" 74 | description: 75 | path: "..\\flutter_clock_helper" 76 | relative: true 77 | source: path 78 | version: "1.0.0+1" 79 | flutter_test: 80 | dependency: "direct dev" 81 | description: flutter 82 | source: sdk 83 | version: "0.0.0" 84 | global_configuration: 85 | dependency: "direct main" 86 | description: 87 | name: global_configuration 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "1.4.0" 91 | http: 92 | dependency: transitive 93 | description: 94 | name: http 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "0.12.0+4" 98 | http_parser: 99 | dependency: transitive 100 | description: 101 | name: http_parser 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "3.1.3" 105 | image: 106 | dependency: transitive 107 | description: 108 | name: image 109 | url: "https://pub.dartlang.org" 110 | source: hosted 111 | version: "2.1.4" 112 | intl: 113 | dependency: transitive 114 | description: 115 | name: intl 116 | url: "https://pub.dartlang.org" 117 | source: hosted 118 | version: "0.16.1" 119 | marquee: 120 | dependency: "direct main" 121 | description: 122 | name: marquee 123 | url: "https://pub.dartlang.org" 124 | source: hosted 125 | version: "1.3.1" 126 | matcher: 127 | dependency: transitive 128 | description: 129 | name: matcher 130 | url: "https://pub.dartlang.org" 131 | source: hosted 132 | version: "0.12.6" 133 | meta: 134 | dependency: transitive 135 | description: 136 | name: meta 137 | url: "https://pub.dartlang.org" 138 | source: hosted 139 | version: "1.1.8" 140 | path: 141 | dependency: transitive 142 | description: 143 | name: path 144 | url: "https://pub.dartlang.org" 145 | source: hosted 146 | version: "1.6.4" 147 | pedantic: 148 | dependency: transitive 149 | description: 150 | name: pedantic 151 | url: "https://pub.dartlang.org" 152 | source: hosted 153 | version: "1.8.0+1" 154 | petitparser: 155 | dependency: transitive 156 | description: 157 | name: petitparser 158 | url: "https://pub.dartlang.org" 159 | source: hosted 160 | version: "2.4.0" 161 | quiver: 162 | dependency: transitive 163 | description: 164 | name: quiver 165 | url: "https://pub.dartlang.org" 166 | source: hosted 167 | version: "2.0.5" 168 | sky_engine: 169 | dependency: transitive 170 | description: flutter 171 | source: sdk 172 | version: "0.0.99" 173 | source_span: 174 | dependency: transitive 175 | description: 176 | name: source_span 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "1.5.5" 180 | spritewidget: 181 | dependency: "direct main" 182 | description: 183 | name: spritewidget 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "0.9.23" 187 | stack_trace: 188 | dependency: transitive 189 | description: 190 | name: stack_trace 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "1.9.3" 194 | stream_channel: 195 | dependency: transitive 196 | description: 197 | name: stream_channel 198 | url: "https://pub.dartlang.org" 199 | source: hosted 200 | version: "2.0.0" 201 | string_scanner: 202 | dependency: transitive 203 | description: 204 | name: string_scanner 205 | url: "https://pub.dartlang.org" 206 | source: hosted 207 | version: "1.0.5" 208 | term_glyph: 209 | dependency: transitive 210 | description: 211 | name: term_glyph 212 | url: "https://pub.dartlang.org" 213 | source: hosted 214 | version: "1.1.0" 215 | test_api: 216 | dependency: transitive 217 | description: 218 | name: test_api 219 | url: "https://pub.dartlang.org" 220 | source: hosted 221 | version: "0.2.11" 222 | typed_data: 223 | dependency: transitive 224 | description: 225 | name: typed_data 226 | url: "https://pub.dartlang.org" 227 | source: hosted 228 | version: "1.1.6" 229 | vector_math: 230 | dependency: transitive 231 | description: 232 | name: vector_math 233 | url: "https://pub.dartlang.org" 234 | source: hosted 235 | version: "2.0.8" 236 | xml: 237 | dependency: transitive 238 | description: 239 | name: xml 240 | url: "https://pub.dartlang.org" 241 | source: hosted 242 | version: "3.5.0" 243 | sdks: 244 | dart: ">=2.5.0 <3.0.0" 245 | flutter: ">=1.6.3 <2.0.0" 246 | -------------------------------------------------------------------------------- /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 | child: widget._clock(_model), 181 | ), 182 | ), 183 | ); 184 | 185 | return MaterialApp( 186 | theme: ThemeData.light(), 187 | darkTheme: ThemeData.dark(), 188 | themeMode: _themeMode, 189 | debugShowCheckedModeBanner: false, 190 | home: Scaffold( 191 | resizeToAvoidBottomPadding: false, 192 | endDrawer: _configDrawer(context), 193 | body: Container( 194 | child: GestureDetector( 195 | behavior: HitTestBehavior.opaque, 196 | onTap: () { 197 | setState(() { 198 | _configButtonShown = !_configButtonShown; 199 | }); 200 | }, 201 | child: Stack( 202 | children: [ 203 | clock, 204 | if (_configButtonShown) 205 | Positioned( 206 | top: 0, 207 | right: 0, 208 | child: Opacity( 209 | opacity: 0.7, 210 | child: _configButton(), 211 | ), 212 | ), 213 | ], 214 | ), 215 | ), 216 | ), 217 | ), 218 | ); 219 | } 220 | } 221 | --------------------------------------------------------------------------------