├── ASETimer-Widget ├── ASETimer-WidgetExtension.entitlements ├── ASETimer_Widget.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── HeroColor.colorset │ │ └── Contents.json │ ├── WidgetBackground.colorset │ │ └── Contents.json │ └── hero_widget.imageset │ │ ├── Contents.json │ │ └── hero_widget@2x.png └── Info.plist ├── ASETimerSwiftUI.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── rahulrs0029.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── ASETimerSwiftUI ├── ASE Timer.swift ├── ASETimerSwiftUI.entitlements ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-20x20.png │ │ ├── Icon-App-20x20@2x-1.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29-1.png │ │ ├── Icon-App-29x29.png │ │ ├── Icon-App-29x29@2x-1.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40.png │ │ ├── Icon-App-40x40@2x-1.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76.png │ │ ├── Icon-App-76x76@2x.png │ │ ├── Icon-App-83.5x83.5@2x.png │ │ └── Icon-App-iTunes.png │ ├── Contents.json │ ├── HeroColor.colorset │ │ └── Contents.json │ ├── LaunchScreenColor.colorset │ │ └── Contents.json │ └── hero.imageset │ │ ├── Contents.json │ │ └── hero@2x.png ├── Info.plist ├── Model │ ├── Event.swift │ └── RowType.swift ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json ├── Supporting Views │ ├── CountdownRow.swift │ ├── CountdownView.swift │ └── SeparatorView.swift ├── View Model │ └── EventManager.swift └── View │ └── ContentView.swift ├── ASETimerTests └── ASETimerTests.swift └── LICENSE /ASETimer-Widget/ASETimer-WidgetExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ASETimer-Widget/ASETimer_Widget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ASETimer_Widget.swift 3 | // ASETimer-Widget 4 | // 5 | // Created by Rahul Sharma on 10/7/20. 6 | // Copyright © 2020 Rahul Sharma. All rights reserved. 7 | // 8 | 9 | import WidgetKit 10 | import SwiftUI 11 | 12 | struct Provider: TimelineProvider { 13 | 14 | func placeholder( 15 | in context: Context 16 | ) -> SimpleEntry { 17 | SimpleEntry() 18 | } 19 | 20 | func getSnapshot( 21 | in context: Context, 22 | completion: @escaping (SimpleEntry) -> () 23 | ) { 24 | let entry = SimpleEntry() 25 | completion(entry) 26 | } 27 | 28 | func getTimeline( 29 | in context: Context, 30 | completion: @escaping (Timeline) -> () 31 | ) { 32 | let entry = SimpleEntry() 33 | if entry.eventConcluded { 34 | let timeline = Timeline(entries: [entry], policy: .never) 35 | completion(timeline) 36 | } else { 37 | let timeline = Timeline(entries: [entry], 38 | policy: .after(entry.eventDate)) 39 | completion(timeline) 40 | } 41 | } 42 | 43 | } 44 | 45 | struct SimpleEntry: TimelineEntry { 46 | var date = Date() 47 | private var event = Event() 48 | var eventDate: Date { Date(timeIntervalSince1970: event.unixTime) } 49 | var eventConcluded: Bool { eventDate < date } 50 | var eventBackgroundColors: [Color] { 51 | event.eventBackgroundColors 52 | } 53 | } 54 | 55 | struct ASETimer_WidgetEntryView : View { 56 | 57 | var entry: Provider.Entry 58 | 59 | @Environment(\.widgetFamily) var widgetFamily 60 | 61 | var imageName: String { 62 | "hero_widget" 63 | } 64 | 65 | var text: some View { 66 | VStack { 67 | Spacer() 68 | HStack { 69 | Group { 70 | if entry.eventConcluded { 71 | Text("Event Ended") 72 | } else { 73 | Text(entry.eventDate, style: .relative) 74 | .fontWeight(.bold) 75 | } 76 | } 77 | .font(widgetFamily == .systemSmall ? .body : .title) 78 | .foregroundColor(Color("HeroColor")) 79 | Spacer() 80 | } 81 | } 82 | .padding() 83 | } 84 | 85 | var body: some View { 86 | ZStack { 87 | LinearGradient(colors: entry.eventBackgroundColors, 88 | startPoint: .top, 89 | endPoint: .bottom) 90 | GeometryReader { geometry in 91 | Image(imageName) 92 | .resizable() 93 | .aspectRatio(contentMode: widgetFamily == .systemSmall ? .fill : .fit) 94 | .frame(width: geometry.size.width, 95 | height: geometry.size.height) 96 | .clipped() 97 | .unredacted() 98 | } 99 | text 100 | } 101 | } 102 | 103 | } 104 | 105 | @main 106 | struct ASETimer_Widget: Widget { 107 | let kind: String = "ASETimer_Widget" 108 | 109 | var body: some WidgetConfiguration { 110 | StaticConfiguration( 111 | kind: kind, provider: Provider() 112 | ) { entry in 113 | ASETimer_WidgetEntryView(entry: entry) 114 | } 115 | .configurationDisplayName("ASE Timer") 116 | .description("Countdown for WWDC 2022 Keynote") 117 | .supportedFamilies([.systemSmall, .systemMedium]) 118 | } 119 | } 120 | 121 | struct ASETimer_Widget_Previews: PreviewProvider { 122 | static var previews: some View { 123 | let entry = SimpleEntry() 124 | let systemSmall = WidgetPreviewContext(family: .systemSmall) 125 | let systemMedium = WidgetPreviewContext(family: .systemMedium) 126 | return Group { 127 | ASETimer_WidgetEntryView(entry: entry) 128 | .previewContext(systemSmall) 129 | ASETimer_WidgetEntryView(entry: entry) 130 | .previewContext(systemMedium) 131 | ASETimer_WidgetEntryView(entry: entry) 132 | .redacted(reason: .placeholder) 133 | .previewContext(systemSmall) 134 | ASETimer_WidgetEntryView(entry: entry) 135 | .redacted(reason: .placeholder) 136 | .previewContext(systemMedium) 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /ASETimer-Widget/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "platform" : "ios", 6 | "reference" : "darkTextColor" 7 | }, 8 | "idiom" : "universal" 9 | } 10 | ], 11 | "info" : { 12 | "author" : "xcode", 13 | "version" : 1 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ASETimer-Widget/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /ASETimer-Widget/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ASETimer-Widget/Assets.xcassets/HeroColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.902", 9 | "green" : "0.882", 10 | "red" : "0.776" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ASETimer-Widget/Assets.xcassets/WidgetBackground.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ASETimer-Widget/Assets.xcassets/hero_widget.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "hero_widget@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ASETimer-Widget/Assets.xcassets/hero_widget.imageset/hero_widget@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimer-Widget/Assets.xcassets/hero_widget.imageset/hero_widget@2x.png -------------------------------------------------------------------------------- /ASETimer-Widget/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | ASE Timer Widget 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSExtension 24 | 25 | NSExtensionPointIdentifier 26 | com.apple.widgetkit-extension 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /ASETimerSwiftUI.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2027F8CF262FF53300ED7A3B /* ASE Timer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2027F8CE262FF53300ED7A3B /* ASE Timer.swift */; }; 11 | 204CBD5E2551108C008EBD1E /* RowType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20E38ADD2318DC6F001BB042 /* RowType.swift */; }; 12 | 208BA80D252D9567003EC6FF /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 208BA80C252D9567003EC6FF /* WidgetKit.framework */; }; 13 | 208BA80F252D9567003EC6FF /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 208BA80E252D9567003EC6FF /* SwiftUI.framework */; }; 14 | 208BA812252D9567003EC6FF /* ASETimer_Widget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 208BA811252D9567003EC6FF /* ASETimer_Widget.swift */; }; 15 | 208BA814252D956B003EC6FF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 208BA813252D956B003EC6FF /* Assets.xcassets */; }; 16 | 208BA818252D956B003EC6FF /* ASETimer-WidgetExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 208BA80A252D9567003EC6FF /* ASETimer-WidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 17 | 208BA821252D95B7003EC6FF /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20E38ADF2318DC83001BB042 /* Event.swift */; }; 18 | 20C4C35A22F833D00011C0B0 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20C4C35922F833D00011C0B0 /* ContentView.swift */; }; 19 | 20C4C35C22F833D10011C0B0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 20C4C35B22F833D10011C0B0 /* Assets.xcassets */; }; 20 | 20C4C35F22F833D10011C0B0 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 20C4C35E22F833D10011C0B0 /* Preview Assets.xcassets */; }; 21 | 20E38ADE2318DC6F001BB042 /* RowType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20E38ADD2318DC6F001BB042 /* RowType.swift */; }; 22 | 20E38AE02318DC83001BB042 /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20E38ADF2318DC83001BB042 /* Event.swift */; }; 23 | 20E38AE22318DC9D001BB042 /* CountdownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20E38AE12318DC9D001BB042 /* CountdownView.swift */; }; 24 | 20E38AE42318DD06001BB042 /* CountdownRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20E38AE32318DD06001BB042 /* CountdownRow.swift */; }; 25 | 20E38AE62318DD29001BB042 /* SeparatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20E38AE52318DD29001BB042 /* SeparatorView.swift */; }; 26 | 20F7E0A924824EAE00966704 /* EventManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20F7E0A824824EAE00966704 /* EventManager.swift */; }; 27 | C27A6923284B3CB0005F6C53 /* ASETimerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C27A6922284B3CB0005F6C53 /* ASETimerTests.swift */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXContainerItemProxy section */ 31 | 208BA816252D956B003EC6FF /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = 20C4C34A22F833D00011C0B0 /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = 208BA809252D9567003EC6FF; 36 | remoteInfo = "ASETimer-WidgetExtension"; 37 | }; 38 | C27A6924284B3CB0005F6C53 /* PBXContainerItemProxy */ = { 39 | isa = PBXContainerItemProxy; 40 | containerPortal = 20C4C34A22F833D00011C0B0 /* Project object */; 41 | proxyType = 1; 42 | remoteGlobalIDString = 20C4C35122F833D00011C0B0; 43 | remoteInfo = ASETimerSwiftUI; 44 | }; 45 | /* End PBXContainerItemProxy section */ 46 | 47 | /* Begin PBXCopyFilesBuildPhase section */ 48 | 208BA81A252D956B003EC6FF /* Embed App Extensions */ = { 49 | isa = PBXCopyFilesBuildPhase; 50 | buildActionMask = 2147483647; 51 | dstPath = ""; 52 | dstSubfolderSpec = 13; 53 | files = ( 54 | 208BA818252D956B003EC6FF /* ASETimer-WidgetExtension.appex in Embed App Extensions */, 55 | ); 56 | name = "Embed App Extensions"; 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | /* End PBXCopyFilesBuildPhase section */ 60 | 61 | /* Begin PBXFileReference section */ 62 | 2027F8CE262FF53300ED7A3B /* ASE Timer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ASE Timer.swift"; sourceTree = ""; }; 63 | 208BA80A252D9567003EC6FF /* ASETimer-WidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "ASETimer-WidgetExtension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | 208BA80C252D9567003EC6FF /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; 65 | 208BA80E252D9567003EC6FF /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; 66 | 208BA811252D9567003EC6FF /* ASETimer_Widget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASETimer_Widget.swift; sourceTree = ""; }; 67 | 208BA813252D956B003EC6FF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 68 | 208BA815252D956B003EC6FF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 69 | 208BA819252D956B003EC6FF /* ASETimer-WidgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "ASETimer-WidgetExtension.entitlements"; sourceTree = ""; }; 70 | 20C4C35222F833D00011C0B0 /* ASE Timer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ASE Timer.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 71 | 20C4C35922F833D00011C0B0 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 72 | 20C4C35B22F833D10011C0B0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 73 | 20C4C35E22F833D10011C0B0 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 74 | 20C4C36322F833D10011C0B0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 75 | 20E38ADC2318DC36001BB042 /* ASETimerSwiftUI.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ASETimerSwiftUI.entitlements; sourceTree = ""; }; 76 | 20E38ADD2318DC6F001BB042 /* RowType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RowType.swift; sourceTree = ""; }; 77 | 20E38ADF2318DC83001BB042 /* Event.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Event.swift; sourceTree = ""; }; 78 | 20E38AE12318DC9D001BB042 /* CountdownView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountdownView.swift; sourceTree = ""; }; 79 | 20E38AE32318DD06001BB042 /* CountdownRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountdownRow.swift; sourceTree = ""; }; 80 | 20E38AE52318DD29001BB042 /* SeparatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorView.swift; sourceTree = ""; }; 81 | 20F7E0A824824EAE00966704 /* EventManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventManager.swift; sourceTree = ""; }; 82 | C27A6920284B3CB0005F6C53 /* ASETimeSwiftUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ASETimeSwiftUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 83 | C27A6922284B3CB0005F6C53 /* ASETimerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASETimerTests.swift; sourceTree = ""; }; 84 | /* End PBXFileReference section */ 85 | 86 | /* Begin PBXFrameworksBuildPhase section */ 87 | 208BA807252D9567003EC6FF /* Frameworks */ = { 88 | isa = PBXFrameworksBuildPhase; 89 | buildActionMask = 2147483647; 90 | files = ( 91 | 208BA80F252D9567003EC6FF /* SwiftUI.framework in Frameworks */, 92 | 208BA80D252D9567003EC6FF /* WidgetKit.framework in Frameworks */, 93 | ); 94 | runOnlyForDeploymentPostprocessing = 0; 95 | }; 96 | 20C4C34F22F833D00011C0B0 /* Frameworks */ = { 97 | isa = PBXFrameworksBuildPhase; 98 | buildActionMask = 2147483647; 99 | files = ( 100 | ); 101 | runOnlyForDeploymentPostprocessing = 0; 102 | }; 103 | C27A691D284B3CB0005F6C53 /* Frameworks */ = { 104 | isa = PBXFrameworksBuildPhase; 105 | buildActionMask = 2147483647; 106 | files = ( 107 | ); 108 | runOnlyForDeploymentPostprocessing = 0; 109 | }; 110 | /* End PBXFrameworksBuildPhase section */ 111 | 112 | /* Begin PBXGroup section */ 113 | 204CBD5425511061008EBD1E /* View Model */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 20F7E0A824824EAE00966704 /* EventManager.swift */, 117 | ); 118 | path = "View Model"; 119 | sourceTree = ""; 120 | }; 121 | 204CBD5525511068008EBD1E /* Model */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 20E38ADF2318DC83001BB042 /* Event.swift */, 125 | 20E38ADD2318DC6F001BB042 /* RowType.swift */, 126 | ); 127 | path = Model; 128 | sourceTree = ""; 129 | }; 130 | 204CBD5625511071008EBD1E /* View */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 20C4C35922F833D00011C0B0 /* ContentView.swift */, 134 | ); 135 | path = View; 136 | sourceTree = ""; 137 | }; 138 | 204CBD5B2551107F008EBD1E /* Supporting Views */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 20E38AE12318DC9D001BB042 /* CountdownView.swift */, 142 | 20E38AE32318DD06001BB042 /* CountdownRow.swift */, 143 | 20E38AE52318DD29001BB042 /* SeparatorView.swift */, 144 | ); 145 | path = "Supporting Views"; 146 | sourceTree = ""; 147 | }; 148 | 208BA80B252D9567003EC6FF /* Frameworks */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | 208BA80C252D9567003EC6FF /* WidgetKit.framework */, 152 | 208BA80E252D9567003EC6FF /* SwiftUI.framework */, 153 | ); 154 | name = Frameworks; 155 | sourceTree = ""; 156 | }; 157 | 208BA810252D9567003EC6FF /* ASETimer-Widget */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 208BA819252D956B003EC6FF /* ASETimer-WidgetExtension.entitlements */, 161 | 208BA811252D9567003EC6FF /* ASETimer_Widget.swift */, 162 | 208BA813252D956B003EC6FF /* Assets.xcassets */, 163 | 208BA815252D956B003EC6FF /* Info.plist */, 164 | ); 165 | path = "ASETimer-Widget"; 166 | sourceTree = ""; 167 | }; 168 | 20C4C34922F833D00011C0B0 = { 169 | isa = PBXGroup; 170 | children = ( 171 | 20C4C35422F833D00011C0B0 /* ASETimerSwiftUI */, 172 | 208BA810252D9567003EC6FF /* ASETimer-Widget */, 173 | C27A6921284B3CB0005F6C53 /* ASETimerTests */, 174 | 208BA80B252D9567003EC6FF /* Frameworks */, 175 | 20C4C35322F833D00011C0B0 /* Products */, 176 | ); 177 | sourceTree = ""; 178 | }; 179 | 20C4C35322F833D00011C0B0 /* Products */ = { 180 | isa = PBXGroup; 181 | children = ( 182 | 20C4C35222F833D00011C0B0 /* ASE Timer.app */, 183 | 208BA80A252D9567003EC6FF /* ASETimer-WidgetExtension.appex */, 184 | C27A6920284B3CB0005F6C53 /* ASETimeSwiftUITests.xctest */, 185 | ); 186 | name = Products; 187 | sourceTree = ""; 188 | }; 189 | 20C4C35422F833D00011C0B0 /* ASETimerSwiftUI */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 20E38ADC2318DC36001BB042 /* ASETimerSwiftUI.entitlements */, 193 | 2027F8CE262FF53300ED7A3B /* ASE Timer.swift */, 194 | 204CBD5525511068008EBD1E /* Model */, 195 | 204CBD5625511071008EBD1E /* View */, 196 | 204CBD5425511061008EBD1E /* View Model */, 197 | 204CBD5B2551107F008EBD1E /* Supporting Views */, 198 | 20C4C35B22F833D10011C0B0 /* Assets.xcassets */, 199 | 20C4C36322F833D10011C0B0 /* Info.plist */, 200 | 20C4C35D22F833D10011C0B0 /* Preview Content */, 201 | ); 202 | path = ASETimerSwiftUI; 203 | sourceTree = ""; 204 | }; 205 | 20C4C35D22F833D10011C0B0 /* Preview Content */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | 20C4C35E22F833D10011C0B0 /* Preview Assets.xcassets */, 209 | ); 210 | path = "Preview Content"; 211 | sourceTree = ""; 212 | }; 213 | C27A6921284B3CB0005F6C53 /* ASETimerTests */ = { 214 | isa = PBXGroup; 215 | children = ( 216 | C27A6922284B3CB0005F6C53 /* ASETimerTests.swift */, 217 | ); 218 | path = ASETimerTests; 219 | sourceTree = ""; 220 | }; 221 | /* End PBXGroup section */ 222 | 223 | /* Begin PBXNativeTarget section */ 224 | 208BA809252D9567003EC6FF /* ASETimer-WidgetExtension */ = { 225 | isa = PBXNativeTarget; 226 | buildConfigurationList = 208BA81D252D956B003EC6FF /* Build configuration list for PBXNativeTarget "ASETimer-WidgetExtension" */; 227 | buildPhases = ( 228 | 208BA806252D9567003EC6FF /* Sources */, 229 | 208BA807252D9567003EC6FF /* Frameworks */, 230 | 208BA808252D9567003EC6FF /* Resources */, 231 | ); 232 | buildRules = ( 233 | ); 234 | dependencies = ( 235 | ); 236 | name = "ASETimer-WidgetExtension"; 237 | productName = "ASETimer-WidgetExtension"; 238 | productReference = 208BA80A252D9567003EC6FF /* ASETimer-WidgetExtension.appex */; 239 | productType = "com.apple.product-type.app-extension"; 240 | }; 241 | 20C4C35122F833D00011C0B0 /* ASETimerSwiftUI */ = { 242 | isa = PBXNativeTarget; 243 | buildConfigurationList = 20C4C36622F833D10011C0B0 /* Build configuration list for PBXNativeTarget "ASETimerSwiftUI" */; 244 | buildPhases = ( 245 | 20C4C34E22F833D00011C0B0 /* Sources */, 246 | 20C4C34F22F833D00011C0B0 /* Frameworks */, 247 | 20C4C35022F833D00011C0B0 /* Resources */, 248 | 208BA81A252D956B003EC6FF /* Embed App Extensions */, 249 | ); 250 | buildRules = ( 251 | ); 252 | dependencies = ( 253 | 208BA817252D956B003EC6FF /* PBXTargetDependency */, 254 | ); 255 | name = ASETimerSwiftUI; 256 | productName = ASETimerSwiftUI; 257 | productReference = 20C4C35222F833D00011C0B0 /* ASE Timer.app */; 258 | productType = "com.apple.product-type.application"; 259 | }; 260 | C27A691F284B3CB0005F6C53 /* ASETimeSwiftUITests */ = { 261 | isa = PBXNativeTarget; 262 | buildConfigurationList = C27A6928284B3CB0005F6C53 /* Build configuration list for PBXNativeTarget "ASETimeSwiftUITests" */; 263 | buildPhases = ( 264 | C27A691C284B3CB0005F6C53 /* Sources */, 265 | C27A691D284B3CB0005F6C53 /* Frameworks */, 266 | C27A691E284B3CB0005F6C53 /* Resources */, 267 | ); 268 | buildRules = ( 269 | ); 270 | dependencies = ( 271 | C27A6925284B3CB0005F6C53 /* PBXTargetDependency */, 272 | ); 273 | name = ASETimeSwiftUITests; 274 | productName = ASETimeSwiftUITests; 275 | productReference = C27A6920284B3CB0005F6C53 /* ASETimeSwiftUITests.xctest */; 276 | productType = "com.apple.product-type.bundle.unit-test"; 277 | }; 278 | /* End PBXNativeTarget section */ 279 | 280 | /* Begin PBXProject section */ 281 | 20C4C34A22F833D00011C0B0 /* Project object */ = { 282 | isa = PBXProject; 283 | attributes = { 284 | LastSwiftUpdateCheck = 1340; 285 | LastUpgradeCheck = 1200; 286 | ORGANIZATIONNAME = "Rahul Sharma"; 287 | TargetAttributes = { 288 | 208BA809252D9567003EC6FF = { 289 | CreatedOnToolsVersion = 12.0.1; 290 | }; 291 | 20C4C35122F833D00011C0B0 = { 292 | CreatedOnToolsVersion = 11.0; 293 | }; 294 | C27A691F284B3CB0005F6C53 = { 295 | CreatedOnToolsVersion = 13.4; 296 | TestTargetID = 20C4C35122F833D00011C0B0; 297 | }; 298 | }; 299 | }; 300 | buildConfigurationList = 20C4C34D22F833D00011C0B0 /* Build configuration list for PBXProject "ASETimerSwiftUI" */; 301 | compatibilityVersion = "Xcode 9.3"; 302 | developmentRegion = en; 303 | hasScannedForEncodings = 0; 304 | knownRegions = ( 305 | en, 306 | Base, 307 | ); 308 | mainGroup = 20C4C34922F833D00011C0B0; 309 | productRefGroup = 20C4C35322F833D00011C0B0 /* Products */; 310 | projectDirPath = ""; 311 | projectRoot = ""; 312 | targets = ( 313 | 20C4C35122F833D00011C0B0 /* ASETimerSwiftUI */, 314 | 208BA809252D9567003EC6FF /* ASETimer-WidgetExtension */, 315 | C27A691F284B3CB0005F6C53 /* ASETimeSwiftUITests */, 316 | ); 317 | }; 318 | /* End PBXProject section */ 319 | 320 | /* Begin PBXResourcesBuildPhase section */ 321 | 208BA808252D9567003EC6FF /* Resources */ = { 322 | isa = PBXResourcesBuildPhase; 323 | buildActionMask = 2147483647; 324 | files = ( 325 | 208BA814252D956B003EC6FF /* Assets.xcassets in Resources */, 326 | ); 327 | runOnlyForDeploymentPostprocessing = 0; 328 | }; 329 | 20C4C35022F833D00011C0B0 /* Resources */ = { 330 | isa = PBXResourcesBuildPhase; 331 | buildActionMask = 2147483647; 332 | files = ( 333 | 20C4C35F22F833D10011C0B0 /* Preview Assets.xcassets in Resources */, 334 | 20C4C35C22F833D10011C0B0 /* Assets.xcassets in Resources */, 335 | ); 336 | runOnlyForDeploymentPostprocessing = 0; 337 | }; 338 | C27A691E284B3CB0005F6C53 /* Resources */ = { 339 | isa = PBXResourcesBuildPhase; 340 | buildActionMask = 2147483647; 341 | files = ( 342 | ); 343 | runOnlyForDeploymentPostprocessing = 0; 344 | }; 345 | /* End PBXResourcesBuildPhase section */ 346 | 347 | /* Begin PBXSourcesBuildPhase section */ 348 | 208BA806252D9567003EC6FF /* Sources */ = { 349 | isa = PBXSourcesBuildPhase; 350 | buildActionMask = 2147483647; 351 | files = ( 352 | 208BA821252D95B7003EC6FF /* Event.swift in Sources */, 353 | 204CBD5E2551108C008EBD1E /* RowType.swift in Sources */, 354 | 208BA812252D9567003EC6FF /* ASETimer_Widget.swift in Sources */, 355 | ); 356 | runOnlyForDeploymentPostprocessing = 0; 357 | }; 358 | 20C4C34E22F833D00011C0B0 /* Sources */ = { 359 | isa = PBXSourcesBuildPhase; 360 | buildActionMask = 2147483647; 361 | files = ( 362 | 20F7E0A924824EAE00966704 /* EventManager.swift in Sources */, 363 | 20E38AE22318DC9D001BB042 /* CountdownView.swift in Sources */, 364 | 20E38AE42318DD06001BB042 /* CountdownRow.swift in Sources */, 365 | 20E38AE62318DD29001BB042 /* SeparatorView.swift in Sources */, 366 | 2027F8CF262FF53300ED7A3B /* ASE Timer.swift in Sources */, 367 | 20E38ADE2318DC6F001BB042 /* RowType.swift in Sources */, 368 | 20C4C35A22F833D00011C0B0 /* ContentView.swift in Sources */, 369 | 20E38AE02318DC83001BB042 /* Event.swift in Sources */, 370 | ); 371 | runOnlyForDeploymentPostprocessing = 0; 372 | }; 373 | C27A691C284B3CB0005F6C53 /* Sources */ = { 374 | isa = PBXSourcesBuildPhase; 375 | buildActionMask = 2147483647; 376 | files = ( 377 | C27A6923284B3CB0005F6C53 /* ASETimerTests.swift in Sources */, 378 | ); 379 | runOnlyForDeploymentPostprocessing = 0; 380 | }; 381 | /* End PBXSourcesBuildPhase section */ 382 | 383 | /* Begin PBXTargetDependency section */ 384 | 208BA817252D956B003EC6FF /* PBXTargetDependency */ = { 385 | isa = PBXTargetDependency; 386 | target = 208BA809252D9567003EC6FF /* ASETimer-WidgetExtension */; 387 | targetProxy = 208BA816252D956B003EC6FF /* PBXContainerItemProxy */; 388 | }; 389 | C27A6925284B3CB0005F6C53 /* PBXTargetDependency */ = { 390 | isa = PBXTargetDependency; 391 | target = 20C4C35122F833D00011C0B0 /* ASETimerSwiftUI */; 392 | targetProxy = C27A6924284B3CB0005F6C53 /* PBXContainerItemProxy */; 393 | }; 394 | /* End PBXTargetDependency section */ 395 | 396 | /* Begin XCBuildConfiguration section */ 397 | 208BA81B252D956B003EC6FF /* Debug */ = { 398 | isa = XCBuildConfiguration; 399 | buildSettings = { 400 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 401 | ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; 402 | CODE_SIGN_ENTITLEMENTS = "ASETimer-Widget/ASETimer-WidgetExtension.entitlements"; 403 | CODE_SIGN_IDENTITY = "Apple Development"; 404 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; 405 | CODE_SIGN_STYLE = Automatic; 406 | CURRENT_PROJECT_VERSION = 13; 407 | DEVELOPMENT_TEAM = 6R75J2CEEH; 408 | "ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = NO; 409 | INFOPLIST_FILE = "ASETimer-Widget/Info.plist"; 410 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 411 | "IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.2; 412 | LD_RUNPATH_SEARCH_PATHS = ( 413 | "$(inherited)", 414 | "@executable_path/Frameworks", 415 | "@executable_path/../../Frameworks", 416 | ); 417 | PRODUCT_BUNDLE_IDENTIFIER = com.rahulrs.asetimer.widget; 418 | "PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*]" = maccatalyst.com.rahulrs.asetimer.widget; 419 | PRODUCT_NAME = "$(TARGET_NAME)"; 420 | PROVISIONING_PROFILE_SPECIFIER = ""; 421 | "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; 422 | SKIP_INSTALL = YES; 423 | SUPPORTS_MACCATALYST = YES; 424 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 425 | SWIFT_VERSION = 5.0; 426 | TARGETED_DEVICE_FAMILY = "1,2,6"; 427 | }; 428 | name = Debug; 429 | }; 430 | 208BA81C252D956B003EC6FF /* Release */ = { 431 | isa = XCBuildConfiguration; 432 | buildSettings = { 433 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 434 | ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; 435 | CODE_SIGN_ENTITLEMENTS = "ASETimer-Widget/ASETimer-WidgetExtension.entitlements"; 436 | CODE_SIGN_IDENTITY = "Apple Development"; 437 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; 438 | CODE_SIGN_STYLE = Automatic; 439 | CURRENT_PROJECT_VERSION = 13; 440 | DEVELOPMENT_TEAM = 6R75J2CEEH; 441 | "ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = NO; 442 | INFOPLIST_FILE = "ASETimer-Widget/Info.plist"; 443 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 444 | "IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.2; 445 | LD_RUNPATH_SEARCH_PATHS = ( 446 | "$(inherited)", 447 | "@executable_path/Frameworks", 448 | "@executable_path/../../Frameworks", 449 | ); 450 | PRODUCT_BUNDLE_IDENTIFIER = com.rahulrs.asetimer.widget; 451 | "PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*]" = maccatalyst.com.rahulrs.asetimer.widget; 452 | PRODUCT_NAME = "$(TARGET_NAME)"; 453 | PROVISIONING_PROFILE_SPECIFIER = ""; 454 | "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; 455 | SKIP_INSTALL = YES; 456 | SUPPORTS_MACCATALYST = YES; 457 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 458 | SWIFT_VERSION = 5.0; 459 | TARGETED_DEVICE_FAMILY = "1,2,6"; 460 | }; 461 | name = Release; 462 | }; 463 | 20C4C36422F833D10011C0B0 /* Debug */ = { 464 | isa = XCBuildConfiguration; 465 | buildSettings = { 466 | ALWAYS_SEARCH_USER_PATHS = NO; 467 | CLANG_ANALYZER_NONNULL = YES; 468 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 469 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 470 | CLANG_CXX_LIBRARY = "libc++"; 471 | CLANG_ENABLE_MODULES = YES; 472 | CLANG_ENABLE_OBJC_ARC = YES; 473 | CLANG_ENABLE_OBJC_WEAK = YES; 474 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 475 | CLANG_WARN_BOOL_CONVERSION = YES; 476 | CLANG_WARN_COMMA = YES; 477 | CLANG_WARN_CONSTANT_CONVERSION = YES; 478 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 479 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 480 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 481 | CLANG_WARN_EMPTY_BODY = YES; 482 | CLANG_WARN_ENUM_CONVERSION = YES; 483 | CLANG_WARN_INFINITE_RECURSION = YES; 484 | CLANG_WARN_INT_CONVERSION = YES; 485 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 486 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 487 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 488 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 489 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 490 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 491 | CLANG_WARN_STRICT_PROTOTYPES = YES; 492 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 493 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 494 | CLANG_WARN_UNREACHABLE_CODE = YES; 495 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 496 | COPY_PHASE_STRIP = NO; 497 | DEBUG_INFORMATION_FORMAT = dwarf; 498 | ENABLE_STRICT_OBJC_MSGSEND = YES; 499 | ENABLE_TESTABILITY = YES; 500 | GCC_C_LANGUAGE_STANDARD = gnu11; 501 | GCC_DYNAMIC_NO_PIC = NO; 502 | GCC_NO_COMMON_BLOCKS = YES; 503 | GCC_OPTIMIZATION_LEVEL = 0; 504 | GCC_PREPROCESSOR_DEFINITIONS = ( 505 | "DEBUG=1", 506 | "$(inherited)", 507 | ); 508 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 509 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 510 | GCC_WARN_UNDECLARED_SELECTOR = YES; 511 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 512 | GCC_WARN_UNUSED_FUNCTION = YES; 513 | GCC_WARN_UNUSED_VARIABLE = YES; 514 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 515 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 516 | MTL_FAST_MATH = YES; 517 | ONLY_ACTIVE_ARCH = YES; 518 | SDKROOT = iphoneos; 519 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 520 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 521 | }; 522 | name = Debug; 523 | }; 524 | 20C4C36522F833D10011C0B0 /* Release */ = { 525 | isa = XCBuildConfiguration; 526 | buildSettings = { 527 | ALWAYS_SEARCH_USER_PATHS = NO; 528 | CLANG_ANALYZER_NONNULL = YES; 529 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 530 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 531 | CLANG_CXX_LIBRARY = "libc++"; 532 | CLANG_ENABLE_MODULES = YES; 533 | CLANG_ENABLE_OBJC_ARC = YES; 534 | CLANG_ENABLE_OBJC_WEAK = YES; 535 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 536 | CLANG_WARN_BOOL_CONVERSION = YES; 537 | CLANG_WARN_COMMA = YES; 538 | CLANG_WARN_CONSTANT_CONVERSION = YES; 539 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 540 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 541 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 542 | CLANG_WARN_EMPTY_BODY = YES; 543 | CLANG_WARN_ENUM_CONVERSION = YES; 544 | CLANG_WARN_INFINITE_RECURSION = YES; 545 | CLANG_WARN_INT_CONVERSION = YES; 546 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 547 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 548 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 549 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 550 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 551 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 552 | CLANG_WARN_STRICT_PROTOTYPES = YES; 553 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 554 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 555 | CLANG_WARN_UNREACHABLE_CODE = YES; 556 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 557 | COPY_PHASE_STRIP = NO; 558 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 559 | ENABLE_NS_ASSERTIONS = NO; 560 | ENABLE_STRICT_OBJC_MSGSEND = YES; 561 | GCC_C_LANGUAGE_STANDARD = gnu11; 562 | GCC_NO_COMMON_BLOCKS = YES; 563 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 564 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 565 | GCC_WARN_UNDECLARED_SELECTOR = YES; 566 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 567 | GCC_WARN_UNUSED_FUNCTION = YES; 568 | GCC_WARN_UNUSED_VARIABLE = YES; 569 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 570 | MTL_ENABLE_DEBUG_INFO = NO; 571 | MTL_FAST_MATH = YES; 572 | SDKROOT = iphoneos; 573 | SWIFT_COMPILATION_MODE = wholemodule; 574 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 575 | VALIDATE_PRODUCT = YES; 576 | }; 577 | name = Release; 578 | }; 579 | 20C4C36722F833D10011C0B0 /* Debug */ = { 580 | isa = XCBuildConfiguration; 581 | buildSettings = { 582 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 583 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 584 | CODE_SIGN_ENTITLEMENTS = ASETimerSwiftUI/ASETimerSwiftUI.entitlements; 585 | CODE_SIGN_IDENTITY = "Apple Development"; 586 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; 587 | CODE_SIGN_STYLE = Automatic; 588 | CURRENT_PROJECT_VERSION = 13; 589 | DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES; 590 | DEVELOPMENT_ASSET_PATHS = "ASETimerSwiftUI/Preview\\ Content"; 591 | DEVELOPMENT_TEAM = 6R75J2CEEH; 592 | "ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = NO; 593 | ENABLE_PREVIEWS = YES; 594 | INFOPLIST_FILE = ASETimerSwiftUI/Info.plist; 595 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 596 | LD_RUNPATH_SEARCH_PATHS = ( 597 | "$(inherited)", 598 | "@executable_path/Frameworks", 599 | ); 600 | PRODUCT_BUNDLE_IDENTIFIER = com.rahulrs.asetimer; 601 | PRODUCT_NAME = "ASE Timer"; 602 | PROVISIONING_PROFILE_SPECIFIER = ""; 603 | "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; 604 | SUPPORTS_MACCATALYST = YES; 605 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 606 | SWIFT_VERSION = 5.0; 607 | TARGETED_DEVICE_FAMILY = "1,2,6"; 608 | }; 609 | name = Debug; 610 | }; 611 | 20C4C36822F833D10011C0B0 /* Release */ = { 612 | isa = XCBuildConfiguration; 613 | buildSettings = { 614 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 615 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 616 | CODE_SIGN_ENTITLEMENTS = ASETimerSwiftUI/ASETimerSwiftUI.entitlements; 617 | CODE_SIGN_IDENTITY = "Apple Development"; 618 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; 619 | CODE_SIGN_STYLE = Automatic; 620 | CURRENT_PROJECT_VERSION = 13; 621 | DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES; 622 | DEVELOPMENT_ASSET_PATHS = "ASETimerSwiftUI/Preview\\ Content"; 623 | DEVELOPMENT_TEAM = 6R75J2CEEH; 624 | "ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = NO; 625 | ENABLE_PREVIEWS = YES; 626 | INFOPLIST_FILE = ASETimerSwiftUI/Info.plist; 627 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 628 | LD_RUNPATH_SEARCH_PATHS = ( 629 | "$(inherited)", 630 | "@executable_path/Frameworks", 631 | ); 632 | PRODUCT_BUNDLE_IDENTIFIER = com.rahulrs.asetimer; 633 | PRODUCT_NAME = "ASE Timer"; 634 | PROVISIONING_PROFILE_SPECIFIER = ""; 635 | "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; 636 | SUPPORTS_MACCATALYST = YES; 637 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 638 | SWIFT_VERSION = 5.0; 639 | TARGETED_DEVICE_FAMILY = "1,2,6"; 640 | }; 641 | name = Release; 642 | }; 643 | C27A6926284B3CB0005F6C53 /* Debug */ = { 644 | isa = XCBuildConfiguration; 645 | buildSettings = { 646 | BUNDLE_LOADER = "$(TEST_HOST)"; 647 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 648 | CODE_SIGN_STYLE = Automatic; 649 | CURRENT_PROJECT_VERSION = 1; 650 | GENERATE_INFOPLIST_FILE = YES; 651 | IPHONEOS_DEPLOYMENT_TARGET = 15.5; 652 | MARKETING_VERSION = 1.0; 653 | PRODUCT_BUNDLE_IDENTIFIER = com.rahulrs.ASETimeSwiftUITests; 654 | PRODUCT_NAME = "$(TARGET_NAME)"; 655 | SWIFT_EMIT_LOC_STRINGS = NO; 656 | SWIFT_VERSION = 5.0; 657 | TARGETED_DEVICE_FAMILY = "1,2"; 658 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ASE Timer.app/ASE Timer"; 659 | }; 660 | name = Debug; 661 | }; 662 | C27A6927284B3CB0005F6C53 /* Release */ = { 663 | isa = XCBuildConfiguration; 664 | buildSettings = { 665 | BUNDLE_LOADER = "$(TEST_HOST)"; 666 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 667 | CODE_SIGN_STYLE = Automatic; 668 | CURRENT_PROJECT_VERSION = 1; 669 | GENERATE_INFOPLIST_FILE = YES; 670 | IPHONEOS_DEPLOYMENT_TARGET = 15.5; 671 | MARKETING_VERSION = 1.0; 672 | PRODUCT_BUNDLE_IDENTIFIER = com.rahulrs.ASETimeSwiftUITests; 673 | PRODUCT_NAME = "$(TARGET_NAME)"; 674 | SWIFT_EMIT_LOC_STRINGS = NO; 675 | SWIFT_VERSION = 5.0; 676 | TARGETED_DEVICE_FAMILY = "1,2"; 677 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ASE Timer.app/ASE Timer"; 678 | }; 679 | name = Release; 680 | }; 681 | /* End XCBuildConfiguration section */ 682 | 683 | /* Begin XCConfigurationList section */ 684 | 208BA81D252D956B003EC6FF /* Build configuration list for PBXNativeTarget "ASETimer-WidgetExtension" */ = { 685 | isa = XCConfigurationList; 686 | buildConfigurations = ( 687 | 208BA81B252D956B003EC6FF /* Debug */, 688 | 208BA81C252D956B003EC6FF /* Release */, 689 | ); 690 | defaultConfigurationIsVisible = 0; 691 | defaultConfigurationName = Release; 692 | }; 693 | 20C4C34D22F833D00011C0B0 /* Build configuration list for PBXProject "ASETimerSwiftUI" */ = { 694 | isa = XCConfigurationList; 695 | buildConfigurations = ( 696 | 20C4C36422F833D10011C0B0 /* Debug */, 697 | 20C4C36522F833D10011C0B0 /* Release */, 698 | ); 699 | defaultConfigurationIsVisible = 0; 700 | defaultConfigurationName = Release; 701 | }; 702 | 20C4C36622F833D10011C0B0 /* Build configuration list for PBXNativeTarget "ASETimerSwiftUI" */ = { 703 | isa = XCConfigurationList; 704 | buildConfigurations = ( 705 | 20C4C36722F833D10011C0B0 /* Debug */, 706 | 20C4C36822F833D10011C0B0 /* Release */, 707 | ); 708 | defaultConfigurationIsVisible = 0; 709 | defaultConfigurationName = Release; 710 | }; 711 | C27A6928284B3CB0005F6C53 /* Build configuration list for PBXNativeTarget "ASETimeSwiftUITests" */ = { 712 | isa = XCConfigurationList; 713 | buildConfigurations = ( 714 | C27A6926284B3CB0005F6C53 /* Debug */, 715 | C27A6927284B3CB0005F6C53 /* Release */, 716 | ); 717 | defaultConfigurationIsVisible = 0; 718 | defaultConfigurationName = Release; 719 | }; 720 | /* End XCConfigurationList section */ 721 | }; 722 | rootObject = 20C4C34A22F833D00011C0B0 /* Project object */; 723 | } 724 | -------------------------------------------------------------------------------- /ASETimerSwiftUI.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ASETimerSwiftUI.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ASETimerSwiftUI.xcodeproj/xcuserdata/rahulrs0029.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ASETimer-WidgetExtension.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 1 11 | 12 | ASETimerSwiftUI.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/ASE Timer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ASE Timer.swift 3 | // ASETimerSwiftUI 4 | // 5 | // Created by Rahul Sharma on 21/04/21. 6 | // Copyright © 2021 Rahul Sharma. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | @main 12 | struct ASE_Timer: App { 13 | 14 | @StateObject var eventManager = EventManager() 15 | 16 | var body: some Scene { 17 | WindowGroup { 18 | ContentView(eventManager: eventManager) 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/ASETimerSwiftUI.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-20x20@2x.png", 5 | "idiom" : "iphone", 6 | "scale" : "2x", 7 | "size" : "20x20" 8 | }, 9 | { 10 | "filename" : "Icon-App-20x20@3x.png", 11 | "idiom" : "iphone", 12 | "scale" : "3x", 13 | "size" : "20x20" 14 | }, 15 | { 16 | "filename" : "Icon-App-29x29.png", 17 | "idiom" : "iphone", 18 | "scale" : "1x", 19 | "size" : "29x29" 20 | }, 21 | { 22 | "filename" : "Icon-App-29x29@2x.png", 23 | "idiom" : "iphone", 24 | "scale" : "2x", 25 | "size" : "29x29" 26 | }, 27 | { 28 | "filename" : "Icon-App-29x29@3x.png", 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "29x29" 32 | }, 33 | { 34 | "filename" : "Icon-App-40x40@2x.png", 35 | "idiom" : "iphone", 36 | "scale" : "2x", 37 | "size" : "40x40" 38 | }, 39 | { 40 | "filename" : "Icon-App-40x40@3x.png", 41 | "idiom" : "iphone", 42 | "scale" : "3x", 43 | "size" : "40x40" 44 | }, 45 | { 46 | "filename" : "Icon-App-60x60@2x.png", 47 | "idiom" : "iphone", 48 | "scale" : "2x", 49 | "size" : "60x60" 50 | }, 51 | { 52 | "filename" : "Icon-App-60x60@3x.png", 53 | "idiom" : "iphone", 54 | "scale" : "3x", 55 | "size" : "60x60" 56 | }, 57 | { 58 | "filename" : "Icon-App-20x20.png", 59 | "idiom" : "ipad", 60 | "scale" : "1x", 61 | "size" : "20x20" 62 | }, 63 | { 64 | "filename" : "Icon-App-20x20@2x-1.png", 65 | "idiom" : "ipad", 66 | "scale" : "2x", 67 | "size" : "20x20" 68 | }, 69 | { 70 | "filename" : "Icon-App-29x29-1.png", 71 | "idiom" : "ipad", 72 | "scale" : "1x", 73 | "size" : "29x29" 74 | }, 75 | { 76 | "filename" : "Icon-App-29x29@2x-1.png", 77 | "idiom" : "ipad", 78 | "scale" : "2x", 79 | "size" : "29x29" 80 | }, 81 | { 82 | "filename" : "Icon-App-40x40.png", 83 | "idiom" : "ipad", 84 | "scale" : "1x", 85 | "size" : "40x40" 86 | }, 87 | { 88 | "filename" : "Icon-App-40x40@2x-1.png", 89 | "idiom" : "ipad", 90 | "scale" : "2x", 91 | "size" : "40x40" 92 | }, 93 | { 94 | "filename" : "Icon-App-76x76.png", 95 | "idiom" : "ipad", 96 | "scale" : "1x", 97 | "size" : "76x76" 98 | }, 99 | { 100 | "filename" : "Icon-App-76x76@2x.png", 101 | "idiom" : "ipad", 102 | "scale" : "2x", 103 | "size" : "76x76" 104 | }, 105 | { 106 | "filename" : "Icon-App-83.5x83.5@2x.png", 107 | "idiom" : "ipad", 108 | "scale" : "2x", 109 | "size" : "83.5x83.5" 110 | }, 111 | { 112 | "filename" : "Icon-App-iTunes.png", 113 | "idiom" : "ios-marketing", 114 | "scale" : "1x", 115 | "size" : "1024x1024" 116 | } 117 | ], 118 | "info" : { 119 | "author" : "xcode", 120 | "version" : 1 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29-1.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-iTunes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/AppIcon.appiconset/Icon-App-iTunes.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/HeroColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0xE6", 9 | "green" : "0xE1", 10 | "red" : "0xC6" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/LaunchScreenColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "extended-gray", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "white" : "0.000" 9 | } 10 | }, 11 | "idiom" : "universal" 12 | } 13 | ], 14 | "info" : { 15 | "author" : "xcode", 16 | "version" : 1 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/hero.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "hero@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/Assets.xcassets/hero.imageset/hero@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyrahulrs/ASETimerSwiftUI/22c5ebe17f9d3736bd3a3a61a8a3a875fb1f96cb/ASETimerSwiftUI/Assets.xcassets/hero.imageset/hero@2x.png -------------------------------------------------------------------------------- /ASETimerSwiftUI/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | LSApplicationCategoryType 22 | public.app-category.utilities 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchScreen 26 | 27 | UIColorName 28 | LaunchScreenColor 29 | 30 | UIRequiredDeviceCapabilities 31 | 32 | armv7 33 | 34 | UISupportedInterfaceOrientations 35 | 36 | UIInterfaceOrientationPortrait 37 | UIInterfaceOrientationPortraitUpsideDown 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/Model/Event.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Event.swift 3 | // ASETimerSwiftUI 4 | // 5 | // Created by Rahul Sharma on 8/30/19. 6 | // Copyright © 2019 Rahul Sharma. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct Event { 12 | 13 | var heading: String { "WWDC 2022" } 14 | 15 | private let dateFormat = "MMMM d' at 'h:mm a" 16 | var timeZone: TimeZone? = nil 17 | 18 | var description: String { 19 | let dateFormatter = DateFormatter() 20 | dateFormatter.dateFormat = dateFormat 21 | dateFormatter.timeZone = timeZone ?? TimeZone.current 22 | let date = dateFormatter.string(from: Date(timeIntervalSince1970: unixTime)) 23 | let abbreviation = abbreviation() 24 | return "Watch on " + date + " " + abbreviation + ".\nView online at apple.com or on the Apple TV app." 25 | } 26 | 27 | func abbreviation() -> String { 28 | for(key, value) in TimeZone.abbreviationDictionary { 29 | if value == (timeZone ?? TimeZone.current).identifier { 30 | return key 31 | } 32 | } 33 | return "" 34 | } 35 | 36 | var unixTime: TimeInterval { 1654534800 } 37 | 38 | var eventBackgroundColors: [Color] = [ 39 | .init(red: 2 / 255, green: 13 / 255, blue: 31 / 255), 40 | .black 41 | ] 42 | 43 | var eventTextColor = Color("HeroColor") 44 | 45 | } 46 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/Model/RowType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RowType.swift 3 | // ASETimerSwiftUI 4 | // 5 | // Created by Rahul Sharma on 8/30/19. 6 | // Copyright © 2019 Rahul Sharma. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum RowType: String { 12 | case days 13 | case hours 14 | case minutes 15 | case seconds 16 | } 17 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ASETimerSwiftUI/Supporting Views/CountdownRow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CountdownRow.swift 3 | // ASETimerSwiftUI 4 | // 5 | // Created by Rahul Sharma on 8/30/19. 6 | // Copyright © 2019 Rahul Sharma. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct CountdownRow: View { 12 | 13 | var number: Int 14 | var text: RowType 15 | 16 | var body: some View { 17 | VStack { 18 | Text(String(format: "%02d", number)) 19 | .fontWeight(.heavy) 20 | .font(Font.system(size: 38.0).monospacedDigit()) 21 | Text(text.rawValue.uppercased()) 22 | .fontWeight(.bold) 23 | .font(.caption) 24 | .opacity(0.7) 25 | } 26 | } 27 | 28 | } 29 | 30 | struct CountdownRow_Previews: PreviewProvider { 31 | static var previews: some View { 32 | CountdownRow(number: 12, text: .hours) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/Supporting Views/CountdownView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CountdownView.swift 3 | // ASETimerSwiftUI 4 | // 5 | // Created by Rahul Sharma on 8/30/19. 6 | // Copyright © 2019 Rahul Sharma. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct CountdownView: View { 12 | 13 | @ObservedObject var eventManager: EventManager 14 | 15 | var body: some View { 16 | if eventManager.isCountdownOver { 17 | Text("Countdown Ended".uppercased()) 18 | .font(.title) 19 | .fontWeight(.bold) 20 | .multilineTextAlignment(.center) 21 | .padding(.horizontal, 18.0) 22 | } else { 23 | HStack(alignment: .top) { 24 | if eventManager.remainingTime.days != 0 { 25 | CountdownRow(number: eventManager.remainingTime.days, 26 | text: .days) 27 | SeparatorView() 28 | } 29 | CountdownRow(number: eventManager.remainingTime.hours, 30 | text: .hours) 31 | SeparatorView() 32 | CountdownRow(number: eventManager.remainingTime.minutes, 33 | text: .minutes) 34 | SeparatorView() 35 | CountdownRow(number: eventManager.remainingTime.seconds, 36 | text: .seconds) 37 | } 38 | } 39 | } 40 | 41 | } 42 | 43 | struct CountdownView_Previews: PreviewProvider { 44 | static var previews: some View { 45 | CountdownView(eventManager: EventManager()) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/Supporting Views/SeparatorView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SeparatorView.swift 3 | // ASETimerSwiftUI 4 | // 5 | // Created by Rahul Sharma on 8/30/19. 6 | // Copyright © 2019 Rahul Sharma. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct SeparatorView: View { 12 | var body: some View { 13 | Text(":") 14 | .bold() 15 | .font(.largeTitle) 16 | .frame(height: 52.7) 17 | .offset(y: -2) 18 | } 19 | } 20 | 21 | struct SeparatorView_Previews: PreviewProvider { 22 | static var previews: some View { 23 | SeparatorView() 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/View Model/EventManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EventManager.swift 3 | // ASETimerSwiftUI 4 | // 5 | // Created by Rahul Sharma on 5/30/20. 6 | // Copyright © 2020 Rahul Sharma. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Combine 11 | 12 | typealias Time = (days: Int, hours: Int, minutes: Int, seconds: Int) 13 | 14 | class EventManager: ObservableObject { 15 | 16 | private var event = Event() 17 | 18 | var timer: Cancellable? 19 | 20 | var eventHeading: String { 21 | event.heading 22 | } 23 | 24 | var eventDescription: String { 25 | event.description 26 | } 27 | 28 | var eventDate: Date { 29 | Date(timeIntervalSince1970: event.unixTime) 30 | } 31 | 32 | var eventBackgroundColors: [Color] { 33 | event.eventBackgroundColors 34 | } 35 | 36 | var eventTextColor: Color { 37 | event.eventTextColor 38 | } 39 | 40 | @Published var isCountdownOver: Bool = false 41 | 42 | var imageName: String { 43 | "hero" 44 | } 45 | 46 | @Published var remainingSeconds = 0 47 | 48 | init() { 49 | updateRemainingSeconds() 50 | if remainingSeconds <= 0 { endTimer(); return } 51 | startTimer() 52 | } 53 | 54 | func startTimer() { 55 | timer = Timer.publish(every: 0.1, on: .main, in: .default) 56 | .autoconnect() 57 | .sink { [self] _ in 58 | if remainingSeconds <= 0 { endTimer(); return } 59 | updateRemainingSeconds() 60 | } 61 | } 62 | 63 | func updateRemainingSeconds() { 64 | remainingSeconds = Int(eventDate.timeIntervalSinceNow) 65 | } 66 | 67 | func endTimer() { 68 | isCountdownOver = true 69 | if timer != nil { 70 | timer?.cancel() 71 | timer = nil 72 | } 73 | } 74 | 75 | var remainingTime: Time { 76 | let remainingTime: Time = ( 77 | days: remainingSeconds / 86400, 78 | hours: (remainingSeconds % 86400) / 3600, 79 | minutes: (remainingSeconds % 3600) / 60, 80 | seconds: (remainingSeconds % 3600) % 60 81 | ) 82 | return remainingTime 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /ASETimerSwiftUI/View/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ASETimerSwiftUI 4 | // 5 | // Created by Rahul Sharma on 8/5/19. 6 | // Copyright © 2019 Rahul Sharma. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | 13 | var eventManager: EventManager 14 | 15 | var body: some View { 16 | GeometryReader { proxy in 17 | ZStack(alignment: .bottom){ 18 | LinearGradient(colors: eventManager.eventBackgroundColors, startPoint: .top, endPoint: .bottom) 19 | .ignoresSafeArea() 20 | VStack { 21 | Image(eventManager.imageName) 22 | .resizable() 23 | .aspectRatio(contentMode: .fit) 24 | .frame(height: proxy.size.height * 0.6) 25 | .scaleEffect(1.2) 26 | Spacer(minLength: 0.0) 27 | } 28 | VStack(spacing: 40.0) { 29 | VStack(spacing: 12.0) { 30 | Text(eventManager.eventHeading) 31 | .font(.system(size: 40.0, weight: .bold)) 32 | Text(eventManager.eventDescription) 33 | .multilineTextAlignment(.center) 34 | .padding(.bottom) 35 | CountdownView(eventManager: eventManager) 36 | } 37 | .layoutPriority(1) 38 | .padding(.horizontal) 39 | .padding(.bottom) 40 | Spacer(minLength: 0) 41 | } 42 | .foregroundColor(eventManager.eventTextColor) 43 | .frame(width: proxy.size.width, 44 | height: proxy.size.height * 0.4) 45 | } 46 | .statusBar(hidden: true) 47 | .frame(width: proxy.size.width, 48 | height: proxy.size.height, 49 | alignment: .bottom) 50 | } 51 | } 52 | 53 | } 54 | 55 | struct ContentView_Previews: PreviewProvider { 56 | static var previews: some View { 57 | let eventManager = EventManager() 58 | return Group { 59 | ContentView(eventManager: eventManager) 60 | .previewDevice("iPhone 13 Pro") 61 | ContentView(eventManager: eventManager) 62 | .previewDevice("iPhone 13 mini") 63 | ContentView(eventManager: eventManager) 64 | .previewDevice("iPhone SE (3rd generation)") 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /ASETimerTests/ASETimerTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ASETimerTests.swift 3 | // ASETimerTests 4 | // 5 | // Created by Rahul Sharma on 04/06/22. 6 | // Copyright © 2022 Rahul Sharma. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | @testable import ASE_Timer 12 | class ASETimerTests: XCTestCase { 13 | 14 | override func setUpWithError() throws { 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDownWithError() throws { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | } 21 | 22 | func testExample() throws { 23 | // This is an example of a functional test case. 24 | // Use XCTAssert and related functions to verify your tests produce the correct results. 25 | // Any test you write for XCTest can be annotated as throws and async. 26 | // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. 27 | // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. 28 | } 29 | 30 | func testPerformanceExample() throws { 31 | // This is an example of a performance test case. 32 | measure { 33 | // Put the code you want to measure the time of here. 34 | } 35 | } 36 | 37 | func testEventDescriptionInIST() { 38 | // given 39 | let event = Event() 40 | 41 | // when 42 | let description = event.description 43 | 44 | // then 45 | let expected = "Watch on June 6 at 10:30 PM IST.\nView online at apple.com or on the Apple TV app." 46 | XCTAssertEqual(description, expected) 47 | } 48 | 49 | func testEventDescriptionInPST() { 50 | // given 51 | var event = Event() 52 | 53 | // when 54 | event.timeZone = TimeZone(abbreviation: "PDT")! 55 | let description = event.description 56 | 57 | // then 58 | let expected = "Watch on June 6 at 10:00 AM PDT.\nView online at apple.com or on the Apple TV app." 59 | XCTAssertEqual(description, expected) 60 | } 61 | 62 | func testTimeRemaining() { 63 | // given 64 | let eventManager = EventManager() 65 | eventManager.endTimer() 66 | 67 | // when 68 | eventManager.remainingSeconds = 3722 69 | 70 | // then 71 | let expectedTime = Time(days: 0, hours: 1, minutes: 2, seconds: 2) 72 | XCTAssertEqual(eventManager.remainingTime.days, expectedTime.days) 73 | XCTAssertEqual(eventManager.remainingTime.hours, expectedTime.hours) 74 | XCTAssertEqual(eventManager.remainingTime.minutes, expectedTime.minutes) 75 | XCTAssertEqual(eventManager.remainingTime.seconds, expectedTime.seconds) 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------