From ce225a9b897c9c446f30eab2488cf2ae229adf23 Mon Sep 17 00:00:00 2001 From: Vladimir Minkin Date: Fri, 19 Jun 2020 19:17:07 +0200 Subject: [PATCH 1/3] [Work In Progress] Initial Commit using Wire and MVC working example --- wire/.gitignore | 73 +++ wire/.metadata | 10 + wire/README.md | 197 +++++++ wire/android/.gitignore | 7 + wire/android/app/build.gradle | 67 +++ .../android/app/src/debug/AndroidManifest.xml | 7 + wire/android/app/src/main/AndroidManifest.xml | 30 + .../com/example/vanilla/MainActivity.kt | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1345 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 927 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 1908 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 2950 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 4067 bytes .../app/src/main/res/values/styles.xml | 8 + .../app/src/profile/AndroidManifest.xml | 7 + wire/android/build.gradle | 31 ++ wire/android/gradle.properties | 4 + .../gradle/wrapper/gradle-wrapper.properties | 6 + wire/android/settings.gradle | 15 + wire/ios/.gitignore | 32 ++ wire/ios/Flutter/AppFrameworkInfo.plist | 26 + wire/ios/Flutter/Debug.xcconfig | 2 + wire/ios/Flutter/Release.xcconfig | 2 + wire/ios/Podfile | 90 +++ wire/ios/Runner.xcodeproj/project.pbxproj | 518 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Runner.xcscheme | 91 +++ .../contents.xcworkspacedata | 7 + wire/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 116 ++++ .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 715 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1591 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 2506 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1068 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 2414 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 3810 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1582 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 3462 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 5543 bytes .../AppIcon.appiconset/Icon-App-60x60@1x.png | Bin 0 -> 2798 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 5868 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 9605 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 3390 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 7082 bytes .../AppIcon.appiconset/Icon-App-76x76@3x.png | Bin 0 -> 10960 bytes .../Icon-App-83.5x83.5@1x.png | Bin 0 -> 3834 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 8074 bytes .../Icon-App-83.5x83.5@3x.png | Bin 0 -> 12001 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 ++ wire/ios/Runner/Base.lproj/Main.storyboard | 26 + wire/ios/Runner/Info.plist | 45 ++ wire/ios/Runner/Runner-Bridging-Header.h | 1 + wire/lib/app.dart | 27 + wire/lib/const/TodoApplicationState.dart | 4 + wire/lib/const/TodoDataParams.dart | 9 + wire/lib/const/TodoFilterValues.dart | 5 + wire/lib/const/TodoViewSignal.dart | 14 + wire/lib/controller/RouteController.dart | 25 + wire/lib/controller/TodoController.dart | 85 +++ wire/lib/data/dto/CreateDTO.dart | 6 + wire/lib/data/dto/EditDTO.dart | 7 + wire/lib/data/vo/TodoVO.dart | 27 + wire/lib/localization.dart | 30 + wire/lib/main.dart | 34 ++ wire/lib/main_web.dart | 34 ++ wire/lib/model/TodoModel.dart | 159 ++++++ wire/lib/models.dart | 54 ++ wire/lib/screens/add_edit_screen.dart | 106 ++++ wire/lib/screens/detail_screen.dart | 89 +++ wire/lib/screens/home_screen.dart | 100 ++++ wire/lib/service/IDatabaseService.dart | 6 + wire/lib/service/MobileDatabaseService.dart | 48 ++ wire/lib/service/WebDatabaseService.dart | 24 + .../widgets/buttons/extra_actions_button.dart | 42 ++ wire/lib/widgets/buttons/filter_button.dart | 94 ++++ wire/lib/widgets/list/todo_item_widget.dart | 56 ++ wire/lib/widgets/list/todo_list_widget.dart | 94 ++++ wire/lib/widgets/stats_counter.dart | 60 ++ wire/pubspec.yaml | 82 +++ wire/test/app_state_test.dart | 110 ++++ wire/test_driver/todo_app.dart | 13 + wire/test_driver/todo_app_test.dart | 9 + wire/web/favicon.png | Bin 0 -> 917 bytes wire/web/icons/Icon-192.png | Bin 0 -> 5292 bytes wire/web/icons/Icon-512.png | Bin 0 -> 8252 bytes wire/web/index.html | 10 + wire/web/manifest.json | 23 + 93 files changed, 3013 insertions(+) create mode 100644 wire/.gitignore create mode 100644 wire/.metadata create mode 100644 wire/README.md create mode 100644 wire/android/.gitignore create mode 100644 wire/android/app/build.gradle create mode 100644 wire/android/app/src/debug/AndroidManifest.xml create mode 100644 wire/android/app/src/main/AndroidManifest.xml create mode 100644 wire/android/app/src/main/kotlin/com/example/vanilla/MainActivity.kt create mode 100644 wire/android/app/src/main/res/drawable/launch_background.xml create mode 100644 wire/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 wire/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 wire/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 wire/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 wire/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 wire/android/app/src/main/res/values/styles.xml create mode 100644 wire/android/app/src/profile/AndroidManifest.xml create mode 100644 wire/android/build.gradle create mode 100644 wire/android/gradle.properties create mode 100644 wire/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 wire/android/settings.gradle create mode 100644 wire/ios/.gitignore create mode 100644 wire/ios/Flutter/AppFrameworkInfo.plist create mode 100644 wire/ios/Flutter/Debug.xcconfig create mode 100644 wire/ios/Flutter/Release.xcconfig create mode 100644 wire/ios/Podfile create mode 100644 wire/ios/Runner.xcodeproj/project.pbxproj create mode 100644 wire/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 wire/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 wire/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 wire/ios/Runner/AppDelegate.swift create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@1x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@3x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@1x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@3x.png create mode 100644 wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 wire/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 wire/ios/Runner/Base.lproj/Main.storyboard create mode 100644 wire/ios/Runner/Info.plist create mode 100644 wire/ios/Runner/Runner-Bridging-Header.h create mode 100644 wire/lib/app.dart create mode 100644 wire/lib/const/TodoApplicationState.dart create mode 100644 wire/lib/const/TodoDataParams.dart create mode 100644 wire/lib/const/TodoFilterValues.dart create mode 100644 wire/lib/const/TodoViewSignal.dart create mode 100644 wire/lib/controller/RouteController.dart create mode 100644 wire/lib/controller/TodoController.dart create mode 100644 wire/lib/data/dto/CreateDTO.dart create mode 100644 wire/lib/data/dto/EditDTO.dart create mode 100644 wire/lib/data/vo/TodoVO.dart create mode 100644 wire/lib/localization.dart create mode 100644 wire/lib/main.dart create mode 100644 wire/lib/main_web.dart create mode 100644 wire/lib/model/TodoModel.dart create mode 100644 wire/lib/models.dart create mode 100644 wire/lib/screens/add_edit_screen.dart create mode 100644 wire/lib/screens/detail_screen.dart create mode 100644 wire/lib/screens/home_screen.dart create mode 100644 wire/lib/service/IDatabaseService.dart create mode 100644 wire/lib/service/MobileDatabaseService.dart create mode 100644 wire/lib/service/WebDatabaseService.dart create mode 100644 wire/lib/widgets/buttons/extra_actions_button.dart create mode 100644 wire/lib/widgets/buttons/filter_button.dart create mode 100644 wire/lib/widgets/list/todo_item_widget.dart create mode 100644 wire/lib/widgets/list/todo_list_widget.dart create mode 100644 wire/lib/widgets/stats_counter.dart create mode 100644 wire/pubspec.yaml create mode 100644 wire/test/app_state_test.dart create mode 100644 wire/test_driver/todo_app.dart create mode 100644 wire/test_driver/todo_app_test.dart create mode 100644 wire/web/favicon.png create mode 100644 wire/web/icons/Icon-192.png create mode 100644 wire/web/icons/Icon-512.png create mode 100644 wire/web/index.html create mode 100644 wire/web/manifest.json diff --git a/wire/.gitignore b/wire/.gitignore new file mode 100644 index 00000000..2ddde2a5 --- /dev/null +++ b/wire/.gitignore @@ -0,0 +1,73 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +/build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/wire/.metadata b/wire/.metadata new file mode 100644 index 00000000..1b5cec02 --- /dev/null +++ b/wire/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 27321ebbad34b0a3fafe99fac037102196d655ff + channel: stable + +project_type: app diff --git a/wire/README.md b/wire/README.md new file mode 100644 index 00000000..e561deae --- /dev/null +++ b/wire/README.md @@ -0,0 +1,197 @@ +# wire_flutter_todo example + +The wire_flutter_todo example uses only the core Widgets and Classes that Flutter provides out of the box to manage state. The most important of these: the `StatefulWidget`. + +## Key Concepts + + * Share State by Lifting State Up - If two Widgets need access to the same state (aka data), "lift" the state up to a parent `StatefulWidget` that passes the state down to each child Widget that needs it. + * Updating State with callbacks - To update state, pass a callback function from the Parent `StatefulWidget` to the child widgets. + * Local persistence - The list of todos is serialized to JSON and stored as a file on disk whenever the State is updated. + * Testing - Pull Business logic out of Widgets into Plain Old Dart Object (PODOs). + +## Share State by Lifting State Up + +Let's start with a Simple Example. Say our app had only 1 Tab: The `List of Todos Tab`. + + ``` ++------------+ +| | +| List | +| of | +| Todos | +| Tab | +| | ++------------+ +``` + +Now, we add a sibling Widget: The `Stats Tab`! But wait, it needs access to the List of Todos so it can calculate how many of them are active and how many are complete. So how do we share that data? + +It can be difficult for siblings to pass their state to each other. For example, say both Widgets were displayed side-by-side at the same time: How would Flutter know when to re-build the `Stats Tab` to reflect the latest count when the List of Todos changes? + +``` ++-------------+ +-------------+ +| | | | +| | Gimme dem Todos | | +| List of | <-------------- + Stats | +| Todos | | Tab | +| Tab | No. Mine. | | +| + --------------> | | +| | | | ++-------------+ +-------------+ +``` + +So how do we share state between these two sibling Widgets? Let's Lift the state up to a Parent Widget and pass it down to each child that needs it! + +``` + +-------------------------+ + | Keeper of the Todos | + | (StatefulWidget) | + +-----+--------------+----+ + | | ++----------|--+ +---|---------+ +| v | | v | +| List of | | Stats | +| Todos | | Tab | +| | | | ++-------------+ +-------------+ +``` + +Now, when we change the List of Todos in the `Keeper of the Todos` widget, both children will reflect the updated State! This concept scales to an entire app. Any time you need to share State between Widgets or Routes, lift it up to a common parent Widget. Here's a diagram of what our app state actually looks like! + +``` + +------------------------------------------+ + | | + | VanillaApp (StatefulWidget) | + | | + | Manages List and "isLoading" | + | | + +---------+---------------------------+----+ + | | ++------------|---------------+ +--------|--------+ +| v | | v | +| Main Tabs Screen | | Add Todo Screen | +| (Stateful) | | (Stateless) | +| | | | +| Manages current tab and | | | +| Visibility filter | | | +| | | | +| +----------+ +----------+ | | | +| | | | | | | | +| | List | | | | | | +| | of | | Stats | | | | +| | Todos | | Tab | | | | +| | Tab | | | | | | +| +----+-----+ +----------+ | | | +| | | | | ++------|---------------------+ +-----------------+ + | ++------|---------+ +| v | +| | +| Todo Details | +| Screen | +| | ++------+---------+ + | ++------|---------+ +| v | +| | +| Edit Todo | +| Screen | +| | ++----------------+ +``` + +Careful Observers might note: We don't lift *all* state up to the parent in this pattern. Only the State that's shared! The Main Tabs Screen can handle which tab is currently active on its own, for example, because this state isn't relevant to other Widgets! + +## Updating State with callbacks + +Ok, so now we have an idea of how to pass data down from parent to child, but how do we update the list of Todos from these different screens / Routes / Widgets? + +We'll also **pass callback functions** from the parent to the children as well. These callback functions are responsible for updating the State at the Parent Widget and calling `setState` so Flutter knows it needs to rebuild! + +In this app, we have a few callbacks we will pass down: + + 1. AddTodo callback + 2. RemoveTodo Callback + 3. UpdateTodo Callback + 4. MarkAllComplete callback + 5. ClearComplete callback + +In this app, we pass the `AddTodo` callback from our `VanillaApp` Widget to the `Add Todo Screen`. Now all our `Add Todo Screen` needs to do is call the `AddTodo` callback with a new `Todo` when a user finishes filling in the form. This will send the `Todo` up to the `VanillaApp` so it can handle how it adds the new todo to the list! + +This demonstrates a core concept of State management in Flutter: Pass data and callback functions down from a parent to a child, and use invoke those callbacks in the Child to send data back up to the parent. + +To make this concrete, Let's see how our callbacks flow in the this app. + +``` + +----------------------------------------------------+ + | | + | VanillaApp (StatefulWidget) | + | | + | Manages List and "isLoading" | + | ^ | + +---------+----------------------+------------|------+ + | | | + | UpdateTodo | AddTodo | Invoke AddTodo + | RemoveTodo | | Callback, sending + | MarkAllComplete | | Data up to the + | ClearComplete | | parent. + | | | ++------------|---------------+ +---|------------+-+ +| v | | v | +| Main Tabs Screen | | Add Todo Screen | +| (Stateful) | | (Stateless) | +| | | | +| Manages current tab and | | | +| Visibility filter | | | +| | | | +| +----------+ +----------+ | | | +| | | | | | | | +| | List | | | | | | +| | of | | Stats | | | | +| | Todos | | Tab | | | | +| | Tab | | | | | | +| +----+-----+ +----------+ | | | +| | | | | ++------|---------------------+ +------------------+ + | + | UpdateTodo + | RemoveTodo + | ++------|---------+ +| v | +| | +| Todo Details | +| Screen | +| | ++------+---------+ + | + | UpdateTodo + | ++------|---------+ +| v | +| | +| Edit Todo | +| Screen | +| | ++----------------+ +``` + +## Testing + +There are a few Strategies for testing: + + 1. Store state and the state mutations (methods) within a `StatefulWidget` + 2. Extract this State and logic out into a "Plain Old Dart Objects" (PODOs) and test those. The `StatefulWidget` can then delegate to this object. + +So which should you choose? For View-related State: Option #1. For App State / Business Logic: Option #2. + +While Option #1 works because Flutter provides a nice set of Widget testing utilities out of the box, Option #2 will generally prove easier to test because it has no Flutter dependencies and does not require you to test against a Widget tree, but simply against an Object. + +## Addendum + +Since Flutter is quite similar to React with regards to State management, many of the resources on the React site are pertinent when thinking about State in flutter. In fact, the ideas in this example were lifted directly from the React site: + + * [Lifting State Up in React](https://reactjs.org/docs/lifting-state-up.html) + * [Thinking in React](https://reactjs.org/docs/thinking-in-react.html) diff --git a/wire/android/.gitignore b/wire/android/.gitignore new file mode 100644 index 00000000..bc2100d8 --- /dev/null +++ b/wire/android/.gitignore @@ -0,0 +1,7 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java diff --git a/wire/android/app/build.gradle b/wire/android/app/build.gradle new file mode 100644 index 00000000..80a76d63 --- /dev/null +++ b/wire/android/app/build.gradle @@ -0,0 +1,67 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 28 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.wire_flutter_todo" + minSdkVersion 16 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' +} diff --git a/wire/android/app/src/debug/AndroidManifest.xml b/wire/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..b38a056a --- /dev/null +++ b/wire/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/wire/android/app/src/main/AndroidManifest.xml b/wire/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..f8468cd9 --- /dev/null +++ b/wire/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + diff --git a/wire/android/app/src/main/kotlin/com/example/vanilla/MainActivity.kt b/wire/android/app/src/main/kotlin/com/example/vanilla/MainActivity.kt new file mode 100644 index 00000000..a2fe75d6 --- /dev/null +++ b/wire/android/app/src/main/kotlin/com/example/vanilla/MainActivity.kt @@ -0,0 +1,12 @@ +package com.example.wire_flutter_todo + +import androidx.annotation.NonNull; +import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.plugins.GeneratedPluginRegistrant + +class MainActivity: FlutterActivity() { + override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { + GeneratedPluginRegistrant.registerWith(flutterEngine); + } +} diff --git a/wire/android/app/src/main/res/drawable/launch_background.xml b/wire/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 00000000..304732f8 --- /dev/null +++ b/wire/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/wire/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/wire/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..a3f285f9e5f45e0961f6e7c2d46032087e550a7f GIT binary patch literal 1345 zcmV-H1-|-;P)uTd_0!V%xTj^~RVz+qQkNle+bG&pJ+~-@fF1He>(R5VVes7IOD>*8pj zqheUWHU<|V7e)gem4GGsJ2+v4(LhI>IrhY(VKk7Fi2z<|iTM&34b&ar1j_BVBq$oF zT^5{XaPhSSL<7+saIV4Zza$tMh~~j%l#2}#2o2PNi5m@Wr%DhsPz$TzUdrtp34jJ_ znQ1?5aIsS|cnuV=f=vu2gk<0vD8TK`l#6|mL2IA@7ekLTU=2jMm@OHo2BH8yg9lB? zAT>}wfRiW}AIb-*2s!8_Z`J0aS1@qoHy_}lPQz#RkE4~2! z=(Z>XqZkO0{yAgr%jc0Yq~kU?n{xX%#oOwWjsPbUd6WU+HDJRj(Jz;3Pq)p5ODGd- zRpPkY*4@5D9@RitX39y?ua@Yk&>~x0XE2eZ_RJA;@u^#pK)8}JPmFl^&f?(|+~wXw zlx{1_o=Py400@z``6J9n3hk?`&=Zu2?MiW&7)&sg2ncJBf3{icIA1y&P$u@O?8x0O z8w6ANfUwMLs0l^6(Xzk}43I58|S(7_2STsgb3Bd;<* zSWm4;S)us6*-BXm&%LSz^u*u)!V9a@q5kF^RULUIcH~tB2yfW%%<|*|I9T;JWvlPV zl> zWXCr#aj@#Fvz(Q*M}0@G_VI6yJOZd~Pq;2> zG2)cDYOmwaEd5xdfMri1N}~YDGjb-}H20OVqDYXKgR~o0O;}k+t{Ul{4}K_j9IRSv zxx3v|cI4{w)Uu@Ys(@Ztn-O+?{~M&L=c#`Z%N?oK8Ww*1pQL%Dy5z}!lGc^q%5iX( zB~2vNEl(~>T3hyWhlL+ome`jZ8I6QEPyDr|C8@qaq{OwQz}f%Uvg8*?P03TslUJAE zK;HNC-|6?0nwBS)Cl!sfCZpi#6&bP@T^i~6H5v9p>yj@bH8^;1uQ~>2b^5MaYqCxw zI(Sbyg!J61w0sKSBRWSTC9ZsWMG8C4>k1tm9i9IG=%)ZpcS>ov00000NkvXXu0mjf DcgJkH literal 0 HcmV?d00001 diff --git a/wire/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/wire/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..5e6f3ac6f7ca7ab1474c50255db0947a4f236568 GIT binary patch literal 927 zcmV;Q17Q4#P)D0gcVJI$m~tEjv=UM0#+Kd63T)IDVl(l zvY&{|q6jFO0HMLQ#b81S0Dyr|HVC0a6X*nBRzW5d1L+np_qFwC#87rFp==?-)R%y< zj}1(H>?1n?7#kA)tAlU}k(G^l;H@(IuS$Va5|bYvz0=YlGw+9MB+BA>!SR-IE8k(W zss)NAY>RFfF#X*6g#X0HZd2j2x#97B2oh{oi$Jl&`b$Sozqmf&KlTM5BC_J)-ZnBj zZgsP_v6)r@tiJZ$7xW!}mA*t7enFz_AUC}F-;d<*bJ(oT0w`fiKX>r>n|RJk``vY$`OxQ*%)P`Z0=`!sm4&|R=Oet|5ds3V>euZ%{TI`LDr?o5zeocvw?J`)O?{o8l!*psNt8|JhsSNR;46T0IM8_na3x~KezsqT zA1)v=Tdr^0D3gl99S1hI0M-S=rog)?z5}}8-E0I${?adS$(Wh&R(v76xwin`PYdu0 zbg#FpqHc-yTEGq6N5U1uCc~TY1qhFY5`Nu@Qolq$Te~WudyfS}=OJKd)eEj2I=&db zQoWbz*OVxUtbEH)$su9rG#CuOwSk+4xXJ=oEs^2_sj&J)NjyPGI}P`CaMH$ab=~d2G%a1mdZ8P~vz1 z6J=A4mv>~R@d~_|Kw~d$&#~%;&@YjbT37hD6KM4L9XW5tHJ9nu@^}YG~34p2iJAov!lV07GM*+YPcV?WX<0QCSHeyl2P0#=U002ovPDHLkV1k9w Bv-l9 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 literal 0 HcmV?d00001 diff --git a/wire/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/wire/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5614ac831d924f5e49e16a3d4391be8964fcdf3 GIT binary patch literal 4067 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 + + + diff --git a/wire/android/app/src/profile/AndroidManifest.xml b/wire/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..b38a056a --- /dev/null +++ b/wire/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/wire/android/build.gradle b/wire/android/build.gradle new file mode 100644 index 00000000..3100ad2d --- /dev/null +++ b/wire/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.3.50' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.5.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/wire/android/gradle.properties b/wire/android/gradle.properties new file mode 100644 index 00000000..38c8d454 --- /dev/null +++ b/wire/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.enableR8=true +android.useAndroidX=true +android.enableJetifier=true diff --git a/wire/android/gradle/wrapper/gradle-wrapper.properties b/wire/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..296b146b --- /dev/null +++ b/wire/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip diff --git a/wire/android/settings.gradle b/wire/android/settings.gradle new file mode 100644 index 00000000..5a2f14fb --- /dev/null +++ b/wire/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/wire/ios/.gitignore b/wire/ios/.gitignore new file mode 100644 index 00000000..e96ef602 --- /dev/null +++ b/wire/ios/.gitignore @@ -0,0 +1,32 @@ +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/wire/ios/Flutter/AppFrameworkInfo.plist b/wire/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..6b4c0f78 --- /dev/null +++ b/wire/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/wire/ios/Flutter/Debug.xcconfig b/wire/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..e8efba11 --- /dev/null +++ b/wire/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/wire/ios/Flutter/Release.xcconfig b/wire/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..399e9340 --- /dev/null +++ b/wire/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/wire/ios/Podfile b/wire/ios/Podfile new file mode 100644 index 00000000..b30a428b --- /dev/null +++ b/wire/ios/Podfile @@ -0,0 +1,90 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def parse_KV_file(file, separator='=') + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return []; + end + generated_key_values = {} + skip_line_start_symbols = ["#", "/"] + File.foreach(file_abs_path) do |line| + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } + plugin = line.split(pattern=separator) + if plugin.length == 2 + podname = plugin[0].strip() + path = plugin[1].strip() + podpath = File.expand_path("#{path}", file_abs_path) + generated_key_values[podname] = podpath + else + puts "Invalid plugin specification: #{line}" + end + end + generated_key_values +end + +target 'Runner' do + use_frameworks! + use_modular_headers! + + # Flutter Pod + + copied_flutter_dir = File.join(__dir__, 'Flutter') + copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') + copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') + unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) + # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. + # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. + # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. + + generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') + unless File.exist?(generated_xcode_build_settings_path) + raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) + cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; + + unless File.exist?(copied_framework_path) + FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) + end + unless File.exist?(copied_podspec_path) + FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) + end + end + + # Keep pod path relative so it can be checked into Podfile.lock. + pod 'Flutter', :path => 'Flutter' + + # Plugin Pods + + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock + # referring to absolute paths on developers' machines. + system('rm -rf .symlinks') + system('mkdir -p .symlinks/plugins') + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.each do |name, path| + symlink = File.join('.symlinks', 'plugins', name) + File.symlink(path, symlink) + pod name, :path => File.join(symlink, 'ios') + end +end + +# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. +install! 'cocoapods', :disable_input_output_paths => true + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['ENABLE_BITCODE'] = 'NO' + end + end +end diff --git a/wire/ios/Runner.xcodeproj/project.pbxproj b/wire/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..d6e3e13e --- /dev/null +++ b/wire/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,518 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B80C3931E831B6300D905FE /* App.framework */, + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEBA1CF902C7004384FC /* Flutter.framework */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.wire_flutter_todo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.wire_flutter_todo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.wire_flutter_todo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/wire/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/wire/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..1d526a16 --- /dev/null +++ b/wire/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/wire/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/wire/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..a28140cf --- /dev/null +++ b/wire/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wire/ios/Runner.xcworkspace/contents.xcworkspacedata b/wire/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..1d526a16 --- /dev/null +++ b/wire/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/wire/ios/Runner/AppDelegate.swift b/wire/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..70693e4a --- /dev/null +++ b/wire/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d22f10b2 --- /dev/null +++ b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..980e5ad64bb0fd4a9c2c6506e9b811ffea9dd64b GIT binary patch literal 715 zcmV;+0yO=JP)5QXpJpN(w?YkRkYwc_j#m|(3>!PrLIwlTJ6&Ufo}SH`I1$#eR?RVOWIzMsU) zrK2WI$*4hFGG^Q^9@T@8zu5)!Yz6I>${V_+j`Ok!^L)v;38fNcW`cbs^X>&xhbk?f zvS`XCEg(wS59HzvL0zJ3#-=Tswu302VRN>z3)sQt+#O8gBeP#+>JsI%uI=(!2l6=C zdFI%h9c;z_@g>lFVht7cT-%~z-i?ZdJmoU8IkPWPB^k`Ff#(xjg!dpSwLVm8y$Z@~ zqGHj@W>6!4&#i3X;(Y3is=Eq_sMPsUsrRE%>p_jmL_k5`*hG^t2U&6%yTe|1|lg*UW~p>+@q!E^s3OEa=e6Ud^0-fp0g z&B!j%6y4G^MmBL1O_42jA+woHwxTJ#r4io)FE___=bK_XXo_uveG`pQHs>9%se`%% x4TYA}o~Ajur)^2@Z#O6Q@F3(a-Ow$UJqP2R#rz($lm7q!002ovPDHLkV1fcFS>pfz literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fd870289028b0d1ba6565d9f29fd42fab6bad5f8 GIT binary patch literal 1591 zcmV-72FUq|P)Ffwcl%S_9_!a48Hv5l6Yg}=#nG6Dbu zla|r7Yb`^I)3=8fNzyX31gi{#!9`fl5R44#X&qjkmK_)Y1VY=0(Q$itxzaMci~?7J zyKH1wcMh7|XLASHg%J|-qf@pXF{&*iD^$-ij0`JyIjqHchvApQ$T03AS7awf2>H=E zVoaL{qYTWnjvBB;p1}%aY1}c541*Qen)UNz#xx^D>)7gbh8TGWBf|hRzyCJ&b&jv; z?q3&e<7axnT(Y$hS>ykYW=?hIQ}~7#Y^@lV`Bx;aHCF{4bPleE-x&PP9*NU9?SY zl0CLylXe)H&){aXGcRRIWPSb@&S>s!or|_aBlZ8FP zV=ahX*88G;#zXBh+X`g1q>VF-4C5|rhyFP)t?X1u_xvxC)$SMVvtD`w4~z_(bj-oX za4o|cKD-zpU*!;ev<20?M;dTJ^JP9;w8MaBVeEme`4cNaiXR?Rv*-WOoSK_wEc2pc z-cOwi3S{=X1Mm9MT7(KGr|8k7U|zR_3oZl*bk_W}NrOHzyJh_`l^26BGOXp>TXEVu zJ10BOU&GnjzWP3*b16ifOF@&4MdhE2FVJHzy+WUu;gYJ19-f7f;h*_ZbaZ}UtK1Xm za>H)G1;cm&;DU?v!V53ZQ!l+tpPk*LuH~=>H3wVyQz%QP7niom-IFL{&bkws3(7B6 zB8po6>4YjMdFI8J=u0!}B=1?l9E|yY#fx-td38B?=O3{Gc1U%R7f}wNr1@>T z^;xf;(1*M^?6XM*M&^PZUgF7`^l^qI?pn#Go_dO&d+s?D(o!rI2_@(EkI5y=dFttd z6|w-V;0y!N=gm`Z6WshW8CqCGkt<71?HrJU=lV4C!WwV}1JUa(P@k_k-woy|o6B8U z(4S0`!;{Ax^;)bl42m!^3`q0`O6UFl5=r{}MYw_QG$|?nTy7;&P*D93dFF%x=0LR)ls9F1Yu%ejZZn!X}O|T+jETCCX&8^lBtgyR)Ok!Lu+j ztOL979@$MeqLu58$R3%5VXzCUVT)brjI*+q2&_fzg|P=_T#?EL1b+x;bbs0r*(Wx^ z$nd*OllQ^Xj1cnUL-EQrXRKOvMl0lCoFE2E)EO*kykCWpVe8!{^UAJxr6M~qLY6c6 zVB)yL6+fslctIn41|!2N!`5tX9`O4sA50u{FhXK}fDdI)uDOzj)2_rJNq896!Dlcs zjC=@Nvu<9IJermr7y%IK_+awrx+`_~H!f?qlZSa8Ja_V9{+g7*5v<@dSY_CnmEFA4 pojS_%e#4bI{@VvLN7oqv!0V&tCp*)&!{Pt{002ovPDHLkV1k)(4H5tV literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75e84cd172d55b1b20971fb3142ff6876ecd45c2 GIT binary patch literal 2506 zcmV;*2{rbKP)Z*FU!m{%*@P8VRsLNIdO-bn8LBcq}8jNvvE!9=H589 zS1q{F% z25_7w7rzc6_W!D9OuwF9IP!hcRh72%UTx5Ve2G1JF&R7ItnWOsxG;yFhdp@D-v_7k z&fdOmnO#2ee(9>pVtq010kWwNld+dE83*wHn9tfxBT2o#zpv%fYznjAHBY*l!u|2m zSf4hSMNGyg$1xwm-`9dY9-PW*J`_Ic{nAyH#QK&>FZOFo43jar5Bt!M3$uIOIUl>v zb9b5X3#kSD-cQS%Eqv6xMP zE1Yp6YpT=?fig_Kh{=PPj6E)4GIp-ZS?ri68GBT|J*YdD^7L~SW~Sf$s_d;n?I9a6 z86O}SlW`cF=fmCqsn)n2%B|DQU3h+l{eDQ{AqgImvG6u_z#8VP?>ut&`^aBtAJJ25 zoAf%WFtdD7GVuJ{!xnPrg0dHT=P{^0c=^-k#J?H&4rDa;IKAL**R;Bg+qyI7Dl?6?0iCgVW32mf*?q1Sfz z=n}fHUmsBNpsPIOBJ3dV4(?VgItv@Fu4~cXjdeNJ4Q-=X zkTvW(53?5w_f601lYAaaEi%u8TyU>q(bA3&^YwMj`h}NX(m!eGVBcXuOvdhcvL<%! ze>SspqOvb!mSs*L%6rh56AHih;)|A_H@E4+{TDD9A2AP;%Z=;jb0;eMNOFOB*o`eL zkL(y1%$N88ldrF9p|It5P46;5*0JRRCYv=(#zJ-Hgl=74E4rxsvheoAymLMogSucY z<-wA%;3_Qqt>G;*$gX227ciKa_|rX8dLX}1blF`~_UegQ<_E&Pw(wC<7~tyqm@cY8;W|KtwlU@|6uqkmeb zH@Ax}D?b_e=>MVDRK+0{Qa zGY;R24>BfWFnyGF7!ufW!Q|`fW4>kK-q-7OZRfb`_vPm!8NIr@S9IC=?H&Eyp`=&P zL*9tV*omA~}ZeJWoy5HD~$=HdkNnt5A zV=2cVg&Qu0Dhp4(@~Zx7`-nY%PkLGJpP=mE>Zblof3o0x)7Z;>GuWdSyY~yq+njVF zYd0LDFg*Y2YdV&i)hGFMdBe;2{~qZ!dO)F8jg@FX&V%1x1y9 zZDCDUN(sv10C;;)A5}S!)_zo&&EmhbwEC8O`st_jLk~TqpM3I3ie6EAZEY=7*{A37 z@3|k7aoF{g#$;tTvvCj~X8hM!8zsS(y!F;w^}`Q8OhG>aOW&W(9o&}@lW}2o7i1r{ zkPmw(`^6AsF&SI_5^J|b;kxUt(+@oGKww!|U0uDRsQm86&8Zc6nB0ZQ*v$|oW5GR7 zNeD}o;V+juY+3o&_`wGslz(MIm4$phuleklvj3V{4u3x;8O;oh`a>Hk*|{ z*FAE+h3xweWDa|nj5&)z5khf!UgL;iGIRXWnM_9C7*F`zF^}D_R>XVBN(NM4_Nc;S z?6V$;hcC@P*}n}=1i8bDSr6nA{Jx=_VVZ=F3f?YGp6iMhm%|?7UV2u9_DTw{2qZ!K}_qW+HdAyG7cc*d6O|2^A=3T($S!#tom$9pNdZ9^Kv*c znLivji9I5iJb?>y@#}7ipAXTgT>i7E+$n=n@)sdGx%LeyTSyJ|A%X*8Zw`~Odp{;m zVKR2Vhb-L;N>BtLl32UN8@4LQ0Zhg|2dW zA%Z~$U>6B&k+WEkHSFAPXJhuAV83+vgVrB5C?J3(I=%6Y==6G?K@gqBu#N>;!=Z>` zGKPTr$*hCCT{;*P00F@JA6atqAGI?Zc?v}^8M}Gk_sd)5&GL4GazXG#e(b7EZI(u6 zHm|NtZp0!p8}aDO=2CQK!(M`250o_w;5bhXyML)RxoO_A5i{?*THYvcHK?QbFVbTr U2?md5F8}}l07*qoM6N<$g7bj+?EnA( literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..03ab8a84f141a4464654d46362eb539fffd7d067 GIT binary patch literal 1068 zcmV+{1k?M8P)eFxfFw`eszE*1VZKxuv6X zwN+Es?jA2G?-={Ew0+ztZ67ns+Q+E$?=gapO^5uxW8A>K^6uFZ;e1z5Oq^BGG4Xg= z=Y&<(F+ogur?L%an0H{sxU!yc7x&SlN-Mf%9xv~jk_RV=?M9hqfL*rDBwJ-RK##zy zk^g!{&$Lz1Jxxx^*?RV#Gv52M2YsTlZ|>9bo*4oaY^HaX4KQPKX1mifOV2JxVH>$y z**o{CsO+CJD*NUMRP@a$+nLSGYd-b<2S$pDhlf-)O!=h?vnH0lp57Z8` zqzvkZS7>N+kMw7uRDHh$%Tl>mJz^s>+X2sf%1&Cw12ngr*ZWkd^S-Da^;6B54Kn*U zoHuDuFlVB}wbZ#UYQ}?9Jr)3j{A}j{)k*X3&N-X&WwQ}Vnnm(@GrM`Y8z7q?EK4U0 z()sDv-{|%BUaG^AV^%vEQU=#A#Au_q?^!syoug*^8y#7S15;rIN`Lv~7kcOKE^3-I z^ci87eaA|Yvik>~h25K3s>A-Iy{~^OYNsPqHys6p%%$MtzdET^7UOrFM}iqL4-Y*H ze_h`rzRT9LsGEtAVm8L5iqHRSr?V%5R67&JoL-2m)4|b^XW_S*9lnQel=Up?=Mu!! z&Bj%!&ewnZMHfy5>AmDO9eEVu_YYIs_MN#n;0)_omd+xhP>3@MgvKRGagLi+U6Pbm_Kpb)6yVzEegg~LO7D6)lbj)N>+S(9a}fH=d?$>LZn zrpk2E=``&W3Un6=<$j~wccVd>v2Tk;-#Rt=Hvn;lK_HcJEyaKPQXuKr2OG+q+4`<% z4sM!FflYEjE^SgUojIxS34aPRwWIdgj?8nEqE9p%+o7i57X1&hcvThN8%S%jZ8m4N z7qWEQ5KW=oPn$zKbSfqjX}Tq_hD=R{D?Ec8@NAn}!n>b}b7I+&mT=Z;4)0NOc$e6& zXgi=qne#5&Yu`ejz-x`=A8(1~s3npmww>8F%@Jigvpx1X^Sm{deO&Onn&_<7ME>!% zSix$E<>W9A@CUGMIKz5Yb2i{T+$dPMj~?NC=VXc{tqJqf*0^c3#Z9v{ULYMgW9!*< m-j?{s#GTfZ`6=$|J^unddhQb0Cw0#N0000oW>oh3TRvgw{P=1#Z!?x zn}<4_r7Pm;=Y`DtGT(NS>r;5D@nGKZ`u{t6qW0CJC+ZrH9j{FtJ6^YX^mwhD|Xp)~1f0tZURa<(;bkKYgRc>_+H9{>i38M^DyQ+j3%uW;lVN7JG5` zC`W9@WE=_hdgs?y>zggc2O&#AZ|^NfPt`r;F9xjD;{e@@m18#JAY*W6xOe%^lXJ|^ zJK6B0cCZ*1LO|a6jstn88fuT7Y7j*a;!MV5>?eHx&7G$m^3K;Euo%dO2hR-Nns=(P z_NbN&;V33!IE~3TBL4Ha*M0A^UEE(;L&!Vb^i*a*qo~Q)N3Q*PAtqxlx`v$`_kQhU zF-q`5{@J!e$IdiKo&_tq8GB((9ngr$*xl1kcKeS*n z-jy#mbnp5e?P&7OxBQ=8?&T~d;|%$jjN{FN@SkY1Gw(-jgEG6evFkkTX!6gszM6mj zx+r-#jB}33*quQ>hsoG?AG4zG|6Ny7Hn+EBabr^p=^FmeeD3pJTCtm* zBCVK=UHrwFyHE2U>mL<9TGY3nTyVav(G*;0O>uE<+OV5*uE(11fwk9C6Lh5LuJ0+h z(3Y}A+gI~1wn-!|U_Y#R_j}e0F1BMghn_FA`J=HJwL{US2JkFemb$Dd)2=4WbDDS-|^?02V`n(BUeX? z=A3T|uXf9RQGm&qY%j%R?C$+W+psLy$4B^3)N`NZTGqDcwI0s`*fq>POvbrkmUljU zzbh>(n_IG%&(h|m=Y5`{MYX*FnsGp_{W@bs*RW?lIsW=@`o?5qYkMypDe9l^*c8?E zW*0PLMK}EZKI|JTrjY;SK%oR9ul&UK$D3`+HR(G73ad?1g0d`il% zb@M&-zVgz@w8Z^PuW!f~+mbo&Fh%wKvKw0T{rBIOr#?CV05~+Cy0yaW;F4 zD*FBZzuGP(oQ=SPttm;atj8{Sd3H(4o89+e@B8&_Sc}@wJgnGFIGZWz z!aI=F`U{q|n9}QZ0a|c2M=ABvRlm*=hp!~dS1k*)1`B{%K4KcuF4gEgdZfW93E8GA4#tvYOE2lCDZF^X1K zS4(>`Epb07XP`O-)5EJHN3d-{_x| z(ssRfOwl*sos7vi7g|(@c4Q!{gS_Kkg_M2s%{S$_=bn=nUwlzUMn)*O=dzRQoAQO; z2`#DjsmYl4U^3?IID^gDly%&YaK^I!)rH#s`c?ef-~J{~J@pi&LYbVL3@tmdwjux5 zGr^tvN@?(ZHASHllW~S$UZ~3!ee%gC<B5QU1~ zX{_w2Y-cJhiS7woY&yz(FYX?NS!yzN_i9IDzeq7C7v&i2(A%wtZ;Xc))IZD3!zoF) zGqTKJH;3Lw4qu4>iV4){>)bQB_%NseBWBpy?7_%X!F6pUm<^Le$~Lj|Cz+V%E1b~oW}%) zdF+KXx5ypVf9b#BmI^IO4!@5ac77gv_k(uSq9!r4P@NdeY{roo#9=I8Cu7b=o9ExZ zfJ5hNH;d7d=8ojjA>B|pv>=#_ZwBG_`5#W+%Y5x-FH(QJk zLMV5St{kiyUHQMN^vbJMBdd*7>E%>adUe%)EdY8UCS#@2X6$DFdEJBE{VRHRO5dVy g(zodwEoL|V4a+}H#QmXIKmY&$07*qoM6N<$g7_o&$^ZZW literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f47613ee46814496f40d58ae909b756976d765e5 GIT binary patch literal 3810 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 Y0j*fAbhL&TLI3~&07*qoM6N<$g0e}{=l}o! literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..7f2230a978c8a2f82d02bf6ca32497c15669e48f GIT binary patch literal 1582 zcmV+}2GRM6P)oxL5Jl&M-bdt-nJLW7%*;tqD$LBxWM;P4BxYtABr|k+c6=+frM0{PRUMscPfyPc zN0@yoyQfc{?VNnEqH9uPrz*Op_Rn@r5@&*uVG9`URCG@6@%|KBtLUD5QNGCt01$L4 z`sPnmbWe?(?Vch@MfWs}3@f@|Q*dT^zM^MlM0Q{V5C~PhTFu#>nF0^-l4(m|mW>RX zor5y-Z0;btFhZh#)ymerTCt*cmW<56$gqN!!zLJK7=9c^hB1p=kewJI|_8U}V?~UIHV-=KJ^z*7+=yB7ENT#Y^8GUQCJV5!-&%@Df?W z2J2MA$b1Huqni0OkwZ6C(4R1wv+aqh5neuGS0GCx!whEGD#I4$k?TfnG?ZCIFJnRM zWH2wPM;%l>YF8jjGgX{nWEius6`IGLG`n0Rv(KA>r0IT9J?5mpalpv1PR%%s3?F9L zg!866?Nf+=-x!ezKGY9`!N zJE=fs|3C1qYv%)$+1@Er4F%JtJ4DT-hd}M2ZyeI-{4ty1cY2=k!pN{Gx7ot9y1PeK zJ}>x_hx?3uMD4VXYNx$AHB-v>4@}aRzy3}akJ{Alj)L#P$nb-%7;WzDTPpW;Jb&aH zT+ojP02iF1pMUSp|=@GNZLSznTN_75zTdq0xJJ;P39Q7eC#4JZ!t z1B0rdSlvfrx|%*Xc`4| ze)#zpx_M+?KQqkp0$B2KJWp0WyIk%$e+qYx*oT61Aq+5_^@1}f2k0l}?qQAUF)!f^ z|CC;{RBm&BpC0kbav^;e3;@nV{al#p=M{A-n-&BQ4NV*7o7jE%qNQ?$y?wgdoxpuA z0W0_q6h`KP3lRbhhkkH)*0daWa$tfNN2ql%O4F+wmdfRK_UL9;QoS{=;0%|5GcFh< z(6Ffd;0OvH&D-NMOV_v(hBs7>!N@RXNi;0+;Zoed10!15asvYclt?5f zpU)p#F1)ovmpPMaH$M)m41+j~OhON~gbs51LWJJy>?tYs%{SjrXJ@BgE*_8T5RG;|v?ojGSc-AUUX-H`Km3q>`Q;as11Kr~x7|=~p}0-w zIezzr zXq;LcY233w7Dk2viDpl3ui2d=Ns~JZmvDQTlJf6MTO>v;YL<6^99(`s?!kb&i55>j z&4CnoSf`0IEV;v%F)cYAimF)#Mutnk?lSMScylSy>R-{Cz00J?!^ki)-Qmv}N)862 zI4_~a2P5a%W%t7h--^ZsS6^(Fm-Hnou)+@;xht5XL^4T#1S0y+xDQPBA;YF%7v7QG zL`$%6vL&!eI(`_e!0Ivsx2ZGE%BBQhQ`BALVleaE}Uo$6^pIG0<|!$AOtJ;4Av=~FT%!boGo)-xh-5M$WDxq<#akCTQzOr z^&*1@O2HW$8CDrKW-IprzhCHxtk*C?qJM#NliMfSq8lS^kqu(xW!My)nao=}hYyKv zj>ry-00;&;qMIk%VjC}VS*<;~k>-ngt-P3jCRnivEBFjn88&9=cHY?@+f4I*tu40o gVn<^0BqIR$3#s8JH79+r6951J07*qoM6N<$f+ET2fdBvi literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..42315c6dc1260f60b9de72e58f1fd4789c1f488a GIT binary patch literal 3462 zcmV;14SDj3P)}00b^74z_|aGC)>rXiR;Q;~6~{lQNx80UE~{HruBZFC zC$mmZnEgR!$K0RfE%GLL8*n9L8$;bKW_7nh^Jg?2e-cS$_>*#-bxv9N`3Y+J^QcIL zb;R4^O5O@w4*xXFoAeG#i^pNnOqFY>&6?DJJQ???&d!gjyxgpOXq2}D_cvZWxazud zze!8K?r5lvlkA{L-qYvBZe&NmDUSc++kUCT0lmZl zstj>Q%5~3_-k&@VVK1D&5q3ZI_e!4wC)|8p zgzf#&pvtwVfG|}aFx$`HtbU%<^fMXx{EaaErSF%&Sm2!e_}%?yuO=RlwD>#&->PzL zd#Cp+%X|OjTUNjMZodM~T^|l-VY`2}o9s!!j&ur=^`khm;Ev-;qHrHv_!awK!m><) zWoBk(hA=ae;xL)QXl7fom}W*WVi=9kwOwv~o9C07aZS6E)j8kZYrT5)s;+T1r~zlr z`*_E>uip<2cSz6Nf^+{9Wz8+)UH~7f@)l}yIcgKu&E#WaGrPWW|IZ!hl>XA9c)rF6(7Atf z#h%l`H}I;87Nb@JKW1R~O7G*H=k|MFJJKa1z+xGJLxzbtoPMYVC#f3^n`d8EOTnXDA*u;mnxtm#qU*T3IER zngXn4|Hux^rfwfU^Un9w(4=JXHMX=|)BZ_-2fEhj6ja#|dsNX{G!+NXbp6Bo`1)91F3zxj z1_7=(=Oe)NLyA$tM3tYsbyzj1NAai+`@a8t^TBS}%SW^917!cI^F`+j7!QQvQRT56 zyX3F0?Xk}NxZhKchCb1z!##3xc0scKdSz^;@;t`8ks7E&1CJ^i;0rIjAXmQnj@0x0 z4Dh}WpF7$oJ*CCW!`oS$k$T7bA<>3IJ!%rvqXq=1T>tW$vgu$KcS7ub_zSH6+VOrF zDlcaq-jl=tuMVUTMkuzupY&u4y^m%Yt6~T@=E66-Ip8JcTy2;INU4s z70@$OA;6HkcD*7E2RhB>dKV47_dMhm?FE@zS$A|MqK>^qoi~!+* zT`x;>9Af>EKCM#?y?dZa_y5v0EQ@PvnTEF#hxhN^QSt9@&aVOXF|d9U#iNQDAUv{j zw|w?sC-t6wP_bTTySlH)N3+bn%4=)#$F7m&UG`5oZ&ZJzU!eXditj_K1_;}B?36F; zZx0^nNAW0tS$|hqa+t+3cd|!w z(92^x(*>yf?alqkqbJT?=qqgn$$bDH&Gt<%NaK2Vn@;3n)T8MLd*Gww8+k>SL-DAR zIzYJcjXkm{evkg&>ll%-58$KOYm+6}V(g>4qU`P5-#8~gJv^!C0cxQE?oJ&Z-1yo% zvh`$6e%?JQvny+vhxh#09Q(w}q6C13yZZO%EbJetd5?mi%Es8EN)`bs2im)&w37X= zyq3`!=1n+(+5v!Xe|&hZ0iGI?O{WSm`VAD1CS(y{cXzi84Gl@LSd_JlKHuu6l{<%~ zWfOD5DHMj#(7X2!d*TVud|-2+O3MWV_}p{PNpEkjXn3F@uCA_LPJPHK3xpi0+ysE`_4t40K40mYHKmWWu@x&9dZQC~K@9&o|JQy7vO&#L$+8O!# zzy$Nh3BK?2Jx z#D�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 literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@1x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..8c552e237629bdd153144a309f497f1dab0e1fbc GIT binary patch literal 2798 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 AX#fBK literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..45537513df37c45e8074c7c131c61cec2eac66ec GIT binary patch literal 5868 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 literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6360ea17a408801185f000acaded313519da49b4 GIT binary patch literal 9605 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

