mycode/myApp/Keging/IOS/HelpView.swift
songyc macbook 4d91c48844 feat(keging): 워치 연결 배지·미연결 시작 경고 + 세팅 기기별 독립(워치 좌스와이프 세팅) + 워치 진동 강화 (7차)
- 폰 첫 화면: 시작 버튼 위 워치 연결 배지(연결됨/미연결/미연동 — iOS 제약상
  '연결됨'은 워치 앱 포그라운드 기준, 설정·도움말에 안내), 미연결 시작 시 확인 창
  (기록은 동일함을 안내), 설정 > 애플워치 > '워치 미연결 경고' 토글.
  단축어·autoStart는 경고 없이 통과
- 세팅 동기화 전면 제거(기기마다 진동 질감이 달라 각자 최적화) — 동기화는 기록만.
  워치 시작 화면 왼쪽 스와이프로 전용 세팅 페이지(TabView .page): 준비/수축/이완/
  횟수 스테퍼(2줄 컴팩트 라벨), 진동 2종 피커(선택 즉시 미리 울림), 운동 유형·강도.
  요약 라인 즉시 반영(SettingsStore EnvironmentObject)
- 워치 진동 강화 재설계: 기본=.start 1방, 톡톡=.start 2방(0.35s),
  지이이잉=.retry 2방 연결(~1.3s), 완주=.retry×3+.success(~2.5s), 세대 토큰 취소
- 도움말 4건·번역(en/ja) 갱신, CLAUDE.md 현행화
- 시뮬 검증: 배지·경고 창·설정 토글, 워치 세팅 페이지(46mm·40mm)·요약 반영,
  3종 빌드 그린·경고 0·l10n 0/0/0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPmp29DQHY6Ahfss5SRopT
2026-09-03 03:05:28 +09:00

