Skip to content

Commit

Permalink
πŸ”€ :: (#538) lock screen κ΅¬ν˜„
Browse files Browse the repository at this point in the history
  • Loading branch information
juyeong525 authored Jul 1, 2023
2 parents a5779b2 + bdbe0df commit 1fede4a
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 2 deletions.
1 change: 1 addition & 0 deletions Application/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ let project = Project(
.SPM.SemicolonDesign,
.Service.MealDataService,
.Service.ScheduleService,
.Service.TimeTableService,
.Module.XDateUtil
] + TargetDependency.universalDependencies
)
Expand Down
1 change: 1 addition & 0 deletions Application/Widget/Sources/Application/XquareWidget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ struct XquareWidget: WidgetBundle {
var body: some Widget {
XquareMealWidget()
XquareScheduleWidget()
// XquareTimeTableWidget()
}

}
58 changes: 56 additions & 2 deletions Application/Widget/Sources/Meal/XquareMealWidget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ struct XquareMealWidgetEntryView: View {
SmallXquareMealWidgetView(entry: entry)
case .systemMedium:
MediumXquareMealWidgetView(entry: entry)
case .accessoryRectangular:
RectangularXquareMealWidgetView(entry: entry)
default:
EmptyView()
}
Expand Down Expand Up @@ -125,6 +127,7 @@ struct SmallXquareMealWidgetView: View {
type: .caption2,
textColor: colorScheme == .light ? .GrayScale.gray900 : .GrayScale.gray100
)
.lineLimit(nil)
} else {
Text("λ“±λ‘λœ 정보가 μ—†μŠ΅λ‹ˆλ‹€.")
.sdText(
Expand Down Expand Up @@ -187,15 +190,66 @@ struct MediumXquareMealWidgetView: View {
.background(colorScheme == .light ? .white : .GrayScale.gray900)
}
}

struct RectangularXquareMealWidgetView: View {
@Environment(\.colorScheme) var colorScheme
var entry: XquareMealWidgetProvider.Entry
var mealMenu: MealMenuEntity?

init(entry: XquareMealWidgetProvider.Entry) {
self.entry = entry
self.mealMenu = entry.meal.menu.first { $0.mealTime == entry.mealTime }
}

var body: some View {
if mealMenu?.menu ?? [] != [] {
ZStack(alignment: .topLeading) {
Text(" \(mealMenu?.menu?.joined(separator: ", ") ?? "")")
.sdText(
type: .caption2,
textColor: colorScheme == .light ? .GrayScale.gray900 : .GrayScale.gray100
)
nowToImage(mealTime: entry.mealTime)
}
} else {
Text("λ“±λ‘λœ 정보가 μ—†μŠ΅λ‹ˆλ‹€.")
.sdText(
type: .caption2,
textColor: colorScheme == .light ? .GrayScale.gray900 : .GrayScale.gray100
)
}
}
func nowToImage(mealTime: MealTime) -> Image {
switch mealTime {
case .breakfast:
return Image(systemName: "sun.max.fill")
case .lunch:
return Image(systemName: "sun.haze.fill")
case .dinner:
return Image(systemName: "moon.stars.fill")
}
}
}

struct XquareMealWidget: Widget {
let kind: String = "XquareMealWidget"

var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: XquareMealWidgetProvider()) { entry in
let configuration = StaticConfiguration(
kind: kind,
provider: XquareMealWidgetProvider()
) { entry in
XquareMealWidgetEntryView(entry: entry)
}
.configurationDisplayName("XQuare Meal Widget")
.description("Xquare μœ„μ ―μ„ 톡해 였늘 ν•˜λ£¨μ˜ 급식을 ν™•μΈν•˜μ„Έμš”.")
.supportedFamilies([.systemSmall, .systemMedium])

if #available(iOSApplicationExtension 16.0, *) {
return configuration
.supportedFamilies([.systemSmall, .systemMedium, .accessoryRectangular])
} else {
return configuration
.supportedFamilies([.systemSmall, .systemMedium])
}
}
}
36 changes: 36 additions & 0 deletions Application/Widget/Sources/TimeTable/TimePeriod.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Foundation
import XDateUtil
enum TimePeriod: Int {
case morning = 0
case period1 = 1
case period2 = 2
case period3 = 3
case period4 = 4
case period5 = 5
case period6 = 6
case period7 = 7
case night = 8
init(date: Date) {
let time = date.toString(format: .time)
switch time {
case "00:00:00"..<"08:40:00":
self = .morning
case "08:40:00"..<"09:40:00":
self = .period1
case "09:40:00"..<"10:40:00":
self = .period2
case "10:40:00"..<"11:40:00":
self = .period3
case "11:40:00"..<"13:30:00":
self = .period4
case "13:30:00"..<"14:30:00":
self = .period5
case "14:30:00"..<"15:30:00":
self = .period6
case "15:30:00"..<"16:30:00":
self = .period7
default:
self = .night
}
}
}
202 changes: 202 additions & 0 deletions Application/Widget/Sources/TimeTable/XquareTimeTableWidget.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import WidgetKit
import SwiftUI

import RxSwift
import XDateUtil
import TimeTableService
import SemicolonDesign

struct XquareTimeTableWidgetProvider: TimelineProvider {

private let fetchTimeTableForWeekUseCase: FetchTimeTableForWeekUseCase
private var disposeBag = DisposeBag()

init() {
self.fetchTimeTableForWeekUseCase = TimeTableServiceDependency.shared.fetchTimeTableForWeekUseCase
}

func placeholder(in context: Context) -> TimeTableEntry {
return .init(weekDay: 1, date: Date(), dayTimeTable: [])
}

func getSnapshot(in context: Context, completion: @escaping (TimeTableEntry) -> Void) {
getTimeTable { timeTable in
completion(.init(weekDay: timeTable.weekDay, date: timeTable.date, dayTimeTable: timeTable.dayTimeTable))
}
}

func getTimeline(in context: Context, completion: @escaping (Timeline<TimeTableEntry>) -> Void) {
let refreshDate = Calendar.current.date(byAdding: .minute, value: 5, to: Date())!

getTimeTable { timeTable in
completion(.init(
entries: [.init(
weekDay: timeTable.weekDay,
date: timeTable.date,
dayTimeTable: timeTable.dayTimeTable
)],
policy: .after(refreshDate))
)
}
}

private func getTimeTable(completion: @escaping ((WeekTimeTableEntity) -> Void)) {
self.fetchTimeTableForWeekUseCase.excute()
.observe(on: MainScheduler.asyncInstance)
.subscribe(onNext: {
let timetable = $0.filter {
$0.weekDay == getWeekDay()
}
completion(timetable.first!)
})
.disposed(by: disposeBag)
}
private func getWeekDay() -> Int {
return (Calendar.current.dateComponents([.weekday], from: Date()).weekday ?? 0) - 1
}
}

struct TimeTableEntry: TimelineEntry {
var weekDay: Int
var date: Date
var dayTimeTable: [DayTimeTableEntity]
}

struct XquareTimeTableWidgetEntryView: View {
@Environment(\.widgetFamily) var widgetFamily
var entry: XquareTimeTableWidgetProvider.Entry

var body: some View {
widgetBody()
}
@ViewBuilder
func widgetBody() -> some View {
switch widgetFamily {
case .systemSmall:
SmallXquareTimeTableWidgetView(entry: entry, dayTimeTable: entry.dayTimeTable)
case .accessoryRectangular:
RectangularXquareTimeTableWidgetView(entry: entry, dayTimeTable: entry.dayTimeTable)
default:
EmptyView()
}
}
}
struct SmallXquareTimeTableWidgetView: View {
@Environment(\.colorScheme) var colorScheme
var entry: XquareTimeTableWidgetProvider.Entry
var dayTimeTable: [DayTimeTableEntity]

init(entry: XquareTimeTableWidgetProvider.Entry, dayTimeTable: [DayTimeTableEntity]) {
self.entry = entry
self.dayTimeTable = dayTimeTable.filter {
$0.period == (TimePeriod(date: Date()).rawValue + 1)
}
}
var body: some View {
ZStack {
if colorScheme == .light {
Color.white.ignoresSafeArea()
} else {
Color.GrayScale.gray900.ignoresSafeArea()
}
HStack {
VStack(alignment: .leading, spacing: 0) {
Text(entry.date.toString(format: "Eμš”μΌ"))
.sdText(
type: .body4,
textColor: colorScheme == .light ? .GrayScale.gray900 : .GrayScale.gray100
)
.padding(.trailing, 10)
.padding(.top, 3)
Text(entry.date.toString(format: .fullDate))
.sdText(
type: .caption2,
textColor: colorScheme == .light ? .GrayScale.gray600 : .GrayScale.gray500
)
.padding(.bottom, 10)
if dayTimeTable != [] {
VStack(alignment: .leading, spacing: 0) {
Text("\(dayTimeTable.first!.period)κ΅μ‹œ")
.sdText(
type: .body1,
textColor: colorScheme == .light ? .GrayScale.gray900 : .GrayScale.gray100
)
Text("\(dayTimeTable.first!.subjectName)")
.fontWeight(.light)
.foregroundColor(colorScheme == .light ? .GrayScale.gray900 : .GrayScale.gray100)
.lineLimit(nil)
}
} else {
Text("λ“±λ‘λœ 정보가 μ—†μŠ΅λ‹ˆλ‹€.")
.sdText(
type: .caption2,
textColor: colorScheme == .light ? .GrayScale.gray900 : .GrayScale.gray100
)
}
Spacer()
}
.padding([.horizontal, .top], 10)
Spacer()
}
}
}
}

struct RectangularXquareTimeTableWidgetView: View {
@Environment(\.colorScheme) var colorScheme
var entry: XquareTimeTableWidgetProvider.Entry
var dayTimeTable: [DayTimeTableEntity]

init(entry: XquareTimeTableWidgetProvider.Entry, dayTimeTable: [DayTimeTableEntity]) {
self.entry = entry
self.dayTimeTable = dayTimeTable.filter {
$0.period == (TimePeriod(date: Date()).rawValue + 1)
}
}
var body: some View {
if dayTimeTable != [] {
HStack {
VStack(alignment: .leading, spacing: 0) {
Text("\(dayTimeTable.first!.period)κ΅μ‹œ")
.sdText(
type: .body1,
textColor: colorScheme == .light ? .GrayScale.gray900 : .GrayScale.gray100
)
Text("\(dayTimeTable.first!.subjectName)")
.fontWeight(.light)
.foregroundColor(colorScheme == .light ? .GrayScale.gray900 : .GrayScale.gray100)
}
Spacer()
}
} else {
Text("λ“±λ‘λœ 정보가 μ—†μŠ΅λ‹ˆλ‹€.")
.sdText(
type: .caption2,
textColor: colorScheme == .light ? .GrayScale.gray900 : .GrayScale.gray100
)
}
}
}

struct XquareTimeTableWidget: Widget {
let kind: String = "XquareTimeTableWidget"

var body: some WidgetConfiguration {
let configuration = StaticConfiguration(
kind: kind,
provider: XquareTimeTableWidgetProvider()
) { entry in
XquareTimeTableWidgetEntryView(entry: entry)
}
.configurationDisplayName("XQuare timeTable Widget")
.description("Xquare μœ„μ ―μ„ 톡해 였늘 μ‹œκ°„ν‘œλ₯Ό ν™•μΈν•˜μ„Έμš”.")

if #available(iOSApplicationExtension 16.0, *) {
return configuration
.supportedFamilies([.systemSmall, .accessoryRectangular])
} else {
return configuration
.supportedFamilies([.systemSmall])
}
}
}

0 comments on commit 1fede4a

Please sign in to comment.