├── android ├── gradle.properties ├── .settings │ └── org.eclipse.buildship.core.prefs ├── app │ ├── .settings │ │ └── org.eclipse.buildship.core.prefs │ ├── src │ │ └── main │ │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── launch_image.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── launch_image.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── launch_image.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── launch_image.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── launch_image.png │ │ │ ├── values │ │ │ │ └── styles.xml │ │ │ └── drawable │ │ │ │ └── launch_background.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── watchtips │ │ │ │ └── MainActivity.java │ │ │ └── AndroidManifest.xml │ ├── .classpath │ ├── .project │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── .project ├── settings.gradle └── build.gradle ├── ios ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── AppFrameworkInfo.plist ├── Runner │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── Icon.png │ │ │ ├── Icon-40.png │ │ │ ├── Icon-72.png │ │ │ ├── Icon-76.png │ │ │ ├── Icon@2x.png │ │ │ ├── Icon-40@2x.png │ │ │ ├── Icon-40@3x.png │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-60@3x.png │ │ │ ├── Icon-72@2x.png │ │ │ ├── Icon-76@2x.png │ │ │ ├── Icon-Small.png │ │ │ ├── Icon-83.5@2x.png │ │ │ ├── Icon-Small-50.png │ │ │ ├── Icon-Small@2x.png │ │ │ ├── Icon-Small@3x.png │ │ │ ├── ios-marketing.png │ │ │ ├── Icon-Small-50@2x.png │ │ │ ├── NotificationIcon@2x.png │ │ │ ├── NotificationIcon@3x.png │ │ │ ├── NotificationIcon~ipad.png │ │ │ ├── NotificationIcon~ipad@2x.png │ │ │ └── Contents.json │ │ └── watchtipssplash.imageset │ │ │ ├── watchtipssplash.png │ │ │ └── Contents.json │ ├── main.m │ ├── AppDelegate.h │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ ├── Info.plist │ └── AppDelegate.m ├── WatchTips │ ├── Assets.xcassets │ │ ├── Contents.json │ │ └── AppIcon.appiconset │ │ │ ├── Icon38mm@2x.png │ │ │ ├── Icon40mm@2x.png │ │ │ ├── Icon42mm@2x.png │ │ │ ├── Icon44mm@2x.png │ │ │ ├── IconLauncher@2x.png │ │ │ ├── IconSettings@2x.png │ │ │ ├── IconSettings@3x.png │ │ │ ├── watch-marketing.png │ │ │ ├── IconQuickLook38mm@2x.png │ │ │ ├── IconQuickLook42mm@2x.png │ │ │ ├── IconQuickLook44mm@2x.png │ │ │ └── Contents.json │ ├── Info.plist │ └── Base.lproj │ │ └── Interface.storyboard ├── WatchTips Extension │ ├── Assets.xcassets │ │ ├── Contents.json │ │ └── Complication.complicationset │ │ │ ├── Circular.imageset │ │ │ └── Contents.json │ │ │ ├── Modular.imageset │ │ │ └── Contents.json │ │ │ ├── Extra Large.imageset │ │ │ └── Contents.json │ │ │ ├── Graphic Bezel.imageset │ │ │ └── Contents.json │ │ │ ├── Utilitarian.imageset │ │ │ └── Contents.json │ │ │ ├── Graphic Circular.imageset │ │ │ └── Contents.json │ │ │ ├── Graphic Corner.imageset │ │ │ └── Contents.json │ │ │ ├── Graphic Large Rectangular.imageset │ │ │ └── Contents.json │ │ │ └── Contents.json │ ├── Info.plist │ ├── ExtensionDelegate.swift │ ├── InterfaceController.swift │ └── BillController.swift ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── Runner.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ ├── xcshareddata │ └── xcschemes │ │ └── Runner.xcscheme │ └── project.pbxproj ├── screenshots └── watchtips.png ├── .metadata ├── lib ├── colors.dart ├── widgets │ ├── key.dart │ └── scaleroute.dart ├── main.dart ├── numberpad.dart └── homescreen.dart ├── test └── widget_test.dart ├── .gitignore ├── pubspec.yaml └── README.md /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /android/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir= 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /android/app/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir=.. 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /screenshots/watchtips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/screenshots/watchtips.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } -------------------------------------------------------------------------------- /ios/WatchTips Extension/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/launch_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/android/app/src/main/res/mipmap-hdpi/launch_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/launch_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/android/app/src/main/res/mipmap-mdpi/launch_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/launch_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/android/app/src/main/res/mipmap-xhdpi/launch_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/launch_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/android/app/src/main/res/mipmap-xxhdpi/launch_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/launch_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/android/app/src/main/res/mipmap-xxxhdpi/launch_image.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-72.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-72@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-Small-50.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/ios-marketing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/ios-marketing.png -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/AppIcon.appiconset/Icon38mm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/WatchTips/Assets.xcassets/AppIcon.appiconset/Icon38mm@2x.png -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/AppIcon.appiconset/Icon40mm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/WatchTips/Assets.xcassets/AppIcon.appiconset/Icon40mm@2x.png -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/AppIcon.appiconset/Icon42mm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/WatchTips/Assets.xcassets/AppIcon.appiconset/Icon42mm@2x.png -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/AppIcon.appiconset/Icon44mm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/WatchTips/Assets.xcassets/AppIcon.appiconset/Icon44mm@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/NotificationIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/NotificationIcon@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/NotificationIcon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/NotificationIcon@3x.png -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/AppIcon.appiconset/IconLauncher@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/WatchTips/Assets.xcassets/AppIcon.appiconset/IconLauncher@2x.png -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/AppIcon.appiconset/IconSettings@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/WatchTips/Assets.xcassets/AppIcon.appiconset/IconSettings@2x.png -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/AppIcon.appiconset/IconSettings@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/WatchTips/Assets.xcassets/AppIcon.appiconset/IconSettings@3x.png -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/AppIcon.appiconset/watch-marketing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/WatchTips/Assets.xcassets/AppIcon.appiconset/watch-marketing.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/NotificationIcon~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/NotificationIcon~ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/watchtipssplash.imageset/watchtipssplash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/watchtipssplash.imageset/watchtipssplash.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/NotificationIcon~ipad@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/NotificationIcon~ipad@2x.png -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/AppIcon.appiconset/IconQuickLook38mm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/WatchTips/Assets.xcassets/AppIcon.appiconset/IconQuickLook38mm@2x.png -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/AppIcon.appiconset/IconQuickLook42mm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/WatchTips/Assets.xcassets/AppIcon.appiconset/IconQuickLook42mm@2x.png -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/AppIcon.appiconset/IconQuickLook44mm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnatronus/flutter-watchtips/HEAD/ios/WatchTips/Assets.xcassets/AppIcon.appiconset/IconQuickLook44mm@2x.png -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip 7 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /android/app/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /ios/WatchTips Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "scale" : "2x", 11 | "screen-width" : ">145" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/WatchTips Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "scale" : "2x", 11 | "screen-width" : ">145" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/WatchTips Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "scale" : "2x", 11 | "screen-width" : ">145" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/WatchTips Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "scale" : "2x", 11 | "screen-width" : ">145" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/WatchTips Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "scale" : "2x", 11 | "screen-width" : ">145" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/WatchTips Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "scale" : "2x", 11 | "screen-width" : ">145" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/WatchTips Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "scale" : "2x", 11 | "screen-width" : ">145" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/WatchTips Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "scale" : "2x", 11 | "screen-width" : ">145" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | 6 | @interface WTUserInfoHandler : NSObject 7 | @end 8 | 9 | // Modified to add the Watch Session Delegate 10 | @interface AppDelegate : FlutterAppDelegate { 11 | @private 12 | WCSession *watchSession; 13 | WTUserInfoHandler* userInfoStreamHandler; 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/watchtipssplash.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "watchtipssplash.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /lib/colors.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// This defines the colours used in the app 4 | const appPrimaryColor = Color(0xFF000000);//Color(0xFFE6E6E6); 5 | const appScaffoldColor = Color(0xFF000000);//Color(0xFFE6E6E6); 6 | const accentTextColor = Color(0xFFFC6666); 7 | const appPrimaryTextColor = Color(0xFFFFFFFF); 8 | const appTextColor = Colors.grey;//Color(0xFF333333); //Color(0xFFFECC66); 9 | const appButtonColor = Color(0xFF7F7F7F); 10 | const appPrimaryButtonColor = Colors.orange; 11 | -------------------------------------------------------------------------------- /android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | android 4 | Project android created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.2.1' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /android/app/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app 4 | Project app created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | -------------------------------------------------------------------------------- /lib/widgets/key.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | 4 | class RoundKey extends StatelessWidget { 5 | 6 | final String value; 7 | final Color color; 8 | final Function onPressed; 9 | 10 | RoundKey(this.value, {@required this.onPressed, this.color: Colors.grey}); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return Padding( 15 | padding: EdgeInsets.all(5.0), 16 | child: RaisedButton( 17 | color: color, 18 | shape: RoundedRectangleBorder( 19 | borderRadius: new BorderRadius.circular(35.0), 20 | ), 21 | onPressed: () { 22 | onPressed(value); 23 | }, 24 | child: Text( 25 | value, 26 | style: Theme.of(context).primaryTextTheme.headline 27 | ), 28 | ), 29 | ); 30 | } 31 | } -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:watchtips/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /ios/WatchTips/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | watch tips 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | UISupportedInterfaceOrientations 24 | 25 | UIInterfaceOrientationPortrait 26 | UIInterfaceOrientationPortraitUpsideDown 27 | 28 | WKCompanionAppBundleIdentifier 29 | uk.spiralarm.tipcalculator 30 | WKWatchKitApp 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ios/WatchTips Extension/Assets.xcassets/Complication.complicationset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets" : [ 3 | { 4 | "idiom" : "watch", 5 | "filename" : "Circular.imageset", 6 | "role" : "circular" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "filename" : "Extra Large.imageset", 11 | "role" : "extra-large" 12 | }, 13 | { 14 | "idiom" : "watch", 15 | "filename" : "Graphic Bezel.imageset", 16 | "role" : "graphic-bezel" 17 | }, 18 | { 19 | "idiom" : "watch", 20 | "filename" : "Graphic Circular.imageset", 21 | "role" : "graphic-circular" 22 | }, 23 | { 24 | "idiom" : "watch", 25 | "filename" : "Graphic Corner.imageset", 26 | "role" : "graphic-corner" 27 | }, 28 | { 29 | "idiom" : "watch", 30 | "filename" : "Graphic Large Rectangular.imageset", 31 | "role" : "graphic-large-rectangular" 32 | }, 33 | { 34 | "idiom" : "watch", 35 | "filename" : "Modular.imageset", 36 | "role" : "modular" 37 | }, 38 | { 39 | "idiom" : "watch", 40 | "filename" : "Utilitarian.imageset", 41 | "role" : "utilitarian" 42 | } 43 | ], 44 | "info" : { 45 | "version" : 1, 46 | "author" : "xcode" 47 | } 48 | } -------------------------------------------------------------------------------- /ios/WatchTips Extension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | WatchTips Extension 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | NSExtension 24 | 25 | NSExtensionAttributes 26 | 27 | WKAppBundleIdentifier 28 | uk.spiralarm.tipcalculator.watchkitapp 29 | 30 | NSExtensionPointIdentifier 31 | com.apple.watchkit 32 | 33 | WKExtensionDelegateClassName 34 | $(PRODUCT_MODULE_NAME).ExtensionDelegate 35 | 36 | 37 | -------------------------------------------------------------------------------- /lib/widgets/scaleroute.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// Navigator Route that scale the specified widget up and down 4 | class ScaleRoute extends PageRouteBuilder { 5 | final Widget widget; 6 | 7 | ScaleRoute({this.widget}) 8 | : super(pageBuilder: (BuildContext context, Animation animation, 9 | Animation secondaryAnimation) { 10 | return widget; 11 | }, transitionsBuilder: (BuildContext context, 12 | Animation animation, 13 | Animation secondaryAnimation, 14 | Widget child) { 15 | return ScaleTransition( 16 | scale: Tween( 17 | begin: 0.0, 18 | end: 1.0, 19 | ).animate( 20 | CurvedAnimation( 21 | parent: animation, 22 | curve: Interval( 23 | 0.00, 24 | 0.50, 25 | curve: Curves.elasticIn, 26 | ), 27 | ), 28 | ), 29 | child: ScaleTransition( 30 | scale: Tween( 31 | begin: 0.5, 32 | end: 1.0, 33 | ).animate( 34 | CurvedAnimation( 35 | parent: animation, 36 | curve: Interval( 37 | 0.50, 38 | 1.00, 39 | curve: Curves.decelerate, 40 | ), 41 | ), 42 | ), 43 | child: child, 44 | ), 45 | ); 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/example/watchtips/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.watchtips; 2 | 3 | import android.os.Bundle; 4 | import io.flutter.app.FlutterActivity; 5 | import io.flutter.plugins.GeneratedPluginRegistrant; 6 | import io.flutter.plugin.common.MethodCall; 7 | import io.flutter.plugin.common.MethodChannel; 8 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 9 | import io.flutter.plugin.common.MethodChannel.Result; 10 | import android.content.res.Resources; 11 | import android.os.LocaleList; 12 | import java.util.*; 13 | 14 | 15 | public class MainActivity extends FlutterActivity { 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | GeneratedPluginRegistrant.registerWith(this); 20 | new MethodChannel(getFlutterView(), "uk.spiralarm.watchtips/tipinfo").setMethodCallHandler( 21 | new MethodCallHandler() { 22 | @Override 23 | public void onMethodCall(MethodCall call, Result result) { 24 | if (call.method.equals("preferredLanguages")) { 25 | result.success(getPreferredLanguages()); 26 | } else { 27 | result.notImplemented(); 28 | } 29 | } 30 | }); 31 | } 32 | 33 | private List getPreferredLanguages() { 34 | LocaleList list = Resources.getSystem().getConfiguration().getLocales().getAdjustedDefault(); 35 | List result = new ArrayList(); 36 | for(int i=0; i 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Watch Tips 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | watchtips 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UIBackgroundModes 28 | 29 | fetch 30 | remote-notification 31 | 32 | UILaunchStoryboardName 33 | LaunchScreen 34 | UIMainStoryboardFile 35 | Main 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | 40 | UISupportedInterfaceOrientations~ipad 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationPortraitUpsideDown 44 | UIInterfaceOrientationLandscapeLeft 45 | UIInterfaceOrientationLandscapeRight 46 | 47 | UIViewControllerBasedStatusBarAppearance 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 10 | 11 | 16 | 20 | 27 | 31 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'homescreen.dart'; 4 | import 'colors.dart'; 5 | 6 | /// Kick the Tyres and Light the Fires 7 | void main() { 8 | SystemChrome.setPreferredOrientations([ 9 | DeviceOrientation.portraitUp, 10 | DeviceOrientation.portraitDown, 11 | ]); 12 | runApp(TipCalculator()); 13 | } 14 | 15 | class TipCalculator extends StatelessWidget { 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | debugShowCheckedModeBanner: false, 20 | title: 'Tip Calculator', 21 | home: HomeScreen(), 22 | theme: _buildAppTheme(), 23 | ); 24 | } 25 | 26 | /// Define a modified theme for the app 27 | ThemeData _buildAppTheme() { 28 | final ThemeData base = ThemeData.light(); 29 | return base.copyWith( 30 | primaryColor: appPrimaryColor, 31 | backgroundColor: Colors.yellow, 32 | scaffoldBackgroundColor: appScaffoldColor, 33 | textSelectionColor: appPrimaryTextColor, 34 | cursorColor: appPrimaryTextColor, 35 | 36 | textTheme: base.textTheme.apply( 37 | bodyColor: appTextColor, 38 | displayColor: appTextColor, 39 | ), 40 | 41 | primaryTextTheme: base.primaryTextTheme.apply( 42 | bodyColor: appPrimaryTextColor, 43 | displayColor: appPrimaryTextColor, 44 | ), 45 | 46 | accentTextTheme: base.primaryTextTheme.apply( 47 | bodyColor: accentTextColor, 48 | displayColor: accentTextColor, 49 | ), 50 | 51 | buttonTheme: base.buttonTheme.copyWith( 52 | buttonColor: appButtonColor, 53 | textTheme: ButtonTextTheme.primary 54 | ), 55 | 56 | iconTheme: base.iconTheme.copyWith( 57 | color: appPrimaryButtonColor, 58 | ), 59 | 60 | /* 61 | inputDecorationTheme: InputDecorationTheme( 62 | labelStyle: TextStyle(color: appTextColor, fontSize: 25.0), 63 | enabledBorder: const OutlineInputBorder( 64 | borderSide: const BorderSide(color: appPrimaryTextColor, width: 2.0), 65 | ), 66 | focusedBorder: const OutlineInputBorder( 67 | borderSide: const BorderSide(color: appPrimaryTextColor, width: 2.0), 68 | ), 69 | ), 70 | */ 71 | 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /ios/WatchTips/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon38mm@2x.png", 5 | "role" : "notificationCenter", 6 | "subtype" : "38mm", 7 | "scale" : "2x", 8 | "idiom" : "watch", 9 | "size" : "24x24" 10 | }, 11 | { 12 | "filename" : "Icon42mm@2x.png", 13 | "role" : "notificationCenter", 14 | "subtype" : "42mm", 15 | "scale" : "2x", 16 | "idiom" : "watch", 17 | "size" : "27.5x27.5" 18 | }, 19 | { 20 | "filename" : "IconSettings@2x.png", 21 | "scale" : "2x", 22 | "role" : "companionSettings", 23 | "idiom" : "watch", 24 | "size" : "29x29" 25 | }, 26 | { 27 | "filename" : "IconSettings@3x.png", 28 | "scale" : "3x", 29 | "role" : "companionSettings", 30 | "idiom" : "watch", 31 | "size" : "29x29" 32 | }, 33 | { 34 | "filename" : "IconLauncher@2x.png", 35 | "role" : "appLauncher", 36 | "subtype" : "38mm", 37 | "scale" : "2x", 38 | "idiom" : "watch", 39 | "size" : "40x40" 40 | }, 41 | { 42 | "filename" : "IconQuickLook38mm@2x.png", 43 | "role" : "quickLook", 44 | "subtype" : "38mm", 45 | "scale" : "2x", 46 | "idiom" : "watch", 47 | "size" : "86x86" 48 | }, 49 | { 50 | "filename" : "IconQuickLook42mm@2x.png", 51 | "role" : "quickLook", 52 | "subtype" : "42mm", 53 | "scale" : "2x", 54 | "idiom" : "watch", 55 | "size" : "98x98" 56 | }, 57 | { 58 | "filename" : "watch-marketing.png", 59 | "scale" : "1x", 60 | "idiom" : "watch-marketing", 61 | "size" : "1024x1024" 62 | }, 63 | { 64 | "filename" : "Icon40mm@2x.png", 65 | "role" : "appLauncher", 66 | "subtype" : "40mm", 67 | "scale" : "2x", 68 | "idiom" : "watch", 69 | "size" : "44x44" 70 | }, 71 | { 72 | "filename" : "Icon44mm@2x.png", 73 | "role" : "appLauncher", 74 | "subtype" : "44mm", 75 | "scale" : "2x", 76 | "idiom" : "watch", 77 | "size" : "50x50" 78 | }, 79 | { 80 | "filename" : "IconQuickLook44mm@2x.png", 81 | "role" : "quickLook", 82 | "subtype" : "44mm", 83 | "scale" : "2x", 84 | "idiom" : "watch", 85 | "size" : "108x108" 86 | } 87 | ], 88 | "info" : { 89 | "author" : "xcode", 90 | "version" : 1 91 | } 92 | } -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | def keystoreProperties = new Properties() 28 | def keystorePropertiesFile = rootProject.file('key.properties') 29 | if (keystorePropertiesFile.exists()) { 30 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 31 | } 32 | 33 | android { 34 | compileSdkVersion 27 35 | 36 | lintOptions { 37 | disable 'InvalidPackage' 38 | } 39 | 40 | defaultConfig { 41 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 42 | applicationId "uk.spiralarm.tipcalculator" 43 | minSdkVersion 16 44 | targetSdkVersion 27 45 | versionCode flutterVersionCode.toInteger() 46 | versionName flutterVersionName 47 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 48 | } 49 | 50 | signingConfigs { 51 | release { 52 | keyAlias keystoreProperties['keyAlias'] 53 | keyPassword keystoreProperties['keyPassword'] 54 | storeFile file(keystoreProperties['storeFile']) 55 | storePassword keystoreProperties['storePassword'] 56 | } 57 | } 58 | buildTypes { 59 | release { 60 | signingConfig signingConfigs.release 61 | } 62 | } 63 | } 64 | 65 | flutter { 66 | source '../..' 67 | } 68 | 69 | dependencies { 70 | testImplementation 'junit:junit:4.12' 71 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 72 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 73 | } 74 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: watchtips 2 | description: A Combined Flutter iOS and watchOS app, now with iPad and Android support 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # Read more about versioning at semver.org. 10 | version: 2.2.0+1 11 | 12 | environment: 13 | sdk: ">=2.0.0-dev.68.0 <3.0.0" 14 | 15 | dependencies: 16 | flutter: 17 | sdk: flutter 18 | 19 | # The following adds the Cupertino Icons font to your application. 20 | # Use with the CupertinoIcons class for iOS style icons. 21 | cupertino_icons: ^0.1.2 22 | intl: ^0.15.7 23 | 24 | dev_dependencies: 25 | flutter_test: 26 | sdk: flutter 27 | 28 | 29 | # For information on the generic Dart part of this file, see the 30 | # following page: https://www.dartlang.org/tools/pub/pubspec 31 | 32 | # The following section is specific to Flutter. 33 | flutter: 34 | 35 | # The following line ensures that the Material Icons font is 36 | # included with your application, so that you can use the icons in 37 | # the material Icons class. 38 | uses-material-design: true 39 | 40 | # To add assets to your application, add an assets section, like this: 41 | # assets: 42 | # - images/a_dot_burr.jpeg 43 | # - images/a_dot_ham.jpeg 44 | 45 | # An image asset can refer to one or more resolution-specific "variants", see 46 | # https://flutter.io/assets-and-images/#resolution-aware. 47 | 48 | # For details regarding adding assets from package dependencies, see 49 | # https://flutter.io/assets-and-images/#from-packages 50 | 51 | # To add custom fonts to your application, add a fonts section here, 52 | # in this "flutter" section. Each entry in this list should have a 53 | # "family" key with the font family name, and a "fonts" key with a 54 | # list giving the asset and other descriptors for the font. For 55 | # example: 56 | # fonts: 57 | # - family: Schyler 58 | # fonts: 59 | # - asset: fonts/Schyler-Regular.ttf 60 | # - asset: fonts/Schyler-Italic.ttf 61 | # style: italic 62 | # - family: Trajan Pro 63 | # fonts: 64 | # - asset: fonts/TrajanPro.ttf 65 | # - asset: fonts/TrajanPro_Bold.ttf 66 | # weight: 700 67 | # 68 | # For details regarding fonts from package dependencies, 69 | # see https://flutter.io/custom-fonts/#from-packages 70 | -------------------------------------------------------------------------------- /ios/WatchTips Extension/ExtensionDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExtensionDelegate.swift 3 | // WatchTips Extension 4 | // 5 | // Created by Stephen Rogers on 27/01/2019. 6 | // Copyright © 2019 The Chromium Authors. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | 11 | class ExtensionDelegate: NSObject, WKExtensionDelegate { 12 | 13 | func applicationDidFinishLaunching() { 14 | // Perform any final initialization of your application. 15 | } 16 | 17 | func applicationDidBecomeActive() { 18 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 19 | } 20 | 21 | func applicationWillResignActive() { 22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 23 | // Use this method to pause ongoing tasks, disable timers, etc. 24 | } 25 | 26 | func handle(_ backgroundTasks: Set) { 27 | // Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one. 28 | for task in backgroundTasks { 29 | // Use a switch statement to check the task type 30 | switch task { 31 | case let backgroundTask as WKApplicationRefreshBackgroundTask: 32 | // Be sure to complete the background task once you’re done. 33 | backgroundTask.setTaskCompletedWithSnapshot(false) 34 | case let snapshotTask as WKSnapshotRefreshBackgroundTask: 35 | // Snapshot tasks have a unique completion call, make sure to set your expiration date 36 | snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil) 37 | case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask: 38 | // Be sure to complete the connectivity task once you’re done. 39 | connectivityTask.setTaskCompletedWithSnapshot(false) 40 | case let urlSessionTask as WKURLSessionRefreshBackgroundTask: 41 | // Be sure to complete the URL session task once you’re done. 42 | urlSessionTask.setTaskCompletedWithSnapshot(false) 43 | //case let relevantShortcutTask as WKRelevantShortcutRefreshBackgroundTask: 44 | // Be sure to complete the relevant-shortcut task once you're done. 45 | // relevantShortcutTask.setTaskCompletedWithSnapshot(false) 46 | //case let intentDidRunTask as WKIntentDidRunRefreshBackgroundTask: 47 | // Be sure to complete the intent-did-run task once you're done. 48 | // intentDidRunTask.setTaskCompletedWithSnapshot(false) 49 | default: 50 | // make sure to complete unhandled task types 51 | task.setTaskCompletedWithSnapshot(false) 52 | } 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | 5 | @implementation WTUserInfoHandler 6 | 7 | FlutterEventSink sink; 8 | NSDictionary *info; 9 | 10 | - (void) updateUserInfo:(nonnull NSDictionary *)userInfo{ 11 | //NSLog(@"Update Recieved"); 12 | if(info != userInfo){ 13 | info = userInfo; 14 | if(sink!=nil){ 15 | sink(@[userInfo]); 16 | } 17 | } 18 | } 19 | 20 | - (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink { 21 | //NSLog(@"Adding Flutter Listener"); 22 | sink = eventSink; 23 | return nil; 24 | } 25 | 26 | - (FlutterError*)onCancelWithArguments:(id)arguments { 27 | //NSLog(@"Removing Flutter Listener"); 28 | if(sink!=nil){ 29 | sink = nil; 30 | } 31 | return nil; 32 | } 33 | 34 | @end 35 | 36 | 37 | @implementation AppDelegate 38 | 39 | // Event triggered when userInfo Rxd 40 | - (void)session:(nonnull WCSession *)session didReceiveUserInfo:(nonnull NSDictionary *)userInfo 41 | { 42 | if(userInfoStreamHandler != nil){ 43 | [userInfoStreamHandler updateUserInfo:userInfo]; 44 | } 45 | } 46 | 47 | // Method used to enable the Watch session 48 | - (void)activateSession 49 | { 50 | [self activateChannel]; 51 | [self watchSession]; 52 | } 53 | 54 | // create our eventChannel 55 | -(FlutterEventChannel *) activateChannel { 56 | userInfoStreamHandler = [[WTUserInfoHandler alloc] init]; 57 | FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController; 58 | FlutterEventChannel *eventChannel = [FlutterEventChannel eventChannelWithName:@"uk.spiralarm.watchtips/tipinfo/watchdata" binaryMessenger:controller]; 59 | [eventChannel setStreamHandler:(NSObject * _Nullable) userInfoStreamHandler ]; 60 | return eventChannel; 61 | } 62 | 63 | 64 | // activate session 65 | - (WCSession *)watchSession 66 | { 67 | if (watchSession == nil) { 68 | if ([WCSession isSupported]) { 69 | watchSession = [WCSession defaultSession]; 70 | [watchSession setDelegate:self]; 71 | [watchSession activateSession]; 72 | } else { 73 | NSLog(@"Error - Watch Connectivity NOT supported"); 74 | } 75 | } 76 | return watchSession; 77 | } 78 | 79 | - (void)dealloc 80 | { 81 | if (watchSession != nil) { 82 | [watchSession setDelegate:nil]; 83 | } 84 | } 85 | 86 | - (BOOL)application:(UIApplication *)application 87 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 88 | 89 | FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController; 90 | FlutterMethodChannel *tipinfoChannel = [FlutterMethodChannel 91 | methodChannelWithName:@"uk.spiralarm.watchtips/tipinfo" 92 | binaryMessenger:controller]; 93 | 94 | 95 | [tipinfoChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { 96 | 97 | // activate Session 98 | if([@"activateSession" isEqualToString:call.method]){ 99 | [self activateSession]; 100 | result(@"WatchTips Activated"); 101 | }else if([@"preferredLanguages" isEqualToString:call.method]){ 102 | result([NSLocale preferredLanguages]); 103 | } else { 104 | result(FlutterMethodNotImplemented);; 105 | } 106 | 107 | }]; 108 | 109 | [GeneratedPluginRegistrant registerWithRegistry:self]; 110 | 111 | // Override point for customization after application launch. 112 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 113 | } 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /ios/WatchTips Extension/InterfaceController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InterfaceController.swift 3 | // WatchTips Extension 4 | // 5 | // Created by Stephen Rogers on 27/01/2019. 6 | // Copyright © 2019 The Chromium Authors. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | import Foundation 11 | import WatchConnectivity 12 | 13 | 14 | class InterfaceController: WKInterfaceController, WCSessionDelegate { 15 | 16 | 17 | var tipAmount: Int = 10 18 | var splitBetween: Int = 1 19 | var billTotal = Double(0) 20 | var focusButton: Int = 0 21 | 22 | @IBOutlet var currentSplit: WKInterfaceLabel! 23 | @IBOutlet var currentTip: WKInterfaceLabel! 24 | @IBOutlet weak var billButton: WKInterfaceButton! 25 | @IBOutlet weak var currentTotal: WKInterfaceLabel! 26 | @IBOutlet weak var costEach: WKInterfaceLabel! 27 | @IBOutlet weak var withTip: WKInterfaceLabel! 28 | 29 | 30 | public func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { 31 | // This will be called when the activation of a session finishes. 32 | } 33 | 34 | 35 | override func awake(withContext context: Any?) { 36 | super.awake(withContext: context) 37 | // Configure interface objects here. 38 | updateCalc() 39 | } 40 | 41 | override func willActivate() { 42 | // This method is called when watch view controller is about to be visible to user 43 | super.willActivate() 44 | if WCSession.isSupported() { 45 | let session = WCSession.default 46 | session.delegate = self 47 | session.activate() 48 | } 49 | updateCalc() 50 | } 51 | 52 | override func didDeactivate() { 53 | // This method is called when watch view controller is no longer visible 54 | super.didDeactivate() 55 | } 56 | 57 | @IBAction func splitDecrease() { 58 | if(splitBetween > 1){ 59 | splitBetween -= 1 60 | } 61 | updateCalc() 62 | } 63 | 64 | @IBAction func splitIncrease() { 65 | if(splitBetween < 99){ 66 | splitBetween += 1 67 | } 68 | updateCalc() 69 | } 70 | 71 | @IBAction func tipPercentReduce() { 72 | if(tipAmount>0){ 73 | tipAmount -= 1 74 | } 75 | updateCalc() 76 | } 77 | 78 | @IBAction func tipPercentIncrease() { 79 | if(tipAmount<100){ 80 | tipAmount += 1 81 | } 82 | updateCalc() 83 | } 84 | 85 | @IBAction func showBillController() { 86 | presentController(withName: "BillController", context: self) 87 | } 88 | 89 | 90 | // Update the actual calculations 91 | func updateCalc(){ 92 | 93 | // do bill calculations 94 | let tip = (billTotal/100) * Double(tipAmount) 95 | let billWithTip = billTotal + tip 96 | let perPerson = billWithTip / Double(splitBetween) 97 | 98 | // update display 99 | currentTip.setText("\(tipAmount)%") 100 | currentSplit.setText("\(splitBetween)") 101 | currentTotal.setText(String(format: "%.2f", billTotal)) 102 | withTip.setText(String(format: "%.2f", billWithTip)) 103 | costEach.setText(String(format: "%.2f", perPerson)) 104 | 105 | // now see if we can sent the calc data back to the app 106 | if WCSession.isSupported() { 107 | let session = WCSession.default 108 | let calcInfo = [ 109 | "tip":"\(tipAmount)", 110 | "split": "\(splitBetween)", 111 | "bill": "\(billTotal)" 112 | ] as [String : Any]; 113 | session.transferUserInfo(calcInfo) 114 | } 115 | } 116 | 117 | 118 | } 119 | -------------------------------------------------------------------------------- /ios/WatchTips Extension/BillController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BillController.swift 3 | // WatchTips Extension 4 | // 5 | // Created by Stephen Rogers on 28/01/2019. 6 | // Copyright © 2019 The Chromium Authors. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | import Foundation 11 | 12 | 13 | class BillController: WKInterfaceController { 14 | 15 | 16 | var billValue = "0" 17 | var decimalAdded = false 18 | var sourceController: InterfaceController! 19 | @IBOutlet weak var totalAmount: WKInterfaceLabel! 20 | 21 | 22 | 23 | override func awake(withContext context: Any?) { 24 | super.awake(withContext: context) 25 | 26 | // Configure interface objects here. 27 | sourceController = context as? InterfaceController 28 | if sourceController.billTotal != 0.0 { 29 | billValue = "\(sourceController.billTotal)" 30 | } else { 31 | billValue = "0" 32 | } 33 | displayBillValue() 34 | 35 | } 36 | 37 | override func willActivate() { 38 | // This method is called when watch view controller is about to be visible to user 39 | super.willActivate() 40 | } 41 | 42 | override func didDeactivate() { 43 | // This method is called when watch view controller is no longer visible 44 | super.didDeactivate() 45 | } 46 | 47 | 48 | // Clear 49 | @IBAction func clearBtn() { 50 | billValue.remove(at: billValue.index(before: billValue.endIndex)) 51 | if billValue.count == 0 { 52 | billValue = "0" 53 | } 54 | displayBillValue() 55 | } 56 | 57 | 58 | @IBAction func decimalBtn() { 59 | appendDecimal() 60 | } 61 | 62 | 63 | @IBAction func zeroBtn() { 64 | appendValue(value: 0) 65 | } 66 | 67 | 68 | @IBAction func oneBtn() { 69 | appendValue(value: 1) 70 | } 71 | 72 | 73 | @IBAction func twoBtn() { 74 | appendValue(value: 2) 75 | } 76 | 77 | @IBAction func threeBtn() { 78 | appendValue(value: 3) 79 | } 80 | 81 | 82 | @IBAction func fourBtn() { 83 | appendValue(value: 4) 84 | } 85 | 86 | 87 | @IBAction func fiveBtn() { 88 | appendValue(value: 5) 89 | } 90 | 91 | 92 | @IBAction func sixBtn() { 93 | appendValue(value: 6) 94 | } 95 | 96 | 97 | @IBAction func sevenBtn() { 98 | appendValue(value: 7) 99 | } 100 | 101 | 102 | @IBAction func eightBtn() { 103 | appendValue(value: 8) 104 | } 105 | 106 | @IBAction func nineBtn() { 107 | appendValue(value: 9) 108 | } 109 | 110 | // display the bill value and update amount in source controller 111 | func displayBillValue(){ 112 | if let _ = billValue.index(of: (".")) { 113 | decimalAdded = true 114 | } else { 115 | decimalAdded = false 116 | } 117 | totalAmount.setText(billValue) 118 | sourceController.billTotal = Double(billValue)! 119 | } 120 | 121 | // Append an amount to the displayed bill 122 | func appendValue(value: Int){ 123 | 124 | let stringValue = "\(value)" 125 | if(billValue == "0"){ 126 | billValue = stringValue 127 | } else { 128 | billValue = billValue + stringValue 129 | } 130 | displayBillValue() 131 | } 132 | 133 | // only add decimal if not already added 134 | func appendDecimal(){ 135 | 136 | // did we have a decimal? 137 | if !decimalAdded { 138 | billValue = billValue + "." 139 | } 140 | 141 | // display total 142 | displayBillValue() 143 | 144 | 145 | } 146 | 147 | } 148 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-40.png", 5 | "scale" : "1x", 6 | "idiom" : "ipad", 7 | "size" : "40x40" 8 | }, 9 | { 10 | "filename" : "Icon-40@2x.png", 11 | "scale" : "2x", 12 | "idiom" : "ipad", 13 | "size" : "40x40" 14 | }, 15 | { 16 | "filename" : "Icon-60@2x.png", 17 | "scale" : "2x", 18 | "idiom" : "iphone", 19 | "size" : "60x60" 20 | }, 21 | { 22 | "filename" : "Icon-72.png", 23 | "scale" : "1x", 24 | "idiom" : "ipad", 25 | "size" : "72x72" 26 | }, 27 | { 28 | "filename" : "Icon-72@2x.png", 29 | "scale" : "2x", 30 | "idiom" : "ipad", 31 | "size" : "72x72" 32 | }, 33 | { 34 | "filename" : "Icon-76.png", 35 | "scale" : "1x", 36 | "idiom" : "ipad", 37 | "size" : "76x76" 38 | }, 39 | { 40 | "filename" : "Icon-76@2x.png", 41 | "scale" : "2x", 42 | "idiom" : "ipad", 43 | "size" : "76x76" 44 | }, 45 | { 46 | "filename" : "Icon-Small-50.png", 47 | "scale" : "1x", 48 | "idiom" : "ipad", 49 | "size" : "50x50" 50 | }, 51 | { 52 | "filename" : "Icon-Small-50@2x.png", 53 | "scale" : "2x", 54 | "idiom" : "ipad", 55 | "size" : "50x50" 56 | }, 57 | { 58 | "filename" : "Icon-Small.png", 59 | "scale" : "1x", 60 | "idiom" : "iphone", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "filename" : "Icon-Small@2x.png", 65 | "scale" : "2x", 66 | "idiom" : "iphone", 67 | "size" : "29x29" 68 | }, 69 | { 70 | "filename" : "Icon.png", 71 | "scale" : "1x", 72 | "idiom" : "iphone", 73 | "size" : "57x57" 74 | }, 75 | { 76 | "filename" : "Icon@2x.png", 77 | "scale" : "2x", 78 | "idiom" : "iphone", 79 | "size" : "57x57" 80 | }, 81 | { 82 | "filename" : "Icon-Small@3x.png", 83 | "scale" : "3x", 84 | "idiom" : "iphone", 85 | "size" : "29x29" 86 | }, 87 | { 88 | "filename" : "Icon-40@3x.png", 89 | "scale" : "3x", 90 | "idiom" : "iphone", 91 | "size" : "40x40" 92 | }, 93 | { 94 | "filename" : "Icon-60@3x.png", 95 | "scale" : "3x", 96 | "idiom" : "iphone", 97 | "size" : "60x60" 98 | }, 99 | { 100 | "filename" : "Icon-40@2x.png", 101 | "scale" : "2x", 102 | "idiom" : "iphone", 103 | "size" : "40x40" 104 | }, 105 | { 106 | "filename" : "Icon-Small.png", 107 | "scale" : "1x", 108 | "idiom" : "ipad", 109 | "size" : "29x29" 110 | }, 111 | { 112 | "filename" : "Icon-Small@2x.png", 113 | "scale" : "2x", 114 | "idiom" : "ipad", 115 | "size" : "29x29" 116 | }, 117 | { 118 | "filename" : "Icon-83.5@2x.png", 119 | "scale" : "2x", 120 | "idiom" : "ipad", 121 | "size" : "83.5x83.5" 122 | }, 123 | { 124 | "filename" : "NotificationIcon@2x.png", 125 | "scale" : "2x", 126 | "idiom" : "iphone", 127 | "size" : "20x20" 128 | }, 129 | { 130 | "filename" : "NotificationIcon@3x.png", 131 | "scale" : "3x", 132 | "idiom" : "iphone", 133 | "size" : "20x20" 134 | }, 135 | { 136 | "filename" : "NotificationIcon~ipad.png", 137 | "scale" : "1x", 138 | "idiom" : "ipad", 139 | "size" : "20x20" 140 | }, 141 | { 142 | "filename" : "NotificationIcon~ipad@2x.png", 143 | "scale" : "2x", 144 | "idiom" : "ipad", 145 | "size" : "20x20" 146 | }, 147 | { 148 | "filename" : "ios-marketing.png", 149 | "scale" : "1x", 150 | "idiom" : "ios-marketing", 151 | "size" : "1024x1024" 152 | } 153 | ], 154 | "info" : { 155 | "author" : "xcode", 156 | "version" : 1 157 | } 158 | } -------------------------------------------------------------------------------- /lib/numberpad.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:intl/intl.dart'; 3 | import 'widgets/key.dart'; 4 | 5 | class NumberPad extends StatefulWidget { 6 | 7 | final TextStyle normalStyle; 8 | final TextStyle errorStyle; 9 | final double currentValue; 10 | final int digitLimit = 7; 11 | 12 | NumberPad(this.currentValue,{@required this.normalStyle, @required this.errorStyle}); 13 | 14 | @override 15 | _NumberPadState createState() => _NumberPadState(); 16 | } 17 | 18 | class _NumberPadState extends State { 19 | 20 | String displayedValue = ""; 21 | double billValue = 0.0; 22 | TextStyle displayStyle; 23 | NumberFormat formatter = NumberFormat("##0.00"); 24 | 25 | @override 26 | void initState() { 27 | super.initState(); 28 | billValue = widget.currentValue; 29 | if(billValue > 0.0) { 30 | displayedValue = formatter.format(billValue); 31 | } 32 | displayStyle = widget.normalStyle; 33 | } 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | return Scaffold( 38 | body: Center( 39 | child: Container( 40 | width: 320.0, 41 | height: 500.0, 42 | child: Container( 43 | decoration: BoxDecoration( 44 | borderRadius: BorderRadius.all(Radius.circular(10.0),), 45 | ), 46 | child: Column( 47 | crossAxisAlignment: CrossAxisAlignment.stretch, 48 | children: [ 49 | 50 | Padding( 51 | padding: EdgeInsets.all(10.0), 52 | child: Text( 53 | "Bill Total", 54 | textAlign: TextAlign.center, 55 | style: Theme.of(context).primaryTextTheme.display1, 56 | ), 57 | ), 58 | 59 | 60 | Card( 61 | margin: EdgeInsets.all(20.0), 62 | child: Text( 63 | displayedValue, 64 | textAlign: TextAlign.right, 65 | maxLines: 1, 66 | style: displayStyle, 67 | ), 68 | ), 69 | 70 | Expanded( 71 | child: GridView.count( 72 | primary: false, 73 | padding: const EdgeInsets.all(20.0), 74 | crossAxisSpacing: 10.0, 75 | crossAxisCount: 4, 76 | children: [ 77 | RoundKey("6", onPressed: keyEntry,), 78 | RoundKey("7", onPressed: keyEntry,), 79 | RoundKey("8", onPressed: keyEntry,), 80 | RoundKey("9", onPressed: keyEntry,), 81 | RoundKey("2", onPressed: keyEntry,), 82 | RoundKey("3", onPressed: keyEntry,), 83 | RoundKey("4", onPressed: keyEntry,), 84 | RoundKey("5", onPressed: keyEntry,), 85 | RoundKey("C", color: Colors.blue, onPressed: keyEntry,), 86 | RoundKey(".", onPressed: keyEntry,), 87 | RoundKey("0", onPressed: keyEntry,), 88 | RoundKey("1", onPressed: keyEntry,), 89 | ], 90 | ), 91 | ), 92 | 93 | Padding( 94 | padding: EdgeInsets.all(10.0), 95 | child: RaisedButton( 96 | shape: RoundedRectangleBorder( 97 | borderRadius: new BorderRadius.circular(30.0), 98 | ), 99 | color: Colors.orange, 100 | onPressed: (){ 101 | try{ 102 | Navigator.pop(context, billValue); 103 | } catch(e) { 104 | 105 | } 106 | }, 107 | child: Text( 108 | "ENTER", 109 | style: Theme.of(context).primaryTextTheme.headline, 110 | ), 111 | ), 112 | ), 113 | 114 | generateiOSCloseButton(), 115 | 116 | ], 117 | ), 118 | ) 119 | ), 120 | ), 121 | ); 122 | } 123 | 124 | Widget generateiOSCloseButton() { 125 | return Container( 126 | child: IconButton( 127 | iconSize: 40.0, 128 | onPressed: () { 129 | Navigator.pop(context); 130 | }, 131 | icon: Icon( 132 | Icons.highlight_off, 133 | color: Colors.grey, 134 | ) 135 | ), 136 | ); 137 | } 138 | 139 | /// Method used to track, check and update the displayed bill total 140 | /// we have a display length limit imposed so we do not overflow the main dsplay 141 | keyEntry(value){ 142 | 143 | String display = displayedValue; 144 | if(value == "C"){ 145 | display = (display.length > 0)?display.substring(0, display.length -1):""; 146 | } else { 147 | if(display.length < widget.digitLimit){ 148 | display += value; 149 | } 150 | } 151 | 152 | double billTotal = 0.0; 153 | if(display.length > 0){ 154 | try{ 155 | billTotal = double.parse(display); 156 | displayStyle = widget.normalStyle; 157 | } catch(e) { 158 | displayStyle = widget.errorStyle; 159 | } 160 | } 161 | setState((){ 162 | displayedValue = display; 163 | billValue = billTotal; 164 | }); 165 | 166 | } 167 | 168 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # watchtips 2 | 3 | ## Update May 2024 4 | I now have a companion demo app that has been broyght up to date and shows **simple** watchOS connectivity between Flutter and a watch app [here](https://github.com/magnatronus/basicwatch) 5 | 6 | ## Update Jul 2022 7 | As there has been no development on the codebase, and hence no app release for some time(this was really a POC). The app in the iOS app store has been withdrawn from sale by Apple. 8 | 9 | ## Update Version 2.2 10 | The Watch tips project has been updated again, The interface has been tidied up and a seperate value for the *tip* cost has been added and displayed ( a requested update). 11 | I have also added a custom 'keypad' rather than using the standard one available for the platform, hopefully the app now looks a bit better than it did - UX/UI design is not my strong point. 12 | 13 | But the biggest update is that there is now also an Android version (without Watch support). Doing this has helped a lot as I can use the Flutter Android app for development purposes so that I now have Hot Reload back (development is **good** again ....) 14 | 15 | For iOS, I still need to run/build (and fail) with the Flutter tools for iOS (this is required to generate the correct build scripts) and finish with XCode, but general dev is know easier. 16 | 17 | ## Overview 18 | This was an originally experiment to see if can use Flutter to build an iOS app with an accompanying watchOS app. My first attempts using the beta product were not successful so the idea was parked. Having now re-visited this I can now get a compiled blank watch app up and running with a Flutter app, so I will, in stages, try and re-create the WatchTips app using Flutter. 19 | 20 | If you interested in the original Titanium version is [here](https://github.com/magnatronus/Watch-Tips) 21 | 22 | 23 | ![Watch App](/screenshots/watchtips.png?raw=true "Watch and Phone App") 24 | 25 | 26 | ## App Store Link 27 | Ths app is a *really simple* app and originally just created as a proof point. 28 | 29 | But for anyone interested here are the release links: 30 | 31 | - Old AppStore Link to Watch Tips (https://itunes.apple.com/us/app/watch-tips/id1205407902). 32 | - [Playstore Link](https://play.google.com/store/apps/details?id=uk.spiralarm.tipcalculator). 33 | 34 | 35 | ## Plan 36 | 37 | - *1.0* Create a vanilla Flutter app (this initial commit) 38 | - *1.1* Add a blank watch project and get it working 39 | - *1.2* Modify the watch app functionally into WatchTips 40 | - *1.3* Update the Flutter app to WatchTips 41 | - *1.4* See if I can bridge between the 2 app (as the Titanium version does) 42 | - *2.0* Tidy up both the Flutter code and the iOS project and use it to submit the app into the App Store 43 | - *2.x+* - updates and improvements 44 | 45 | 46 | ## Flutter Package Project 47 | From the results of this test project, I have started developing a Flutter Package to allow communication between a Flutter iOS app and a watch app. This should allow easier integration with some standard functionality, though it is still a pain ATM as after you add a Watch Kit target to the iOS project as Flutter run/build no longer works. This means all package testing and development then needs to be done via XCode. 48 | 49 | I have got messaging working from an iOS app to the watch via the plugin, this can be seen working in a[video here](https://butterfly-mobile.uk/flutter-and-apple-watch). 50 | 51 | 52 | 53 | 54 | 55 | ## Generating a Distro build 56 | The only way, so far, I have found of creating a distro build is following this seqence. 57 | 58 | ### Set the Bundle ID 59 | BEFORE adding the Watch Kit app target set the final bundle ID, as the Watch app and associated extension needs to use the same prefix. If not you may need to update all references BEFORE creating the final Archive. 60 | 61 | ### Change ALL the Version and Build values 62 | This **MUST** be done for each target (in this case 3), change them to **$(FLUTTER_BUILD_NAME)** and **$(FLUTTER_BUILD_NUMBER)** respectively, otherwise although the test runs work, the Archive will not unless the version numbers match. 63 | 64 | ### Run the Flutter build first 65 | This will fail, but it generates the *correct shell scripts* to enable iOS to carry out the build (*flutter build ios --release*). 66 | 67 | ### Create Archive in XCode 68 | - 1 Select Generic Device + watchOS Device as the destination 69 | - 2 Run Product -> Archive 70 | - 3 If build successful , run the Validate App 71 | - 4 If validate successful - upload to App Store!!! 72 | 73 | 74 | 75 | ## Versions 76 | 77 | ### 2.1 78 | - updated Watch and Phone UI 79 | - currency now defaults to the phone/ipad locale 80 | - package made universal, so it runs on iPad (no watch supoort) 81 | 82 | ### 2.0 83 | - first app store release 84 | 85 | ### 1.4 - Rough and Ready but Working! 86 | I have now managed to add the required code into the iOS project to allow it to communicate with Flutter and send data updates from the watch so they are reflected in the app. 87 | Basically if you do a calculation for a Tip on the watch then the data is transferred to the associated device. 88 | 89 | You need to forgive the (bad?) Objective C coding as it is not really my thing - who in their right mind thought of it in the first place anyway :-) . A lot of this was just brute force trial and error as well as a lot of searching and testing. 90 | 91 | Apart from that the difficult issue for me was that although **MethodChannel** is quite well documented, **EventChannel** is not, the only examples I found were to do with Plugin extensions, but again probably due to my dislike (due to not understanding it very well) of Objective C. 92 | 93 | I will try to create a generic plug-in later, but that will be done in Swift. 94 | 95 | 96 | ### 1.3 97 | So after a bit of a hair pulling out session I have managed to get this working. I now have a iWatch app as well as a Flutter iOS app to build and run. I have tested this by building and distribuing to a physical phone via HockeyApp. Now the bad news...... 98 | 99 | I cannot use Flutter to either build the Flutter project or do the iOS release build, so I actually built the Flutter app in a seperate project then added the lib dir back into this one. 100 | This is a major pain as to do an testing, on device or simulator I need to use XCode to do all the build (i.e. no hot-reloading), but it does work. 101 | 102 | To create the AD-HOC distro of the app I again used XCode, set the target to Generic Device and Archived the project. The resulting AD-OC signed app works well. 103 | 104 | But I think the last stage will be a major hurdle as I WILL need to do all building using XCode......... 105 | 106 | 107 | ### 1.2 108 | Updated Watch app and added functioning WatchTips. Watch app can now be used to calculate Bill split and tips. 109 | 110 | ### 1.1 111 | After using XCode to define a simulator with an attached Watch Emulator the standard Vanilla app (from 1.0) was updated as follows 112 | 113 | - Set a bundle id on the iOS Runner app (u.spiralarm.watchtips) 114 | - Add a new Target in XCode (File->New->Target), a WatchKit app was selected 115 | - Untick *Include Notification Scene* and *Include Complication* 116 | - Name the product *WatchTips* 117 | - Generate 2 sets of assets (I use an app called **Asset Catalog Creator**), one for the Runner app and one for the Watch App so that both have a full set of icons. 118 | - Open the interface.storyboard for rhe WatchTips app and add a button to the screen 119 | 120 | After this I can no longer user the IDE (VSC) to start the app up in debug mode as I get the following error ( perhaps some sort of cusom build configuration is required): 121 | 122 | ``` 123 | === BUILD TARGET WatchTips Extension OF PROJECT Runner WITH CONFIGURATION Debug === 124 | target specifies product type 'com.apple.product-type.watchkit2-extension', but there's no such product type for the 'iphonesimulator' platform 125 | Could not build the application for the simulator. 126 | Error launching application on iPhone 7 with Watch 42mm. 127 | ``` 128 | 129 | However, if I use XCode I can use XCode to compile the app and run the watch app on the emulator. 130 | 131 | 132 | 133 | ## Getting Started 134 | 135 | This project is a starting point for a Flutter application. 136 | 137 | A few resources to get you started if this is your first Flutter project: 138 | 139 | - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) 140 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) 141 | 142 | For help getting started with Flutter, view our 143 | [online documentation](https://flutter.io/docs), which offers tutorials, 144 | samples, guidance on mobile development, and a full API reference. 145 | -------------------------------------------------------------------------------- /lib/homescreen.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io' show Platform; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | import 'package:intl/intl.dart'; 6 | import 'numberpad.dart'; 7 | import 'widgets/scaleroute.dart'; 8 | 9 | class HomeScreen extends StatefulWidget { 10 | @override 11 | _HomeScreenState createState() => _HomeScreenState(); 12 | } 13 | 14 | class _HomeScreenState extends State { 15 | static const platform = const MethodChannel('uk.spiralarm.watchtips/tipinfo'); 16 | static const stream = const EventChannel('uk.spiralarm.watchtips/tipinfo/watchdata'); 17 | StreamSubscription tipSubscription; 18 | 19 | NumberFormat formatter = NumberFormat("##0.00"); 20 | TextEditingController billTotalController = TextEditingController(); 21 | int tipPercent = 10, tipSplit = 1; 22 | double billTotal = 0.0; 23 | double tip = 0.0; 24 | double totalWithTip = 0.0; 25 | double totalEach = 0.0; 26 | 27 | @override 28 | void initState() { 29 | super.initState(); 30 | setupDeviceLocale(); 31 | if(Platform.isIOS){ 32 | activateWatchConnection(); 33 | } 34 | } 35 | 36 | @override 37 | void dispose() { 38 | if (tipSubscription != null) { 39 | tipSubscription.cancel(); 40 | tipSubscription = null; 41 | } 42 | super.dispose(); 43 | } 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | return Scaffold( 48 | appBar: AppBar( 49 | brightness: Brightness.light, 50 | centerTitle: true, 51 | elevation: 0.0, 52 | title: Text( 53 | "Tip Calculator", 54 | style: Theme.of(context).primaryTextTheme.display1, 55 | ), 56 | ), 57 | body: Container( 58 | padding: EdgeInsets.all(20.0), 59 | child: Column( 60 | children: [ 61 | 62 | Row( 63 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 64 | children: [ 65 | 66 | RaisedButton( 67 | elevation: 0.0, 68 | onPressed: () async { 69 | var value = await Navigator.push( 70 | context, 71 | ScaleRoute(widget: NumberPad( 72 | billTotal, 73 | normalStyle: Theme.of(context).textTheme.display2, 74 | errorStyle: Theme.of(context).accentTextTheme.display2, 75 | )), 76 | ); 77 | if(value != null){ 78 | calculateBill(value); 79 | } 80 | }, 81 | color: Colors.orange, 82 | child: Text( 83 | "Bill Total", 84 | style: Theme.of(context).primaryTextTheme.headline, 85 | ), 86 | shape: RoundedRectangleBorder( 87 | borderRadius: new BorderRadius.circular(30.0), 88 | ), 89 | ), 90 | 91 | Text( 92 | "${formatter.format(billTotal)}", 93 | style: Theme.of(context).primaryTextTheme.headline, 94 | textAlign: TextAlign.right, 95 | ), 96 | ], 97 | ), 98 | 99 | SizedBox(height: 20.0), 100 | 101 | Row( 102 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 103 | children: [ 104 | Text( 105 | "tip @ $tipPercent%", 106 | style: Theme.of(context).textTheme.headline, 107 | ), 108 | Text( 109 | "${formatter.format(tip)}", 110 | style: Theme.of(context).primaryTextTheme.headline, 111 | textAlign: TextAlign.right, 112 | ), 113 | ], 114 | ), 115 | 116 | Row( 117 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 118 | children: [ 119 | Text( 120 | "Total with tip", 121 | style: Theme.of(context).textTheme.headline, 122 | ), 123 | Text( 124 | "${formatter.format(totalWithTip)}", 125 | style: Theme.of(context).primaryTextTheme.headline, 126 | textAlign: TextAlign.right, 127 | ), 128 | ], 129 | ), 130 | 131 | Container( 132 | margin: EdgeInsets.all(15.0), 133 | height: 1.0, 134 | color: Theme.of(context).textTheme.headline.color 135 | ), 136 | 137 | Row( 138 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 139 | children: [ 140 | Text( 141 | "Split between", 142 | style: Theme.of(context).textTheme.headline, 143 | ), 144 | Text( 145 | "$tipSplit", 146 | style: Theme.of(context).primaryTextTheme.headline, 147 | textAlign: TextAlign.right, 148 | ), 149 | ], 150 | ), 151 | 152 | Row( 153 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 154 | children: [ 155 | Text( 156 | "Cost each", 157 | style: Theme.of(context).textTheme.headline, 158 | ), 159 | Text( 160 | "${formatter.format(totalEach)}", 161 | style: Theme.of(context).primaryTextTheme.headline, 162 | textAlign: TextAlign.right, 163 | ), 164 | ], 165 | ), 166 | 167 | 168 | Container( 169 | margin: EdgeInsets.all(15.0), 170 | height: 1.0, 171 | color: Theme.of(context).textTheme.headline.color 172 | ), 173 | 174 | Expanded( 175 | child: Center( 176 | child: Column( 177 | mainAxisAlignment: MainAxisAlignment.center, 178 | children: [ 179 | 180 | 181 | Row( 182 | mainAxisAlignment: MainAxisAlignment.end, 183 | children: [ 184 | Text( 185 | "Tip Percentage", 186 | style: Theme.of(context).primaryTextTheme.title, 187 | textAlign: TextAlign.right, 188 | ), 189 | 190 | IconButton( 191 | iconSize: 50.0, 192 | onPressed: () { 193 | if (tipPercent > 0) { 194 | tipPercent--; 195 | calculateBill(null); 196 | } 197 | }, 198 | icon: Icon( 199 | Icons.remove_circle, 200 | ), 201 | ), 202 | 203 | IconButton( 204 | iconSize: 50.0, 205 | onPressed: () { 206 | if (tipPercent < 100) { 207 | tipPercent++; 208 | calculateBill(null); 209 | } 210 | }, 211 | icon: Icon( 212 | Icons.add_circle, 213 | ), 214 | ), 215 | 216 | ], 217 | ), 218 | 219 | Row( 220 | mainAxisAlignment: MainAxisAlignment.end, 221 | children: [ 222 | Text( 223 | "Split between", 224 | style: Theme.of(context).primaryTextTheme.title, 225 | textAlign: TextAlign.right, 226 | ), 227 | IconButton( 228 | iconSize: 50.0, 229 | onPressed: () { 230 | if (tipSplit > 1) { 231 | tipSplit--; 232 | calculateBill(null); 233 | } 234 | }, 235 | icon: Icon( 236 | Icons.remove_circle, 237 | ), 238 | ), 239 | 240 | IconButton( 241 | iconSize: 50.0, 242 | onPressed: () { 243 | if (tipSplit < 50) { 244 | tipSplit++; 245 | calculateBill(null); 246 | } 247 | }, 248 | icon: Icon( 249 | Icons.add_circle, 250 | ), 251 | ), 252 | 253 | ], 254 | ), 255 | 256 | ], 257 | ), 258 | ), 259 | ), 260 | 261 | ], 262 | ), 263 | 264 | ), 265 | ); 266 | } 267 | 268 | /// Simple calculation of bill amounts 269 | calculateBill(double total) { 270 | total = (total ?? billTotal); 271 | setState(() { 272 | billTotal = total; 273 | billTotalController.text = "${formatter.format(billTotal)}"; 274 | tip = (total / 100) * tipPercent; 275 | totalWithTip = total + tip; 276 | totalEach = (totalWithTip / tipSplit); 277 | }); 278 | } 279 | 280 | /// Active and start the connection to the Watch App 281 | activateWatchConnection() async { 282 | 283 | // Start initial Session to allow watch and iOS to swap user data 284 | await platform.invokeMethod("activateSession"); 285 | 286 | // Connect up our stream so we can monitor for watch updates 287 | stream.receiveBroadcastStream().listen((value) { 288 | List result = value; 289 | if (result[0] != null) { 290 | tipPercent = int.tryParse(result[0]['tip']); 291 | tipSplit = int.tryParse(result[0]['split']); 292 | billTotal = double.tryParse(result[0]['bill']); 293 | calculateBill(null); 294 | } 295 | }); 296 | } 297 | 298 | /// Get the device locale so we can correctly format the currency 299 | setupDeviceLocale() async { 300 | List locales = await platform.invokeMethod("preferredLanguages"); 301 | debugPrint("$locales"); 302 | if (locales.length > 0) { 303 | formatter = NumberFormat.simpleCurrency(locale: locales[0]); 304 | } 305 | billTotalController.text = formatter.format(0.0); 306 | setState(() {}); 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /ios/WatchTips/Base.lproj/Interface.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 29 | 30 | 31 | 32 | 33 | 36 | 41 | 48 | 49 | 50 | 51 | 54 | 59 | 66 | 67 | 68 | 69 | 70 | 71 | 76 | 77 | 78 | 79 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 108 | 109 | 110 | 111 | 112 | 117 | 122 | 127 | 132 | 133 | 134 | 135 | 136 | 141 | 146 | 151 | 156 | 157 | 158 | 159 | 160 | 166 | 171 | 176 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 2D020CB921FEF5A100DC71C2 /* BillController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D020CB821FEF5A100DC71C2 /* BillController.swift */; }; 12 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 13 | 2D69490521FDFD9600B94252 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2D69490321FDFD9600B94252 /* Interface.storyboard */; }; 14 | 2D69490721FDFD9700B94252 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2D69490621FDFD9700B94252 /* Assets.xcassets */; }; 15 | 2D69490E21FDFD9700B94252 /* WatchTips Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 2D69490D21FDFD9700B94252 /* WatchTips Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 16 | 2D69491321FDFD9700B94252 /* InterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D69491221FDFD9700B94252 /* InterfaceController.swift */; }; 17 | 2D69491521FDFD9700B94252 /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D69491421FDFD9700B94252 /* ExtensionDelegate.swift */; }; 18 | 2D69491721FDFD9700B94252 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2D69491621FDFD9700B94252 /* Assets.xcassets */; }; 19 | 2D69491B21FDFD9700B94252 /* WatchTips.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 2D69490121FDFD9600B94252 /* WatchTips.app */; }; 20 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 21 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 22 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 23 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 24 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 25 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 26 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 27 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 28 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 29 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 30 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXContainerItemProxy section */ 34 | 2D69490F21FDFD9700B94252 /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = 97C146E61CF9000F007C117D /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = 2D69490C21FDFD9700B94252; 39 | remoteInfo = "WatchTips Extension"; 40 | }; 41 | 2D69491921FDFD9700B94252 /* PBXContainerItemProxy */ = { 42 | isa = PBXContainerItemProxy; 43 | containerPortal = 97C146E61CF9000F007C117D /* Project object */; 44 | proxyType = 1; 45 | remoteGlobalIDString = 2D69490021FDFD9600B94252; 46 | remoteInfo = WatchTips; 47 | }; 48 | /* End PBXContainerItemProxy section */ 49 | 50 | /* Begin PBXCopyFilesBuildPhase section */ 51 | 2D69492021FDFD9700B94252 /* Embed App Extensions */ = { 52 | isa = PBXCopyFilesBuildPhase; 53 | buildActionMask = 2147483647; 54 | dstPath = ""; 55 | dstSubfolderSpec = 13; 56 | files = ( 57 | 2D69490E21FDFD9700B94252 /* WatchTips Extension.appex in Embed App Extensions */, 58 | ); 59 | name = "Embed App Extensions"; 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | 2D69492521FDFD9700B94252 /* Embed Watch Content */ = { 63 | isa = PBXCopyFilesBuildPhase; 64 | buildActionMask = 2147483647; 65 | dstPath = "$(CONTENTS_FOLDER_PATH)/Watch"; 66 | dstSubfolderSpec = 16; 67 | files = ( 68 | 2D69491B21FDFD9700B94252 /* WatchTips.app in Embed Watch Content */, 69 | ); 70 | name = "Embed Watch Content"; 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 74 | isa = PBXCopyFilesBuildPhase; 75 | buildActionMask = 2147483647; 76 | dstPath = ""; 77 | dstSubfolderSpec = 10; 78 | files = ( 79 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 80 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 81 | ); 82 | name = "Embed Frameworks"; 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | /* End PBXCopyFilesBuildPhase section */ 86 | 87 | /* Begin PBXFileReference section */ 88 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 89 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 90 | 2D020CB821FEF5A100DC71C2 /* BillController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BillController.swift; sourceTree = ""; }; 91 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 92 | 2D69490121FDFD9600B94252 /* WatchTips.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WatchTips.app; sourceTree = BUILT_PRODUCTS_DIR; }; 93 | 2D69490421FDFD9600B94252 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = ""; }; 94 | 2D69490621FDFD9700B94252 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 95 | 2D69490821FDFD9700B94252 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 96 | 2D69490D21FDFD9700B94252 /* WatchTips Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "WatchTips Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 97 | 2D69491221FDFD9700B94252 /* InterfaceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterfaceController.swift; sourceTree = ""; }; 98 | 2D69491421FDFD9700B94252 /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = ""; }; 99 | 2D69491621FDFD9700B94252 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 100 | 2D69491821FDFD9700B94252 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 101 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 102 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 103 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 104 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 105 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 106 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 107 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 108 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 109 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 110 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 111 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 112 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 113 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 114 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 115 | /* End PBXFileReference section */ 116 | 117 | /* Begin PBXFrameworksBuildPhase section */ 118 | 2D69490A21FDFD9700B94252 /* Frameworks */ = { 119 | isa = PBXFrameworksBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 126 | isa = PBXFrameworksBuildPhase; 127 | buildActionMask = 2147483647; 128 | files = ( 129 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 130 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 131 | ); 132 | runOnlyForDeploymentPostprocessing = 0; 133 | }; 134 | /* End PBXFrameworksBuildPhase section */ 135 | 136 | /* Begin PBXGroup section */ 137 | 2D69490221FDFD9600B94252 /* WatchTips */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 2D69490321FDFD9600B94252 /* Interface.storyboard */, 141 | 2D69490621FDFD9700B94252 /* Assets.xcassets */, 142 | 2D69490821FDFD9700B94252 /* Info.plist */, 143 | ); 144 | path = WatchTips; 145 | sourceTree = ""; 146 | }; 147 | 2D69491121FDFD9700B94252 /* WatchTips Extension */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 2D69491221FDFD9700B94252 /* InterfaceController.swift */, 151 | 2D69491421FDFD9700B94252 /* ExtensionDelegate.swift */, 152 | 2D69491621FDFD9700B94252 /* Assets.xcassets */, 153 | 2D69491821FDFD9700B94252 /* Info.plist */, 154 | 2D020CB821FEF5A100DC71C2 /* BillController.swift */, 155 | ); 156 | path = "WatchTips Extension"; 157 | sourceTree = ""; 158 | }; 159 | 9740EEB11CF90186004384FC /* Flutter */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, 163 | 3B80C3931E831B6300D905FE /* App.framework */, 164 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 165 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 166 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 167 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 168 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 169 | ); 170 | name = Flutter; 171 | sourceTree = ""; 172 | }; 173 | 97C146E51CF9000F007C117D = { 174 | isa = PBXGroup; 175 | children = ( 176 | 9740EEB11CF90186004384FC /* Flutter */, 177 | 97C146F01CF9000F007C117D /* Runner */, 178 | 2D69490221FDFD9600B94252 /* WatchTips */, 179 | 2D69491121FDFD9700B94252 /* WatchTips Extension */, 180 | 97C146EF1CF9000F007C117D /* Products */, 181 | ); 182 | sourceTree = ""; 183 | }; 184 | 97C146EF1CF9000F007C117D /* Products */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | 97C146EE1CF9000F007C117D /* Runner.app */, 188 | 2D69490121FDFD9600B94252 /* WatchTips.app */, 189 | 2D69490D21FDFD9700B94252 /* WatchTips Extension.appex */, 190 | ); 191 | name = Products; 192 | sourceTree = ""; 193 | }; 194 | 97C146F01CF9000F007C117D /* Runner */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 198 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 199 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 200 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 201 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 202 | 97C147021CF9000F007C117D /* Info.plist */, 203 | 97C146F11CF9000F007C117D /* Supporting Files */, 204 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 205 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 206 | ); 207 | path = Runner; 208 | sourceTree = ""; 209 | }; 210 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | 97C146F21CF9000F007C117D /* main.m */, 214 | ); 215 | name = "Supporting Files"; 216 | sourceTree = ""; 217 | }; 218 | /* End PBXGroup section */ 219 | 220 | /* Begin PBXNativeTarget section */ 221 | 2D69490021FDFD9600B94252 /* WatchTips */ = { 222 | isa = PBXNativeTarget; 223 | buildConfigurationList = 2D69492121FDFD9700B94252 /* Build configuration list for PBXNativeTarget "WatchTips" */; 224 | buildPhases = ( 225 | 2D6948FF21FDFD9600B94252 /* Resources */, 226 | 2D69492021FDFD9700B94252 /* Embed App Extensions */, 227 | ); 228 | buildRules = ( 229 | ); 230 | dependencies = ( 231 | 2D69491021FDFD9700B94252 /* PBXTargetDependency */, 232 | ); 233 | name = WatchTips; 234 | productName = WatchTips; 235 | productReference = 2D69490121FDFD9600B94252 /* WatchTips.app */; 236 | productType = "com.apple.product-type.application.watchapp2"; 237 | }; 238 | 2D69490C21FDFD9700B94252 /* WatchTips Extension */ = { 239 | isa = PBXNativeTarget; 240 | buildConfigurationList = 2D69491C21FDFD9700B94252 /* Build configuration list for PBXNativeTarget "WatchTips Extension" */; 241 | buildPhases = ( 242 | 2D69490921FDFD9700B94252 /* Sources */, 243 | 2D69490A21FDFD9700B94252 /* Frameworks */, 244 | 2D69490B21FDFD9700B94252 /* Resources */, 245 | ); 246 | buildRules = ( 247 | ); 248 | dependencies = ( 249 | ); 250 | name = "WatchTips Extension"; 251 | productName = "WatchTips Extension"; 252 | productReference = 2D69490D21FDFD9700B94252 /* WatchTips Extension.appex */; 253 | productType = "com.apple.product-type.watchkit2-extension"; 254 | }; 255 | 97C146ED1CF9000F007C117D /* Runner */ = { 256 | isa = PBXNativeTarget; 257 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 258 | buildPhases = ( 259 | 9740EEB61CF901F6004384FC /* Run Script */, 260 | 97C146EA1CF9000F007C117D /* Sources */, 261 | 97C146EB1CF9000F007C117D /* Frameworks */, 262 | 97C146EC1CF9000F007C117D /* Resources */, 263 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 264 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 265 | 2D69492521FDFD9700B94252 /* Embed Watch Content */, 266 | ); 267 | buildRules = ( 268 | ); 269 | dependencies = ( 270 | 2D69491A21FDFD9700B94252 /* PBXTargetDependency */, 271 | ); 272 | name = Runner; 273 | productName = Runner; 274 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 275 | productType = "com.apple.product-type.application"; 276 | }; 277 | /* End PBXNativeTarget section */ 278 | 279 | /* Begin PBXProject section */ 280 | 97C146E61CF9000F007C117D /* Project object */ = { 281 | isa = PBXProject; 282 | attributes = { 283 | DefaultBuildSystemTypeForWorkspace = Original; 284 | LastSwiftUpdateCheck = 1010; 285 | LastUpgradeCheck = 0910; 286 | ORGANIZATIONNAME = "The Chromium Authors"; 287 | TargetAttributes = { 288 | 2D69490021FDFD9600B94252 = { 289 | CreatedOnToolsVersion = 10.1; 290 | DevelopmentTeam = QJ23459J94; 291 | ProvisioningStyle = Automatic; 292 | }; 293 | 2D69490C21FDFD9700B94252 = { 294 | CreatedOnToolsVersion = 10.1; 295 | DevelopmentTeam = QJ23459J94; 296 | ProvisioningStyle = Automatic; 297 | SystemCapabilities = { 298 | com.apple.BackgroundModes.watchos.extension = { 299 | enabled = 0; 300 | }; 301 | }; 302 | }; 303 | 97C146ED1CF9000F007C117D = { 304 | CreatedOnToolsVersion = 7.3.1; 305 | DevelopmentTeam = QJ23459J94; 306 | SystemCapabilities = { 307 | com.apple.BackgroundModes = { 308 | enabled = 1; 309 | }; 310 | }; 311 | }; 312 | }; 313 | }; 314 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 315 | compatibilityVersion = "Xcode 3.2"; 316 | developmentRegion = English; 317 | hasScannedForEncodings = 0; 318 | knownRegions = ( 319 | en, 320 | Base, 321 | ); 322 | mainGroup = 97C146E51CF9000F007C117D; 323 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 324 | projectDirPath = ""; 325 | projectRoot = ""; 326 | targets = ( 327 | 97C146ED1CF9000F007C117D /* Runner */, 328 | 2D69490021FDFD9600B94252 /* WatchTips */, 329 | 2D69490C21FDFD9700B94252 /* WatchTips Extension */, 330 | ); 331 | }; 332 | /* End PBXProject section */ 333 | 334 | /* Begin PBXResourcesBuildPhase section */ 335 | 2D6948FF21FDFD9600B94252 /* Resources */ = { 336 | isa = PBXResourcesBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | 2D69490721FDFD9700B94252 /* Assets.xcassets in Resources */, 340 | 2D69490521FDFD9600B94252 /* Interface.storyboard in Resources */, 341 | ); 342 | runOnlyForDeploymentPostprocessing = 0; 343 | }; 344 | 2D69490B21FDFD9700B94252 /* Resources */ = { 345 | isa = PBXResourcesBuildPhase; 346 | buildActionMask = 2147483647; 347 | files = ( 348 | 2D69491721FDFD9700B94252 /* Assets.xcassets in Resources */, 349 | ); 350 | runOnlyForDeploymentPostprocessing = 0; 351 | }; 352 | 97C146EC1CF9000F007C117D /* Resources */ = { 353 | isa = PBXResourcesBuildPhase; 354 | buildActionMask = 2147483647; 355 | files = ( 356 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 357 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 358 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 359 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 360 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 361 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 362 | ); 363 | runOnlyForDeploymentPostprocessing = 0; 364 | }; 365 | /* End PBXResourcesBuildPhase section */ 366 | 367 | /* Begin PBXShellScriptBuildPhase section */ 368 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 369 | isa = PBXShellScriptBuildPhase; 370 | buildActionMask = 2147483647; 371 | files = ( 372 | ); 373 | inputPaths = ( 374 | ); 375 | name = "Thin Binary"; 376 | outputPaths = ( 377 | ); 378 | runOnlyForDeploymentPostprocessing = 0; 379 | shellPath = /bin/sh; 380 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 381 | }; 382 | 9740EEB61CF901F6004384FC /* Run Script */ = { 383 | isa = PBXShellScriptBuildPhase; 384 | buildActionMask = 2147483647; 385 | files = ( 386 | ); 387 | inputPaths = ( 388 | ); 389 | name = "Run Script"; 390 | outputPaths = ( 391 | ); 392 | runOnlyForDeploymentPostprocessing = 0; 393 | shellPath = /bin/sh; 394 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 395 | }; 396 | /* End PBXShellScriptBuildPhase section */ 397 | 398 | /* Begin PBXSourcesBuildPhase section */ 399 | 2D69490921FDFD9700B94252 /* Sources */ = { 400 | isa = PBXSourcesBuildPhase; 401 | buildActionMask = 2147483647; 402 | files = ( 403 | 2D020CB921FEF5A100DC71C2 /* BillController.swift in Sources */, 404 | 2D69491521FDFD9700B94252 /* ExtensionDelegate.swift in Sources */, 405 | 2D69491321FDFD9700B94252 /* InterfaceController.swift in Sources */, 406 | ); 407 | runOnlyForDeploymentPostprocessing = 0; 408 | }; 409 | 97C146EA1CF9000F007C117D /* Sources */ = { 410 | isa = PBXSourcesBuildPhase; 411 | buildActionMask = 2147483647; 412 | files = ( 413 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 414 | 97C146F31CF9000F007C117D /* main.m in Sources */, 415 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 416 | ); 417 | runOnlyForDeploymentPostprocessing = 0; 418 | }; 419 | /* End PBXSourcesBuildPhase section */ 420 | 421 | /* Begin PBXTargetDependency section */ 422 | 2D69491021FDFD9700B94252 /* PBXTargetDependency */ = { 423 | isa = PBXTargetDependency; 424 | target = 2D69490C21FDFD9700B94252 /* WatchTips Extension */; 425 | targetProxy = 2D69490F21FDFD9700B94252 /* PBXContainerItemProxy */; 426 | }; 427 | 2D69491A21FDFD9700B94252 /* PBXTargetDependency */ = { 428 | isa = PBXTargetDependency; 429 | target = 2D69490021FDFD9600B94252 /* WatchTips */; 430 | targetProxy = 2D69491921FDFD9700B94252 /* PBXContainerItemProxy */; 431 | }; 432 | /* End PBXTargetDependency section */ 433 | 434 | /* Begin PBXVariantGroup section */ 435 | 2D69490321FDFD9600B94252 /* Interface.storyboard */ = { 436 | isa = PBXVariantGroup; 437 | children = ( 438 | 2D69490421FDFD9600B94252 /* Base */, 439 | ); 440 | name = Interface.storyboard; 441 | sourceTree = ""; 442 | }; 443 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 444 | isa = PBXVariantGroup; 445 | children = ( 446 | 97C146FB1CF9000F007C117D /* Base */, 447 | ); 448 | name = Main.storyboard; 449 | sourceTree = ""; 450 | }; 451 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 452 | isa = PBXVariantGroup; 453 | children = ( 454 | 97C147001CF9000F007C117D /* Base */, 455 | ); 456 | name = LaunchScreen.storyboard; 457 | sourceTree = ""; 458 | }; 459 | /* End PBXVariantGroup section */ 460 | 461 | /* Begin XCBuildConfiguration section */ 462 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 463 | isa = XCBuildConfiguration; 464 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 465 | buildSettings = { 466 | ALWAYS_SEARCH_USER_PATHS = NO; 467 | CLANG_ANALYZER_NONNULL = YES; 468 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 469 | CLANG_CXX_LIBRARY = "libc++"; 470 | CLANG_ENABLE_MODULES = YES; 471 | CLANG_ENABLE_OBJC_ARC = YES; 472 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 473 | CLANG_WARN_BOOL_CONVERSION = YES; 474 | CLANG_WARN_COMMA = YES; 475 | CLANG_WARN_CONSTANT_CONVERSION = YES; 476 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 477 | CLANG_WARN_EMPTY_BODY = YES; 478 | CLANG_WARN_ENUM_CONVERSION = YES; 479 | CLANG_WARN_INFINITE_RECURSION = YES; 480 | CLANG_WARN_INT_CONVERSION = YES; 481 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 482 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 483 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 484 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 485 | CLANG_WARN_STRICT_PROTOTYPES = YES; 486 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 487 | CLANG_WARN_UNREACHABLE_CODE = YES; 488 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 489 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 490 | COPY_PHASE_STRIP = NO; 491 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 492 | ENABLE_NS_ASSERTIONS = NO; 493 | ENABLE_STRICT_OBJC_MSGSEND = YES; 494 | GCC_C_LANGUAGE_STANDARD = gnu99; 495 | GCC_NO_COMMON_BLOCKS = YES; 496 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 497 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 498 | GCC_WARN_UNDECLARED_SELECTOR = YES; 499 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 500 | GCC_WARN_UNUSED_FUNCTION = YES; 501 | GCC_WARN_UNUSED_VARIABLE = YES; 502 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 503 | MTL_ENABLE_DEBUG_INFO = NO; 504 | SDKROOT = iphoneos; 505 | TARGETED_DEVICE_FAMILY = "1,2"; 506 | VALIDATE_PRODUCT = YES; 507 | }; 508 | name = Profile; 509 | }; 510 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 511 | isa = XCBuildConfiguration; 512 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 513 | buildSettings = { 514 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 515 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 516 | DEVELOPMENT_TEAM = QJ23459J94; 517 | ENABLE_BITCODE = NO; 518 | FRAMEWORK_SEARCH_PATHS = ( 519 | "$(inherited)", 520 | "$(PROJECT_DIR)/Flutter", 521 | ); 522 | INFOPLIST_FILE = Runner/Info.plist; 523 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 524 | LIBRARY_SEARCH_PATHS = ( 525 | "$(inherited)", 526 | "$(PROJECT_DIR)/Flutter", 527 | ); 528 | PRODUCT_BUNDLE_IDENTIFIER = uk.spiralarm.tipcalculator; 529 | PRODUCT_NAME = "$(TARGET_NAME)"; 530 | TARGETED_DEVICE_FAMILY = "1,2"; 531 | VERSIONING_SYSTEM = "apple-generic"; 532 | }; 533 | name = Profile; 534 | }; 535 | 2D69491D21FDFD9700B94252 /* Debug */ = { 536 | isa = XCBuildConfiguration; 537 | buildSettings = { 538 | ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; 539 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 540 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 541 | CLANG_ENABLE_OBJC_WEAK = YES; 542 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 543 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 544 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 545 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 546 | CODE_SIGN_STYLE = Automatic; 547 | DEVELOPMENT_TEAM = QJ23459J94; 548 | GCC_C_LANGUAGE_STANDARD = gnu11; 549 | INFOPLIST_FILE = "WatchTips Extension/Info.plist"; 550 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 551 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 552 | MTL_FAST_MATH = YES; 553 | PRODUCT_BUNDLE_IDENTIFIER = uk.spiralarm.tipcalculator.watchkitapp.watchkitextension; 554 | PRODUCT_NAME = "${TARGET_NAME}"; 555 | SDKROOT = watchos; 556 | SKIP_INSTALL = YES; 557 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 558 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 559 | SWIFT_VERSION = 4.2; 560 | TARGETED_DEVICE_FAMILY = 4; 561 | WATCHOS_DEPLOYMENT_TARGET = 4.3; 562 | }; 563 | name = Debug; 564 | }; 565 | 2D69491E21FDFD9700B94252 /* Release */ = { 566 | isa = XCBuildConfiguration; 567 | buildSettings = { 568 | ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; 569 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 570 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 571 | CLANG_ENABLE_OBJC_WEAK = YES; 572 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 573 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 574 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 575 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 576 | CODE_SIGN_STYLE = Automatic; 577 | DEVELOPMENT_TEAM = QJ23459J94; 578 | GCC_C_LANGUAGE_STANDARD = gnu11; 579 | INFOPLIST_FILE = "WatchTips Extension/Info.plist"; 580 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 581 | MTL_FAST_MATH = YES; 582 | PRODUCT_BUNDLE_IDENTIFIER = uk.spiralarm.tipcalculator.watchkitapp.watchkitextension; 583 | PRODUCT_NAME = "${TARGET_NAME}"; 584 | SDKROOT = watchos; 585 | SKIP_INSTALL = YES; 586 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 587 | SWIFT_VERSION = 4.2; 588 | TARGETED_DEVICE_FAMILY = 4; 589 | WATCHOS_DEPLOYMENT_TARGET = 4.3; 590 | }; 591 | name = Release; 592 | }; 593 | 2D69491F21FDFD9700B94252 /* Profile */ = { 594 | isa = XCBuildConfiguration; 595 | buildSettings = { 596 | ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; 597 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 598 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 599 | CLANG_ENABLE_OBJC_WEAK = YES; 600 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 601 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 602 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 603 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 604 | CODE_SIGN_STYLE = Automatic; 605 | DEVELOPMENT_TEAM = QJ23459J94; 606 | GCC_C_LANGUAGE_STANDARD = gnu11; 607 | INFOPLIST_FILE = "WatchTips Extension/Info.plist"; 608 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 609 | MTL_FAST_MATH = YES; 610 | PRODUCT_BUNDLE_IDENTIFIER = uk.spiralarm.tipcalculator.watchkitapp.watchkitextension; 611 | PRODUCT_NAME = "${TARGET_NAME}"; 612 | SDKROOT = watchos; 613 | SKIP_INSTALL = YES; 614 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 615 | SWIFT_VERSION = 4.2; 616 | TARGETED_DEVICE_FAMILY = 4; 617 | WATCHOS_DEPLOYMENT_TARGET = 4.3; 618 | }; 619 | name = Profile; 620 | }; 621 | 2D69492221FDFD9700B94252 /* Debug */ = { 622 | isa = XCBuildConfiguration; 623 | buildSettings = { 624 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 625 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 626 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 627 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 628 | CLANG_ENABLE_OBJC_WEAK = YES; 629 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 630 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 631 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 632 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 633 | CODE_SIGN_STYLE = Automatic; 634 | DEVELOPMENT_TEAM = QJ23459J94; 635 | GCC_C_LANGUAGE_STANDARD = gnu11; 636 | IBSC_MODULE = WatchTips_Extension; 637 | INFOPLIST_FILE = WatchTips/Info.plist; 638 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 639 | MTL_FAST_MATH = YES; 640 | PRODUCT_BUNDLE_IDENTIFIER = uk.spiralarm.tipcalculator.watchkitapp; 641 | PRODUCT_NAME = "$(TARGET_NAME)"; 642 | SDKROOT = watchos; 643 | SKIP_INSTALL = YES; 644 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 645 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 646 | SWIFT_VERSION = 4.2; 647 | TARGETED_DEVICE_FAMILY = 4; 648 | WATCHOS_DEPLOYMENT_TARGET = 4.3; 649 | }; 650 | name = Debug; 651 | }; 652 | 2D69492321FDFD9700B94252 /* Release */ = { 653 | isa = XCBuildConfiguration; 654 | buildSettings = { 655 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 656 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 657 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 658 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 659 | CLANG_ENABLE_OBJC_WEAK = YES; 660 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 661 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 662 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 663 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 664 | CODE_SIGN_STYLE = Automatic; 665 | DEVELOPMENT_TEAM = QJ23459J94; 666 | GCC_C_LANGUAGE_STANDARD = gnu11; 667 | IBSC_MODULE = WatchTips_Extension; 668 | INFOPLIST_FILE = WatchTips/Info.plist; 669 | MTL_FAST_MATH = YES; 670 | PRODUCT_BUNDLE_IDENTIFIER = uk.spiralarm.tipcalculator.watchkitapp; 671 | PRODUCT_NAME = "$(TARGET_NAME)"; 672 | SDKROOT = watchos; 673 | SKIP_INSTALL = YES; 674 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 675 | SWIFT_VERSION = 4.2; 676 | TARGETED_DEVICE_FAMILY = 4; 677 | WATCHOS_DEPLOYMENT_TARGET = 4.3; 678 | }; 679 | name = Release; 680 | }; 681 | 2D69492421FDFD9700B94252 /* Profile */ = { 682 | isa = XCBuildConfiguration; 683 | buildSettings = { 684 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 685 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 686 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 687 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 688 | CLANG_ENABLE_OBJC_WEAK = YES; 689 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 690 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 691 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 692 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 693 | CODE_SIGN_STYLE = Automatic; 694 | DEVELOPMENT_TEAM = QJ23459J94; 695 | GCC_C_LANGUAGE_STANDARD = gnu11; 696 | IBSC_MODULE = WatchTips_Extension; 697 | INFOPLIST_FILE = WatchTips/Info.plist; 698 | MTL_FAST_MATH = YES; 699 | PRODUCT_BUNDLE_IDENTIFIER = uk.spiralarm.tipcalculator.watchkitapp; 700 | PRODUCT_NAME = "$(TARGET_NAME)"; 701 | SDKROOT = watchos; 702 | SKIP_INSTALL = YES; 703 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 704 | SWIFT_VERSION = 4.2; 705 | TARGETED_DEVICE_FAMILY = 4; 706 | WATCHOS_DEPLOYMENT_TARGET = 4.3; 707 | }; 708 | name = Profile; 709 | }; 710 | 97C147031CF9000F007C117D /* Debug */ = { 711 | isa = XCBuildConfiguration; 712 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 713 | buildSettings = { 714 | ALWAYS_SEARCH_USER_PATHS = NO; 715 | CLANG_ANALYZER_NONNULL = YES; 716 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 717 | CLANG_CXX_LIBRARY = "libc++"; 718 | CLANG_ENABLE_MODULES = YES; 719 | CLANG_ENABLE_OBJC_ARC = YES; 720 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 721 | CLANG_WARN_BOOL_CONVERSION = YES; 722 | CLANG_WARN_COMMA = YES; 723 | CLANG_WARN_CONSTANT_CONVERSION = YES; 724 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 725 | CLANG_WARN_EMPTY_BODY = YES; 726 | CLANG_WARN_ENUM_CONVERSION = YES; 727 | CLANG_WARN_INFINITE_RECURSION = YES; 728 | CLANG_WARN_INT_CONVERSION = YES; 729 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 730 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 731 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 732 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 733 | CLANG_WARN_STRICT_PROTOTYPES = YES; 734 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 735 | CLANG_WARN_UNREACHABLE_CODE = YES; 736 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 737 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 738 | COPY_PHASE_STRIP = NO; 739 | DEBUG_INFORMATION_FORMAT = dwarf; 740 | ENABLE_STRICT_OBJC_MSGSEND = YES; 741 | ENABLE_TESTABILITY = YES; 742 | GCC_C_LANGUAGE_STANDARD = gnu99; 743 | GCC_DYNAMIC_NO_PIC = NO; 744 | GCC_NO_COMMON_BLOCKS = YES; 745 | GCC_OPTIMIZATION_LEVEL = 0; 746 | GCC_PREPROCESSOR_DEFINITIONS = ( 747 | "DEBUG=1", 748 | "$(inherited)", 749 | ); 750 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 751 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 752 | GCC_WARN_UNDECLARED_SELECTOR = YES; 753 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 754 | GCC_WARN_UNUSED_FUNCTION = YES; 755 | GCC_WARN_UNUSED_VARIABLE = YES; 756 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 757 | MTL_ENABLE_DEBUG_INFO = YES; 758 | ONLY_ACTIVE_ARCH = YES; 759 | SDKROOT = iphoneos; 760 | TARGETED_DEVICE_FAMILY = "1,2"; 761 | }; 762 | name = Debug; 763 | }; 764 | 97C147041CF9000F007C117D /* Release */ = { 765 | isa = XCBuildConfiguration; 766 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 767 | buildSettings = { 768 | ALWAYS_SEARCH_USER_PATHS = NO; 769 | CLANG_ANALYZER_NONNULL = YES; 770 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 771 | CLANG_CXX_LIBRARY = "libc++"; 772 | CLANG_ENABLE_MODULES = YES; 773 | CLANG_ENABLE_OBJC_ARC = YES; 774 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 775 | CLANG_WARN_BOOL_CONVERSION = YES; 776 | CLANG_WARN_COMMA = YES; 777 | CLANG_WARN_CONSTANT_CONVERSION = YES; 778 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 779 | CLANG_WARN_EMPTY_BODY = YES; 780 | CLANG_WARN_ENUM_CONVERSION = YES; 781 | CLANG_WARN_INFINITE_RECURSION = YES; 782 | CLANG_WARN_INT_CONVERSION = YES; 783 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 784 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 785 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 786 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 787 | CLANG_WARN_STRICT_PROTOTYPES = YES; 788 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 789 | CLANG_WARN_UNREACHABLE_CODE = YES; 790 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 791 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 792 | COPY_PHASE_STRIP = NO; 793 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 794 | ENABLE_NS_ASSERTIONS = NO; 795 | ENABLE_STRICT_OBJC_MSGSEND = YES; 796 | GCC_C_LANGUAGE_STANDARD = gnu99; 797 | GCC_NO_COMMON_BLOCKS = YES; 798 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 799 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 800 | GCC_WARN_UNDECLARED_SELECTOR = YES; 801 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 802 | GCC_WARN_UNUSED_FUNCTION = YES; 803 | GCC_WARN_UNUSED_VARIABLE = YES; 804 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 805 | MTL_ENABLE_DEBUG_INFO = NO; 806 | SDKROOT = iphoneos; 807 | TARGETED_DEVICE_FAMILY = "1,2"; 808 | VALIDATE_PRODUCT = YES; 809 | }; 810 | name = Release; 811 | }; 812 | 97C147061CF9000F007C117D /* Debug */ = { 813 | isa = XCBuildConfiguration; 814 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 815 | buildSettings = { 816 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 817 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 818 | DEVELOPMENT_TEAM = QJ23459J94; 819 | ENABLE_BITCODE = NO; 820 | FRAMEWORK_SEARCH_PATHS = ( 821 | "$(inherited)", 822 | "$(PROJECT_DIR)/Flutter", 823 | ); 824 | INFOPLIST_FILE = Runner/Info.plist; 825 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 826 | LIBRARY_SEARCH_PATHS = ( 827 | "$(inherited)", 828 | "$(PROJECT_DIR)/Flutter", 829 | ); 830 | PRODUCT_BUNDLE_IDENTIFIER = uk.spiralarm.tipcalculator; 831 | PRODUCT_NAME = "$(TARGET_NAME)"; 832 | TARGETED_DEVICE_FAMILY = "1,2"; 833 | VERSIONING_SYSTEM = "apple-generic"; 834 | }; 835 | name = Debug; 836 | }; 837 | 97C147071CF9000F007C117D /* Release */ = { 838 | isa = XCBuildConfiguration; 839 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 840 | buildSettings = { 841 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 842 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 843 | DEVELOPMENT_TEAM = QJ23459J94; 844 | ENABLE_BITCODE = NO; 845 | FRAMEWORK_SEARCH_PATHS = ( 846 | "$(inherited)", 847 | "$(PROJECT_DIR)/Flutter", 848 | ); 849 | INFOPLIST_FILE = Runner/Info.plist; 850 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 851 | LIBRARY_SEARCH_PATHS = ( 852 | "$(inherited)", 853 | "$(PROJECT_DIR)/Flutter", 854 | ); 855 | PRODUCT_BUNDLE_IDENTIFIER = uk.spiralarm.tipcalculator; 856 | PRODUCT_NAME = "$(TARGET_NAME)"; 857 | TARGETED_DEVICE_FAMILY = "1,2"; 858 | VERSIONING_SYSTEM = "apple-generic"; 859 | }; 860 | name = Release; 861 | }; 862 | /* End XCBuildConfiguration section */ 863 | 864 | /* Begin XCConfigurationList section */ 865 | 2D69491C21FDFD9700B94252 /* Build configuration list for PBXNativeTarget "WatchTips Extension" */ = { 866 | isa = XCConfigurationList; 867 | buildConfigurations = ( 868 | 2D69491D21FDFD9700B94252 /* Debug */, 869 | 2D69491E21FDFD9700B94252 /* Release */, 870 | 2D69491F21FDFD9700B94252 /* Profile */, 871 | ); 872 | defaultConfigurationIsVisible = 0; 873 | defaultConfigurationName = Release; 874 | }; 875 | 2D69492121FDFD9700B94252 /* Build configuration list for PBXNativeTarget "WatchTips" */ = { 876 | isa = XCConfigurationList; 877 | buildConfigurations = ( 878 | 2D69492221FDFD9700B94252 /* Debug */, 879 | 2D69492321FDFD9700B94252 /* Release */, 880 | 2D69492421FDFD9700B94252 /* Profile */, 881 | ); 882 | defaultConfigurationIsVisible = 0; 883 | defaultConfigurationName = Release; 884 | }; 885 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 886 | isa = XCConfigurationList; 887 | buildConfigurations = ( 888 | 97C147031CF9000F007C117D /* Debug */, 889 | 97C147041CF9000F007C117D /* Release */, 890 | 249021D3217E4FDB00AE95B9 /* Profile */, 891 | ); 892 | defaultConfigurationIsVisible = 0; 893 | defaultConfigurationName = Release; 894 | }; 895 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 896 | isa = XCConfigurationList; 897 | buildConfigurations = ( 898 | 97C147061CF9000F007C117D /* Debug */, 899 | 97C147071CF9000F007C117D /* Release */, 900 | 249021D4217E4FDB00AE95B9 /* Profile */, 901 | ); 902 | defaultConfigurationIsVisible = 0; 903 | defaultConfigurationName = Release; 904 | }; 905 | /* End XCConfigurationList section */ 906 | }; 907 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 908 | } 909 | --------------------------------------------------------------------------------