139 lines
10 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// HelpView.swift
// Keging
//
// . .
//
import SwiftUI
struct HelpView: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
NavigationStack {
List {
Section {
helpRow(
symbol: "play.circle.fill",
title: Text("바로 시작하기"),
body: Text("첫 화면의 큰 시작 버튼을 누르면 저장된 세팅대로 운동이 시작돼요. 준비 시간을 설정해 두면 그만큼 카운트다운 후에 첫 수축이 시작돼요. 화면의 원이 수축할 때 함께 조이고, 커질 때 힘을 풀면 돼요. 정해진 횟수를 모두 마치면 완료 화면이 뜨고 기록이 저장돼요. 시작 버튼 위에는 워치 연결 상태가 떠요 — 워치 없이 시작해도 기록은 똑같이 저장되고, 미연결 확인 창은 설정에서 끌 수 있어요.")
)
helpRow(
symbol: "slider.horizontal.3",
title: Text("운동 세팅 바꾸기"),
body: Text("오른쪽 위 슬라이더 버튼이 운동 세팅이에요. 준비 시간(010초), 수축 시간(160초), 이완 시간(160초), 반복 횟수(1100회)를 정할 수 있어요. 예를 들어 수축 10초·이완 5초·20회로 설정하면, 수축과 이완을 20번 반복하는 한 세트가 약 5분이 돼요. 시작 버튼 아래의 카드를 눌러도 이 화면이 열려요.")
)
helpRow(
symbol: "iphone.radiowaves.left.and.right",
title: Text("진동으로 구분하기"),
body: Text("수축이 시작될 때와 이완이 시작될 때 서로 다른 진동이 울려요. 그래서 화면을 보지 않아도 지금 조여야 할지 풀어야 할지 알 수 있어요. 기본값은 수축=지이이잉(아주 긴 진동), 이완=기본(짧은 한 번)이라 첫 순간의 질감으로 바로 구분돼요. 패턴은 운동 세팅에서 국면별로 고를 수 있고(기본·톡톡·지이이잉), '미리 느끼기' 버튼으로 실제 진동을 확인할 수 있어요. 세트를 끝까지 마치면 아주 길게 축하 진동이 울려요. 화면이 꺼져 있거나 다른 앱을 쓰는 중에는 시스템 진동으로 대신 울려서 질감이 조금 다를 수 있어요. 워치는 손목에 맞춘 더 강한 전용 진동 세트를 쓰고 워치에서 따로 골라요. 진동은 실기기에서만 느껴져요.")
)
helpRow(
symbol: "stop.circle",
title: Text("중간에 중단하면"),
body: Text("운동 중 아래의 중단 버튼을 누르면 확인 후 세트가 끝나요. 중단한 세트는 아예 하지 않은 것으로 처리돼서 기록과 통계에 남지 않아요. 끝까지 마친 세트만 기록돼요.")
)
} header: {
Text("기본 사용법")
}
Section {
helpRow(
symbol: "chart.xyaxis.line",
title: Text("통계 열기"),
body: Text("첫 화면을 위로 쓸어올리거나 아래 가운데의 손잡이를 누르면 통계 화면이 올라와요. 닫을 때는 아래로 쓸어내리거나 X 버튼을 누르면 돼요.")
)
helpRow(
symbol: "calendar",
title: Text("하루 · 주간 · 월간"),
body: Text("하루 탭 맨 위의 타임라인에서 오늘 언제 운동했는지 24시간 축 위의 점으로 한눈에 볼 수 있어요(점이 클수록 횟수가 많은 세트). 아래로는 시간대별 꺾은선 그래프와 오늘 기록 목록이 이어져요. 주간·월간 탭에서는 일별 횟수를 꺾은선 그래프와 합계(세트·횟수)로 보여줘요. 주는 월요일에 시작해요.")
)
helpRow(
symbol: "arrow.left.arrow.right",
title: Text("이번 주 ↔ 지난 7일 전환"),
body: Text("주간·월간 화면 위의 스위치로 두 가지 방식을 오갈 수 있어요. '이번 주 / 이번 달'은 달력 기준(월요일~일요일, 1일말일)이고, '지난 7일 / 지난 30일'은 오늘을 기준으로 거슬러 세는 방식이에요.")
)
} header: {
Text("통계")
}
Section {
helpRow(
symbol: "bolt.horizontal.circle",
title: Text("다이나믹 아일랜드"),
body: Text("운동 중에 앱을 나가면 다이나믹 아일랜드와 잠금화면에 실시간 현황이 떠요. 세트 전체를 국면 색(민트=수축·앰버=이완)으로 칠한 타임라인 바 위로 밝은 줄이 실제 시간에 맞춰 차오르는데, 줄 끝이 걸친 색이 지금 국면이에요. 남은 시간 숫자와 함께 전부 시스템이 직접 그려서 세트가 끝날 때까지 멈추지 않아요. 지금 조여야 할지 풀어야 할지는 진동으로도 늘 알 수 있고, 정확한 횟수는 앱을 열면 보여요.")
)
helpRow(
symbol: "square.and.arrow.up",
title: Text("단축어와 시리"),
body: Text("단축어 앱에서 '케겔 운동 시작' 동작을 추가할 수 있어요. 실행하면 케깅이 열리면서 저장된 세팅대로 바로 시작돼요. 홈 화면 아이콘·잠금화면 위젯·뒷면 탭 등 단축어를 부를 수 있는 곳이라면 어디서든 쓸 수 있어요.")
)
} header: {
Text("앱 밖에서")
}
Section {
helpRow(
symbol: "applewatch",
title: Text("애플워치에서 운동하기"),
body: Text("워치 앱을 열면 시작 버튼이 있고, 누르면 바로 시작돼요. 화면에 수축·이완 상태와 남은 시간, 몇 번째인지가 한눈에 보여요. 시작 화면에서 왼쪽으로 쓸어넘기면 워치 전용 세팅(준비·수축·이완·횟수·진동·애플 건강)을 바꿀 수 있어요. 워치에서 실행하면 진동은 워치에서만 울려요. 중단 버튼을 누르면 그 세트는 기록되지 않아요.")
)
helpRow(
symbol: "arrow.triangle.2.circlepath",
title: Text("워치와 아이폰 동기화"),
body: Text("운동 세팅은 아이폰과 워치가 각자 따로 저장해요 — 기기마다 진동 느낌이 달라서 각자에게 맞게 다르게 세팅할 수 있게요. 워치 세팅은 워치의 시작 화면에서 왼쪽으로 쓸어넘겨 바꿔요. 끝까지 마친 세트 기록은 아이폰으로 넘어와 통계에 합쳐지고, 워치가 아이폰과 떨어져 있어도 기록은 쌓였다가 연결되면 자동으로 전송돼요.")
)
} header: {
Text("애플워치")
}
Section {
helpRow(
symbol: "heart.circle",
title: Text("애플 건강 연동"),
body: Text("운동을 끝까지 마치면 그 시간이 애플 건강에 운동으로 자동 기록돼요. 운동 유형(기타·코어 트레이닝)과 운동 강도(110)는 설정에서 고를 수 있어요. 처음 시작할 때 건강 권한을 물어보고, 허용하면 그다음부터는 알아서 저장돼요. 워치에서 하면 워치가 심박수를 실측해 함께 기록하고, 아이폰에서 하면 애플워치의 '기타 운동' 방식(빠르게 걷기 상당)으로 칼로리를 추정해요 — 그래서 둘의 칼로리가 조금 다를 수 있어요. 중단한 세트는 건강에도 기록되지 않고, 원치 않으면 건강 앱에서 케깅의 권한을 끄면 돼요.")
)
helpRow(
symbol: "paintbrush",
title: Text("테마와 언어"),
body: Text("왼쪽 위 톱니바퀴 버튼이 설정이에요. 화면 모드(시스템·라이트·다크)와 언어(시스템·한국어·English·日本語)를 고를 수 있어요. 언어는 앱을 완전히 종료했다가 다시 실행하면 적용돼요. 워치는 워치의 시스템 언어를 따라요.")
)
helpRow(
symbol: "lock.shield",
title: Text("데이터와 개인정보"),
body: Text("케깅은 광고와 결제가 없는 완전 무료 앱이에요. 모든 기록은 이 기기(그리고 워치)에만 저장되고, 외부 서버로 전송되지 않아요.")
)
} header: {
Text("설정·기타")
}
}
.navigationTitle("도움말")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button("완료") { dismiss() }
}
}
}
}
private func helpRow(symbol: String, title: Text, body: Text) -> some View {
VStack(alignment: .leading, spacing: 6) {
HStack(spacing: 8) {
Image(systemName: symbol)
.font(.body)
.foregroundStyle(AppTheme.green)
.frame(width: 24)
title
.font(.headline)
}
body
.font(.subheadline)
.foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
}
.padding(.vertical, 4)
}
}