Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ private struct GoalCreateTitleField: View {
.focused(focusedField, equals: .title)
.font(.body)
.padding()
.background(Color.surface, in: .rect(cornerRadius: 24))
.background(Color.surface, in: .rect(cornerRadius: 16))
}
.disabled(store.isSaving)
}
Expand All @@ -144,7 +144,7 @@ private struct GoalCreateDescriptionEditor: View {
Group {
switch store.selectedTab {
case .write:
TextEditorContentLayout(minimumHeight: 120 - 24) {
TextEditorContentLayout(minimumHeight: 120) {
Text(RecordPresentation.text("development_goal_create_markdown_hint"))
.font(.caption)
.foregroundStyle(Color.textTertiary)
Expand All @@ -167,33 +167,41 @@ private struct GoalCreateDescriptionEditor: View {
sizeThatFits: { UIKitTextEditor.fittingSize(proposal: $0, textEditor: $1) }
)
.focused(focusedField, equals: .content)
.padding(12)
.background(Color.surface, in: .rect(cornerRadius: 16))
}
.padding(12)
.contentShape(.rect)
.onTapGesture { focusedField.wrappedValue = .content }
case .preview:
Group {
if store.markdownContent.isEmpty {
ContentUnavailableView {
VStack(spacing: 8) {
Text(RecordPresentation.text("development_goal_create_preview_empty_title"))
.bold()
} description: {
.font(.headline)
Text(RecordPresentation.text("development_goal_create_preview_empty_message"))
.font(.subheadline)
.foregroundStyle(.secondary)
}
.frame(maxWidth: .infinity)
.frame(height: 120)
.multilineTextAlignment(.center)
.padding(12)
.frame(maxWidth: .infinity, minHeight: 120, alignment: .center)
.background(Color.surface, in: .rect(cornerRadius: 16))
} else {
MarkdownContentView(content: store.markdownContent)
.padding(.vertical, 16)
MarkdownContentView(
content: store.markdownContent,
isScrollEnabled: false
)
// MarkdownRenderer 내부의 좌우 여백을 상쇄해 입력 본문과 정렬
.padding(.horizontal, -16)
.padding(12)
.frame(minHeight: 120, alignment: .topLeading)
.background(Color.surface, in: .rect(cornerRadius: 16))
}
}
}
}
.frame(minHeight: 120, alignment: .topLeading)
.background(Color.surfaceSecondary, in: .rect(cornerRadius: 16))
}
.padding(16)
.background(Color.surface, in: .rect(cornerRadius: 24))
}
.disabled(store.isSaving)
}
Expand Down Expand Up @@ -260,7 +268,7 @@ private struct GoalCreateStatusField: View {
Spacer()
}
.padding(20)
.background(Color.surface, in: .rect(cornerRadius: 24))
.background(Color.surface, in: .rect(cornerRadius: 16))
}
}
}
Expand Down Expand Up @@ -296,7 +304,7 @@ private struct GoalCreateTodoField: View {
.buttonStyle(.plain)
}
.padding(20)
.background(Color.surface, in: .rect(cornerRadius: 24))
.background(Color.surface, in: .rect(cornerRadius: 16))
}
.disabled(store.isSaving)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public struct RecordEditorView: View {
LazyVStack(alignment: .leading, spacing: 20) {
versionCard
titleCard
contentCard
contentEditor
}
.padding(.horizontal)
.padding(.bottom, 20)
Expand Down Expand Up @@ -110,35 +110,36 @@ public struct RecordEditorView: View {
}

private var versionCard: some View {
FieldCard(title: RecordPresentation.text("development_record_version")) {
FieldSection(title: RecordPresentation.text("development_record_version")) {
Text(RecordPresentation.versionLabel(store.versionNumber))
.font(.body)
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
.background(Color.surfaceSecondary, in: .rect(cornerRadius: 16))
.background(Color.surface, in: .rect(cornerRadius: 16))
}
}

private var titleCard: some View {
FieldCard(title: RecordPresentation.text("development_record_title")) {
FieldSection(title: RecordPresentation.text("development_record_title")) {
TextField(
RecordPresentation.text("development_record_title_placeholder"),
text: $store.title
)
.font(.body)
.focused($focusedField, equals: .title)
.padding()
.background(Color.surfaceSecondary, in: .rect(cornerRadius: 16))
.background(Color.surface, in: .rect(cornerRadius: 16))
}
.disabled(store.isLoading)
}

private var contentCard: some View {
private var contentEditor: some View {
VStack(spacing: 16) {
ModePicker(store: store, focusedField: _focusedField)

switch store.selectedTab {
case .write:
TextEditorContentLayout(minimumHeight: 340 - 24) {
TextEditorContentLayout(minimumHeight: 340) {
Text(RecordPresentation.text("development_record_markdown_hint"))
.font(.caption)
.foregroundStyle(Color.textTertiary)
Expand All @@ -161,37 +162,42 @@ public struct RecordEditorView: View {
sizeThatFits: { UIKitTextEditor.fittingSize(proposal: $0, textEditor: $1) }
)
.focused($focusedField, equals: .content)
.padding(12)
.background(Color.surface, in: .rect(cornerRadius: 16))
}
.padding(12)
.frame(minHeight: 340, alignment: .topLeading)
.background(Color.surfaceSecondary, in: .rect(cornerRadius: 16))
.contentShape(.rect)
.onTapGesture { focusedField = .content }
case .preview:
Group {
if store.markdownContent.isEmpty {
ContentUnavailableView(
RecordPresentation.text("development_record_preview_empty_title"),
systemImage: "doc.text.magnifyingglass",
description: Text(
RecordPresentation.text("development_record_preview_empty_message")
)
)
VStack(spacing: 8) {
Text(RecordPresentation.text("development_record_preview_empty_title"))
.font(.headline)
Text(RecordPresentation.text("development_record_preview_empty_message"))
.font(.subheadline)
.foregroundStyle(.secondary)
}
.multilineTextAlignment(.center)
.padding(12)
.frame(maxWidth: .infinity, minHeight: 340, alignment: .center)
.background(Color.surface, in: .rect(cornerRadius: 16))
} else {
MarkdownContentView(content: store.markdownContent)
.padding(.vertical, 16)
MarkdownContentView(
content: store.markdownContent,
isScrollEnabled: false
)
// MarkdownRenderer 내부의 좌우 여백을 상쇄해 입력 본문과 정렬
.padding(.horizontal, -16)
.padding(12)
.frame(minHeight: 340, alignment: .topLeading)
.background(Color.surface, in: .rect(cornerRadius: 16))
}
}
.frame(minHeight: 340)
.background(Color.surfaceSecondary, in: .rect(cornerRadius: 16))
.frame(minHeight: 340, alignment: .topLeading)
}

}
.padding(20)
.background {
RoundedRectangle(cornerRadius: 24)
.fill(Color.surface)
}
.disabled(store.isLoading)
}

Expand Down Expand Up @@ -235,7 +241,7 @@ public struct RecordEditorView: View {

}

private struct FieldCard<Content: View>: View {
private struct FieldSection<Content: View>: View {
let title: String
@ViewBuilder let content: Content

Expand All @@ -249,11 +255,6 @@ private struct FieldCard<Content: View>: View {
Text(title)
.font(.headline)
content
.padding(20)
.background {
RoundedRectangle(cornerRadius: 24)
.fill(Color.surface)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1085,8 +1085,8 @@
"development_record_markdown_hint" : {
"extractionState" : "manual",
"localizations" : {
"en" : { "stringUnit" : { "state" : "translated", "value" : "Markdown supported. The date is recorded automatically." } },
"ko" : { "stringUnit" : { "state" : "translated", "value" : "Markdown 문법을 사용할 수 있어요. 날짜는 자동으로 기록돼요." } }
"en" : { "stringUnit" : { "state" : "translated", "value" : "Markdown supported." } },
"ko" : { "stringUnit" : { "state" : "translated", "value" : "Markdown 문법을 사용할 수 있어요." } }
}
},
"development_record_preview" : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,33 @@ import MarkdownRenderer

public struct MarkdownContentView: View {
private let content: String
private let isScrollEnabled: Bool

public init(content: String) {
public init(content: String, isScrollEnabled: Bool = true) {
self.content = content
self.isScrollEnabled = isScrollEnabled
}

public var body: some View {
MarkdownRendererView(markdown: content)
.frame(maxWidth: .infinity, maxHeight: .infinity)
MarkdownRendererView(markdown: content, isScrollEnabled: isScrollEnabled)
.frame(maxWidth: .infinity, maxHeight: isScrollEnabled ? .infinity : nil)
}
}

struct TodoMarkdownContentView: View {
let content: String
let referenceItems: [Int: TodoReferenceItem]
var isScrollEnabled = true
var onOpenTodoID: ((String) -> Void)?

var body: some View {
MarkdownRendererView(
markdown: content,
references: rendererReferences,
isScrollEnabled: isScrollEnabled,
onOpenReferenceID: onOpenTodoID
)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.frame(maxWidth: .infinity, maxHeight: isScrollEnabled ? .infinity : nil)
}

private var rendererReferences: [Int: MarkdownRendererReference] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ public struct TodoEditorView: View {
VStack(alignment: .trailing, spacing: 16) {
TitleField(store: store, field: _field)
ModePicker(store: store, field: _field)
.frame(maxWidth: horizontalSizeClass == .regular ? 280 : .infinity)
}
.onGeometryChange(for: CGFloat.self) { proxy in
proxy.size.height
Expand Down Expand Up @@ -259,16 +258,10 @@ private struct TitleField: View {
)
.foregroundColor(Color.secondary),
)
.font(.title2)
.font(.body)
.focused($field, equals: .title)
.frame(height: 30)
.padding(.vertical, 8)
.padding(.horizontal, 12)
.background {
RoundedRectangle(cornerRadius: 16)
.fill(Color.surface)
.strokeBorder(Color.border, lineWidth: 2)
}
.padding()
.background(Color.surface, in: .rect(cornerRadius: 16))
}
}

Expand Down Expand Up @@ -332,7 +325,7 @@ private struct ContentView: View {
let isContentFocused = field == .content
Group {
if store.tabViewTag == .editor {
TextEditorContentLayout(minimumHeight: max(0, minimumHeight - 20)) {
TextEditorContentLayout(minimumHeight: minimumHeight) {
markdownHint
UIKitTextEditor()
.composable(
Expand All @@ -357,46 +350,49 @@ private struct ContentView: View {
)
// SwiftUI 포커싱 시스템에 등록하기 위해 사용
.focused($field, equals: .content)
.padding(12)
.background(Color.surface, in: .rect(cornerRadius: 16))
}
.padding(.horizontal)
} else {
if store.content.isEmpty {
previewPlaceholder
.padding(.horizontal)
} else {
TodoMarkdownContentView(
content: store.content,
referenceItems: store.referenceItems,
isScrollEnabled: false,
onOpenTodoID: { store.send(.showInspector(.todo(TodoIdItem(id: $0)))) }
)
// MarkdownRenderer 내부의 좌우 여백을 상쇄해 입력 본문과 정렬
.padding(.horizontal, -16)
.padding(12)
.frame(minHeight: minimumHeight, alignment: .topLeading)
.background(Color.surface, in: .rect(cornerRadius: 16))
}
}
}
.padding(.vertical, 10)
.frame(minHeight: minimumHeight, alignment: .topLeading)
.background {
RoundedRectangle(cornerRadius: 16)
.fill(Color.surface)
.strokeBorder(Color.border, lineWidth: 2)
}
.contentShape(.rect)
}

private var markdownHint: some View {
Text(String(localized: "todo_editor_markdown_hint", bundle: PresentationResources.bundle))
.font(.caption)
.foregroundStyle(.secondary)
.foregroundStyle(Color.textTertiary)
}

private var previewPlaceholder: some View {
VStack(alignment: .leading, spacing: 6) {
VStack(spacing: 8) {
Text(String(localized: "todo_editor_markdown_preview_title", bundle: PresentationResources.bundle))
.font(.subheadline.weight(.semibold))
.font(.headline)
Text(String(localized: "todo_editor_markdown_preview_message", bundle: PresentationResources.bundle))
.font(.footnote)
.font(.subheadline)
.foregroundStyle(.secondary)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
.padding(.vertical, 8)
.multilineTextAlignment(.center)
.padding(12)
.frame(maxWidth: .infinity, minHeight: minimumHeight, alignment: .center)
.background(Color.surface, in: .rect(cornerRadius: 16))
}
}

Expand Down
Loading
Loading