diff --git a/App/Moda/Info.plist b/App/Moda/Info.plist
index 118ae21..bacae88 100644
--- a/App/Moda/Info.plist
+++ b/App/Moda/Info.plist
@@ -11,9 +11,9 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 1.4.0
+ 1.5.0
CFBundleVersion
- 1.4.0.1
+ 1.5.0.3
GoogleServiceFileName
$(ENV_GOOGLE_INFO_PLIST)
ITSAppUsesNonExemptEncryption
diff --git a/App/Moda/Sources/Feature/Home/Components/DailyMemo/HomeDailyMemoCore.swift b/App/Moda/Sources/Feature/Home/Components/DailyMemo/HomeDailyMemoCore.swift
index bb37237..15b2ed6 100644
--- a/App/Moda/Sources/Feature/Home/Components/DailyMemo/HomeDailyMemoCore.swift
+++ b/App/Moda/Sources/Feature/Home/Components/DailyMemo/HomeDailyMemoCore.swift
@@ -16,6 +16,7 @@ struct HomeDailyMemoCore: Reducer {
struct State: Equatable {
var currentDate: Date
var isFolded: Bool = true
+ var memosUpdatingTrigger: Int = 0
var memos: [DailyMemo] = []
}
@@ -24,6 +25,7 @@ struct HomeDailyMemoCore: Reducer {
case view(View)
enum View: BindableAction {
case binding(BindingAction)
+ case onFirstAppear
case optionTapped(DailyMemo)
}
@@ -46,6 +48,9 @@ struct HomeDailyMemoCore: Reducer {
// From DailyMemoEditBottomSheet
case updateMemo(DailyMemo)
+
+ // From DailyMemoCategory
+ case reorderMemos
}
}
@@ -72,6 +77,12 @@ struct HomeDailyMemoCore: Reducer {
case let .view(viewAction):
switch viewAction {
+ case .onFirstAppear:
+ if userData.firstMemoShown.value {
+ state.isFolded = false
+ userData.firstMemoShown.update(false)
+ }
+ return .none
case let .optionTapped(memo):
return .send(.delegate(.showMemoOption(memo)))
@@ -85,7 +96,9 @@ struct HomeDailyMemoCore: Reducer {
return .send(.view(.binding(.set(\.currentDate, date))))
case let .addMemo(memo):
- state.memos.append(memo)
+ var updated = state.memos
+ updated.append(memo)
+ state.memos = updated.orderingByCategory().reordering()
return .send(.delegate(.memoUpdated(state.memos)))
case let .updateMemo(memo):
@@ -107,6 +120,10 @@ struct HomeDailyMemoCore: Reducer {
await toast.show(.init(icon: .icDelete, message: "삭제 완료!"))
}
)
+
+ case .reorderMemos:
+ state.memosUpdatingTrigger += 1
+ return .none
}
default:
diff --git a/App/Moda/Sources/Feature/Home/Components/DailyMemo/HomeDailyMemoView.swift b/App/Moda/Sources/Feature/Home/Components/DailyMemo/HomeDailyMemoView.swift
index 1c2aca9..20a00b4 100644
--- a/App/Moda/Sources/Feature/Home/Components/DailyMemo/HomeDailyMemoView.swift
+++ b/App/Moda/Sources/Feature/Home/Components/DailyMemo/HomeDailyMemoView.swift
@@ -15,7 +15,6 @@ struct HomeDailyMemoView: View {
@Bindable var store: StoreOf
- @State var skipUpdate: Bool = true
@Environment(\.modelContext) var modelContext
@Query var memosEntities: [DailyMemosEntity]
@Query var memoCategoryEntities: [DailyMemoCategoryEntity]
@@ -23,27 +22,24 @@ struct HomeDailyMemoView: View {
var body: some View {
content
.onFirstAppear {
- let id = store.currentDate.format(.yyMMdd)
- let memos = memosEntities.first(where: { $0.id == id })?.memos.toDomain ?? []
- send(.binding(.set(\.memos, memos)))
+ send(.onFirstAppear)
}
.onChange(of: store.currentDate, initial: true) {
- skipUpdate = true
change(by: $1)
}
- .onChange(of: store.memos, initial: true) {
- if skipUpdate {
- skipUpdate = false
- return
- }
+ .onChange(of: store.memos) {
update(memos: $1)
}
+ .onChange(of: store.memosUpdatingTrigger) {
+ change(by: store.currentDate)
+ }
}
private func change(by currentDate: Date) {
let id = currentDate.format(.yyMMdd)
- let memos = memosEntities.first(where: { $0.id == id })?.memos.toDomain ?? []
- send(.binding(.set(\.memos, memos)))
+ let memos = memosEntities.first(where: { $0.id == id })?.memos.toDomain
+ let ordered = memos?.orderingByCategory() ?? []
+ send(.binding(.set(\.memos, ordered)))
}
private func update(memos: [DailyMemo]) {
@@ -160,3 +156,40 @@ private extension HomeDailyMemoView {
}
}
}
+
+#Preview {
+ HomeDailyMemoView(
+ store: .init(initialState: HomeDailyMemoCore.State(currentDate: .today)) {
+ HomeDailyMemoCore()
+ }
+ )
+ .modelContainer(previewContainer)
+}
+
+@MainActor
+let previewContainer: ModelContainer = {
+ do {
+ let container = try ModelContainer(for: DailyMemosEntity.self, DailyMemoCategoryEntity.self,
+ configurations: .init(isStoredInMemoryOnly: true))
+
+ let entity = DailyMemoCategoryEntity(
+ id: "123",
+ order: 0,
+ usesCount: 0,
+ isAdded: true,
+ emoji: .Affirmation,
+ name: "123123"
+ )
+ container.mainContext.insert(entity)
+ container.mainContext.insert(
+ DailyMemosEntity(id: Date.today.format(.yyMMdd), memos: [
+ DailyMemoEntity(id: "123", order: 0, content: "123123", category: entity)
+ ])
+ )
+ try container.mainContext.save()
+
+ return container
+ } catch {
+ fatalError("Failed to create container")
+ }
+}()
diff --git a/App/Moda/Sources/Feature/Home/Components/Selector/HomeDateSelectorView.swift b/App/Moda/Sources/Feature/Home/Components/Selector/HomeDateSelectorView.swift
index a35e122..223e3f6 100644
--- a/App/Moda/Sources/Feature/Home/Components/Selector/HomeDateSelectorView.swift
+++ b/App/Moda/Sources/Feature/Home/Components/Selector/HomeDateSelectorView.swift
@@ -58,6 +58,8 @@ struct HomeDateSelectorView: View {
if let idx = weekDates[1].firstIndex(where: { $0.date == new.date }) {
weekDates[1][idx] = new
}
+ } else {
+ initialize()
}
}
}
@@ -86,3 +88,18 @@ struct HomeDateSelectorView: View {
}
}
}
+
+#Preview {
+ @Previewable @State var date: HomeDate = .today
+ @Previewable @State var weekDates: [[HomeDate]] = [
+ DateManager.shared.weekDates(for: .today.addDays(-7)),
+ DateManager.shared.weekDates(for: .today),
+ DateManager.shared.weekDates(for: .today.addDays(7))
+ ]
+
+ HomeDateSelectorView(
+ currentDate: $date,
+ weekDates: $weekDates,
+ selection: 1
+ )
+}
diff --git a/App/Moda/Sources/Feature/Home/HomeCore.swift b/App/Moda/Sources/Feature/Home/HomeCore.swift
index 236e176..f1b726c 100644
--- a/App/Moda/Sources/Feature/Home/HomeCore.swift
+++ b/App/Moda/Sources/Feature/Home/HomeCore.swift
@@ -304,7 +304,9 @@ struct HomeCore: Reducer {
// MARK: Child - Routine
case let .memo(.delegate(.memoUpdated(memos))):
- state.currentDate.hasMemo = !memos.isEmpty
+ if state.currentDate.hasMemo != !memos.isEmpty {
+ state.currentDate.hasMemo = !memos.isEmpty
+ }
return .none
default:
diff --git a/App/Moda/Sources/Feature/MainTab/MainTabCore.swift b/App/Moda/Sources/Feature/MainTab/MainTabCore.swift
index c20830d..7abeb23 100644
--- a/App/Moda/Sources/Feature/MainTab/MainTabCore.swift
+++ b/App/Moda/Sources/Feature/MainTab/MainTabCore.swift
@@ -258,7 +258,7 @@ struct MainTabCore: Reducer {
case .delegate(.close):
state.updateMemoAddTrigger += 1
state.dailyMemoEdit = nil
- return .none
+ return .send(.home(.memo(.passThrough(.reorderMemos))))
default:
return .none
diff --git a/App/Moda/Sources/Feature/Splash/SplashCore.swift b/App/Moda/Sources/Feature/Splash/SplashCore.swift
index 87871ca..3057445 100644
--- a/App/Moda/Sources/Feature/Splash/SplashCore.swift
+++ b/App/Moda/Sources/Feature/Splash/SplashCore.swift
@@ -24,6 +24,7 @@ struct SplashCore: Reducer {
var routineRecords: [RoutineRecord] = []
// Memo
+ var memos: [DailyMemo] = []
var memoCategories: [DailyMemoCategory] = []
}
@@ -57,6 +58,11 @@ struct SplashCore: Reducer {
}
if userData.firstRoutineMemo.value {
+ state.memos = [
+ .init(id: "0", order: 0, content: "오늘 하루는 컨디션이 너무 아쉬웠다.. 요즘에 커피를 많이 마셔서 그런듯 🥹 앞으로는 디카페인만 마시면서 당분간은 컨디션 회복이 제일 우선일듯 하다!", category: .writing),
+ .init(id: "1", order: 1, content: "오늘 기분 쏘쏘~", category: .mood),
+ .init(id: "2", order: 2, content: "점심 : 김치찌개\n저녁 : 직접 만든 참치 포케", category: .diet)
+ ]
state.memoCategories = .guideline
userData.firstRoutineMemo.update(false)
}
diff --git a/App/Moda/Sources/Feature/Splash/SplashView.swift b/App/Moda/Sources/Feature/Splash/SplashView.swift
index dffaed0..250e00a 100644
--- a/App/Moda/Sources/Feature/Splash/SplashView.swift
+++ b/App/Moda/Sources/Feature/Splash/SplashView.swift
@@ -19,8 +19,12 @@ struct SplashView: View {
@Query var dailyTodosList: [DailyTodos]
@Query var routines: [RoutineEntity]
@Query var routineRecords: [RoutineRecordEntity]
+ @Query var memosEntities: [DailyMemosEntity]
@Query var memoCategories: [DailyMemoCategoryEntity]
+ @State var isMemoCategoriesStored: Bool = false
+ @State var tmpMemoCategories: [DailyMemoCategoryEntity] = []
+
public init(store: StoreOf) {
self.store = store
}
@@ -61,8 +65,22 @@ struct SplashView: View {
.onChange(of: store.memoCategories) {
guard memoCategories.count == 0 else { return }
$1.forEach {
- modelContext.insert($0.toEntity)
+ let entity = $0.toEntity
+ modelContext.insert(entity)
+ tmpMemoCategories.append(entity)
+ }
+ try? modelContext.save()
+ isMemoCategoriesStored = true
+ }
+ .onChange(of: isMemoCategoriesStored) { _, _ in
+ guard memosEntities.count == 0 else { return }
+ var memoEntities: [DailyMemoEntity] = []
+ store.memos.forEach { memo in
+ if let category = tmpMemoCategories.first(where: { $0.id == memo.category.id }) {
+ memoEntities.append(DailyMemoEntity(id: memo.id, order: memo.order, content: memo.content, category: category))
+ }
}
+ modelContext.insert(DailyMemosEntity(id: Date.today.format(.yyMMdd), memos: memoEntities))
try? modelContext.save()
}
}
diff --git a/App/Moda/Sources/Util/UserData.swift b/App/Moda/Sources/Util/UserData.swift
index 6bafb4c..cf68eb7 100644
--- a/App/Moda/Sources/Util/UserData.swift
+++ b/App/Moda/Sources/Util/UserData.swift
@@ -34,6 +34,7 @@ enum UserDataKey: String, CaseIterable {
// 1.5.0
case firstRoutineMemo
case hasBeenShownMemoGuideline
+ case firstMemoShown
}
public final class UserData {
@@ -53,6 +54,7 @@ public final class UserData {
public let firstRoutineUsage = DataStorage(key: .firstRoutineUsage, defaultValue: true)
public let firstRoutineMemo = DataStorage(key: .firstRoutineMemo, defaultValue: true)
public let hasBeenShownMemoGuideline = DataStorage(key: .hasBeenShownMemoGuideline, defaultValue: false)
+ public let firstMemoShown = DataStorage(key: .firstMemoShown, defaultValue: true)
}
public extension UserData {
diff --git a/App/ModaWidget/Info.plist b/App/ModaWidget/Info.plist
index ac5f969..96fd114 100644
--- a/App/ModaWidget/Info.plist
+++ b/App/ModaWidget/Info.plist
@@ -13,9 +13,9 @@
CFBundleName
ModaWidget
CFBundleShortVersionString
- 1.4.0
+ 1.5.0
CFBundleVersion
- 1.4.0.1
+ 1.5.0.3
NSExtension
NSExtensionPointIdentifier
diff --git a/Core/ModaData/Sources/Entity/DailyMemoCategoryEntity.swift b/Core/ModaData/Sources/Entity/DailyMemoCategoryEntity.swift
index 151e1b2..aefdaa2 100644
--- a/Core/ModaData/Sources/Entity/DailyMemoCategoryEntity.swift
+++ b/Core/ModaData/Sources/Entity/DailyMemoCategoryEntity.swift
@@ -13,6 +13,7 @@ import Foundation
public class DailyMemoCategoryEntity: Identifiable, Equatable, Hashable {
@Attribute(.unique) public var id: String
+ // priority
public var order: Int
public var usesCount: Int
public var isAdded: Bool
diff --git a/Core/ModaData/Sources/Model/Bookmark.swift b/Core/ModaData/Sources/Model/Bookmark.swift
index 799aa9d..bcd22f0 100644
--- a/Core/ModaData/Sources/Model/Bookmark.swift
+++ b/Core/ModaData/Sources/Model/Bookmark.swift
@@ -28,7 +28,7 @@ public struct Bookmark: Identifiable, Equatable, Hashable {
public init(title: String, isFolded: Bool = false, todos: [BookmarkTodo] = []) {
self.id = Self.uniqueId
- self.order = -1
+ self.order = Int.max
self.title = title
self.isFolded = isFolded
self.todos = todos
diff --git a/Core/ModaData/Sources/Model/DailyMemo.swift b/Core/ModaData/Sources/Model/DailyMemo.swift
index 6053d3b..bd6b5ce 100644
--- a/Core/ModaData/Sources/Model/DailyMemo.swift
+++ b/Core/ModaData/Sources/Model/DailyMemo.swift
@@ -14,7 +14,7 @@ public struct DailyMemo: Identifiable, Equatable, Hashable, Orderable {
public var content: String
public var category: DailyMemoCategory
- init(id: String, order: Int, content: String, category: DailyMemoCategory) {
+ public init(id: String, order: Int, content: String, category: DailyMemoCategory) {
self.id = id
self.order = order
self.content = content
@@ -23,10 +23,21 @@ public struct DailyMemo: Identifiable, Equatable, Hashable, Orderable {
public init(content: String, category: DailyMemoCategory) {
self.id = Self.uniqueId
- self.order = -1
+ self.order = Int.max
self.content = content
self.category = category
}
public static var uniqueId: String { String(Int(Date().timeIntervalSince1970)) }
}
+
+public extension [DailyMemo] {
+ func orderingByCategory() -> Self {
+ self.sorted {
+ if $0.category.order == $1.category.order {
+ return $0.order < $1.order
+ }
+ return $0.category.order < $1.category.order
+ }
+ }
+}
diff --git a/Core/ModaData/Sources/Model/DailyMemoCategory.swift b/Core/ModaData/Sources/Model/DailyMemoCategory.swift
index c38e679..b325790 100644
--- a/Core/ModaData/Sources/Model/DailyMemoCategory.swift
+++ b/Core/ModaData/Sources/Model/DailyMemoCategory.swift
@@ -27,7 +27,7 @@ public struct DailyMemoCategory: Identifiable, Equatable, Hashable, Orderable {
public init(emoji: Emoji, name: String) {
self.id = Self.uniqueId
- self.order = -1
+ self.order = Int.max
self.usesCount = 0
self.isAdded = true
self.emoji = emoji
diff --git a/Core/ModaData/Sources/Model/Routine.swift b/Core/ModaData/Sources/Model/Routine.swift
index 2cd8531..1b65ba7 100644
--- a/Core/ModaData/Sources/Model/Routine.swift
+++ b/Core/ModaData/Sources/Model/Routine.swift
@@ -27,7 +27,7 @@ public struct Routine: Identifiable, Equatable {
public init(emoji: Emoji, name: String, duration: RoutineDuration = .weekday(.init(Weekday.allCases))) {
self.id = name + Self.uniqueId
- self.order = -1
+ self.order = Int.max
self.emoji = emoji
self.name = name
self.duration = duration