$mXuqN7}uZSD=w7ko)>69%HJrp{x1n$RbE! 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 K)eG-g1^+*MxH5nM literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..152d5e12500b4809d4a5e1bae2d1fa52ebd2757b GIT binary patch literal 3390 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 UptyngmjD0&07*qoM6N<$f{32#_W%F@ literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..310b0b8f4f1ed5dec5fe5480c3aaa1ad05efc440 GIT binary patch literal 7082 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 literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@3x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..40ac4ea7a9434539521c5b9e693c804e1ef8273f GIT binary patch literal 10960 zcmX9^cQ~8x*SGhqS}j6reOr605wo;vRa>hSqgGM7MnY^_v%@Miiq;lt7qKadq9|&X z)Fy-^k|%Had!Orip8SzB?sLxPocq4dbzWMS8L={5VWOa*V7+5(aG(79=ikdfNB$;R zC#6zQ+{nITp!*<{axYi8@v$mL0=L_yirM_TLs~3*R;A@#Im}^w^vPf7COhx zf)8rT77LrK_GcFwf7h5cfg7y`R7>GiW&7}L(gj;~lhxuA8m*nye9*POQ3N!>^|0_D z=kWbu{$T+$3K|WKfyP4Ppz+WIXri1+v>_D18g>|z$DO@c-I@EUt22v7LyMPZh61hj zT2FxLd$51^izH|L>{&;%CHv<#7+LJ+PzfB)> z4|y*DoHBiL6lSBWiUReNk582z-gAb;2Tp7b`Fh7Swz11Cp>Y6GWzAKhZ9Ve3=KL}B41PXowoFYf9Y^)1F^))F_YnM6$T|wgB zD_o{P()RYR8gSTmY4vRVR_$Yb@q|Y35l2|Z6l@1VJh5L@)y=Vp;T5-E24}J%;#Viw zPBLEjOFm~|9pU}MKcr=u?uERB2FSEr_E;Yd@wg&Gg01j3s6F5=oXD`C$oA=@EJc$$ zTm&*4HiN{2)(b&m$k*Rs@ui1veU_nb*%ciAPz{V5Ret{r{DdExM&8UMvE(X+v;Vr~ zV>}bUo9HZ(_Oz9aQ+W%$Y4iuz+ltam!dsJKNTP>Y2049e2=VDEB&SMH;_>B-posxW z>V3thB3ZK~Y-8!&Ir9{2yFZb5h>>rCT*-P|f5IbQ)BA_}^}!RA9OgZLk7Pccad$lC zXrtgb4*0{2iBcaahhtBcvx>Xz_y`rIeE$&kfA|SiCkS zm#_0zwW?}uw1#9NH&jmT64|@mMV}wrUYTG?w&x0oFnAmIlIUXwR#tKfTo?#5{>sp< zBt+n63tU|eh~7LILH(oCBb^R1Sh)#D{i$JpB=#LJD;B2uL3@6=-*B=ZCOYjVf@~l+ z_Ot4sZ>n4pSK92@hwE39C|Q|kF^4OONw*@wm^z^9tWe4AK$K;jCU7$wB803}Cwd_$ zr^q2okq{UP)y?5LXOb=_3wnr0wG8^E$rC-N?_g>|F9wtZDT;XT&ry*An{S(Mmq8^+fQc&Eg{|;7ZfIzUz^*d`Up<9aH|whUu6$yDH;1nT ztJp%#l+`?~?-j9Pt$_!!&5L-kVtx-8fu>SHTHlJVOWA3|+X3tq+ zkt)~jWxk97$q~W7)NZS3TR7~uL|$YO+^Aff=7-ZSr_CQss24C$;g1Z?FxjuEo7L3t zB>*f23{p2FX(fz!Ma&hNgv&E^q*u4)%Pq77*p^9X@<>UC7_q~k#v4y9#^yu$ic1Fi z&6Mp^7U_s&?_5}x}^!HNW)$y2XiVFccoN3tW zv~HT32iWV~9*Mk4I}_!=oK)jq0w#|}KU}|Zy9NFxibw*1g0iX8xN}1?=EofSV2K~7 z%Hrhd4x~ZC>JWln3E;g0clXS!UFt9t>QgCw4C?Wy zm@=913_q0IC$9Pk-xGD$0?t0hQ7~ee77Yg4}#>hj|Br@CUm+1;QYo z`R9&5LF(%2W9=WA62+g!5@-|`#oXkDum@1BZq9UDn?feCCHBcxLAD)CyvrHy@vJnL zMR?}N__n8!Y6w_?%Fxlii(xJ%hgkqi{mj=)S@KfP;CB-Zk5`Q3;XD?(D_O5 z4#=Ch(p%+6^fZ1*OkftieA(NY(slSaSCBECdKAF&3%G>7-%3 z&;L@40C+M6hXg98PPds$l@oUI?C@R(}A#7GBqvwU$Bl?grFZ1-{+%u&`zGpd;!!EHrWyUx(~MmnX^XGB)| z#P6C+Hng`jU=B;>188;jZtk!3V+gZ@VvU$Wgi6>V|5pABS5I)2I)CEYL9(H6L2^(pZdtEAe?7=?<$e?JDUTAQ^3dh>SNmO8 zNdXTy`ELpPMKtI~`P@I-IJ(UgG&M!7g=+O?3eY<&I{A=&|=b$#2uvp z>$UrG30Hl7;`5@YGm6+Aw*-!@(bEv1G38Ei3=0IiI{obH)V>UH^~%dqz_iv?bAFt`V{|(X{-)zso-BT>YI$zCFyt3#-vkVntoC-$ z$5D%D9&f@lmxb5J&`oC~`{wLlyz3M4DK2KBe>@-Nm}9=UEvFB9+3vKkxrR^3LCOqU<3sZMFw5+ly-6Vm^kPI8@c`N4K>Y;XHki~7cJ z`08(+?QLBz7e}6IDq2=L1Y4JSVyw=;bU4&xvk{N!wO$naIWhc>if6xhodqD^B+>BJ z(%0?c;@`3g)1NKq*C2ak1(wR=iJmpyX!j%mlKag!O2f6iwtjjEcJRz%N9R5{N2%R}(4F3D;pprMhw~K#I^l?* zw;_AX_?EPrDXpZU<&w$wRs7T6uJr_q-8uznVHru$VTjYJ%aXM5>h~|!-&MQev5CEq zG!Prf{Mn-Cvn@zf|NJeLJLf#A2@Y^E?wO%hh7Q+F?B5wfwxK%C@wv9dO-k$MWSFtnyLrTPi>$f++e2ZB9rX+F*H0dwoS1ij^P zG1#e7;E`g_!r96Qr-Fm)IjBzi&xa=d=860onut{%R=o@)J*3|~+eA^X!b?k5Zpm+9 z(kDj0)H6!A@J_}*+~eBLi(i#G1E+H zmxiUDCJV>MOS|1Wi%kFVeeT9_wQiT5_Sz9W?C5xil+{ajmnGF!Vvr~p@wyg?22E0= z$nloOeSj17TOg*w4yz3B!7$Qp?pp2o?PvWD)siDsR6>lpfE&YfHg6#8yJx9p#%Y~! z!1VmFH1B#MVvQww3w0fcExU6!)!a_ZfHt0k?S13kjeH<-p7*A`i#0r6mkpqxH_w>J9wIVd3dO++!nAdg2xTxr ze=O;Vi-f8D3+~#GfcFLE9xq*q+;p@IalKrkN3*}Y8cU0Ghk~oAv1q!)?iG?6Jqr1Q zyi?<;tLR7bT7s&~>m%9}}8#y;+qrOK4tC|SM%wVynVjl|KW6_u%4NU+ITec85 z$nT~-i;A~idsD&{WPL|r7LzC(rn_nF$o5(emMtv%Erwk1C1fY3I>Nhp0wP6@c(2gO zJwudvLMs=$s{DTTZ3KB)a-E4ZW2}vB=&pZb%$s00$hfjnsAe*%YZq$Bk^*NqvF28p z`l)?U+sn~y+Op-yE3KddYO1i;?n zRJoP!=aSb}d&)X}H_7t$pWV7KW2IgNh=4o8QQXt)skuKthjBC$V2dToH>G$^vW5>+ zBxn6v>*}34V8bPv)U5#CjSi6{MEBmd!6IxofCjf`pu$G8 zlte4)!I+o&#LP(!DyIZJ8*@jNlUOa0UuCBnwbt@%t5>eTH(*#S*GnGM;ga{ouV2d& zhv^+Fud9(Gmop?syX5Se??!5Mx83GPGo%us@MT;o`a>p|so%{wp;mKd>oJoM&26yS(>4iUoB3 z2{&j3ZUlCV&)asNJLq^wY8QCvuHVNOp7v+nA6KRUjymUJ*_r=-YTUn(-<5a~`Q+{i zyO78ngppOah%pPd9LJ}}DJoM24yjF?Da-B{|LQPQ&iC4QLQqO+tN zl$<@3{DAoL5-2VXcd6Kdma!w^Al#Vn3r3eBZN3PX>R_7FQa4P0)aVQR{i=0_Uq4jWS=2LCGr3`;>iu;Ij6x_0^hxds(UNGT8TsXy7wO%i~Ps zrn)7W;M!%JA-yVSp5AlYETh|Z$b9;S^oYO_igw!NJhR0jnT$&`{cX?SJBnwz)LktU zYOTVEIq_qg&fapQLYUzijk;XczJ1E)Is=o8?m@WO)B>Ts8+Q_#F1C=*uIPQCzM`sk z6AMuCpMkoB8Jr?*h=<>eM4b3jL?yhn!43ZaYtOtBvoUd`XPWqsWG^3iDlt4twE(f| zp<5xLVVSuc)r+cj8O8jwy4b>ok?g6%u{y>SWLnvNUhs!UMBf4Iufi*ngwFG9{R5-G zq?iO&1dxJM5bmb#osb)kt~V~s*t?I11RbW1=wQ8I%QO41+&Uj{-U7ZKp!!2p0nzvF z!Vj@bX;C^1T7gYUQ_eJJpAV7RLDKcB1i0sZ)6NZnu31vzmO~<`;fCiq*cmN92FKr>q5URP29dUx12k^Y4L5^`W~A`l6t{ zBmBxm823`baOf=|3DK|b9QKk)4NAaX!y&m|qMUu_f|;n4xZ+4$Jj1r6WWvveH#`M8 zv#%g@qp+0g&CN2P4UVUKM>_*CVaJfyXA}0J+|ND26C5h{pJLoOF4Ff^x#BcI!K=ia zQ6L*vrA{BF!xpFq6NpI>Tkgzo?}wXuGIO&m1aq@Nc1cfz6PG{%)F&tmpH$%?DEbsR z2I-L(74GS^PbdQ$IZw= zo97pht-7VS-=%KfddHh|5m8X9&A7rgJ05#^Do9~hDe1AA1POX$q10C+l>B|Jb4EI;YObcIwjUCZ-HdC+m&5==VXzk}JTJoW%U>UHjgirp;NkfUo=qGJIVmwrd+DA$5nP zoXmB-Pkxe|OYW5;b^H3VhrZJ$p#m033h*-O@jQ-LjXUaV0}{hlpUo@-O>VNXvD!-v zPIq2!T&f0+;(=okk9x3E;53;$KSPIK>I9Wbk^FhcQJE)Gc%nedq^723W_EVVF?3$Y zQfOO9p%$qLIRFRhGB9+ISN6Zm2c<#=4s)~rSo1`xuMez0D-VnRwu&rN^NI<-XsbU4WW!Fj{{8PHQ@CLBc)boBJR`*V2G?84z^ zAVB{sbc&L&x3%k*xJlLDv2;d`xCo`XuG3?)44-HAdtlej7yDP@+*2iwn*fOFIj$B= z;}S`Aj8(wm1K^_@x<}SI?^v@wqk3;?SF>c@gP9LsH%e1e0fSe>Zt+u7QzvhE5y9R& z#}K%!9Qx!4*Sb^(i%k0$t5q6A@j9J$V5g?aHO-*E9D-_oQD+CgO$-eUZ#&cAFD_h2 zO+ejTh^!4UJDa@81XAL8gKGbAD)=UWhOc%ti{81K{^3W=I;{OL7!sj*{8Z9E*d!mIS-cF zrgg8qJ`%fKR97eK2H6Fhrauf}!c1feQ~e#{xF|faW*FyjWDM7zh!4JS+pv50z3~{k zZDCk$-bcJR*SNOS32nLFy}#Hpoh5BAU~gqbt!pbb(tP}1c+o9x58@_p0)`|A$np}n zBe!)f5IOInDeSuqsUkJ17tcjIK8Z3~ZV@Kp@k((FA$#+>_ASrLzUQe<52juflvhzw z(lKU!wYn-1@01_Jh}kI z1esPw{hZ`-!cjReQuM-{mN;FbB+7WMo9QR{O@A^?W0MQwdz|RO*5l&vL`^ zl{e4l5tP?TA(6QFNc^@0ek~DnTJf^VPhCGGBt*395?YTWS;JBWpidsl9TAyDZxQRV z+NiqE%@|I$3fLh+*<7ObeiE}z=OFNShV8G1T_wI$OgeDgZrV{WP;d%59UsJ(T9BG2zNC)f1o&L0j{NRPaiovd% z&W*R<(YGgFw}xxxeZ};m>NGF0cu>1anM}mTBX3EM1OtW@16xTJg$XN>7t#?#%-kut z2|nds7;(E0hJINJhR$jfXv*|Ye{9O)s@nl*0n{r znoFD5G32S4mF$_S495MMBQ9qsT@)?`7EZr_8Oq;?x<2yOJyj;jOa2*W7iQM}bnvS0 zEY`uk%aa*945_{ zS2FWxS4ZW{f>Z_xnT#S@bXU9S7$!zHhFz`f3jw96E4u5Dm+xj~rk<6wJVqo}0`=qy zE%g@=j8%dN@v1x!mKp-T+iB5z*P7(;&UjL*?9O5MH`Xqj9T1ePT7i-kyWpJGtPn>- z-J{EFP+>lJvuu-mm`(Plrb_+{9HZ)vl8;p6=3|8JvP#{xT>lz6&XYOmvspvA2NBo> z!GXQFy@YsnFE(`t84AlC^Xt4H_(OS)tHD?dk$I(=wW5L8Mcog})5-zEGUJhx_!I7y`4tAwB8Zi))@Qz`Ta zk?&_)a-*t`d?A?6{e@3%I#>YZU!P#owc$+-pP=5ZrtF@7A>Hq}wwV2fugY*Uv>n6Z z2?`w%@scG_F*DTp0cJ`EyJ1UiJVyXk&%y^EgzL5B7im7Hhz-?3j6qsqZ0n^dMSM*W z%5~S|0G<9_UsiaHVN*l1YHkD-;>gK$cw%&y`u2(I>b_TLe~$O_PblWfz+UnNt|b|6 zYJR^g{aYM~R_zaK2nED`%zr46w$dpKc7l_FCn;QVuJ-aMl1SbO7zBUBw4@K+`5rn@@wqGQm%QN8-|{j%Q#Fp{5RQOo$G|$1TZQN1gKh%V-Rn z4Oxk7%n@sW`^K=(GOgYL3@Cm8H#4l5YqzvBJAcraFtLKiCk`WPLlW&C&Rx8oi#c-A zik8ofT0}AC`C1&|c3SH2Gb1ngWXUl5@G|WPXAdFy;k=|Pe`1L2J5=$i$F zI7&@8-$#}sS%Uc=QV0~q`r9}lZY?YOQkypyPV?8}A8zOz{x|65MT2E1ul$?yWs`Sk z33$u$MLhlNRSHqL)%G@-b>g|(ZfBQXi8>9+rY8}(Y+CY_q|n&%)u>_aL#ILr>7)*c z|7@#d+0-&rAN|2i(%D0ofj8?gka@&844zFwK9P2l^yDM?ulhBI9xM=uUc{Do_L^GU4~^zNqK;h7X~ z?StYZU%hzd%o@i%Mb}k1fUu@-3j=O@lJ}qFb8|)GFUHiKH=33myxA~45xUI~?)T|h zXR%ZY)ZfMQjVDjfU8`wW#3G|kekZcITK@VU7i53GiBDhFa(@>6fGgd`xIDI-SU>Kf z<^1Sgfn4DQasTcFR8l@=lpXY68N3F540zH>4^EDH?GVehSujPoc^|$VBIoP1d2=(r z^cjChLLw=XKN62`iWs`Phs5HmNWhx`zHr;h&$6rZ!@L=+as2&u+a`P~#JHGmK&Q6V z6jBJAp=I_T>7DI*Z!A%wJHSP5gd+ePv~ZG-Th>p!%V+ z!G(A+2O&<6*|Ox&6xCmGs)td)$JchlC^<$MU(by)9zp8J!v^FCY)R1x&#y{j_O|OP zFm-J*lH!eQ|Fc3C%zJ=3G$K}!^oZ=WKgg1FDDEx&g@=8)bUQnK%Y_t&FPu1*{Wn1{ zK!)v?98HF(FnyQSo0aU(6CsEs8nz;w+Nvfcd4hl$4f;vf;yEiNJ|XI8klG{rNl_{4 zTEbmKQ{LOva_y+C4Mc(kd0K&jq~yZWmrIjUs=n0eL^D`QEyz2zubaVN9-@Z>SkCU5 z<-j0hdC4c{if-}(Gy+zhEP#~IeAKlA{fJA~_zGNl$dfIy-Qe$80~`Vy;fVPwNVUqk zS{FsiA=+Yepcyt?T{rR~@q#=OQt0-|ZPb~8ty8W3Dr`})xHsOqIH{QH3OVBRQ{iWt zG2=6GYXEs*<8y8UAMfe9Xj`t4O}US$IB~73hfKVxc}Gs%~^;!ob%=TDrDX2{n9)G+L84m zl(XJudMJ&v6M5#P7;w?h=ee#cd#%pPZK6VH&dxG0K;(Y^q^;w{>o7@^oDz!l2oF#? zvB&{cL8fE{uw=7Gu$j+|W+i zBnlY+vnk!)>)hjol-m`KdxlF_BI(>hW6IJc8=UqwU&~#vj2!eG`BFIOtfC;~=&!j; zx!L_4NN#PzQyb~!F#76u2(yrgCn0}^&)p6GFp_-<3572S0Nu{8B3{`yQqcP|S8B)J zAYP@C9fjlM9GM$MeWxcor?{qx`#pE^F=aGpe~;fk5JTcL*I_1SATw)as&_umu6dS_De-44Vuprn~O?FBxt~ z%p;5TQa^C6qmR7wa9MB#<;G$ft=Iz^GM>Ue5U0R=GCto<(+^d)t@$bhwB#(ZidPcqHcSjlco zDDu$8=-GBCMAj>xx`)KP`cH>O3}Gf?qeJPR;O9_59lffVcF0;l+i?oG8LzeEq zUpG!KYC0v6(*yqJ#HLT=OdI01NKWd>#jBm+{;iA7%}g}*BUfu(zkW2sXO?QTH^0sp zr|A!fMtl7}qz7n&KV<8j)WaZYFgOM*LAv8kZk=`B(RwCt&l=NqlqCfXpR!HoZQu4? ze|{^2so@8M5Npq@$?%2zJdmVSpf6EQQpX*p(a*%rB+tC%QIzEv6U3{cc{Db%B|e-= z+)?f9XO@KbZ|%ljF&-pE0<5I~^NG3E?atd;iSR;yjVQ;(`k?zv z;|_!F+&-4I2<^kIf;lKJs^Ius!zrQt)UPG3qn9vQ1Kvh|%Px1^94&bBSP=QNSY!E% zpL_&LPl9N-WD5TfGz}N~eXOg|`q^ixfwbQ)xP000KjnC3ZyeDowPN-`V5Js@0z-wN o!O&qCFiaR0OxnP^Xd{Y{)%3ZzJNI|Uld2SV49yH`^&DgV4^qiy*#H0l literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@1x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dfc408df0c17b54e2a2e125e64fedb5e4ba7e09a GIT binary patch literal 3834 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 literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..092b7bfeee1274504bc6b7c25fdcd8ba6bf8e15f GIT binary patch literal 8074 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

U=w(Q@cUi! z+&tyT;AU;W)5Pa>O|<2h{H+Q-o6qKgkpK3Z1RlF7k+QW@$xRH3qYEj%B+h&Gj5Ryc z^e#`I7$67ENefif=KC2odP_*655CnN-+@NY75q&2hz7MKD!r{)C%V z5%W$1X%?;xVd9y=$fGF8NgB5Fe!X}ig;;Zp%>nK`1|AHtF z9^GQbE)ZP`d_{tS{%OdRaIo#ISYqVjdE7@?ebkOlJ2>8OsnN?)aTn(IV|$utwa>*r zYxhGcf9x%3EZAf66|5zZElh42e&9Tiojc*?3RW??4LT(qi}=p@hyiKKWtpvJ|E&|#(8fPeMFw7oy7RI zY2xSUa0;)xJxh8{V^aIADWt>pfbGKSeY;p_ls)6N1LW6(NhR9Un-Sg~dxU3OBbe6U z6?h3^TrYM=`LYTjo#R(>e6(kP7r>u!zmI0H-pjP|23@~Z!TiV0VtMt(mGaB*`2Pbu Cq9<$s literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@3x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..521c3e2a6269c88c8d6e6797b53448fe60b6c712 GIT binary patch literal 12001 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

5eY9Ic(R#5mEx&xP_ z|EZa5m~5TwjkA~1lfMXlwv#zJ(=5{qOR7O)u0pi5C;jY9|NZiS)kHK?;2iX;Ge_@D zVY5z)`TtFRIahSnp&`UCtkHY1UQ zImfw=>~u)c`o7Sz;?ZTh*+~sB^+ViFr?zXhHr0&ldeRlPK6wA88IOG>iA{PR!arHQpflW%7{Na+ Td|?l~x(+hbH_@xS=^XQanEHEm literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 00000000..0bedcf2f --- /dev/null +++ b/wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/wire/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +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. \ No newline at end of file diff --git a/wire/ios/Runner/Base.lproj/LaunchScreen.storyboard b/wire/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/wire/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wire/ios/Runner/Base.lproj/Main.storyboard b/wire/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/wire/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wire/ios/Runner/Info.plist b/wire/ios/Runner/Info.plist new file mode 100644 index 00000000..9a1b826d --- /dev/null +++ b/wire/ios/Runner/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + wire_flutter_todo + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/wire/ios/Runner/Runner-Bridging-Header.h b/wire/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..7335fdf9 --- /dev/null +++ b/wire/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" \ No newline at end of file diff --git a/wire/lib/app.dart b/wire/lib/app.dart new file mode 100644 index 00000000..8f020fb0 --- /dev/null +++ b/wire/lib/app.dart @@ -0,0 +1,27 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'package:flutter/material.dart'; +import 'package:todos_app_core/todos_app_core.dart'; +import 'package:wire_flutter_todo/localization.dart'; +import 'package:wire_flutter_todo/screens/add_edit_screen.dart'; +import 'package:wire_flutter_todo/screens/home_screen.dart'; + +class WireApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + onGenerateTitle: (context) => VanillaLocalizations.of(context).appTitle, + theme: ArchSampleTheme.theme, + localizationsDelegates: [ + ArchSampleLocalizationsDelegate(), + VanillaLocalizationsDelegate(), + ], + routes: { + ArchSampleRoutes.home: (context) => HomeScreen(), + ArchSampleRoutes.addTodo: (context) => AddEditScreen(), + }, + ); + } +} diff --git a/wire/lib/const/TodoApplicationState.dart b/wire/lib/const/TodoApplicationState.dart new file mode 100644 index 00000000..f0864f9e --- /dev/null +++ b/wire/lib/const/TodoApplicationState.dart @@ -0,0 +1,4 @@ +enum TodoApplicationState { + LOADING, + READY +} \ No newline at end of file diff --git a/wire/lib/const/TodoDataParams.dart b/wire/lib/const/TodoDataParams.dart new file mode 100644 index 00000000..12779d7b --- /dev/null +++ b/wire/lib/const/TodoDataParams.dart @@ -0,0 +1,9 @@ +class TodoDataParams { + static const String + LIST = 'DATA_TODO__ALL_LIST', + COUNT = 'DATA_TODO__NOT_COMPLETED_COUNT', + FILTER = 'DATA_TODO__FILTER', + STATE = 'DATA_TODO__STATE' + ; +} + diff --git a/wire/lib/const/TodoFilterValues.dart b/wire/lib/const/TodoFilterValues.dart new file mode 100644 index 00000000..3ee05ac4 --- /dev/null +++ b/wire/lib/const/TodoFilterValues.dart @@ -0,0 +1,5 @@ +enum TodoFilterValue { + ALL, + ACTIVE, + COMPLETED +} \ No newline at end of file diff --git a/wire/lib/const/TodoViewSignal.dart b/wire/lib/const/TodoViewSignal.dart new file mode 100644 index 00000000..06780343 --- /dev/null +++ b/wire/lib/const/TodoViewSignal.dart @@ -0,0 +1,14 @@ +class TodoViewSignal { + static const String + INPUT = 'SIGNAL__INPUT_TODO', + EDIT = 'SIGNAL__EDIT_TODO', + DELETE = 'SIGNAL__DELETE_TODO', + DISMISSED = 'SIGNAL__DISMISSED_TODO', + TOGGLE = 'SIGNAL__TOGGLE_TODO', + FILTER = 'SIGNAL__FILTER_TODO', + CLEAR_INPUT = 'SIGNAL__CLEAR_TODO', + CLEAR_COMPLETED = 'SIGNAL__CLEAR_COMPLETED', + COMPLETE_ALL = 'SIGNAL__COMPLETE_ALL' + ; +} + diff --git a/wire/lib/controller/RouteController.dart b/wire/lib/controller/RouteController.dart new file mode 100644 index 00000000..8cb2c307 --- /dev/null +++ b/wire/lib/controller/RouteController.dart @@ -0,0 +1,25 @@ +import 'dart:html'; + +import 'package:wire/wire.dart'; + +import '../const/TodoFilterValues.dart'; +import '../const/TodoViewSignal.dart'; + +class RouteController { + RouteController() { + window.onHashChange.listen((e) { + checkFilterRouterChanged(); + }); + checkFilterRouterChanged(); + } + + void checkFilterRouterChanged () { + var filter; + switch (window.location.hash) { + case '#/': filter = TodoFilterValue.ALL; break; + case '#/active': filter = TodoFilterValue.ACTIVE; break; + case '#/completed': filter = TodoFilterValue.COMPLETED; break; + } + if (filter != null) Wire.send(TodoViewSignal.FILTER, filter); + } +} \ No newline at end of file diff --git a/wire/lib/controller/TodoController.dart b/wire/lib/controller/TodoController.dart new file mode 100644 index 00000000..2cd0ebdc --- /dev/null +++ b/wire/lib/controller/TodoController.dart @@ -0,0 +1,85 @@ +import 'package:wire/wire.dart'; + +import '../const/TodoFilterValues.dart'; +import '../const/TodoViewSignal.dart'; +import '../data/dto/CreateDTO.dart'; +import '../model/TodoModel.dart'; +import '../data/dto/EditDTO.dart'; + +class TodoController { + TodoModel todoModel; + TodoController(this.todoModel) { + + /* + Wire.add(this, TodoViewSignal.INPUT, (data) {s + var text = data as String; + print('> TodoProcessor -> TodoViewOutputSignal.INPUT: ' + text); + if (text != null && text.isNotEmpty) { + todoModel.create(text); + Wire.send(TodoViewSignal.CLEAR); + } + }); + + Wire.add(this, TodoViewSignal.DELETE, (data) { + var todoId = data as String; + print('> TodoProcessor -> TodoViewOutputSignal.DELETE: ' + todoId); + todoModel.remove(todoId); + }); + * */ + + Wire.add(this, TodoViewSignal.INPUT, _SignalProcessor); + Wire.add(this, TodoViewSignal.EDIT, _SignalProcessor); + Wire.add(this, TodoViewSignal.DELETE, _SignalProcessor); + Wire.add(this, TodoViewSignal.TOGGLE, _SignalProcessor); + Wire.add(this, TodoViewSignal.FILTER, _SignalProcessor); + Wire.add(this, TodoViewSignal.CLEAR_COMPLETED, _SignalProcessor); + Wire.add(this, TodoViewSignal.COMPLETE_ALL, _SignalProcessor); + + print('Processor Ready'); + } + + void _SignalProcessor(Wire wire, dynamic data) { + print('> TodoProcessor -> ${wire.signal}: data = ' + data.toString()); + switch (wire.signal) { + case TodoViewSignal.INPUT: + var createDTO = data as CreateDTO; + var text = createDTO.text; + var note = createDTO.note; + if (text != null && text.isNotEmpty) { + todoModel.create(text, note); + Wire.send(TodoViewSignal.CLEAR_INPUT); + } + break; + case TodoViewSignal.EDIT: + var editTodoDTO = data as EditDTO; + var todoText = editTodoDTO.text; + var todoNote = editTodoDTO.note; + var todoId = editTodoDTO.id; + if (todoText.isEmpty) { + todoModel.remove(todoId); + } else { + todoModel.update(todoId, todoText, todoNote); + } + break; + case TodoViewSignal.TOGGLE: + var todoId = data as String; + todoModel.toggle(todoId); + break; + case TodoViewSignal.DELETE: + var todoId = data as String; + todoModel.remove(todoId); + break; + case TodoViewSignal.FILTER: + var filter = data as TodoFilterValue; + todoModel.filter(filter); + break; + case TodoViewSignal.CLEAR_COMPLETED: + todoModel.clearCompleted(); + break; + case TodoViewSignal.COMPLETE_ALL: + var completed = data as bool; + todoModel.setCompletionToAll(completed); + break; + } + } +} \ No newline at end of file diff --git a/wire/lib/data/dto/CreateDTO.dart b/wire/lib/data/dto/CreateDTO.dart new file mode 100644 index 00000000..cb707f35 --- /dev/null +++ b/wire/lib/data/dto/CreateDTO.dart @@ -0,0 +1,6 @@ +class CreateDTO { + final String text; + final String note; + + CreateDTO(this.text, this.note); +} \ No newline at end of file diff --git a/wire/lib/data/dto/EditDTO.dart b/wire/lib/data/dto/EditDTO.dart new file mode 100644 index 00000000..23ff5749 --- /dev/null +++ b/wire/lib/data/dto/EditDTO.dart @@ -0,0 +1,7 @@ +class EditDTO { + final String text; + final String note; + final String id; + + EditDTO(this.id, this.text, this.note); +} \ No newline at end of file diff --git a/wire/lib/data/vo/TodoVO.dart b/wire/lib/data/vo/TodoVO.dart new file mode 100644 index 00000000..171eba4a --- /dev/null +++ b/wire/lib/data/vo/TodoVO.dart @@ -0,0 +1,27 @@ +import 'dart:math'; + +class TodoVO { + bool completed; + String text; + String note; + String id; + + bool visible = true; + + TodoVO(this.id, this.text, this.note, this.completed); + + TodoVO.fromJson(Map json): + id = json['id'], + text = json['text'], + note = json['note'], + completed = json['completed'] + ; + + Map toJson() => + { + 'id': id, + 'text': text, + 'note': note, + 'completed': completed + }; +} \ No newline at end of file diff --git a/wire/lib/localization.dart b/wire/lib/localization.dart new file mode 100644 index 00000000..6bb0bedb --- /dev/null +++ b/wire/lib/localization.dart @@ -0,0 +1,30 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter/material.dart'; + +class VanillaLocalizations { + static VanillaLocalizations of(BuildContext context) { + return Localizations.of( + context, VanillaLocalizations); + } + + String get appTitle => 'Wire Flutter Example'; +} + +class VanillaLocalizationsDelegate + extends LocalizationsDelegate { + @override + Future load(Locale locale) => + Future(() => VanillaLocalizations()); + + @override + bool shouldReload(VanillaLocalizationsDelegate old) => false; + + @override + bool isSupported(Locale locale) => + locale.languageCode.toLowerCase().contains('en'); +} diff --git a/wire/lib/main.dart b/wire/lib/main.dart new file mode 100644 index 00000000..e4528230 --- /dev/null +++ b/wire/lib/main.dart @@ -0,0 +1,34 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:wire/wire.dart'; +import 'package:wire_flutter_todo/service/WebDatabaseService.dart'; + +import 'app.dart'; +import 'const/TodoDataParams.dart'; +import 'const/TodoApplicationState.dart'; +import 'controller/TodoController.dart'; +import 'model/TodoModel.dart'; +import 'service/MobileDatabaseService.dart'; + +var todoModel; +var todoController; + +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + + Wire.data(TodoDataParams.STATE, TodoApplicationState.LOADING); + + var databaseService = kIsWeb ? WebDatabaseService() : MobileDatabaseService(); + await databaseService.init(TodoModel.LOCAL_STORAGE_KEY); + + todoModel = TodoModel(databaseService); + todoController = TodoController(todoModel); + + runApp(WireApp()); + + Wire.data(TodoDataParams.STATE, TodoApplicationState.READY); +} diff --git a/wire/lib/main_web.dart b/wire/lib/main_web.dart new file mode 100644 index 00000000..b50bb799 --- /dev/null +++ b/wire/lib/main_web.dart @@ -0,0 +1,34 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'dart:html'; + +import 'package:flutter/material.dart'; +import 'package:wire/wire.dart'; +import 'package:wire_flutter_todo/app.dart'; +import 'package:wire_flutter_todo/const/TodoApplicationState.dart'; +import 'package:wire_flutter_todo/controller/TodoController.dart'; +import 'package:wire_flutter_todo/service/WebDatabaseService.dart'; + +import 'const/TodoDataParams.dart'; +import 'model/TodoModel.dart'; + +var todoModel; +var todoController; + +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + + Wire.data(TodoDataParams.STATE, TodoApplicationState.LOADING); + + var databaseService = WebDatabaseService(); + await databaseService.init(TodoModel.LOCAL_STORAGE_KEY); + + todoModel = TodoModel(databaseService); + todoController = TodoController(todoModel); + + runApp(WireApp()); + + Wire.data(TodoDataParams.STATE, TodoApplicationState.READY); +} diff --git a/wire/lib/model/TodoModel.dart b/wire/lib/model/TodoModel.dart new file mode 100644 index 00000000..036b1b87 --- /dev/null +++ b/wire/lib/model/TodoModel.dart @@ -0,0 +1,159 @@ +import 'package:wire/wire.dart'; +import '../const/TodoDataParams.dart'; +import '../const/TodoFilterValues.dart'; +import '../service/IDatabaseService.dart'; +import '../data/vo/TodoVO.dart'; + +class TodoModel { + static const String LOCAL_STORAGE_KEY = 'todo-mvc-dart-wire'; + + final IDatabaseService _dbService; + + TodoModel(this._dbService) { + var idsList = []; + var notCompletedCount = 0; + if (_dbService.exist(LOCAL_STORAGE_KEY)) { + try { + _dbService.retrieve(LOCAL_STORAGE_KEY).forEach((obj){ + if (obj != null) { + var todoVO = TodoVO.fromJson(obj); + Wire.data(todoVO.id, todoVO); + idsList.add(todoVO.id); + if (!todoVO.completed) notCompletedCount++; + } + }); + } catch (e) { + print('Error loading form local storage: ' + e.toString()); + } + } + print('> TodoModel list: ${idsList.length}'); + print('> TodoModel count: ${notCompletedCount}'); + Wire.data(TodoDataParams.LIST, idsList); + Wire.data(TodoDataParams.COUNT, notCompletedCount); + } + + TodoVO create(String text, String note) { + final time = DateTime.now().millisecondsSinceEpoch; + final id = time.toString(); + final todoVO = TodoVO(id, text, note, false); + final listData = Wire.data(TodoDataParams.LIST); + final todoList = listData.value as List; + final count = Wire.data(TodoDataParams.COUNT).value as int; + + todoList.add(todoVO.id); + Wire.data(todoVO.id, todoVO); + Wire.data(TodoDataParams.LIST, todoList); + Wire.data(TodoDataParams.COUNT, count + 1); + + _save(); + + print('> TodoModel -> created: ' + todoVO.id + ' - ' + todoVO.text); + return todoVO; + } + + TodoVO remove(String id) { + final todoList = Wire.data(TodoDataParams.LIST).value as List; + final count = Wire.data(TodoDataParams.COUNT).value as int; + final todoWireData = Wire.data(id); + final todoVO = todoWireData.value as TodoVO; + + todoList.remove(id); + todoWireData.remove(); + + if (todoVO.completed == false) { + Wire.data(TodoDataParams.COUNT, count -1); + } + + _save(); + + print('> TodoModel -> removed: ' + id); + return todoVO; + } + + TodoVO update(String id, String text, String note) { + final todoWireData = Wire.data(id); + final todoVO = todoWireData.value as TodoVO; + todoVO.text = text; + todoVO.note = note; + Wire.data(id, todoVO); + _save(); + + print('> TodoModel -> updated: ' + todoVO.id + ' - ' + todoVO.text); + return todoVO; + } + + TodoVO toggle(String id) { + final todoWireData = Wire.data(id); + final todoVO = todoWireData.value as TodoVO; + final count = Wire.data(TodoDataParams.COUNT).value as int; + + todoVO.completed = !todoVO.completed; + + Wire.data(id, todoVO); + Wire.data(TodoDataParams.COUNT, count + (todoVO.completed ? -1 : 1)); + + _save(); + + print('> TodoModel -> toggled: ' + todoVO.id + ' - ' + todoVO.text); + return null; + } + + void filter(TodoFilterValue filter) { + final todoList = Wire.data(TodoDataParams.LIST).value as List; + todoList.forEach((id) { + var todoWireData = Wire.data(id); + var todoVO = todoWireData.value as TodoVO; + var todoVisible = todoVO.visible; + switch (filter) { + case TodoFilterValue.ALL: todoVisible = true; break; + case TodoFilterValue.ACTIVE: todoVisible = !todoVO.completed; break; + case TodoFilterValue.COMPLETED: todoVisible = todoVO.completed; break; + } + if (todoVO.visible != todoVisible) { + todoVO.visible = todoVisible; + Wire.data(id, todoVO); + } + }); + Wire.data(TodoDataParams.FILTER, filter); + print('> TodoModel -> filtered: ' + filter.toString()); + } + + void setCompletionToAll(value) { + final todoList = Wire.data(TodoDataParams.LIST).value as List; + var count = Wire.data(TodoDataParams.COUNT).value as int; + todoList.forEach((id) { + var todoWireData = Wire.data(id); + var todoVO = todoWireData.value as TodoVO; + if (todoVO.completed != value) { + count += value ? -1 : 1; + todoVO.completed = value; + Wire.data(id, todoVO); + } + }); + Wire.data(TodoDataParams.COUNT, count); + _save(); + } + + void clearCompleted() { + final todoList = Wire.data(TodoDataParams.LIST).value as List; + todoList.removeWhere((id) { + var todoWireData = Wire.data(id); + var todoVO = todoWireData.value as TodoVO; + if (todoVO.completed) { + todoWireData.remove(); + } + return todoVO.completed; + }); + Wire.data(TodoDataParams.LIST, todoList); + _save(); + print('> TodoModel -> clearCompleted: length = ' + todoList.length.toString()); + } + + void _save() { + var listToSave = []; + (Wire.data(TodoDataParams.LIST).value as List).forEach((id) => + listToSave.add(Wire.data(id).value) + ); + _dbService.save(LOCAL_STORAGE_KEY, listToSave); + } +} \ No newline at end of file diff --git a/wire/lib/models.dart b/wire/lib/models.dart new file mode 100644 index 00000000..ae77f7d5 --- /dev/null +++ b/wire/lib/models.dart @@ -0,0 +1,54 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'package:todos_app_core/todos_app_core.dart'; +import 'package:todos_repository_core/todos_repository_core.dart'; + +enum AppTab { todos, stats } + +enum ExtraAction { toggleAllComplete, clearCompleted } + +class Todo { + bool complete; + String id; + String note; + String task; + + Todo(this.task, {this.complete = false, this.note = '', String id}) + : id = id ?? Uuid().generateV4(); + + @override + int get hashCode => + complete.hashCode ^ task.hashCode ^ note.hashCode ^ id.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Todo && + runtimeType == other.runtimeType && + complete == other.complete && + task == other.task && + note == other.note && + id == other.id; + + @override + String toString() { + return 'Todo{complete: $complete, task: $task, note: $note, id: $id}'; + } + + TodoEntity toEntity() { + return TodoEntity(task, id, note, complete); + } + + static Todo fromEntity(TodoEntity entity) { + return Todo( + entity.task, + complete: entity.complete ?? false, + note: entity.note, + id: entity.id ?? Uuid().generateV4(), + ); + } +} + +enum VisibilityFilter { all, active, completed } diff --git a/wire/lib/screens/add_edit_screen.dart b/wire/lib/screens/add_edit_screen.dart new file mode 100644 index 00000000..0780b83b --- /dev/null +++ b/wire/lib/screens/add_edit_screen.dart @@ -0,0 +1,106 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:todos_app_core/todos_app_core.dart'; +import 'package:wire_flutter/wire_flutter.dart'; +import 'package:wire_flutter_todo/data/vo/TodoVO.dart'; +import 'package:wire_flutter_todo/data/dto/EditDTO.dart'; +import 'package:wire_flutter_todo/const/TodoViewSignal.dart'; +import 'package:wire_flutter_todo/data/dto/CreateDTO.dart'; +import 'package:wire/wire.dart'; + +class AddEditScreen extends StatefulWidget { + final String id; + + AddEditScreen({ + this.id, + }) : super(key: ArchSampleKeys.addTodoScreen); + + @override + _AddEditScreenState createState() => _AddEditScreenState(); +} + +class _AddEditScreenState extends State { + static final GlobalKey formKey = GlobalKey(); + + String _text; + String _note; + + @override + Widget build(BuildContext context) { + print('isEditing ${isEditing}'); + return Scaffold( + appBar: AppBar( + title: Text(isEditing + ? ArchSampleLocalizations.of(context).editTodo + : ArchSampleLocalizations.of(context).addTodo), + ), + body: Padding( + padding: EdgeInsets.all(16.0), + child: Form( + key: formKey, + autovalidate: false, + onWillPop: () { + return Future(() => true); + }, + child: !isEditing ? ListViewWidget(context, null) : + WireDataBuilder( param: widget.id, + builder: (ctx, todoVO) => ListViewWidget(ctx, todoVO), + ), + ), + ), + floatingActionButton: FloatingActionButton( + key: isEditing + ? ArchSampleKeys.saveTodoFab + : ArchSampleKeys.saveNewTodo, + tooltip: isEditing + ? ArchSampleLocalizations.of(context).saveChanges + : ArchSampleLocalizations.of(context).addTodo, + child: Icon(isEditing ? Icons.check : Icons.add), + onPressed: () { + final form = formKey.currentState; + if (form.validate()) { + form.save(); + + if (isEditing) { + Wire.send(TodoViewSignal.EDIT, EditDTO(widget.id, _text, _note)); + } else { + Wire.send(TodoViewSignal.INPUT, CreateDTO(_text, _note)); + } + + Navigator.pop(context); + } + }), + ); + } + + Widget ListViewWidget(context, todoVO) => ListView( + children: [ + TextFormField( + initialValue: todoVO?.text ?? '', + key: ArchSampleKeys.taskField, + autofocus: isEditing ? false : true, + style: Theme.of(context).textTheme.headline, + decoration: InputDecoration(hintText: ArchSampleLocalizations.of(context).newTodoHint), + validator: (val) => val.trim().isEmpty + ? ArchSampleLocalizations.of(context).emptyTodoError + : null, + onSaved: (value) => _text = value, + ), + TextFormField( + initialValue: todoVO?.note ?? '', + key: ArchSampleKeys.noteField, + maxLines: 10, + style: Theme.of(context).textTheme.subhead, + decoration: InputDecoration(hintText: ArchSampleLocalizations.of(context).notesHint,), + onSaved: (value) => _note = value, + ) + ], + ); + + bool get isEditing => widget.id != null; +} diff --git a/wire/lib/screens/detail_screen.dart b/wire/lib/screens/detail_screen.dart new file mode 100644 index 00000000..ac2e2058 --- /dev/null +++ b/wire/lib/screens/detail_screen.dart @@ -0,0 +1,89 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:todos_app_core/todos_app_core.dart'; +import 'package:wire_flutter_todo/const/TodoViewSignal.dart'; +import 'package:wire_flutter_todo/data/vo/TodoVO.dart'; +import 'package:wire_flutter_todo/screens/add_edit_screen.dart'; +import 'package:wire/wire.dart'; +import 'package:wire_flutter/wire_flutter.dart'; + +class DetailScreen extends StatelessWidget { + final String id; + final Function onDelete; + + DetailScreen({ + @required this.id, + @required this.onDelete, + }) : super(key: ArchSampleKeys.todoDetailsScreen); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(ArchSampleLocalizations.of(context).todoDetails), + actions: [ + IconButton( + key: ArchSampleKeys.deleteTodoButton, + tooltip: ArchSampleLocalizations.of(context).deleteTodo, + icon: Icon(Icons.delete), + onPressed: () { + Navigator.pop(context); + onDelete(); + }, + ) + ], + ), + body: Padding( + padding: EdgeInsets.all(16.0), + child: WireDataBuilder( + param: id, + builder: (context, todoVO) => ListView( + children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(right: 8.0), + child: Checkbox( value: todoVO.completed, + key: ArchSampleKeys.detailsTodoItemCheckbox, + onChanged: (value) => Wire.send(TodoViewSignal.TOGGLE, id), + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(top: 8.0, bottom: 16.0,), + child: Text(todoVO.text, + key: ArchSampleKeys.detailsTodoItemTask, + style: Theme.of(context).textTheme.headline, + ), + ), + Text(todoVO.note, + key: ArchSampleKeys.detailsTodoItemNote, + style: Theme.of(context).textTheme.subhead, + ) + ], + ), + ), + ]), + ], + ), + ), + ), + floatingActionButton: FloatingActionButton( + tooltip: ArchSampleLocalizations.of(context).editTodo, + child: Icon(Icons.edit), + key: ArchSampleKeys.editTodoFab, + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => AddEditScreen(id: id)), + ); + }, + ), + ); + } +} diff --git a/wire/lib/screens/home_screen.dart b/wire/lib/screens/home_screen.dart new file mode 100644 index 00000000..bed947ba --- /dev/null +++ b/wire/lib/screens/home_screen.dart @@ -0,0 +1,100 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:wire/wire.dart'; +import 'package:todos_app_core/todos_app_core.dart'; +import 'package:wire_flutter/wire_flutter.dart'; +import 'package:wire_flutter_todo/const/TodoDataParams.dart'; +import 'package:wire_flutter_todo/const/TodoFilterValues.dart'; +import 'package:wire_flutter_todo/const/TodoViewSignal.dart'; +import 'package:wire_flutter_todo/localization.dart'; +import 'package:wire_flutter_todo/models.dart'; +import 'package:wire_flutter_todo/widgets/buttons/extra_actions_button.dart'; +import 'package:wire_flutter_todo/widgets/buttons/filter_button.dart'; +import 'package:wire_flutter_todo/widgets/stats_counter.dart'; +import 'package:wire_flutter_todo/widgets/list/todo_list_widget.dart'; + +class HomeScreen extends StatefulWidget { + HomeScreen() : super(key: ArchSampleKeys.homeScreen); + @override + State createState() => HomeScreenState(); +} + +class HomeScreenState extends State { + AppTab activeTab = AppTab.todos; + + void _updateTab(AppTab tab) { + setState(() { + activeTab = tab; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(VanillaLocalizations.of(context).appTitle), + actions: [ + FilterButton( + isActive: activeTab == AppTab.todos, + activeFilter: TodoFilterValue.ALL, + onSelected: (filter) => Wire.send(TodoViewSignal.FILTER, filter), + ), + WireDataBuilder( + param: TodoDataParams.COUNT, + builder: (context, not_completed_count) { + var allTodoCount = Wire.data(TodoDataParams.LIST).value.length; + var allCompleted = not_completed_count == 0 && allTodoCount > 0; + var hasCompletedTodos = (allTodoCount - not_completed_count) > 0; + return ExtraActionsButton( + allComplete: allCompleted, + hasCompletedTodos: hasCompletedTodos, + onSelected: (action) { + if (action == ExtraAction.toggleAllComplete) { + Wire.send(TodoViewSignal.COMPLETE_ALL, !allCompleted); + } else if (action == ExtraAction.clearCompleted) { + Wire.send(TodoViewSignal.CLEAR_COMPLETED); + } + }, + );}, + ) + ], + ), + body: activeTab == AppTab.todos + ? TodoList() + : StatsCounter(), + + floatingActionButton: FloatingActionButton( + key: ArchSampleKeys.addTodoFab, + onPressed: () => Navigator.pushNamed(context, ArchSampleRoutes.addTodo), + child: Icon(Icons.add), + tooltip: ArchSampleLocalizations.of(context).addTodo, + ), + bottomNavigationBar: BottomNavigationWidget(activeTab) + ); + } + + Widget BottomNavigationWidget(activeTab) => BottomNavigationBar( + key: ArchSampleKeys.tabs, + currentIndex: AppTab.values.indexOf(activeTab), + onTap: (index) { _updateTab(AppTab.values[index]); }, + items: AppTab.values.map((tab) { + return BottomNavigationBarItem( + icon: Icon( + tab == AppTab.todos ? Icons.list : Icons.show_chart, + key: tab == AppTab.stats + ? ArchSampleKeys.statsTab + : ArchSampleKeys.todoTab, + ), + title: Text( + tab == AppTab.stats + ? ArchSampleLocalizations.of(context).stats + : ArchSampleLocalizations.of(context).todos, + ), + ); + }).toList(), + ); +} diff --git a/wire/lib/service/IDatabaseService.dart b/wire/lib/service/IDatabaseService.dart new file mode 100644 index 00000000..ae6c1cc4 --- /dev/null +++ b/wire/lib/service/IDatabaseService.dart @@ -0,0 +1,6 @@ +abstract class IDatabaseService { + Future init([String key]); + bool exist(String key); + dynamic retrieve(String key); + void save(String key, dynamic data); +} \ No newline at end of file diff --git a/wire/lib/service/MobileDatabaseService.dart b/wire/lib/service/MobileDatabaseService.dart new file mode 100644 index 00000000..1529772b --- /dev/null +++ b/wire/lib/service/MobileDatabaseService.dart @@ -0,0 +1,48 @@ +import 'dart:convert'; + +import 'package:key_value_store_flutter/key_value_store_flutter.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:wire_flutter_todo/models.dart'; +import 'package:todos_repository_core/todos_repository_core.dart'; +import 'package:todos_repository_local_storage/todos_repository_local_storage.dart'; + +import 'IDatabaseService.dart'; + +class MobileDatabaseService extends IDatabaseService { + MobileDatabaseService(); + + TodosRepository repository; + var jsonList = []; + + @override + Future init([String key]) async { + repository = LocalStorageRepository( + localStorage: KeyValueStorage( + key, + FlutterKeyValueStore(await SharedPreferences.getInstance()), + )); + await repository.loadTodos().then((loadedTodos) { + loadedTodos.forEach((todoEntry) => { + jsonList.add({ + 'id': todoEntry.id, + 'text': todoEntry.task, + 'note': todoEntry.note, + 'completed': todoEntry.complete + }) + }); + }); + } + + @override + bool exist(String key) { return true; } + + @override + dynamic retrieve(String key) { + return jsonList; + } + + @override + void save(String key, dynamic data) { + + } +} \ No newline at end of file diff --git a/wire/lib/service/WebDatabaseService.dart b/wire/lib/service/WebDatabaseService.dart new file mode 100644 index 00000000..b0ba08d7 --- /dev/null +++ b/wire/lib/service/WebDatabaseService.dart @@ -0,0 +1,24 @@ +import 'dart:html'; +import 'dart:convert'; + +import 'IDatabaseService.dart'; + +class WebDatabaseService extends IDatabaseService { + @override + bool exist(String key) { + return window.localStorage.containsKey(key); + } + + @override + dynamic retrieve(String key) { + return jsonDecode(window.localStorage[key]); + } + + @override + void save(String key, dynamic data) { + window.localStorage[key] = jsonEncode(data); + } + + @override + Future init([String key]) { } +} \ No newline at end of file diff --git a/wire/lib/widgets/buttons/extra_actions_button.dart b/wire/lib/widgets/buttons/extra_actions_button.dart new file mode 100644 index 00000000..a6ee7358 --- /dev/null +++ b/wire/lib/widgets/buttons/extra_actions_button.dart @@ -0,0 +1,42 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'package:flutter/material.dart'; +import 'package:todos_app_core/todos_app_core.dart'; +import 'package:wire_flutter_todo/models.dart'; + +class ExtraActionsButton extends StatelessWidget { + final PopupMenuItemSelected onSelected; + final bool allComplete; + final bool hasCompletedTodos; + + ExtraActionsButton({ + this.onSelected, + this.allComplete, + this.hasCompletedTodos, + Key key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return PopupMenuButton( + key: ArchSampleKeys.extraActionsButton, + onSelected: onSelected, + itemBuilder: (BuildContext context) => >[ + PopupMenuItem( + key: ArchSampleKeys.toggleAll, + value: ExtraAction.toggleAllComplete, + child: Text(allComplete + ? ArchSampleLocalizations.of(context).markAllIncomplete + : ArchSampleLocalizations.of(context).markAllComplete), + ), + if (hasCompletedTodos) PopupMenuItem( + key: ArchSampleKeys.clearCompleted, + value: ExtraAction.clearCompleted, + child: Text(ArchSampleLocalizations.of(context).clearCompleted), + ), + ], + ); + } +} diff --git a/wire/lib/widgets/buttons/filter_button.dart b/wire/lib/widgets/buttons/filter_button.dart new file mode 100644 index 00000000..4c583fed --- /dev/null +++ b/wire/lib/widgets/buttons/filter_button.dart @@ -0,0 +1,94 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'package:flutter/material.dart'; +import 'package:todos_app_core/todos_app_core.dart'; +import 'package:wire_flutter_todo/const/TodoFilterValues.dart'; + +class FilterButton extends StatelessWidget { + final PopupMenuItemSelected onSelected; + final TodoFilterValue activeFilter; + final bool isActive; + + FilterButton({this.onSelected, this.activeFilter, this.isActive, Key key}) + : super(key: key); + + @override + Widget build(BuildContext context) { + final defaultStyle = Theme.of(context).textTheme.body1; + final activeStyle = Theme.of(context) + .textTheme + .body1 + .copyWith(color: Theme.of(context).accentColor); + final button = _Button( + onSelected: onSelected, + activeFilter: activeFilter, + activeStyle: activeStyle, + defaultStyle: defaultStyle, + ); + + return AnimatedOpacity( + opacity: isActive ? 1.0 : 0.0, + duration: Duration(milliseconds: 150), + child: isActive ? button : IgnorePointer(child: button), + ); + } +} + +class _Button extends StatelessWidget { + const _Button({ + Key key, + @required this.onSelected, + @required this.activeFilter, + @required this.activeStyle, + @required this.defaultStyle, + }) : super(key: key); + + final PopupMenuItemSelected onSelected; + final TodoFilterValue activeFilter; + final TextStyle activeStyle; + final TextStyle defaultStyle; + + @override + Widget build(BuildContext context) { + return PopupMenuButton( + key: ArchSampleKeys.filterButton, + tooltip: ArchSampleLocalizations.of(context).filterTodos, + onSelected: onSelected, + itemBuilder: (BuildContext context) => >[ + PopupMenuItem( + key: ArchSampleKeys.allFilter, + value: TodoFilterValue.ALL, + child: Text( + ArchSampleLocalizations.of(context).showAll, + style: activeFilter == TodoFilterValue.ALL + ? activeStyle + : defaultStyle, + ), + ), + PopupMenuItem( + key: ArchSampleKeys.activeFilter, + value: TodoFilterValue.ACTIVE, + child: Text( + ArchSampleLocalizations.of(context).showActive, + style: activeFilter == TodoFilterValue.ACTIVE + ? activeStyle + : defaultStyle, + ), + ), + PopupMenuItem( + key: ArchSampleKeys.completedFilter, + value: TodoFilterValue.COMPLETED, + child: Text( + ArchSampleLocalizations.of(context).showCompleted, + style: activeFilter == TodoFilterValue.COMPLETED + ? activeStyle + : defaultStyle, + ), + ), + ], + icon: Icon(Icons.filter_list), + ); + } +} diff --git a/wire/lib/widgets/list/todo_item_widget.dart b/wire/lib/widgets/list/todo_item_widget.dart new file mode 100644 index 00000000..96ab7c50 --- /dev/null +++ b/wire/lib/widgets/list/todo_item_widget.dart @@ -0,0 +1,56 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:todos_app_core/todos_app_core.dart'; +import 'package:wire_flutter_todo/const/TodoViewSignal.dart'; +import 'package:wire_flutter_todo/data/vo/TodoVO.dart'; +import 'package:wire_flutter_todo/models.dart'; +import 'package:wire/wire.dart'; +import 'package:wire_flutter/wire_flutter.dart'; + +class TodoItem extends StatelessWidget { + + final String id; + final GestureTapCallback onTap; + final ValueChanged onToggle; + + TodoItem({ + Key key, + @required this.id, + @required this.onTap, + @required this.onToggle, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return WireDataBuilder( + param: id, + builder: (context, todoVO) => Visibility( + visible: todoVO.visible, + child: ListTile( + onTap: onTap, + leading: Checkbox( + key: ArchSampleKeys.todoItemCheckbox(todoVO.id), + value: todoVO.completed, + onChanged: onToggle, + ), + title: Text( + todoVO.text, + key: ArchSampleKeys.todoItemTask(todoVO.id), + style: Theme.of(context).textTheme.title, + ), + subtitle: Text( + todoVO.note, + key: ArchSampleKeys.todoItemNote(todoVO.id), + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.subhead, + ), + ), + ), + ); + } +} diff --git a/wire/lib/widgets/list/todo_list_widget.dart b/wire/lib/widgets/list/todo_list_widget.dart new file mode 100644 index 00000000..b5fad31a --- /dev/null +++ b/wire/lib/widgets/list/todo_list_widget.dart @@ -0,0 +1,94 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:todos_app_core/todos_app_core.dart'; +import 'package:wire_flutter_todo/const/TodoDataParams.dart'; +import 'package:wire_flutter_todo/const/TodoViewSignal.dart'; +import 'package:wire_flutter_todo/const/TodoApplicationState.dart'; +import 'package:wire_flutter_todo/data/dto/CreateDTO.dart'; +import 'package:wire_flutter_todo/data/vo/TodoVO.dart'; +import 'package:wire_flutter_todo/screens/detail_screen.dart'; +import 'package:wire_flutter_todo/widgets/list/todo_item_widget.dart'; +import 'package:wire/wire.dart'; +import 'package:wire_flutter/wire_flutter.dart'; + +import '../../const/TodoDataParams.dart'; + +class TodoList extends StatelessWidget { + + TodoList() : super(key: ArchSampleKeys.todoList); + + @override + Widget build(BuildContext context) { + return WireDataBuilder( + param: TodoDataParams.STATE, + builder: (context, state) => Container( + child: state == TodoApplicationState.LOADING + ? Center( + child: CircularProgressIndicator( + key: ArchSampleKeys.todosLoading, + )) + : WireDataBuilder>( + param: TodoDataParams.LIST, + builder: (context, list) => ListView.builder( + key: ArchSampleKeys.todoList, + itemCount: list.length, + itemBuilder: (BuildContext context, int index) { + final todoId = list[index]; + return Dismissible( + key: ArchSampleKeys.todoItem(todoId), + onDismissed: (direction) { + _removeTodo(context, todoId); + }, + child: TodoItem( + id: todoId, + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) { + return DetailScreen( + id: todoId, + onDelete: () => { + _removeTodo(context, todoId) + }, + ); + }, + ), + ); + }, + onToggle: (value) => + Wire.send(TodoViewSignal.TOGGLE, todoId), + ), + ); + }, + ), + ), + ), + ); + } + + void _removeTodo(BuildContext context, String todoId) { + var todoWireData = Wire.data(todoId); + TodoVO todoVO = todoWireData.value; + Wire.send(TodoViewSignal.DELETE, todoId); + + Scaffold.of(context).showSnackBar( + SnackBar( + key: ArchSampleKeys.snackbar, + duration: Duration(seconds: 2), + content: Text( + ArchSampleLocalizations.of(context).todoDeleted(todoVO.text), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + action: SnackBarAction( + label: ArchSampleLocalizations.of(context).undo, + onPressed: () => Wire.send(TodoViewSignal.INPUT, CreateDTO(todoVO.text, todoVO.note)) + ), + ), + ); + } +} diff --git a/wire/lib/widgets/stats_counter.dart b/wire/lib/widgets/stats_counter.dart new file mode 100644 index 00000000..23511a14 --- /dev/null +++ b/wire/lib/widgets/stats_counter.dart @@ -0,0 +1,60 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:todos_app_core/todos_app_core.dart'; +import 'package:wire/wire.dart'; +import 'package:wire_flutter/wire_flutter.dart'; +import 'package:wire_flutter_todo/const/TodoDataParams.dart'; + +class StatsCounter extends StatelessWidget { + StatsCounter() : super(key: ArchSampleKeys.statsCounter); + + @override + Widget build(BuildContext context) { + return Center( + child: WireDataBuilder( + param: TodoDataParams.COUNT, + builder: (context, not_completed_count) { + var allTodoCount = Wire.data(TodoDataParams.LIST).value.length; + var numCompleted = allTodoCount - not_completed_count; + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + ArchSampleLocalizations.of(context).completedTodos, + style: Theme.of(context).textTheme.title, + ), + ), + Padding( + padding: EdgeInsets.only(bottom: 24.0), + child: Text('$numCompleted', + key: ArchSampleKeys.statsNumCompleted, + style: Theme.of(context).textTheme.subhead, + ), + ), + Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + ArchSampleLocalizations.of(context).activeTodos, + style: Theme.of(context).textTheme.title, + ), + ), + Padding( + padding: EdgeInsets.only(bottom: 24.0), + child: Text( + '$not_completed_count', + key: ArchSampleKeys.statsNumActive, + style: Theme.of(context).textTheme.subhead, + ), + ) + ], + );}, + ), + ); + } +} diff --git a/wire/pubspec.yaml b/wire/pubspec.yaml new file mode 100644 index 00000000..75a45b0a --- /dev/null +++ b/wire/pubspec.yaml @@ -0,0 +1,82 @@ +name: wire_flutter_todo +description: A new Flutter project. + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=2.2.2 <3.0.0" + +dependencies: + flutter: + sdk: flutter + todos_app_core: + path: ../todos_app_core + todos_repository_local_storage: + path: ../todos_repository_local_storage + key_value_store_flutter: + key_value_store_web: + shared_preferences: + wire: + wire_flutter: + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_driver: + sdk: flutter + test: + mockito: + integration_tests: + path: ../integration_tests + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/wire/test/app_state_test.dart b/wire/test/app_state_test.dart new file mode 100644 index 00000000..7f83856d --- /dev/null +++ b/wire/test/app_state_test.dart @@ -0,0 +1,110 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'package:test/test.dart'; +import 'package:wire_flutter_todo/models.dart'; + +void main() { + group('AppState', () { +// test('should check if there are completed todos', () { +// final state = AppState(todos: [ +// Todo('a'), +// Todo('b'), +// Todo('c', complete: true), +// ]); +// +// expect(state.hasCompletedTodos, true); +// }); +// +// test('should calculate the number of active todos', () { +// final state = AppState(todos: [ +// Todo('a'), +// Todo('b'), +// Todo('c', complete: true), +// ]); +// +// expect(state.numActive, 2); +// }); +// +// +// test('should return active todos if the VisibilityFilter is active', () { +// final todo1 = Todo('a'); +// final todo2 = Todo('b'); +// final todo3 = Todo('c', complete: true); +// final todos = [ +// todo1, +// todo2, +// todo3, +// ]; +// final state = AppState( +// todos: todos, +// ); +// +// expect(state.filteredTodos(VisibilityFilter.active), [ +// todo1, +// todo2, +// ]); +// }); +// +// test('should return completed todos if the VisibilityFilter is completed', +// () { +// final todo1 = Todo('a'); +// final todo2 = Todo('b'); +// final todo3 = Todo('c', complete: true); +// final todos = [ +// todo1, +// todo2, +// todo3, +// ]; +// final state = AppState( +// todos: todos, +// ); +// +// expect(state.filteredTodos(VisibilityFilter.completed), [todo3]); +// }); +// +// test('should clear the completed todos', () { +// final todo1 = Todo('a'); +// final todo2 = Todo('b'); +// final todo3 = Todo('c', complete: true); +// final todos = [ +// todo1, +// todo2, +// todo3, +// ]; +// final state = AppState( +// todos: todos, +// ); +// +// state.clearCompleted(); +// +// expect(state.todos, [ +// todo1, +// todo2, +// ]); +// }); +// +// test('toggle all as complete or incomplete', () { +// final todo1 = Todo('a'); +// final todo2 = Todo('b'); +// final todo3 = Todo('c', complete: true); +// final todos = [ +// todo1, +// todo2, +// todo3, +// ]; +// final state = AppState( +// todos: todos, +// ); +// +// // Toggle all complete +// state.toggleAll(); +// expect(state.todos.every((t) => t.complete), isTrue); +// +// // Toggle all incomplete +// state.toggleAll(); +// expect(state.todos.every((t) => !t.complete), isTrue); +// }); + }); +} diff --git a/wire/test_driver/todo_app.dart b/wire/test_driver/todo_app.dart new file mode 100644 index 00000000..dd9b3ec2 --- /dev/null +++ b/wire/test_driver/todo_app.dart @@ -0,0 +1,13 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +// This line imports the extension +import 'package:flutter_driver/driver_extension.dart'; +import 'package:wire_flutter_todo/main.dart' as app; + +void main() { + enableFlutterDriverExtension(); + + app.main(); +} diff --git a/wire/test_driver/todo_app_test.dart b/wire/test_driver/todo_app_test.dart new file mode 100644 index 00000000..ad93f5a5 --- /dev/null +++ b/wire/test_driver/todo_app_test.dart @@ -0,0 +1,9 @@ +// Copyright 2018 The Flutter Architecture Sample Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be found +// in the LICENSE file. + +import 'package:integration_tests/integration_tests.dart' as integration_tests; + +void main() { + integration_tests.main(); +} diff --git a/wire/web/favicon.png b/wire/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/wire/web/icons/Icon-192.png b/wire/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/wire/web/icons/Icon-512.png b/wire/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/wire/web/index.html b/wire/web/index.html new file mode 100644 index 00000000..31c9d35b --- /dev/null +++ b/wire/web/index.html @@ -0,0 +1,10 @@ + + + + + wire_flutter_todo + + + + + diff --git a/wire/web/manifest.json b/wire/web/manifest.json new file mode 100644 index 00000000..20bf7247 --- /dev/null +++ b/wire/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "wire_flutter_todo", + "short_name": "wire_flutter_todo", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "Wire Flutter application.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} From afe33e56417faef82c279fe8174d61c9692dec63 Mon Sep 17 00:00:00 2001 From: Vladimir Minkin Date: Tue, 14 Jul 2020 19:48:36 +0200 Subject: [PATCH 2/3] [Work In Progress] Updated version to match changes and rendering strategy in wire_flutter. Also material theme update. --- .../kotlin/com/example/wire/MainActivity.kt | 6 ++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++ .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++ .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++++++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes wire/lib/controller/TodoController.dart | 3 +- wire/lib/data/dto/CreateDTO.dart | 3 +- wire/lib/data/vo/TodoVO.dart | 2 -- wire/lib/main.dart | 4 +-- wire/lib/model/TodoModel.dart | 11 ++++--- wire/lib/screens/add_edit_screen.dart | 4 +-- wire/lib/screens/detail_screen.dart | 4 +-- wire/lib/screens/home_screen.dart | 7 ++--- wire/lib/service/MobileDatabaseService.dart | 3 -- wire/lib/widgets/buttons/filter_button.dart | 4 +-- wire/lib/widgets/list/todo_item_widget.dart | 7 ++--- wire/lib/widgets/list/todo_list_widget.dart | 3 +- wire/lib/widgets/stats_counter.dart | 14 ++++----- wire/test/app_state_test.dart | 1 - wire/test/widget_test.dart | 27 ++++++++++++++++++ .../src}/WebDatabaseService.dart | 4 +-- wire/{lib => web/src}/main_web.dart | 8 ++---- 23 files changed, 101 insertions(+), 46 deletions(-) create mode 100644 wire/android/app/src/main/kotlin/com/example/wire/MainActivity.kt create mode 100644 wire/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 wire/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 wire/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 wire/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 wire/test/widget_test.dart rename wire/{lib/service => web/src}/WebDatabaseService.dart (81%) rename wire/{lib => web/src}/main_web.dart (79%) diff --git a/wire/android/app/src/main/kotlin/com/example/wire/MainActivity.kt b/wire/android/app/src/main/kotlin/com/example/wire/MainActivity.kt new file mode 100644 index 00000000..eb7d1bff --- /dev/null +++ b/wire/android/app/src/main/kotlin/com/example/wire/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.wire + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/wire/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/wire/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/wire/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/wire/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/wire/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/wire/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/wire/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/wire/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/wire/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/wire/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/wire/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/wire/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/wire/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 main() async { Wire.data(TodoDataParams.STATE, TodoApplicationState.LOADING); - var databaseService = kIsWeb ? WebDatabaseService() : MobileDatabaseService(); + var databaseService = MobileDatabaseService(); await databaseService.init(TodoModel.LOCAL_STORAGE_KEY); todoModel = TodoModel(databaseService); diff --git a/wire/lib/model/TodoModel.dart b/wire/lib/model/TodoModel.dart index 036b1b87..ee3f9f51 100644 --- a/wire/lib/model/TodoModel.dart +++ b/wire/lib/model/TodoModel.dart @@ -32,10 +32,10 @@ class TodoModel { Wire.data(TodoDataParams.COUNT, notCompletedCount); } - TodoVO create(String text, String note) { + TodoVO create(String text, String note, bool completed) { final time = DateTime.now().millisecondsSinceEpoch; final id = time.toString(); - final todoVO = TodoVO(id, text, note, false); + final todoVO = TodoVO(id, text, note, completed); final listData = Wire.data(TodoDataParams.LIST); final todoList = listData.value as List; final count = Wire.data(TodoDataParams.COUNT).value as int; @@ -43,7 +43,7 @@ class TodoModel { todoList.add(todoVO.id); Wire.data(todoVO.id, todoVO); Wire.data(TodoDataParams.LIST, todoList); - Wire.data(TodoDataParams.COUNT, count + 1); + Wire.data(TodoDataParams.COUNT, count + (completed ? 0 : 1)); _save(); @@ -61,8 +61,10 @@ class TodoModel { todoWireData.remove(); if (todoVO.completed == false) { - Wire.data(TodoDataParams.COUNT, count -1); + Wire.data(TodoDataParams.COUNT, count - 1); } + // Only difference with web version in Wire repositories (example TodoMVC) + Wire.data(TodoDataParams.LIST, todoList); _save(); @@ -121,6 +123,7 @@ class TodoModel { void setCompletionToAll(value) { final todoList = Wire.data(TodoDataParams.LIST).value as List; var count = Wire.data(TodoDataParams.COUNT).value as int; + print('> TodoModel -> setCompletionToAll: $value - ' + count.toString()); todoList.forEach((id) { var todoWireData = Wire.data(id); var todoVO = todoWireData.value as TodoVO; diff --git a/wire/lib/screens/add_edit_screen.dart b/wire/lib/screens/add_edit_screen.dart index 0780b83b..f9759cde 100644 --- a/wire/lib/screens/add_edit_screen.dart +++ b/wire/lib/screens/add_edit_screen.dart @@ -84,7 +84,7 @@ class _AddEditScreenState extends State { initialValue: todoVO?.text ?? '', key: ArchSampleKeys.taskField, autofocus: isEditing ? false : true, - style: Theme.of(context).textTheme.headline, + style: Theme.of(context).textTheme.headline6, decoration: InputDecoration(hintText: ArchSampleLocalizations.of(context).newTodoHint), validator: (val) => val.trim().isEmpty ? ArchSampleLocalizations.of(context).emptyTodoError @@ -95,7 +95,7 @@ class _AddEditScreenState extends State { initialValue: todoVO?.note ?? '', key: ArchSampleKeys.noteField, maxLines: 10, - style: Theme.of(context).textTheme.subhead, + style: Theme.of(context).textTheme.subtitle1, decoration: InputDecoration(hintText: ArchSampleLocalizations.of(context).notesHint,), onSaved: (value) => _note = value, ) diff --git a/wire/lib/screens/detail_screen.dart b/wire/lib/screens/detail_screen.dart index ac2e2058..2686bd4c 100644 --- a/wire/lib/screens/detail_screen.dart +++ b/wire/lib/screens/detail_screen.dart @@ -59,12 +59,12 @@ class DetailScreen extends StatelessWidget { padding: EdgeInsets.only(top: 8.0, bottom: 16.0,), child: Text(todoVO.text, key: ArchSampleKeys.detailsTodoItemTask, - style: Theme.of(context).textTheme.headline, + style: Theme.of(context).textTheme.headline6, ), ), Text(todoVO.note, key: ArchSampleKeys.detailsTodoItemNote, - style: Theme.of(context).textTheme.subhead, + style: Theme.of(context).textTheme.subtitle1, ) ], ), diff --git a/wire/lib/screens/home_screen.dart b/wire/lib/screens/home_screen.dart index bed947ba..fdd68c96 100644 --- a/wire/lib/screens/home_screen.dart +++ b/wire/lib/screens/home_screen.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by the MIT license that can be found // in the LICENSE file. -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:wire/wire.dart'; import 'package:todos_app_core/todos_app_core.dart'; @@ -45,10 +44,10 @@ class HomeScreenState extends State { ), WireDataBuilder( param: TodoDataParams.COUNT, - builder: (context, not_completed_count) { + builder: (context, notCompletedCount) { var allTodoCount = Wire.data(TodoDataParams.LIST).value.length; - var allCompleted = not_completed_count == 0 && allTodoCount > 0; - var hasCompletedTodos = (allTodoCount - not_completed_count) > 0; + var allCompleted = notCompletedCount == 0 && allTodoCount > 0; + var hasCompletedTodos = (allTodoCount - notCompletedCount) > 0; return ExtraActionsButton( allComplete: allCompleted, hasCompletedTodos: hasCompletedTodos, diff --git a/wire/lib/service/MobileDatabaseService.dart b/wire/lib/service/MobileDatabaseService.dart index 1529772b..ac234e04 100644 --- a/wire/lib/service/MobileDatabaseService.dart +++ b/wire/lib/service/MobileDatabaseService.dart @@ -1,8 +1,5 @@ -import 'dart:convert'; - import 'package:key_value_store_flutter/key_value_store_flutter.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:wire_flutter_todo/models.dart'; import 'package:todos_repository_core/todos_repository_core.dart'; import 'package:todos_repository_local_storage/todos_repository_local_storage.dart'; diff --git a/wire/lib/widgets/buttons/filter_button.dart b/wire/lib/widgets/buttons/filter_button.dart index 4c583fed..d74c5991 100644 --- a/wire/lib/widgets/buttons/filter_button.dart +++ b/wire/lib/widgets/buttons/filter_button.dart @@ -16,10 +16,10 @@ class FilterButton extends StatelessWidget { @override Widget build(BuildContext context) { - final defaultStyle = Theme.of(context).textTheme.body1; + final defaultStyle = Theme.of(context).textTheme.bodyText1; final activeStyle = Theme.of(context) .textTheme - .body1 + .bodyText1 .copyWith(color: Theme.of(context).accentColor); final button = _Button( onSelected: onSelected, diff --git a/wire/lib/widgets/list/todo_item_widget.dart b/wire/lib/widgets/list/todo_item_widget.dart index 96ab7c50..02d1a228 100644 --- a/wire/lib/widgets/list/todo_item_widget.dart +++ b/wire/lib/widgets/list/todo_item_widget.dart @@ -5,10 +5,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:todos_app_core/todos_app_core.dart'; -import 'package:wire_flutter_todo/const/TodoViewSignal.dart'; import 'package:wire_flutter_todo/data/vo/TodoVO.dart'; -import 'package:wire_flutter_todo/models.dart'; -import 'package:wire/wire.dart'; import 'package:wire_flutter/wire_flutter.dart'; class TodoItem extends StatelessWidget { @@ -40,14 +37,14 @@ class TodoItem extends StatelessWidget { title: Text( todoVO.text, key: ArchSampleKeys.todoItemTask(todoVO.id), - style: Theme.of(context).textTheme.title, + style: Theme.of(context).textTheme.headline6, ), subtitle: Text( todoVO.note, key: ArchSampleKeys.todoItemNote(todoVO.id), maxLines: 1, overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.subhead, + style: Theme.of(context).textTheme.subtitle1, ), ), ), diff --git a/wire/lib/widgets/list/todo_list_widget.dart b/wire/lib/widgets/list/todo_list_widget.dart index b5fad31a..3a77bb0d 100644 --- a/wire/lib/widgets/list/todo_list_widget.dart +++ b/wire/lib/widgets/list/todo_list_widget.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by the MIT license that can be found // in the LICENSE file. -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:todos_app_core/todos_app_core.dart'; import 'package:wire_flutter_todo/const/TodoDataParams.dart'; @@ -86,7 +85,7 @@ class TodoList extends StatelessWidget { ), action: SnackBarAction( label: ArchSampleLocalizations.of(context).undo, - onPressed: () => Wire.send(TodoViewSignal.INPUT, CreateDTO(todoVO.text, todoVO.note)) + onPressed: () => Wire.send(TodoViewSignal.INPUT, CreateDTO(todoVO.text, todoVO.note, todoVO.completed)) ), ), ); diff --git a/wire/lib/widgets/stats_counter.dart b/wire/lib/widgets/stats_counter.dart index 23511a14..135d5d59 100644 --- a/wire/lib/widgets/stats_counter.dart +++ b/wire/lib/widgets/stats_counter.dart @@ -17,9 +17,9 @@ class StatsCounter extends StatelessWidget { return Center( child: WireDataBuilder( param: TodoDataParams.COUNT, - builder: (context, not_completed_count) { + builder: (context, notCompletedCount) { var allTodoCount = Wire.data(TodoDataParams.LIST).value.length; - var numCompleted = allTodoCount - not_completed_count; + var numCompleted = allTodoCount - notCompletedCount; return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -27,29 +27,29 @@ class StatsCounter extends StatelessWidget { padding: EdgeInsets.only(bottom: 8.0), child: Text( ArchSampleLocalizations.of(context).completedTodos, - style: Theme.of(context).textTheme.title, + style: Theme.of(context).textTheme.bodyText1, ), ), Padding( padding: EdgeInsets.only(bottom: 24.0), child: Text('$numCompleted', key: ArchSampleKeys.statsNumCompleted, - style: Theme.of(context).textTheme.subhead, + style: Theme.of(context).textTheme.subtitle1, ), ), Padding( padding: EdgeInsets.only(bottom: 8.0), child: Text( ArchSampleLocalizations.of(context).activeTodos, - style: Theme.of(context).textTheme.title, + style: Theme.of(context).textTheme.subtitle2, ), ), Padding( padding: EdgeInsets.only(bottom: 24.0), child: Text( - '$not_completed_count', + '$notCompletedCount', key: ArchSampleKeys.statsNumActive, - style: Theme.of(context).textTheme.subhead, + style: Theme.of(context).textTheme.subtitle1, ), ) ], diff --git a/wire/test/app_state_test.dart b/wire/test/app_state_test.dart index 7f83856d..634b936a 100644 --- a/wire/test/app_state_test.dart +++ b/wire/test/app_state_test.dart @@ -3,7 +3,6 @@ // in the LICENSE file. import 'package:test/test.dart'; -import 'package:wire_flutter_todo/models.dart'; void main() { group('AppState', () { diff --git a/wire/test/widget_test.dart b/wire/test/widget_test.dart new file mode 100644 index 00000000..5967b1a8 --- /dev/null +++ b/wire/test/widget_test.dart @@ -0,0 +1,27 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. +// await tester.pumpWidget(MyApp()); +// +// // Verify that our counter starts at 0. +// expect(find.text('0'), findsOneWidget); +// expect(find.text('1'), findsNothing); +// +// // Tap the '+' icon and trigger a frame. +// await tester.tap(find.byIcon(Icons.add)); +// await tester.pump(); +// +// // Verify that our counter has incremented. +// expect(find.text('0'), findsNothing); +// expect(find.text('1'), findsOneWidget); + }); +} diff --git a/wire/lib/service/WebDatabaseService.dart b/wire/web/src/WebDatabaseService.dart similarity index 81% rename from wire/lib/service/WebDatabaseService.dart rename to wire/web/src/WebDatabaseService.dart index b0ba08d7..fa60f79c 100644 --- a/wire/lib/service/WebDatabaseService.dart +++ b/wire/web/src/WebDatabaseService.dart @@ -1,7 +1,7 @@ import 'dart:html'; import 'dart:convert'; -import 'IDatabaseService.dart'; +import '../../lib/service/IDatabaseService.dart'; class WebDatabaseService extends IDatabaseService { @override @@ -20,5 +20,5 @@ class WebDatabaseService extends IDatabaseService { } @override - Future init([String key]) { } + Future init([String key]) { return null; } } \ No newline at end of file diff --git a/wire/lib/main_web.dart b/wire/web/src/main_web.dart similarity index 79% rename from wire/lib/main_web.dart rename to wire/web/src/main_web.dart index b50bb799..3d617c18 100644 --- a/wire/lib/main_web.dart +++ b/wire/web/src/main_web.dart @@ -2,17 +2,15 @@ // Use of this source code is governed by the MIT license that can be found // in the LICENSE file. -import 'dart:html'; - import 'package:flutter/material.dart'; import 'package:wire/wire.dart'; import 'package:wire_flutter_todo/app.dart'; import 'package:wire_flutter_todo/const/TodoApplicationState.dart'; import 'package:wire_flutter_todo/controller/TodoController.dart'; -import 'package:wire_flutter_todo/service/WebDatabaseService.dart'; +import 'file:///Users/vladimir.minkin/Documents/Projects/Personal/Flutter/flutter_architecture_samples/wire/web/src/WebDatabaseService.dart'; -import 'const/TodoDataParams.dart'; -import 'model/TodoModel.dart'; +import '../../lib/const/TodoDataParams.dart'; +import '../../lib/model/TodoModel.dart'; var todoModel; var todoController; From bb30fc619ba1860d3878893b62aa5e11de9446ce Mon Sep 17 00:00:00 2001 From: Vladimir Minkin Date: Sat, 25 Jul 2020 21:48:41 +0200 Subject: [PATCH 3/3] [Work In Progress] Underlaying library update (now explicit) - wire updated to 0.9.7 and wire_flutter to 0.9.0, necessary updates in the application was applied. --- wire/lib/controller/TodoController.dart | 3 ++- wire/lib/screens/add_edit_screen.dart | 2 +- wire/lib/screens/detail_screen.dart | 2 +- wire/lib/screens/home_screen.dart | 2 +- wire/lib/widgets/list/todo_item_widget.dart | 2 +- wire/lib/widgets/list/todo_list_widget.dart | 4 ++-- wire/lib/widgets/stats_counter.dart | 2 +- wire/pubspec.yaml | 4 ++-- 8 files changed, 11 insertions(+), 10 deletions(-) diff --git a/wire/lib/controller/TodoController.dart b/wire/lib/controller/TodoController.dart index e9cad601..c5e3ea7d 100644 --- a/wire/lib/controller/TodoController.dart +++ b/wire/lib/controller/TodoController.dart @@ -38,7 +38,8 @@ class TodoController { print('Processor Ready'); } - void _SignalProcessor(Wire wire, dynamic data) { + void _SignalProcessor(dynamic data, int wid) { + var wire = Wire.get(wid: wid).single; print('> TodoProcessor -> ${wire.signal}: data = ' + data.toString()); switch (wire.signal) { case TodoViewSignal.INPUT: diff --git a/wire/lib/screens/add_edit_screen.dart b/wire/lib/screens/add_edit_screen.dart index f9759cde..238cbac8 100644 --- a/wire/lib/screens/add_edit_screen.dart +++ b/wire/lib/screens/add_edit_screen.dart @@ -48,7 +48,7 @@ class _AddEditScreenState extends State { return Future(() => true); }, child: !isEditing ? ListViewWidget(context, null) : - WireDataBuilder( param: widget.id, + WireDataBuilder( dataKey: widget.id, builder: (ctx, todoVO) => ListViewWidget(ctx, todoVO), ), ), diff --git a/wire/lib/screens/detail_screen.dart b/wire/lib/screens/detail_screen.dart index 2686bd4c..28cbc74d 100644 --- a/wire/lib/screens/detail_screen.dart +++ b/wire/lib/screens/detail_screen.dart @@ -40,7 +40,7 @@ class DetailScreen extends StatelessWidget { body: Padding( padding: EdgeInsets.all(16.0), child: WireDataBuilder( - param: id, + dataKey: id, builder: (context, todoVO) => ListView( children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/wire/lib/screens/home_screen.dart b/wire/lib/screens/home_screen.dart index fdd68c96..2a325164 100644 --- a/wire/lib/screens/home_screen.dart +++ b/wire/lib/screens/home_screen.dart @@ -43,7 +43,7 @@ class HomeScreenState extends State { onSelected: (filter) => Wire.send(TodoViewSignal.FILTER, filter), ), WireDataBuilder( - param: TodoDataParams.COUNT, + dataKey: TodoDataParams.COUNT, builder: (context, notCompletedCount) { var allTodoCount = Wire.data(TodoDataParams.LIST).value.length; var allCompleted = notCompletedCount == 0 && allTodoCount > 0; diff --git a/wire/lib/widgets/list/todo_item_widget.dart b/wire/lib/widgets/list/todo_item_widget.dart index 02d1a228..05e26d13 100644 --- a/wire/lib/widgets/list/todo_item_widget.dart +++ b/wire/lib/widgets/list/todo_item_widget.dart @@ -24,7 +24,7 @@ class TodoItem extends StatelessWidget { @override Widget build(BuildContext context) { return WireDataBuilder( - param: id, + dataKey: id, builder: (context, todoVO) => Visibility( visible: todoVO.visible, child: ListTile( diff --git a/wire/lib/widgets/list/todo_list_widget.dart b/wire/lib/widgets/list/todo_list_widget.dart index 3a77bb0d..7f07480d 100644 --- a/wire/lib/widgets/list/todo_list_widget.dart +++ b/wire/lib/widgets/list/todo_list_widget.dart @@ -23,7 +23,7 @@ class TodoList extends StatelessWidget { @override Widget build(BuildContext context) { return WireDataBuilder( - param: TodoDataParams.STATE, + dataKey: TodoDataParams.STATE, builder: (context, state) => Container( child: state == TodoApplicationState.LOADING ? Center( @@ -31,7 +31,7 @@ class TodoList extends StatelessWidget { key: ArchSampleKeys.todosLoading, )) : WireDataBuilder>( - param: TodoDataParams.LIST, + dataKey: TodoDataParams.LIST, builder: (context, list) => ListView.builder( key: ArchSampleKeys.todoList, itemCount: list.length, diff --git a/wire/lib/widgets/stats_counter.dart b/wire/lib/widgets/stats_counter.dart index 135d5d59..a2141695 100644 --- a/wire/lib/widgets/stats_counter.dart +++ b/wire/lib/widgets/stats_counter.dart @@ -16,7 +16,7 @@ class StatsCounter extends StatelessWidget { Widget build(BuildContext context) { return Center( child: WireDataBuilder( - param: TodoDataParams.COUNT, + dataKey: TodoDataParams.COUNT, builder: (context, notCompletedCount) { var allTodoCount = Wire.data(TodoDataParams.LIST).value.length; var numCompleted = allTodoCount - notCompletedCount; diff --git a/wire/pubspec.yaml b/wire/pubspec.yaml index 75a45b0a..f6922863 100644 --- a/wire/pubspec.yaml +++ b/wire/pubspec.yaml @@ -26,8 +26,8 @@ dependencies: key_value_store_flutter: key_value_store_web: shared_preferences: - wire: - wire_flutter: + wire: ^0.9.7 + wire_flutter: ^0.9.0 dev_dependencies: flutter_test: