Skip to content

Commit

Permalink
Merge pull request #49 from DeveloperAcademy-POSTECH/feat/#25
Browse files Browse the repository at this point in the history
Feat/#25: set ProgressView and create automatic live activity with currentDate
  • Loading branch information
grootwo authored May 23, 2024
2 parents d25e422 + 6fa8b0b commit 2c1361a
Show file tree
Hide file tree
Showing 11 changed files with 233 additions and 104 deletions.
3 changes: 1 addition & 2 deletions LiveTimeWidget/Assets.xcassets/alarm.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
{
"images" : [
{
"filename" : "alarm.png",
"filename" : "_Lockscreen.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "alarm (1).png",
"idiom" : "universal",
"scale" : "2x"
},
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
21 changes: 21 additions & 0 deletions LiveTimeWidget/Assets.xcassets/pilling.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "pilling.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
112 changes: 70 additions & 42 deletions LiveTimeWidget/LiveTimeWidget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,63 +10,68 @@ import SwiftUI
import ActivityKit

struct LiveTimeWidget: Widget {
let progressTotal = 10.0
var body: some WidgetConfiguration {
ActivityConfiguration(for: LiveTimeAttributes.self) { context in
// lock screen & standby(잠금 화면과 notification center, 그리고 전체화면 버전)
VStack {
HStack {
Image(systemName: "leaf.fill")
.foregroundStyle(.customGreen)
Text("잔디를 심을 시간이에요!")
Spacer()
Text(context.state.restOfTime, style: .relative)
.foregroundStyle(.customGreen)
.frame(width: 77, height: 30)
HStack {
VStack(alignment: .leading, spacing: 10) {
Text("필링")
.font(.caption)
Text("잔디를 심을 시간이")
.bold()
HStack(alignment: .bottom) {
Text(context.state.restOfTime)
.font(.title)
Text(context.state.step <= 1 ? "남았어요" : "지났어요")
}
.foregroundStyle(context.state.step >= 3 ? .red : .customGreen)
ProgressView(value: context.state.progressAmount, total: progressTotal)
.tint(context.state.step >= 3 ? .red : .customGreen)
}
Divider()
ProgressView(value: context.state.progressAmount, total: 600)
.padding()
Image(context.state.step >= 3 ? "pilling" : "alarm")
}
.padding()
} dynamicIsland: { context in
// dynamic island
DynamicIsland {
// expanded dynamic island bottom(다이나믹 아일랜드 꾹 눌러서 확장되는 버전)
DynamicIslandExpandedRegion(.leading) {
Image("alarm")
.resizable()
.scaledToFit()
}
DynamicIslandExpandedRegion(.trailing) {
Text(context.state.restOfTime, style: .relative)
.foregroundStyle(.customGreen)
}
DynamicIslandExpandedRegion(.bottom) {
VStack {
Divider()
.frame(minHeight: 1)
.overlay(.customGreen)
Button(action: {}, label: {
Spacer()
Text("Button")
Spacer()
})
.foregroundColor(.customGreen)
.buttonStyle(.plain)
// expanded dynamic island(다이나믹 아일랜드 꾹 눌러서 확장되는 버전)
DynamicIslandExpandedRegion(.center) {
HStack {
VStack(alignment: .leading) {
Text("잔디를 심을 시간이")
.font(.headline)
.bold()
HStack(alignment: .bottom) {
Text(context.state.restOfTime)
.foregroundStyle(context.state.step >= 3 ? .red : .customGreen)
.font(.title)
Text(context.state.step <= 1 ? "남았어요" : "지났어요")
.font(.headline)
.foregroundStyle(context.state.step >= 3 ? .red : .customGreen)
}
ProgressView(value: context.state.progressAmount, total: progressTotal)
.tint(context.state.step >= 3 ? .red : .customGreen)
}
Image(context.state.step >= 3 ? "pilling" : "alarm")
.resizable()
.scaledToFit()
}
.padding()
}
} compactLeading: {
// compact leading(다이나믹 아일랜드 소형 버전 왼쪽)
Image("alarm")
Image(context.state.step >= 3 ? "pilling" : "alarm")
.resizable()
.scaledToFit()
} compactTrailing: {
// compact trailing(다이나믹 아일랜드 소형 버전 오른쪽)
Text(context.state.restOfTime, style: .relative)
.foregroundStyle(.customGreen)
.frame(width: 66)
Text(context.state.restOfTime)
.foregroundStyle(context.state.step >= 3 ? .red : .customGreen)
} minimal: {
// minimal(다이나믹 아일랜드 가장 작은 버전)
Text(context.state.restOfTime, style: .relative)
.foregroundStyle(.customGreen)
ProgressView(value: context.state.progressAmount, total: progressTotal)
.progressViewStyle(.circular)
.tint(context.state.step >= 3 ? .red : .customGreen)
}
}
}
Expand All @@ -76,7 +81,30 @@ struct TimeWidgetView: View {
let context: ActivityViewContext<LiveTimeAttributes>

var body: some View {
Text(context.state.restOfTime, style: .relative)
Text(context.state.restOfTime)
}
}


// preview 설정
extension LiveTimeAttributes.ContentState {
fileprivate static var start: LiveTimeAttributes.ContentState {
LiveTimeAttributes.ContentState(restOfTime: "3분 3초", progressAmount: 8, step: 1)
}

fileprivate static var middle: LiveTimeAttributes.ContentState {
LiveTimeAttributes.ContentState(restOfTime: "28분 58초", progressAmount: 300, step: 2)
}

fileprivate static var end: LiveTimeAttributes.ContentState {
LiveTimeAttributes.ContentState(restOfTime: "3시간 37분", progressAmount: 600, step: 3)
}
}

#Preview(as: .content, using: LiveTimeAttributes(), widget: {
LiveTimeWidget()
}, contentStates: {
LiveTimeAttributes.ContentState.start
LiveTimeAttributes.ContentState.middle
LiveTimeAttributes.ContentState.end
})
12 changes: 8 additions & 4 deletions MC2-Team3-Pilling.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
1B38E53A2BFDE11500CFD48B /* LiveActivityTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B38E5392BFDE11500CFD48B /* LiveActivityTestView.swift */; };
1B6530442BFB7C1600452ACB /* LiveTimeAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6530432BFB7C1600452ACB /* LiveTimeAttributes.swift */; };
1B65304C2BFB8A0C00452ACB /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B65304B2BFB8A0C00452ACB /* WidgetKit.framework */; };
1B65304E2BFB8A0C00452ACB /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B65304D2BFB8A0C00452ACB /* SwiftUI.framework */; };
Expand Down Expand Up @@ -61,6 +62,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
1B38E5392BFDE11500CFD48B /* LiveActivityTestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveActivityTestView.swift; sourceTree = "<group>"; };
1B6530432BFB7C1600452ACB /* LiveTimeAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTimeAttributes.swift; sourceTree = "<group>"; };
1B6530492BFB8A0C00452ACB /* LiveTimeWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = LiveTimeWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
1B65304B2BFB8A0C00452ACB /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -137,6 +139,7 @@
children = (
93EF92D52BFC4187004DEEF1 /* ChooseStatusView.swift */,
939C87E12BF307B600572EDC /* ContentView.swift */,
1B38E5392BFDE11500CFD48B /* LiveActivityTestView.swift */,
9B0411752BF593A0006F8BB9 /* MainView.swift */,
939C88312BF6B4AC00572EDC /* MedicineSheetView.swift */,
939C882D2BF5CC9100572EDC /* OnboardingFirstView.swift */,
Expand Down Expand Up @@ -322,6 +325,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1B38E53A2BFDE11500CFD48B /* LiveActivityTestView.swift in Sources */,
21B5E33B2BFCC83700D1FC06 /* PiriFirstView.swift in Sources */,
939C87E22BF307B600572EDC /* ContentView.swift in Sources */,
93EF92D62BFC4187004DEEF1 /* ChooseStatusView.swift in Sources */,
Expand Down Expand Up @@ -361,7 +365,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = F5WP2FDW4U;
DEVELOPMENT_TEAM = 62WZR6T98R;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = LiveTimeWidget/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = LiveTimeWidget;
Expand Down Expand Up @@ -390,7 +394,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = F5WP2FDW4U;
DEVELOPMENT_TEAM = 62WZR6T98R;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = LiveTimeWidget/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = LiveTimeWidget;
Expand Down Expand Up @@ -537,7 +541,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"MC2-Team3-Pilling/Preview Content\"";
DEVELOPMENT_TEAM = F5WP2FDW4U;
DEVELOPMENT_TEAM = 62WZR6T98R;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
Expand Down Expand Up @@ -577,7 +581,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"MC2-Team3-Pilling/Preview Content\"";
DEVELOPMENT_TEAM = F5WP2FDW4U;
DEVELOPMENT_TEAM = 62WZR6T98R;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
Expand Down
3 changes: 2 additions & 1 deletion MC2-Team3-Pilling/Model/LiveTimeAttributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ struct LiveTimeAttributes: ActivityAttributes {
public typealias TimeStatus = ContentState

public struct ContentState: Codable, Hashable {
var restOfTime: Date
var restOfTime: String
var progressAmount: Double
var step: Int
}
}
57 changes: 2 additions & 55 deletions MC2-Team3-Pilling/View/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,10 @@

import SwiftUI
import SwiftData
import ActivityKit

struct ContentView: View {
static let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "MM/dd/yyyy_HH:mm:ss"
return formatter
}()
@Environment(\.modelContext) private var modelContext

@State private var isTracking = false
@State private var alarmTime = dateFormatter.date(from: "\(Date.now.formatted(date: .numeric, time: .omitted))_23:00:00")!
@State private var activity: Activity<LiveTimeAttributes>? = nil
@State private var progressAmount = 0.0

@Query private var user: [UserInfo] // 하나만 쓰고싶다면?

var body: some View {
Expand Down Expand Up @@ -50,50 +39,8 @@ struct ContentView: View {
NavigationLink(destination: PiriFirstView()){
Text("PiriView")
}


}


Button(action: {
isTracking.toggle()
if isTracking {
// start live activity
progressAmount = 0.0
let attributes = LiveTimeAttributes()
let state = LiveTimeAttributes.ContentState(restOfTime: alarmTime, progressAmount: progressAmount)
let content = ActivityContent<LiveTimeAttributes.ContentState>(state: state, staleDate: nil)
activity = try? Activity<LiveTimeAttributes>.request(attributes: attributes, content: content, pushType: nil)
} else {
// end live activity
let state = LiveTimeAttributes.ContentState(restOfTime: alarmTime, progressAmount: 600)
let content = ActivityContent<LiveTimeAttributes.ContentState>(state: state, staleDate: alarmTime.addingTimeInterval(600))
Task {
await activity?.end(content, dismissalPolicy:.immediate)
}
}
}, label: {
Text(isTracking ? "end live activity" : "start live activity")
})
.buttonStyle(.bordered)
if isTracking {
Button(action: {
progressAmount += 50
let attributes = LiveTimeAttributes()
let state = LiveTimeAttributes.ContentState(restOfTime: alarmTime, progressAmount: progressAmount)
let content = ActivityContent<LiveTimeAttributes.ContentState>(state: state, staleDate: nil)
Task {
await activity?.update(content)
}
}, label: {
Text("update live activity")
})
.buttonStyle(.bordered)
}
if isTracking {
HStack {
Text("알람까지 남은 시간")
Text(alarmTime, style: .relative)
NavigationLink(destination: LiveActivityTestView()){
Text("LiveActivityTestView")
}
}
}
Expand Down
Loading

0 comments on commit 2c1361a

Please sign in to comment.