diff --git a/.DS_Store b/.DS_Store index 5008ddf..fca884c 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.github/workflows/work-log.yml b/.github/workflows/work-log.yml new file mode 100644 index 0000000..98ecea4 --- /dev/null +++ b/.github/workflows/work-log.yml @@ -0,0 +1,134 @@ + name: Archive Worklog to Notion + 2 + 3 on: + 4 push: + 5 branches: + 6 - main # main 브랜치에 push 될 때만 실행합니다. 필요시 다른 + 브랜치로 변경하세요. + 7 + 8 jobs: + 9 archive: + 10 runs-on: ubuntu-latest + 11 steps: + 12 - name: Checkout code + 13 uses: actions/checkout@v4 + 14 with: + 15 fetch-depth: 0 # 모든 커밋 히스토리를 가져오기 위해 + 필요합니다. + 16 + 17 - name: Set up Python + 18 uses: actions/setup-python@v4 + 19 with: + 20 python-version: '3.10' + 21 + 22 - name: Install dependencies + 23 run: pip install requests + 24 + 25 - name: Process commits and send to Notion + 26 env: + 27 NOTION_API_KEY: ${{ secrets.NOTION_API_KEY }} + 28 NOTION_DATABASE_ID: "25f0778f-fac8-802e-8444-c1a490714fd8" + 29 GITHUB_REPOSITORY: ${{ github.repository }} + 30 run: | + 31 import os + 32 import requests + 33 import json + 34 import subprocess + 35 + 36 api_key = os.getenv('NOTION_API_KEY') + 37 db_id = os.getenv('NOTION_DATABASE_ID') + 38 repo_name = os.getenv('GITHUB_REPOSITORY') + 39 + 40 commits = json.loads('''${{ toJSON(github.event.commits) + }}''') + 41 + 42 headers = { + 43 "Authorization": f"Bearer {api_key}", + 44 "Content-Type": "application/json", + 45 "Notion-Version": "2022-06-28" + 46 } + 47 + 48 for commit in commits: + 49 commit_sha = commit['id'] + 50 commit_message_full = commit['message'] + 51 commit_title = commit_message_full.split('\n')[0] + 52 author_name = commit['author']['name'] + 53 commit_timestamp = commit['timestamp'] + 54 + 55 # 1. 속성값으로 페이지 생성 + 56 page_data = { + 57 "parent": {"database_id": db_id}, + 58 "properties": { + 59 "Commit": {"title": [{"text": {"content": + commit_title}}]}, + 60 "SHA": {"rich_text": [{"text": {"content": + commit_sha}}]}, + 61 "Project": {"select": {"name": repo_name}}, + 62 "Date": {"date": {"start": commit_timestamp}} + 63 } + 64 } + 65 + 66 create_response = + requests.post("https://api.notion.com/v1/pages", headers=headers, + json=page_data) + 67 + 68 if create_response.status_code != 200: + 69 print(f"Failed to create page for commit {commit_sha[ + :7]}.") + 70 print(create_response.text) + 71 continue + 72 + 73 new_page_id = create_response.json()['id'] + 74 print(f"Successfully created page for commit {commit_sha[ + :7]}. Page ID: {new_page_id}") + 75 + 76 # 2. 생성된 페이지에 콘텐츠(블록) 추가 + 77 code_diff = subprocess.run(['git', 'show', commit_sha], + capture_output=True, text=True).stdout + 78 if len(code_diff) > 1990: + 79 code_diff = code_diff[:1990] + "\n..." + 80 + 81 blocks_data = { + 82 "children": [ + 83 { + 84 "object": "block", + 85 "type": "heading_2", + 86 "heading_2": {"rich_text": [{"type": "text", + "text": {"content": "Commit Message"}}]} + 87 }, + 88 { + 89 "object": "block", + 90 "type": "paragraph", + 91 "paragraph": {"rich_text": [{"type": "text", + "text": {"content": commit_message_full}}]} + 92 }, + 93 { + 94 "object": "block", + 95 "type": "heading_2", + 96 "heading_2": {"rich_text": [{"type": "text", + "text": {"content": "Code Diff"}}]} + 97 }, + 98 { + 99 "object": "block", + 100 "type": "code", + 101 "code": { + 102 "rich_text": [{"type": "text", "text": { + "content": code_diff}}], + 103 "language": "diff" + 104 } + 105 } + 106 ] + 107 } + 108 + 109 append_response = + requests.patch(f"https://api.notion.com/v1/blocks/{new_page_id}/childre + n", headers=headers, json=blocks_data) + 110 + 111 if append_response.status_code == 200: + 112 print(f"Successfully appended content to page { + new_page_id}.") + 113 else: + 114 print(f"Failed to append content to page {new_page_id + }.") + 115 print(append_response.text) + diff --git a/.gitignore b/.gitignore index 52fe2f7..6aef459 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,9 @@ fastlane/report.xml fastlane/Preview.html fastlane/screenshots/**/*.png fastlane/test_output + +JLPTVoca/GEMINI.md + +JLPTVoca/SwiftData.md + +JLPTVoca/WordStability.md diff --git a/JLPTVoca/.DS_Store b/JLPTVoca/.DS_Store new file mode 100644 index 0000000..d811d2f Binary files /dev/null and b/JLPTVoca/.DS_Store differ diff --git a/JLPTVoca/JLPTVoca/.DS_Store b/JLPTVoca/JLPTVoca/.DS_Store new file mode 100644 index 0000000..b181329 Binary files /dev/null and b/JLPTVoca/JLPTVoca/.DS_Store differ diff --git a/JLPTVoca/JLPTVoca/Managers/WordManager.swift b/JLPTVoca/JLPTVoca/Managers/WordManager.swift index 023d4f4..8589b7a 100644 --- a/JLPTVoca/JLPTVoca/Managers/WordManager.swift +++ b/JLPTVoca/JLPTVoca/Managers/WordManager.swift @@ -12,21 +12,44 @@ import SwiftData @Observable final class WordManager { var allWords: [Word] = [] - var dailyWordDeck: [Word] = [] + var wordDeck: [Word] = [] private var context: ModelContext? - func setup(context: ModelContext, words: [Word]) { + func setup( + context: ModelContext, + words: [Word] + ) { self.context = context self.allWords = words - self.dailyWordDeck = words } - func onSwipeLeft(id: UUID) { - print("memorized") + func prepareSession() { + self.wordDeck = allWords } - func onSwipeRight(id: UUID) { - print("unknown") + func onCardSwipe( + id: UUID, + direction: CardSwipeDirection + ) { + guard let swipedWord = allWords.first(where: { $0.id == id }) else { + return + } + + if direction == .left { + swipedWord.maturityState += 1 + } else { + swipedWord.maturityState = 1 + } + + wordDeck.removeAll { $0.id == id } + + if wordDeck.isEmpty { + do { + try context?.save() + } catch { + print("@Log - \(error.localizedDescription)") + } + } } } diff --git a/JLPTVoca/JLPTVoca/Views/Enum/CardSwipeDirections.swift b/JLPTVoca/JLPTVoca/Views/Enum/CardSwipeDirections.swift index 2606422..20ddb9a 100644 --- a/JLPTVoca/JLPTVoca/Views/Enum/CardSwipeDirections.swift +++ b/JLPTVoca/JLPTVoca/Views/Enum/CardSwipeDirections.swift @@ -7,12 +7,12 @@ import Foundation -enum CardSwipeDirections { +enum CardSwipeDirection { case left case right } typealias CardSwipe = ( _ id: UUID, - _ direction: CardSwipeDirections + _ direction: CardSwipeDirection ) -> Void diff --git a/JLPTVoca/JLPTVoca/Views/HomeView.swift b/JLPTVoca/JLPTVoca/Views/HomeView.swift index fcc37b6..7dbaeed 100644 --- a/JLPTVoca/JLPTVoca/Views/HomeView.swift +++ b/JLPTVoca/JLPTVoca/Views/HomeView.swift @@ -10,8 +10,33 @@ import SwiftUI struct HomeView: View { @Environment(WordManager.self) private var wordManager + @State private var isStudyViewActive = false + var body: some View { - Text("Home View") + NavigationStack { + VStack(spacing: 20) { + NavigationLink( + destination: WordStudyView(), + isActive: $isStudyViewActive + ) { + EmptyView() + } + + Button(action: { + wordManager.prepareSession() + isStudyViewActive = true + }) { + Text("단어 학습 시작") + .font(.title2) + .fontWeight(.bold) + .padding() + .background(Color.blue) + .foregroundColor(.white) + .cornerRadius(10) + } + } + .navigationTitle("홈") + } } } diff --git a/JLPTVoca/JLPTVoca/Views/WordStudyView.swift b/JLPTVoca/JLPTVoca/Views/WordStudyView.swift index 3c9ac7f..6d0dd2f 100644 --- a/JLPTVoca/JLPTVoca/Views/WordStudyView.swift +++ b/JLPTVoca/JLPTVoca/Views/WordStudyView.swift @@ -13,17 +13,17 @@ struct WordStudyView: View { var body: some View { ZStack { - ForEach(wordManager.dailyWordDeck) { word in + ForEach(wordManager.wordDeck) { word in WordCardView( id: word.id, japanese: word.plainJapanese, korean: word.korean - ) { id, direction in - if direction == .left { - wordManager.onSwipeLeft(id: id) - } else { - wordManager.onSwipeRight(id: id) - } + ) { + id, direction in + wordManager.onCardSwipe( + id: id, + direction: direction + ) } } }