From 305f9e7f10a317ee47131625672135abf90b6230 Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 16:41:59 +0900 Subject: [PATCH 01/25] chore: Bookmark -> Bookmarks --- .../RollTheDice.xcodeproj/project.pbxproj | 16 ++-- .../RollTheDice/RollTheDiceApp.swift | 2 +- .../View/Bookmark/BookmarkCard/Bookmark.swift | 31 -------- .../BookmarkCard/BookmarkListViewModel.swift | 30 ------- .../Bookmark/BookmarkCard/Bookmarks.swift | 46 +++++++++++ .../BookmarkCard/BookmarksListViewModel.swift | 78 +++++++++++++++++++ 6 files changed, 133 insertions(+), 70 deletions(-) delete mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmark.swift delete mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkListViewModel.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmarks.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 43967286..92249e2e 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -18,10 +18,10 @@ 357699442C09C7B900AD2DA4 /* AuthAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357699432C09C7B900AD2DA4 /* AuthAPI.swift */; }; 357FC6EA2BCE866B00AD8915 /* DetailCardNews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */; }; 35C71BF22B79F39900F777D1 /* ExyteChat in Frameworks */ = {isa = PBXBuildFile; productRef = 35C71BF12B79F39900F777D1 /* ExyteChat */; }; - 6C32379F2B7C376D00B699AB /* Bookmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C32379E2B7C376D00B699AB /* Bookmark.swift */; }; + 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C32379E2B7C376D00B699AB /* Bookmarks.swift */; }; 6C3237A12B7C377600B699AB /* BookmarkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */; }; 6C3237A52B7C37D100B699AB /* BookmarkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A42B7C37D100B699AB /* BookmarkView.swift */; }; - 6C3237A72B7C37E500B699AB /* BookmarkListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A62B7C37E500B699AB /* BookmarkListViewModel.swift */; }; + 6C3237A72B7C37E500B699AB /* BookmarksListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A62B7C37E500B699AB /* BookmarksListViewModel.swift */; }; 6C3237AA2B7C381500B699AB /* NewsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A92B7C381500B699AB /* NewsView.swift */; }; 6C3237AC2B7C382200B699AB /* NewsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237AB2B7C382200B699AB /* NewsList.swift */; }; 6C3237AE2B7C382E00B699AB /* DetailNewsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237AD2B7C382E00B699AB /* DetailNewsViewModel.swift */; }; @@ -103,10 +103,10 @@ 357666122BBD54AA002C226A /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = ""; }; 357699432C09C7B900AD2DA4 /* AuthAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPI.swift; sourceTree = ""; }; 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailCardNews.swift; sourceTree = ""; }; - 6C32379E2B7C376D00B699AB /* Bookmark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bookmark.swift; sourceTree = ""; }; + 6C32379E2B7C376D00B699AB /* Bookmarks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bookmarks.swift; sourceTree = ""; }; 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkViewModel.swift; sourceTree = ""; }; 6C3237A42B7C37D100B699AB /* BookmarkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkView.swift; sourceTree = ""; }; - 6C3237A62B7C37E500B699AB /* BookmarkListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkListViewModel.swift; sourceTree = ""; }; + 6C3237A62B7C37E500B699AB /* BookmarksListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksListViewModel.swift; sourceTree = ""; }; 6C3237A92B7C381500B699AB /* NewsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsView.swift; sourceTree = ""; }; 6C3237AB2B7C382200B699AB /* NewsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsList.swift; sourceTree = ""; }; 6C3237AD2B7C382E00B699AB /* DetailNewsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailNewsViewModel.swift; sourceTree = ""; }; @@ -213,10 +213,10 @@ 6C32379D2B7C374E00B699AB /* BookmarkCard */ = { isa = PBXGroup; children = ( - 6C32379E2B7C376D00B699AB /* Bookmark.swift */, + 6C32379E2B7C376D00B699AB /* Bookmarks.swift */, + 6C3237A62B7C37E500B699AB /* BookmarksListViewModel.swift */, 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */, 6C3237A42B7C37D100B699AB /* BookmarkView.swift */, - 6C3237A62B7C37E500B699AB /* BookmarkListViewModel.swift */, ); path = BookmarkCard; sourceTree = ""; @@ -754,7 +754,7 @@ 6C77048F2B7229B1001B17CB /* NewsListView.swift in Sources */, 357666132BBD54AA002C226A /* SplashView.swift in Sources */, 6C4F7BAD2BDE510900ED01DA /* DailyReportViewModel.swift in Sources */, - 6C3237A72B7C37E500B699AB /* BookmarkListViewModel.swift in Sources */, + 6C3237A72B7C37E500B699AB /* BookmarksListViewModel.swift in Sources */, 6C454A822B9DAFA3006FD9D0 /* Path.swift in Sources */, 6C94799E2BD3C00C00D5AEEB /* Image.swift in Sources */, 6C454A842B9DAFCB006FD9D0 /* PathType.swift in Sources */, @@ -766,7 +766,7 @@ 6CA901962BA2EC0100E20259 /* Font.swift in Sources */, 6CF130C22BAB786600A437B6 /* APIHeaderManager.swift in Sources */, 6CDB29FB2BAA07B10081037B /* GPTChatViewModel.swift in Sources */, - 6C32379F2B7C376D00B699AB /* Bookmark.swift in Sources */, + 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */, 6C454A7E2B9DAA3F006FD9D0 /* SignUpFinishView.swift in Sources */, 6C7704A12B722CEB001B17CB /* ProfileView.swift in Sources */, 6C4F7BAB2BDE50C600ED01DA /* DailyReportModel.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index 3e61f628..42aaece7 100644 --- a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift +++ b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift @@ -20,7 +20,7 @@ struct RollTheDiceApp: App { var signUpViewModel = SignUpViewModel() var newsListViewModel = NewsListViewModel() - @StateObject var bookmarkListViewModel = BookmarkListViewModel() + @StateObject var bookmarkListViewModel = BookmarksListViewModel() init() { KakaoSDK.initSDK(appKey: "ff09b3d83873ed4e320f0d6bc90759d6") diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmark.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmark.swift deleted file mode 100644 index 39455078..00000000 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmark.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// Bookmark.swift -// RollTheDice -// -// Created by Subeen on 2/12/24. -// - -import Foundation - -struct Bookmark: Hashable { - var id: UUID = UUID() - var title: String - var date: String - var image: String - var content: String - var isBookmarked: Bool - - init( - title: String = "", - date: String = "", - image: String = "", - content: String = "", - isBookmarked: Bool = false - ) { - self.title = title - self.date = date - self.image = image - self.content = content - self.isBookmarked = isBookmarked - } -} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkListViewModel.swift deleted file mode 100644 index 8d2a5731..00000000 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkListViewModel.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// BookmarkListViewModel.swift -// RollTheDice -// -// Created by Subeen on 2/12/24. -// - -import Foundation - -public class BookmarkListViewModel: ObservableObject { - @Published var bookmarkList: [Bookmark] - - init( - bookmarkList: [Bookmark] = [ - .init(title: "2024년 ‘소셜 미디어 다이어트’를 위해 바꿔볼 것", date: "2023년12월3일", image: "exampleNews", content: "2024년으로 접어든지 한 달이 넘었다. 하지만 올 해가 어떻게 흘러갈지 예측하기는 쉽지 않다. 한 가지 확실한 것은 정치적으로 매우 중요한 해라는 점이다. 미국과 러시아, 우크라이나, 방글라데시, 인도, 대만, 한국, 남아프리카공화국, 유럽의회, 영국에서 선거가 치러질 예정이다.", isBookmarked: false), - .init(title: "앤스로픽 최신 AI 모델 '클로드3' 출시", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/014/2024/03/05/0005151141_001_20240305101610000.jpg?type=w647", content: "오픈AI의 대항마 앤스로픽이 생성형 인공지능(AI) 최신 모델 '클로드'(Claude)3를 선보이면서 생성형 AI 주도권을 잡기 위한 경쟁이 다시 뜨거워지고 있다. 앤스로픽은 지난 한 해 동안 구글과 세일즈포스, 아마존 등에서 총 73억 달러(약 9조7309억 원)를 투자받고 '클로드3'를 내놨는데 오픈AI의 챗GPT-4를 능가한다고 도발했다.", isBookmarked: true), - .init(title: "SK C&C, 외부 전문가 대거 영입… “신성장 동력 강화”", date: "2023년2월13일", image: "https://imgnews.pstatic.net/image/366/2024/03/05/0000975131_001_20240305093504301.jpg?type=w647", content: "SK C&C는 국내외 신성장 동력 강화를 위해 인공지능(AI)·클라우드·디지털 팩토리·ESG(환경·사회·지배구조) 등 4대 성장 사업과 디지털 컨설팅 중심으로 외부 전문가를 대거 영입해 전진 배치했다고 5일 밝혔다.", isBookmarked: false), - .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), - - .init(title: "이종호 과기장관 5년 뒤 구축될 바이오파운드리에 산학연 역량 모아야", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/003/2024/03/05/NISI20231030_0001398722_web_20231030141808_20240305103108748.jpg?type=w647", content: "정부가 내년부터 합성생물학의 필수 인프라인 '국가 바이오파운드리' 구축에 본격 나서는 가운데 이종호 과학기술정보통신부 장관이 한국생명공학연구원에서 운영 중인 사전연구용 시설을 찾아 구체적인 인프라 구축 계획 등을 점검했다.이 장관은 5일 합성생물학 육성을 위해 바이오파운드리 연구현장을 방문하고, 산·학·연 전문가들을 만났다. 이번 방문은 지난해 미국, 영국과의 정상회담 시 논의됐던 첨단바이오 협력을 위한 후속조치의 일환으로 추진됐다.", isBookmarked: false), - .init(title: "SW산업 육성에 7308억 예산투자, SaaS 등 육성", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/008/2024/03/05/0005007507_001_20240305135301539.jpg?type=w647", content: "SW(소프트웨어) 산업의 SaaS(서비스형 소프트웨어) 전환 등 SW산업 육성을 위해 정부 예산 7308억원이 투자된다. 강도현 과학기술정보통신부 제2차관은 5일 오전 서울 을지로 더존비즈온 을지사옥에서 열린 'AI(인공지능) 일상화, SW도 이제 서비스형 SW'라는 주제로 열린 현장 간담회에서 정부도 대한민국 SW산업의 미래가 SaaS에 있다고 생각하고 올해 'SaaS 혁신펀드'를 새롭게 조성하는 등 SaaS 육성 및 기존 SW 기업의 SaaS 전환을 위해 다양한 지원을 추진 중이라며 이같이 밝혔다.", isBookmarked: false), - .init(title: "파수, 기업용 AI ‘엔터프라이즈 LLM’ 출시", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/018/2024/03/05/0005685566_001_20240305103201036.jpg?type=w647", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), - .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), - .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), - .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), - ] - ) { - self.bookmarkList = bookmarkList - } -} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmarks.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmarks.swift new file mode 100644 index 00000000..13e6518b --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/Bookmarks.swift @@ -0,0 +1,46 @@ +// +// Bookmark.swift +// RollTheDice +// +// Created by Subeen on 2/12/24. +// + +import Foundation + + +// MARK: - Bookmark +struct Bookmarks: Codable, Identifiable { + let id = UUID().uuidString + let newsId: Int + let title, thumbnailURL, postDate: String? + let isBookmarked: Bool? + + enum CodingKeys: String, CodingKey { + case newsId = "id" + case title, thumbnailURL, postDate, isBookmarked + } +} + + +//struct Bookmarks: Hashable { +// var id: UUID = UUID() +// var title: String +// var date: String +// var image: String +// var content: String +// var isBookmarked: Bool +// +// init( +// title: String = "", +// date: String = "", +// image: String = "", +// content: String = "", +// isBookmarked: Bool = false +// ) { +// self.title = title +// self.date = date +// self.image = image +// self.content = content +// self.isBookmarked = isBookmarked +// } +//} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift new file mode 100644 index 00000000..fc069789 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarksListViewModel.swift @@ -0,0 +1,78 @@ +// +// BookmarkListViewModel.swift +// RollTheDice +// +// Created by Subeen on 2/12/24. +// + +import Foundation +import Combine +import CombineMoya +import Moya +import SwiftUI + +@Observable class BookmarksListViewModel{ + var bookmarksList: [Bookmarks]? + var bookmarksCancellable: AnyCancellable? + + let provider = MoyaProvider(plugins: [MoyaLoggingPlugin()]) + + func bookmarksToViewModel(_ list: [Bookmarks]) { + self.bookmarksList = list + } +} + +extension BookmarksListViewModel { + public func getAllBookmarksData(page: Int, size: Int) { + let accessToken = "5Gu45OmOoZnvANl-qfZv-xHv_2eSweVeAAAAAQopyNkAAAGQFbGnJSn2EFsnJsRZ" + + if let cancellable = bookmarksCancellable { + cancellable.cancel() + } + + bookmarksCancellable = provider.requestWithProgressPublisher( + .allBookmarks( + page: page, + size: size, + accessToken: accessToken + ) + + ) + .compactMap { $0.response?.data } + .receive(on: DispatchQueue.main) + .decode(type: [Bookmarks].self, decoder: JSONDecoder()) + .sink(receiveCompletion: { result in + switch result { + case .finished: + print("all bookmarks 조회 성공") + case .failure(let error): + Log.network("network error", error.localizedDescription) + } + }, receiveValue: { [weak self] response in + self?.bookmarksToViewModel(response) + print(response) + }) + } +} + +//public class BookmarksListViewModel: ObservableObject { +// @Published var bookmarkList: [Bookmarks] +// +// init( +// bookmarkList: [Bookmarks] = [ +// .init(title: "2024년 ‘소셜 미디어 다이어트’를 위해 바꿔볼 것", date: "2023년12월3일", image: "exampleNews", content: "2024년으로 접어든지 한 달이 넘었다. 하지만 올 해가 어떻게 흘러갈지 예측하기는 쉽지 않다. 한 가지 확실한 것은 정치적으로 매우 중요한 해라는 점이다. 미국과 러시아, 우크라이나, 방글라데시, 인도, 대만, 한국, 남아프리카공화국, 유럽의회, 영국에서 선거가 치러질 예정이다.", isBookmarked: false), +// .init(title: "앤스로픽 최신 AI 모델 '클로드3' 출시", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/014/2024/03/05/0005151141_001_20240305101610000.jpg?type=w647", content: "오픈AI의 대항마 앤스로픽이 생성형 인공지능(AI) 최신 모델 '클로드'(Claude)3를 선보이면서 생성형 AI 주도권을 잡기 위한 경쟁이 다시 뜨거워지고 있다. 앤스로픽은 지난 한 해 동안 구글과 세일즈포스, 아마존 등에서 총 73억 달러(약 9조7309억 원)를 투자받고 '클로드3'를 내놨는데 오픈AI의 챗GPT-4를 능가한다고 도발했다.", isBookmarked: true), +// .init(title: "SK C&C, 외부 전문가 대거 영입… “신성장 동력 강화”", date: "2023년2월13일", image: "https://imgnews.pstatic.net/image/366/2024/03/05/0000975131_001_20240305093504301.jpg?type=w647", content: "SK C&C는 국내외 신성장 동력 강화를 위해 인공지능(AI)·클라우드·디지털 팩토리·ESG(환경·사회·지배구조) 등 4대 성장 사업과 디지털 컨설팅 중심으로 외부 전문가를 대거 영입해 전진 배치했다고 5일 밝혔다.", isBookmarked: false), +// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), +// +// .init(title: "이종호 과기장관 5년 뒤 구축될 바이오파운드리에 산학연 역량 모아야", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/003/2024/03/05/NISI20231030_0001398722_web_20231030141808_20240305103108748.jpg?type=w647", content: "정부가 내년부터 합성생물학의 필수 인프라인 '국가 바이오파운드리' 구축에 본격 나서는 가운데 이종호 과학기술정보통신부 장관이 한국생명공학연구원에서 운영 중인 사전연구용 시설을 찾아 구체적인 인프라 구축 계획 등을 점검했다.이 장관은 5일 합성생물학 육성을 위해 바이오파운드리 연구현장을 방문하고, 산·학·연 전문가들을 만났다. 이번 방문은 지난해 미국, 영국과의 정상회담 시 논의됐던 첨단바이오 협력을 위한 후속조치의 일환으로 추진됐다.", isBookmarked: false), +// .init(title: "SW산업 육성에 7308억 예산투자, SaaS 등 육성", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/008/2024/03/05/0005007507_001_20240305135301539.jpg?type=w647", content: "SW(소프트웨어) 산업의 SaaS(서비스형 소프트웨어) 전환 등 SW산업 육성을 위해 정부 예산 7308억원이 투자된다. 강도현 과학기술정보통신부 제2차관은 5일 오전 서울 을지로 더존비즈온 을지사옥에서 열린 'AI(인공지능) 일상화, SW도 이제 서비스형 SW'라는 주제로 열린 현장 간담회에서 정부도 대한민국 SW산업의 미래가 SaaS에 있다고 생각하고 올해 'SaaS 혁신펀드'를 새롭게 조성하는 등 SaaS 육성 및 기존 SW 기업의 SaaS 전환을 위해 다양한 지원을 추진 중이라며 이같이 밝혔다.", isBookmarked: false), +// .init(title: "파수, 기업용 AI ‘엔터프라이즈 LLM’ 출시", date: "2023년3월13일", image: "https://imgnews.pstatic.net/image/018/2024/03/05/0005685566_001_20240305103201036.jpg?type=w647", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), +// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), +// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), +// .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false), +// ] +// ) { +// self.bookmarkList = bookmarkList +// } +//} From 8a92c41d07811e5b6189a328753665fe8b92e8b9 Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 16:42:19 +0900 Subject: [PATCH 02/25] feat: Bookmark API --- .../RollTheDice.xcodeproj/project.pbxproj | 4 ++++ .../Source/Domain/ScoopAPI/ScoopAPIBookmarks.swift | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPIBookmarks.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 92249e2e..107c522a 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -41,6 +41,7 @@ 6C454A882B9DB6C2006FD9D0 /* CustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C454A872B9DB6C2006FD9D0 /* CustomNavigationBar.swift */; }; 6C4F7BAB2BDE50C600ED01DA /* DailyReportModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4F7BAA2BDE50C600ED01DA /* DailyReportModel.swift */; }; 6C4F7BAD2BDE510900ED01DA /* DailyReportViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4F7BAC2BDE510900ED01DA /* DailyReportViewModel.swift */; }; + 6C5B0C8A2C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */; }; 6C7651382BF37E7200196536 /* MoyaLoggingPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7651372BF37E7200196536 /* MoyaLoggingPlugin.swift */; }; 6C76513C2BF37ED300196536 /* Extension+Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C76513B2BF37ED300196536 /* Extension+Log.swift */; }; 6C76513E2BF37F1E00196536 /* Extension+OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C76513D2BF37F1E00196536 /* Extension+OSLog.swift */; }; @@ -126,6 +127,7 @@ 6C454A872B9DB6C2006FD9D0 /* CustomNavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomNavigationBar.swift; sourceTree = ""; }; 6C4F7BAA2BDE50C600ED01DA /* DailyReportModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyReportModel.swift; sourceTree = ""; }; 6C4F7BAC2BDE510900ED01DA /* DailyReportViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyReportViewModel.swift; sourceTree = ""; }; + 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScoopAPIBookmarks.swift; sourceTree = ""; }; 6C7651372BF37E7200196536 /* MoyaLoggingPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoyaLoggingPlugin.swift; sourceTree = ""; }; 6C76513B2BF37ED300196536 /* Extension+Log.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+Log.swift"; sourceTree = ""; }; 6C76513D2BF37F1E00196536 /* Extension+OSLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+OSLog.swift"; sourceTree = ""; }; @@ -619,6 +621,7 @@ children = ( 6CF130C42BAB79DE00A437B6 /* ScoopAPI.swift */, 6CF130C62BAB7B9800A437B6 /* ScoopAPINews.swift */, + 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */, ); path = ScoopAPI; sourceTree = ""; @@ -728,6 +731,7 @@ 357699442C09C7B900AD2DA4 /* AuthAPI.swift in Sources */, 6C76513C2BF37ED300196536 /* Extension+Log.swift in Sources */, 6CE103102BD56A5B00498AA4 /* TypeReportViewModel.swift in Sources */, + 6C5B0C8A2C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift in Sources */, 6CF130C52BAB79DE00A437B6 /* ScoopAPI.swift in Sources */, 6CE103132BD56B1200498AA4 /* DailyReportView.swift in Sources */, 6C454A7A2B9DA67C006FD9D0 /* SignUpViewModel.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPIBookmarks.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPIBookmarks.swift new file mode 100644 index 00000000..1905043d --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPIBookmarks.swift @@ -0,0 +1,12 @@ +// +// ScoopAPIBookmark.swift +// RollTheDice +// +// Created by Subeen on 6/14/24. +// + +import Foundation + +public enum ScoopAPIBookmarks { + public static let bookmarks = String("/bookmarks") +} From 7141ef7484ba906857df80c5896f054bf0cac11f Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 16:42:49 +0900 Subject: [PATCH 03/25] feat: Bookmarks Service --- .../RollTheDice.xcodeproj/project.pbxproj | 4 + .../Domain/Service/BookmarksService.swift | 81 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 iOS/RollTheDice/RollTheDice/Source/Domain/Service/BookmarksService.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 107c522a..6a886cd3 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -42,6 +42,7 @@ 6C4F7BAB2BDE50C600ED01DA /* DailyReportModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4F7BAA2BDE50C600ED01DA /* DailyReportModel.swift */; }; 6C4F7BAD2BDE510900ED01DA /* DailyReportViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C4F7BAC2BDE510900ED01DA /* DailyReportViewModel.swift */; }; 6C5B0C8A2C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */; }; + 6C5B0C8C2C1C32C000A0D5F4 /* BookmarksService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5B0C8B2C1C32C000A0D5F4 /* BookmarksService.swift */; }; 6C7651382BF37E7200196536 /* MoyaLoggingPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7651372BF37E7200196536 /* MoyaLoggingPlugin.swift */; }; 6C76513C2BF37ED300196536 /* Extension+Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C76513B2BF37ED300196536 /* Extension+Log.swift */; }; 6C76513E2BF37F1E00196536 /* Extension+OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C76513D2BF37F1E00196536 /* Extension+OSLog.swift */; }; @@ -128,6 +129,7 @@ 6C4F7BAA2BDE50C600ED01DA /* DailyReportModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyReportModel.swift; sourceTree = ""; }; 6C4F7BAC2BDE510900ED01DA /* DailyReportViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyReportViewModel.swift; sourceTree = ""; }; 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScoopAPIBookmarks.swift; sourceTree = ""; }; + 6C5B0C8B2C1C32C000A0D5F4 /* BookmarksService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksService.swift; sourceTree = ""; }; 6C7651372BF37E7200196536 /* MoyaLoggingPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoyaLoggingPlugin.swift; sourceTree = ""; }; 6C76513B2BF37ED300196536 /* Extension+Log.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+Log.swift"; sourceTree = ""; }; 6C76513D2BF37F1E00196536 /* Extension+OSLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extension+OSLog.swift"; sourceTree = ""; }; @@ -594,6 +596,7 @@ children = ( 6C7651432BF381B000196536 /* Log */, 6CF130B12BAB74BA00A437B6 /* NewsService.swift */, + 6C5B0C8B2C1C32C000A0D5F4 /* BookmarksService.swift */, ); path = Service; sourceTree = ""; @@ -769,6 +772,7 @@ 6C454A782B9DA657006FD9D0 /* SignUpQuestionView.swift in Sources */, 6CA901962BA2EC0100E20259 /* Font.swift in Sources */, 6CF130C22BAB786600A437B6 /* APIHeaderManager.swift in Sources */, + 6C5B0C8C2C1C32C000A0D5F4 /* BookmarksService.swift in Sources */, 6CDB29FB2BAA07B10081037B /* GPTChatViewModel.swift in Sources */, 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */, 6C454A7E2B9DAA3F006FD9D0 /* SignUpFinishView.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/Service/BookmarksService.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/BookmarksService.swift new file mode 100644 index 00000000..926408bc --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/BookmarksService.swift @@ -0,0 +1,81 @@ +// +// BookmarksService.swift +// RollTheDice +// +// Created by Subeen on 6/14/24. +// + +import Foundation +import Moya + +enum BookmarksService { + case bookmarksIsChecked(newsId: Int, accessToken: String) ///뉴스 북마크 여부 조회 + case saveBookmarks(newsId: Int, accessToken: String) ///북마크 저장 + case deleteBookmarks(newsId: Int, accessToken: String) ///북마크 삭제 + case allBookmarks(page: Int, size: Int, accessToken: String) ///북마크 전체 조회/ +} + +extension BookmarksService: BaseTargetType { + + var baseURL: URL { + return URL(string: ScoopAPI.baseURL)! + } + + var path: String { + switch self { + case .bookmarksIsChecked(let newsId, _), + .saveBookmarks(let newsId, _), + .deleteBookmarks(let newsId, _) + : + return "\(ScoopAPIBookmarks.bookmarks)/\(newsId)" + + case .allBookmarks: + return ScoopAPIBookmarks.bookmarks + } + } + + var method: Moya.Method { + switch self { + case .bookmarksIsChecked: + return .get + case .saveBookmarks: + return .post + case .deleteBookmarks: + return .delete + case .allBookmarks: + return .get + } + } + + var task: Moya.Task { + switch self { + case .bookmarksIsChecked(let newsId, _), + .saveBookmarks(let newsId, _), + .deleteBookmarks(let newsId, _): + let parameters : [String : Any] = [:] + return .requestParameters(parameters: parameters, encoding: URLEncoding.default) + + case .allBookmarks(let page, let size, _): + let parameters : [String : Any] = [ + "page" : page, + "size" : size, + ] + return .requestParameters(parameters: parameters, + encoding: URLEncoding.queryString) + } + } + + var headers: [String : String]? { + let accessToken: String + switch self { + case .bookmarksIsChecked(_, let accessToken), + .saveBookmarks(_, let accessToken), + .deleteBookmarks(_, let accessToken), + .allBookmarks(_, _, let accessToken): + return [ + "Authorization": "Bearer \(accessToken)", + "X-Content-Type_Options" : "nosniff" + ] + } + } +} From e9b2248949b8511e93ae52b49b78d5fdac7d99e7 Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 16:46:36 +0900 Subject: [PATCH 04/25] =?UTF-8?q?chore:=20Macro=20=EC=A0=81=EC=9A=A9=20?= =?UTF-8?q?=ED=9B=84=20@StateObject=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index 42aaece7..17bfa543 100644 --- a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift +++ b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift @@ -20,7 +20,7 @@ struct RollTheDiceApp: App { var signUpViewModel = SignUpViewModel() var newsListViewModel = NewsListViewModel() - @StateObject var bookmarkListViewModel = BookmarksListViewModel() + var bookmarkListViewModel = BookmarksListViewModel() init() { KakaoSDK.initSDK(appKey: "ff09b3d83873ed4e320f0d6bc90759d6") From b5a7f594a9591ab917caab88924004e8d2eec4d0 Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 16:47:06 +0900 Subject: [PATCH 05/25] =?UTF-8?q?chore:=20NewsList=20=EB=B7=B0=20spacing?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice/Source/View/News/NewsCard/NewsListView.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListView.swift index faf04761..d95bb351 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListView.swift @@ -28,12 +28,11 @@ struct NewsListView: View { private struct NewsListContentView: View { var newsList: [NewsList] - fileprivate var body: some View { GeometryReader { proxy in ScrollView(.horizontal, showsIndicators: false) { - LazyHStack(spacing: -234567876455) { + LazyHStack { ForEach(newsList) { news in NewsView(news: news) From 67e45ef82091d7b646d4fce2d27d13e2a37edefc Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 16:47:31 +0900 Subject: [PATCH 06/25] =?UTF-8?q?feat:=20=EB=B6=81=EB=A7=88=ED=81=AC?= =?UTF-8?q?=EB=B7=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Bookmark/BookmarkCard/BookmarkView.swift | 26 ++++++++++++------- .../View/Bookmark/BookmarkListView.swift | 15 +++++++---- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift index c62ed345..ea1086b4 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkCard/BookmarkView.swift @@ -7,17 +7,20 @@ import SwiftUI +//let id = UUID().uuidString +//let newsId: Int +//let title, thumbnailURL, postDate: String +//let isBookmarked: Bool + struct BookmarkView: View { - - @State var bookmark: Bookmark - + @State var bookmark: Bookmarks var body: some View { ZStack { Color.gray07.ignoresSafeArea(.all) VStack(alignment: .leading, spacing: 0) { - Text(bookmark.title) + Text(bookmark.title ?? "네트워크 통신 중") .font(.system(size: 24, weight: .bold)) .foregroundStyle(.basicWhite) .multilineTextAlignment(.leading) @@ -26,7 +29,7 @@ struct BookmarkView: View { Spacer() HStack { - AsyncImage(url: URL(string: bookmark.image)) { image in + AsyncImage(url: URL(string: bookmark.thumbnailURL ?? "")) { image in image .resizable() .scaledToFill() @@ -54,7 +57,8 @@ struct BookmarkView: View { .overlay { Button { // TODO: 북마크 설정 / 해제 - bookmark.isBookmarked.toggle() +// bookmark.isBookmarked.toggle() + } label: { Image(systemName: "bookmark.fill") @@ -62,7 +66,7 @@ struct BookmarkView: View { .frame(width: 40, height: 65) // .fixedSize() - .foregroundStyle(bookmark.isBookmarked ? .primary01 : .gray01) + .foregroundStyle(bookmark.isBookmarked ?? true ? .primary01 : .gray01) } .offset(x: 110, y: -130) @@ -70,6 +74,8 @@ struct BookmarkView: View { } } -#Preview { - BookmarkView(bookmark: .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false)) -} +//#Preview { +// BookmarkView(bookmark: .init(newsId: 0, title: "NHN, 작년 영업익 555억원...전년비 42% ↑", thumbnailURL: <#T##String#>, postDate: <#T##String#>, isBookmarked: <#T##Bool#>)) +// +// BookmarkView(bookmark: .init(title: "NHN, 작년 영업익 555억원...전년비 42% ↑", date: "2023년2월13일", image: "https://cdnimage.dailian.co.kr/news/202402/news_1707866329_1327972_m_1.png", content: "2NHN은 연결기준 지난해 영업이익이 555억원으로 전년 대비 42.2% 증가했다고 14일 밝혔다.같은 기간 매출은 7.3% 증가한 2조2696억원으로 연간 최대치를 기록했다. 작년 4분기 매출은 5983억원으로 전년 동기 대비 6.7% 올랐다. 반면 영업손실은 78억원으로 적자전환했다. 커머스 부문의 장기 미회수채권 대손상각비 인식과 기술 부문의 기 인식 매출 차감 등 일회성 요인이 영향을 미쳤다.", isBookmarked: false)) +//} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkListView.swift index ad0be59d..ae4c8175 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Bookmark/BookmarkListView.swift @@ -8,8 +8,10 @@ import SwiftUI struct BookmarkListView: View { + @EnvironmentObject var pathModel: PathModel - @StateObject var bookmarkListViewModel : BookmarkListViewModel + var bookmarkListViewModel : BookmarksListViewModel + var bookmarkPage: Int? @State var selectedIndex: Int = 0 var columns: [GridItem] = [ GridItem(), GridItem()] @@ -39,16 +41,19 @@ struct BookmarkListView: View { Spacer() } } + .task { + bookmarkListViewModel.getAllBookmarksData(page: 0, size: 10) + } .navigationBarBackButtonHidden() } + @ViewBuilder var bookmarkListView: some View { - ScrollViewReader { value in ScrollView(.horizontal, showsIndicators: false) { LazyHGrid(rows: columns, spacing: 10) { - ForEach(bookmarkListViewModel.bookmarkList, id: \.self) { bookmark in + ForEach(bookmarkListViewModel.bookmarksList ?? []) { bookmark in BookmarkView(bookmark: bookmark) // .onTapGesture { // withAnimation { @@ -89,6 +94,6 @@ struct BookmarkListView: View { } #Preview { - BookmarkListView(bookmarkListViewModel: BookmarkListViewModel()) - .environmentObject(BookmarkListViewModel()) + BookmarkListView(bookmarkListViewModel: BookmarksListViewModel()) + .environmentObject(PathModel()) } From 82c53dbad12d0861cc4f580433b44ab219b0a7b2 Mon Sep 17 00:00:00 2001 From: realhsb Date: Tue, 18 Jun 2024 17:18:26 +0900 Subject: [PATCH 07/25] =?UTF-8?q?chore:=20News=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice.xcodeproj/project.pbxproj | 32 +++++++++---------- .../DetailNewsCard/DetailCardNews.swift | 0 .../DetailNews.swift | 0 .../DetailNewsViewModel.swift | 0 .../{NewsCard => NewsList}/NewsList.swift | 0 .../{NewsCard => NewsList}/NewsListView.swift | 0 .../NewsListViewModel.swift | 0 .../{NewsCard => NewsList}/NewsView.swift | 0 .../News/{NewsCard => }/WebView/WebView.swift | 0 9 files changed, 16 insertions(+), 16 deletions(-) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => }/DetailNewsCard/DetailCardNews.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => DetailNewsCard}/DetailNews.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => DetailNewsCard}/DetailNewsViewModel.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => NewsList}/NewsList.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => NewsList}/NewsListView.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => NewsList}/NewsListViewModel.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => NewsList}/NewsView.swift (100%) rename iOS/RollTheDice/RollTheDice/Source/View/News/{NewsCard => }/WebView/WebView.swift (100%) diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 6a886cd3..714e0466 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -225,21 +225,6 @@ path = BookmarkCard; sourceTree = ""; }; - 6C3237A82B7C380200B699AB /* NewsCard */ = { - isa = PBXGroup; - children = ( - 6C7651472BF5FDB100196536 /* WebView */, - 6C94799F2BD3CC0400D5AEEB /* DetailNewsCard */, - 6C77048E2B7229B1001B17CB /* NewsListView.swift */, - 6C3237B12B7C385000B699AB /* NewsListViewModel.swift */, - 6C3237A92B7C381500B699AB /* NewsView.swift */, - 6C3237AD2B7C382E00B699AB /* DetailNewsViewModel.swift */, - 6C3237AB2B7C382200B699AB /* NewsList.swift */, - 6C7651452BF5B45A00196536 /* DetailNews.swift */, - ); - path = NewsCard; - sourceTree = ""; - }; 6C3237B32B7C433000B699AB /* ChatType */ = { isa = PBXGroup; children = ( @@ -392,7 +377,9 @@ 6C77048D2B7229A3001B17CB /* News */ = { isa = PBXGroup; children = ( - 6C3237A82B7C380200B699AB /* NewsCard */, + 6CC673782C217999009FB30E /* NewsList */, + 6C7651472BF5FDB100196536 /* WebView */, + 6C94799F2BD3CC0400D5AEEB /* DetailNewsCard */, ); path = News; sourceTree = ""; @@ -436,6 +423,8 @@ 6C94799F2BD3CC0400D5AEEB /* DetailNewsCard */ = { isa = PBXGroup; children = ( + 6C3237AD2B7C382E00B699AB /* DetailNewsViewModel.swift */, + 6C7651452BF5B45A00196536 /* DetailNews.swift */, 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */, ); path = DetailNewsCard; @@ -503,6 +492,17 @@ path = "Preview Content"; sourceTree = ""; }; + 6CC673782C217999009FB30E /* NewsList */ = { + isa = PBXGroup; + children = ( + 6C3237A92B7C381500B699AB /* NewsView.swift */, + 6C77048E2B7229B1001B17CB /* NewsListView.swift */, + 6C3237B12B7C385000B699AB /* NewsListViewModel.swift */, + 6C3237AB2B7C382200B699AB /* NewsList.swift */, + ); + path = NewsList; + sourceTree = ""; + }; 6CDB29F72BAA06FB0081037B /* ChatGPT */ = { isa = PBXGroup; children = ( diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/DetailNewsCard/DetailCardNews.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/DetailNewsCard/DetailCardNews.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/DetailNewsCard/DetailCardNews.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/DetailNewsCard/DetailCardNews.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/DetailNews.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/DetailNewsCard/DetailNews.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/DetailNews.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/DetailNewsCard/DetailNews.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/DetailNewsViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/DetailNewsCard/DetailNewsViewModel.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/DetailNewsViewModel.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/DetailNewsCard/DetailNewsViewModel.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsList.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsList.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsList.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsList.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListView.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListView.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListView.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListViewModel.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsListViewModel.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsListViewModel.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/NewsView.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/NewsList/NewsView.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/WebView/WebView.swift b/iOS/RollTheDice/RollTheDice/Source/View/News/WebView/WebView.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/News/NewsCard/WebView/WebView.swift rename to iOS/RollTheDice/RollTheDice/Source/View/News/WebView/WebView.swift From 93999e1dbce5d3f265c466903b2dafcc05357675 Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 03:35:07 +0900 Subject: [PATCH 08/25] =?UTF-8?q?feat:=20AuthAPI=20->=20LoginService=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice.xcodeproj/project.pbxproj | 5 +- .../Source/Domain/Service/LoginService.swift | 56 +++++++++++++++++++ .../Source/View/Authentication/AuthAPI.swift | 54 ------------------ 3 files changed, 59 insertions(+), 56 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift delete mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthAPI.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 714e0466..c6aa52ca 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -103,7 +103,7 @@ 350909192C1C1248007D76A1 /* TokenManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenManager.swift; sourceTree = ""; }; 3576660F2BBD4BF6002C226A /* ReportListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportListView.swift; sourceTree = ""; }; 357666122BBD54AA002C226A /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = ""; }; - 357699432C09C7B900AD2DA4 /* AuthAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPI.swift; sourceTree = ""; }; + 357699432C09C7B900AD2DA4 /* LoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginService.swift; sourceTree = ""; }; 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailCardNews.swift; sourceTree = ""; }; 6C32379E2B7C376D00B699AB /* Bookmarks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bookmarks.swift; sourceTree = ""; }; 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkViewModel.swift; sourceTree = ""; }; @@ -731,13 +731,14 @@ files = ( 6C454A882B9DB6C2006FD9D0 /* CustomNavigationBar.swift in Sources */, 6CF130BF2BAB783300A437B6 /* APIConstants.swift in Sources */, - 357699442C09C7B900AD2DA4 /* AuthAPI.swift in Sources */, + 357699442C09C7B900AD2DA4 /* LoginService.swift in Sources */, 6C76513C2BF37ED300196536 /* Extension+Log.swift in Sources */, 6CE103102BD56A5B00498AA4 /* TypeReportViewModel.swift in Sources */, 6C5B0C8A2C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift in Sources */, 6CF130C52BAB79DE00A437B6 /* ScoopAPI.swift in Sources */, 6CE103132BD56B1200498AA4 /* DailyReportView.swift in Sources */, 6C454A7A2B9DA67C006FD9D0 /* SignUpViewModel.swift in Sources */, + 6CC6737A2C217C4B009FB30E /* ScoopAPILogin.swift in Sources */, 6C3237AA2B7C381500B699AB /* NewsView.swift in Sources */, 6CF130C92BAB7CC200A437B6 /* BaseTargetType.swift in Sources */, 6C7651492BF5FDB900196536 /* WebView.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift new file mode 100644 index 00000000..7b1b2ef7 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift @@ -0,0 +1,56 @@ +// +// AuthAPI.swift +// RollTheDice +// +// Created by 신예진 on 5/31/24. +// + +import Foundation +import Moya + +enum LoginService { + case login(token: String, socialType: String) +} + +//struct LoginService { +// static let provider = MoyaProvider() +//} + +extension LoginService: BaseTargetType { + + var baseURL: URL { + return URL(string: ScoopAPI.baseURL)! + } + + var path: String { + switch self { + case .login: + return ScoopAPILogin.login + } + } + + var method: Moya.Method { + switch self { + case .login: + return .post + } + } + + var task: Task { + switch self { + case .login(let token, let socialType): + let parameters : [String : Any] = [ + "token" : token, + "socialType" : socialType, + ] + + return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString) + } + } + + var headers: [String: String]? { + return [ + "X-Content-Type_Options" : "nosniff" + ] + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthAPI.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthAPI.swift deleted file mode 100644 index 54af7c2c..00000000 --- a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthAPI.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// AuthAPI.swift -// RollTheDice -// -// Created by 신예진 on 5/31/24. -// - -import Foundation -import Moya - -struct AuthProvider { - static let provider = MoyaProvider() -} - -enum AuthTarget: TargetType { - case login(token: String) - - var baseURL: URL { - return URL(string: "http://ec2-13-124-191-244.ap-northeast-2.compute.amazonaws.com:8080")! - } - - var path: String { - switch self { - case .login: - return "/login" - } - } - - var method: Moya.Method { - switch self { - case .login: - return .post - } - } - - var task: Task { - switch self { - case .login(let token): - return .requestParameters(parameters: ["accessToken": token], encoding: JSONEncoding.default) - } - } - -// var headers: [String: String]? { -// return ["Content-Type": "application/json"] -// } - - var headers: [String: String]? { - var headers = [String: String]() - if let token = TokenManager.shared.accessToken { - headers["Authorization"] = "Bearer \(token)" - } - return headers - } -} From f0fc24f0482de06bb9b9f8f58b9e91e4bd9447ff Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 03:37:27 +0900 Subject: [PATCH 09/25] =?UTF-8?q?feat:=20baseURL=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice/Source/Domain/API/APIHeaderManager.swift | 4 ++-- .../RollTheDice/Source/Domain/ScoopAPI/ScoopAPI.swift | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/API/APIHeaderManager.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/API/APIHeaderManager.swift index 81c204d8..cc337cd0 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Domain/API/APIHeaderManager.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/API/APIHeaderManager.swift @@ -12,8 +12,8 @@ public class APIHeaderManager { static let shared = APIHeaderManager() let contentType: String = "application/json" - let scoopHost: String = "ec2-13-124-191-244.ap-northeast-2.compute.amazonaws.com:8080" +// let scoopHost: String = "ec2-13-124-191-244.ap-northeast-2.compute.amazonaws.com:8080" + let scoopHost: String = "roll-the-dice.store:8080" } - // http://ec2-13-124-191-244.ap-northeast-2.compute.amazonaws.com:8080/swagger-ui/index.html diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPI.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPI.swift index 0784adf7..966bd589 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPI.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPI.swift @@ -8,5 +8,6 @@ import Foundation enum ScoopAPI { - static let baseURL = "http://ec2-13-124-191-244.ap-northeast-2.compute.amazonaws.com:8080" +// static let baseURL = "http://ec2-13-124-191-244.ap-northeast-2.compute.amazonaws.com:8080" + static let baseURL = "http://roll-the-dice.store:8080" } From 1c20dffed0846a3da9f8b8332933b79f4fcd4d9c Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 03:38:39 +0900 Subject: [PATCH 10/25] =?UTF-8?q?feat:=20Auth=20(=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=20response)=20=EB=AA=A8=EB=8D=B8=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice.xcodeproj/project.pbxproj | 7 +++++-- .../Source/View/Authentication/Auth.swift | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index c6aa52ca..7e9dacb6 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -15,7 +15,7 @@ 3576993E2C09C1EB00AD2DA4 /* KakaoSDKCert in Frameworks */ = {isa = PBXBuildFile; productRef = 3576993D2C09C1EB00AD2DA4 /* KakaoSDKCert */; }; 357699402C09C1EB00AD2DA4 /* KakaoSDKCertCore in Frameworks */ = {isa = PBXBuildFile; productRef = 3576993F2C09C1EB00AD2DA4 /* KakaoSDKCertCore */; }; 357699422C09C1EB00AD2DA4 /* KakaoSDKCommon in Frameworks */ = {isa = PBXBuildFile; productRef = 357699412C09C1EB00AD2DA4 /* KakaoSDKCommon */; }; - 357699442C09C7B900AD2DA4 /* AuthAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357699432C09C7B900AD2DA4 /* AuthAPI.swift */; }; + 357699442C09C7B900AD2DA4 /* LoginService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357699432C09C7B900AD2DA4 /* LoginService.swift */; }; 357FC6EA2BCE866B00AD8915 /* DetailCardNews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */; }; 35C71BF22B79F39900F777D1 /* ExyteChat in Frameworks */ = {isa = PBXBuildFile; productRef = 35C71BF12B79F39900F777D1 /* ExyteChat */; }; 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C32379E2B7C376D00B699AB /* Bookmarks.swift */; }; @@ -64,6 +64,7 @@ 6CC4DDC92B5574670080E7E8 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC4DDC82B5574670080E7E8 /* ContentView.swift */; }; 6CC4DDCB2B5574690080E7E8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CC4DDCA2B5574690080E7E8 /* Assets.xcassets */; }; 6CC4DDCE2B5574690080E7E8 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CC4DDCD2B5574690080E7E8 /* Preview Assets.xcassets */; }; + 6CC6737C2C21BA5B009FB30E /* Auth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC6737B2C21BA5B009FB30E /* Auth.swift */; }; 6CDB29C92BA97C550081037B /* Pretendard-Black.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C02BA97C550081037B /* Pretendard-Black.otf */; }; 6CDB29CA2BA97C550081037B /* Pretendard-ExtraBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C12BA97C550081037B /* Pretendard-ExtraBold.otf */; }; 6CDB29CB2BA97C550081037B /* Pretendard-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C22BA97C550081037B /* Pretendard-Regular.otf */; }; @@ -152,6 +153,7 @@ 6CC4DDC82B5574670080E7E8 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 6CC4DDCA2B5574690080E7E8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 6CC4DDCD2B5574690080E7E8 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 6CC6737B2C21BA5B009FB30E /* Auth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Auth.swift; sourceTree = ""; }; 6CDB29BF2BA9735C0081037B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6CDB29C02BA97C550081037B /* Pretendard-Black.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Black.otf"; sourceTree = ""; }; 6CDB29C12BA97C550081037B /* Pretendard-ExtraBold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-ExtraBold.otf"; sourceTree = ""; }; @@ -575,7 +577,7 @@ children = ( 6CF130AC2BAB0C4400A437B6 /* AuthenticationViewModel.swift */, 6CF130AE2BAB0C4F00A437B6 /* AuthenticatedView.swift */, - 357699432C09C7B900AD2DA4 /* AuthAPI.swift */, + 6CC6737B2C21BA5B009FB30E /* Auth.swift */, ); path = Authentication; sourceTree = ""; @@ -755,6 +757,7 @@ 6C3237AC2B7C382200B699AB /* NewsList.swift in Sources */, 6CE1030E2BD56A5200498AA4 /* TypeReportModel.swift in Sources */, 6C76513E2BF37F1E00196536 /* Extension+OSLog.swift in Sources */, + 6CC6737C2C21BA5B009FB30E /* Auth.swift in Sources */, 357FC6EA2BCE866B00AD8915 /* DetailCardNews.swift in Sources */, 6CC4DDC92B5574670080E7E8 /* ContentView.swift in Sources */, 6C3237A52B7C37D100B699AB /* BookmarkView.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift new file mode 100644 index 00000000..00c267c9 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift @@ -0,0 +1,18 @@ +// +// Auth.swift +// RollTheDice +// +// Created by Subeen on 6/18/24. +// + +import Foundation + +struct AuthModel { + let Authorization: String? + let AuthorizationRefresh: String? + + enum CodingKeys: String, CodingKey { + case Authorization + case AuthorizationRefresh = "Authorization-refresh" + } +} From 34027cd9f33723875c09bb5583436dfce9d020ef Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 03:39:23 +0900 Subject: [PATCH 11/25] =?UTF-8?q?feat:=20login=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice.xcodeproj/project.pbxproj | 4 ++++ .../Source/Domain/ScoopAPI/ScoopAPILogin.swift | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPILogin.swift diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 7e9dacb6..64081947 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -64,6 +64,7 @@ 6CC4DDC92B5574670080E7E8 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC4DDC82B5574670080E7E8 /* ContentView.swift */; }; 6CC4DDCB2B5574690080E7E8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CC4DDCA2B5574690080E7E8 /* Assets.xcassets */; }; 6CC4DDCE2B5574690080E7E8 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CC4DDCD2B5574690080E7E8 /* Preview Assets.xcassets */; }; + 6CC6737A2C217C4B009FB30E /* ScoopAPILogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC673792C217C4B009FB30E /* ScoopAPILogin.swift */; }; 6CC6737C2C21BA5B009FB30E /* Auth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC6737B2C21BA5B009FB30E /* Auth.swift */; }; 6CDB29C92BA97C550081037B /* Pretendard-Black.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C02BA97C550081037B /* Pretendard-Black.otf */; }; 6CDB29CA2BA97C550081037B /* Pretendard-ExtraBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 6CDB29C12BA97C550081037B /* Pretendard-ExtraBold.otf */; }; @@ -153,6 +154,7 @@ 6CC4DDC82B5574670080E7E8 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 6CC4DDCA2B5574690080E7E8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 6CC4DDCD2B5574690080E7E8 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 6CC673792C217C4B009FB30E /* ScoopAPILogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScoopAPILogin.swift; sourceTree = ""; }; 6CC6737B2C21BA5B009FB30E /* Auth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Auth.swift; sourceTree = ""; }; 6CDB29BF2BA9735C0081037B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6CDB29C02BA97C550081037B /* Pretendard-Black.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Black.otf"; sourceTree = ""; }; @@ -599,6 +601,7 @@ 6C7651432BF381B000196536 /* Log */, 6CF130B12BAB74BA00A437B6 /* NewsService.swift */, 6C5B0C8B2C1C32C000A0D5F4 /* BookmarksService.swift */, + 357699432C09C7B900AD2DA4 /* LoginService.swift */, ); path = Service; sourceTree = ""; @@ -627,6 +630,7 @@ 6CF130C42BAB79DE00A437B6 /* ScoopAPI.swift */, 6CF130C62BAB7B9800A437B6 /* ScoopAPINews.swift */, 6C5B0C892C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift */, + 6CC673792C217C4B009FB30E /* ScoopAPILogin.swift */, ); path = ScoopAPI; sourceTree = ""; diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPILogin.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPILogin.swift new file mode 100644 index 00000000..0aa1c3ba --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/ScoopAPI/ScoopAPILogin.swift @@ -0,0 +1,12 @@ +// +// ScoopAPILogin.swift +// RollTheDice +// +// Created by Subeen on 6/18/24. +// + +import Foundation + +public enum ScoopAPILogin { + public static let login = String("/login") +} From b078e145de9681fda86579acc1ef74d0b5a6274b Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 03:39:41 +0900 Subject: [PATCH 12/25] =?UTF-8?q?chore:=20AuthVM=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuthenticationViewModel.swift | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift index 521d3965..fcec3dc1 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift @@ -8,6 +8,7 @@ import Foundation import KakaoSDKAuth import KakaoSDKUser +import Moya enum AuthenticationState { @@ -20,9 +21,13 @@ enum AuthenticationState { // 로그인 상태에 따라 화면 분기처리 var authenticationState: AuthenticationState = .unauthenticated var isLoading = false + + let provider = MoyaProvider() } extension AuthenticationViewModel { + + func loginWithKakao() { if (UserApi.isKakaoTalkLoginAvailable()) { UserApi.shared.loginWithKakaoTalk { (oauthToken, error) in @@ -34,10 +39,14 @@ extension AuthenticationViewModel { UserApi.shared.me { (user, error) in if let error = error { print("Kakao user info error: \(error)") + self.authenticationState = .unauthenticated } else { // 사용자 정보 처리 - self.authenticationState = .authenticated +// self.authenticationState = .authenticated + self.loginToBackend(with: oauthToken!.accessToken, socialType: "KAKAO") + + } } } @@ -50,14 +59,19 @@ extension AuthenticationViewModel { } extension AuthenticationViewModel { - func loginToBackend(with token: String) { - AuthProvider.provider.request(.login(token: token)) { result in + func loginToBackend(with token: String, socialType: String) { + self.provider.request(.login(token: token, socialType: socialType)) { result in switch result { case .success(let response): + + do { let json = try response.mapJSON() print("Login response: \(json)") - self.authenticationState = .completedSignUp +// self.authenticationState = .completedSignUp + + TokenManager.shared.accessToken = token + } catch { print("Login error: \(error)") self.authenticationState = .unauthenticated From 3b452128b8ea2561a90de4f972c5b939ef05147a Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 05:05:44 +0900 Subject: [PATCH 13/25] =?UTF-8?q?chore:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Authentication/AuthenticatedView.swift | 39 +------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticatedView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticatedView.swift index 72eb4ff6..759b8bd8 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticatedView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticatedView.swift @@ -122,45 +122,8 @@ struct AuthenticatedView: View { .frame(height: 50) } -// Button { -// if (UserApi.isKakaoTalkLoginAvailable()) { -// UserApi.shared.loginWithKakaoTalk {(oauthToken, error) in -// print(oauthToken) -// print(error) -// } -// } else { -// UserApi.shared.loginWithKakaoAccount {(oauthToken, error) in -// print(oauthToken) -// print(error) -// } -// } -// -// } label: { -// Image(.kakaoSignInBtn01) -// .resizable() -// .aspectRatio(contentMode: .fit) -// .frame(height: 50) -// } Button { - if UserApi.isKakaoTalkLoginAvailable() { - UserApi.shared.loginWithKakaoTalk { (oauthToken, error) in - if let error = error { - print("Kakao Login Error: \(error)") - } else if let oauthToken = oauthToken { - print("Kakao Login Success: \(oauthToken)") - TokenManager.shared.accessToken = oauthToken.accessToken - authViewModel.authenticationState = .completedSignUp } - } - } else { - UserApi.shared.loginWithKakaoAccount { (oauthToken, error) in - if let error = error { - print("Kakao Login Error: \(error)") - } else if let oauthToken = oauthToken { - print("Kakao Login Success: \(oauthToken)") - TokenManager.shared.accessToken = oauthToken.accessToken - authViewModel.authenticationState = .completedSignUp } - } - } + authViewModel.loginWithKakao() } label: { Image(.kakaoSignInBtn01) .resizable() From 2ee803c717f54ffac531f64cebc841a395a2b019 Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 05:06:45 +0900 Subject: [PATCH 14/25] =?UTF-8?q?chore:=20auth=20=EB=AA=A8=EB=8D=B8=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Source/View/Authentication/Auth.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift index 00c267c9..8fb26bff 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift @@ -7,12 +7,12 @@ import Foundation -struct AuthModel { - let Authorization: String? - let AuthorizationRefresh: String? +struct AuthModel: Codable { + let accessToken: String? + let refreshToken: String? - enum CodingKeys: String, CodingKey { - case Authorization - case AuthorizationRefresh = "Authorization-refresh" - } +// enum CodingKeys: String, CodingKey { +// case Authorization +// case AuthorizationRefresh = "Authorization-refresh" +// } } From fbca176f5ad60aeb964053334e7693231c061651 Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 05:07:31 +0900 Subject: [PATCH 15/25] =?UTF-8?q?feat:=20auth=20request=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RollTheDice/Source/View/Authentication/Auth.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift index 8fb26bff..61d65c61 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/Auth.swift @@ -16,3 +16,8 @@ struct AuthModel: Codable { // case AuthorizationRefresh = "Authorization-refresh" // } } + +struct AuthRequestModel: Codable { + let token: String? + let socialType: String? +} From 6f74dce9b69a8d6ee78cc4bf2c027392d0cd3f6f Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 05:07:56 +0900 Subject: [PATCH 16/25] =?UTF-8?q?chore:=20auth=20request=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Source/Domain/Service/LoginService.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift index 7b1b2ef7..5a82988d 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Domain/Service/LoginService.swift @@ -9,7 +9,7 @@ import Foundation import Moya enum LoginService { - case login(token: String, socialType: String) + case login(request: AuthRequestModel) } //struct LoginService { @@ -36,15 +36,15 @@ extension LoginService: BaseTargetType { } } - var task: Task { + var task: Moya.Task { switch self { - case .login(let token, let socialType): - let parameters : [String : Any] = [ - "token" : token, - "socialType" : socialType, - ] - - return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString) + case .login(let request): +// let parameters : [String : Any] = [ +// "token" : token, +// "socialType" : socialType, +// ] +// return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString) + return .requestJSONEncodable(request) } } From 2e2914d4ee0f1ed3c9aebb0efc9ee10475d79e50 Mon Sep 17 00:00:00 2001 From: realhsb Date: Wed, 19 Jun 2024 05:08:26 +0900 Subject: [PATCH 17/25] =?UTF-8?q?chore:=20auth=20VM=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuthenticationViewModel.swift | 80 ++++++++++++++----- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift index fcec3dc1..89cfa146 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Authentication/AuthenticationViewModel.swift @@ -9,6 +9,8 @@ import Foundation import KakaoSDKAuth import KakaoSDKUser import Moya +import Combine +import CombineMoya enum AuthenticationState { @@ -22,13 +24,24 @@ enum AuthenticationState { var authenticationState: AuthenticationState = .unauthenticated var isLoading = false - let provider = MoyaProvider() + + + var authModel: AuthModel? + var authCancellable: AnyCancellable? + + let provider = MoyaProvider(plugins: [MoyaLoggingPlugin()]) + + func authModelToViewModel(_ list: AuthModel) { + self.authModel = list + } } extension AuthenticationViewModel { func loginWithKakao() { + + print("loginWithKakao") if (UserApi.isKakaoTalkLoginAvailable()) { UserApi.shared.loginWithKakaoTalk { (oauthToken, error) in if let error = error { @@ -44,43 +57,66 @@ extension AuthenticationViewModel { } else { // 사용자 정보 처리 // self.authenticationState = .authenticated - self.loginToBackend(with: oauthToken!.accessToken, socialType: "KAKAO") - + // oauthToken 카카오에서 발급한 accessToken +// self.loginToBackend(with: oauthToken!.accessToken, socialType: "KAKAO") + let authRequest = AuthRequestModel(token: oauthToken!.accessToken, socialType: "KAKAO") + self.loginToBackend(authRequest: authRequest) } } } } } else { // Kakao 계정으로 로그인할 수 없는 경우 처리 - self.authenticationState = .unauthenticated + UserApi.shared.loginWithKakaoAccount { (oauthToken, error) in + if let error = error { + print("Kakao Login Error: \(error)") + self.authenticationState = .unauthenticated + } else if let oauthToken = oauthToken { + print("Kakao Login Success: \(oauthToken)") + self.authenticationState = .authenticated + + let authRequest = AuthRequestModel(token: oauthToken.accessToken, socialType: "KAKAO") + self.loginToBackend(authRequest: authRequest) + + } + } + } } } extension AuthenticationViewModel { - func loginToBackend(with token: String, socialType: String) { - self.provider.request(.login(token: token, socialType: socialType)) { result in + + func loginToBackend(authRequest: AuthRequestModel) { + print("loginToBackend \(authRequest.token)") + + if let cancellable = authCancellable { + cancellable.cancel() + } + + authCancellable = provider.requestWithProgressPublisher( + .login(request: authRequest) + ) + .compactMap { $0.response?.data } + .receive(on: DispatchQueue.main) + .decode(type: AuthModel.self, decoder: JSONDecoder()) + .sink(receiveCompletion: { result in switch result { - case .success(let response): - + case .finished: + print("서버 토큰 발급 연결 성공") - do { - let json = try response.mapJSON() - print("Login response: \(json)") -// self.authenticationState = .completedSignUp - - TokenManager.shared.accessToken = token - - } catch { - print("Login error: \(error)") - self.authenticationState = .unauthenticated - } + // TODO: 여기 지워야 함. 로그인 -> 회원가입 -> 메인 절차 + self.authenticationState = .completedSignUp case .failure(let error): - print("Login error: \(error)") - self.authenticationState = .unauthenticated + Log.network("network error 서버 토큰 발급 연결 실패", error.localizedDescription) } - } + }, receiveValue: { [weak self] response in + self?.authModelToViewModel(response) + print("서버 토큰 : \(response.accessToken)") + + TokenManager.shared.accessToken = response.accessToken + }) } } From ad8fc2dedd45f1f0a26b0f18c4ae0ffb18302c32 Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Wed, 19 Jun 2024 13:13:56 +0900 Subject: [PATCH 18/25] =?UTF-8?q?fix=20&=20feat=20:=20=ED=86=A0=EB=A1=A0?= =?UTF-8?q?=EB=B0=A9=20=EC=83=9D=EC=84=B1=20API=20=EC=97=B0=EB=8F=99=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/.DS_Store | Bin 6148 -> 6148 bytes .../RollTheDice.xcodeproj/project.pbxproj | 32 ++++++++++- .../RollTheDice/RollTheDiceApp.swift | 2 + .../Source/Model/Path/PathType.swift | 2 + .../Debate/ChatList/RecentNewsCardView.swift | 17 +++++- .../Service/CreateDebateRoomService.swift | 50 ++++++++++++++++++ .../ViewModel/CreateDebateRoomViewModel.swift | 45 ++++++++++++++++ 7 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/CreateDebateRoomService.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 0ed7ed287d10ca2ba122648fa0235e0d173b019d..301a5825fd4fa17371c375e78153dfbe265e7e66 100644 GIT binary patch delta 61 zcmZoMXffE}&cw|4(tGkbCcViOOgwDS57Sq<3r;@6WH5ObGS`-g$zZb}^EZ}>4Q!j) IIsWnk0F(0+{r~^~ delta 61 zcmZoMXffE}&cw{j>OT1#liuVCCLT7^784atzR72p3?}bF=Grnb2W%E({>Cz~fo(H8 H$6tN`3K0=M diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 64081947..20e34247 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 350909192C1C1248007D76A1 /* TokenManager.swift */; }; + 3544D7402C228EFC007DBD18 /* CreateDebateRoomService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */; }; + 3544D7432C228F54007DBD18 /* CreateDebateRoomViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */; }; 357666102BBD4BF6002C226A /* ReportListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3576660F2BBD4BF6002C226A /* ReportListView.swift */; }; 357666132BBD54AA002C226A /* SplashView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357666122BBD54AA002C226A /* SplashView.swift */; }; 3576993A2C09C1EB00AD2DA4 /* KakaoSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 357699392C09C1EB00AD2DA4 /* KakaoSDK */; }; @@ -103,6 +105,8 @@ /* Begin PBXFileReference section */ 350909192C1C1248007D76A1 /* TokenManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenManager.swift; sourceTree = ""; }; + 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateDebateRoomService.swift; sourceTree = ""; }; + 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateDebateRoomViewModel.swift; sourceTree = ""; }; 3576660F2BBD4BF6002C226A /* ReportListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportListView.swift; sourceTree = ""; }; 357666122BBD54AA002C226A /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = ""; }; 357699432C09C7B900AD2DA4 /* LoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginService.swift; sourceTree = ""; }; @@ -210,6 +214,22 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 3544D73E2C228EDB007DBD18 /* Service */ = { + isa = PBXGroup; + children = ( + 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */, + ); + path = Service; + sourceTree = ""; + }; + 3544D7412C228F39007DBD18 /* ViewModel */ = { + isa = PBXGroup; + children = ( + 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; 357666112BBD5494002C226A /* Splah */ = { isa = PBXGroup; children = ( @@ -249,6 +269,8 @@ 6C41B8D62BE1048500274FA4 /* ChatList */ = { isa = PBXGroup; children = ( + 3544D7412C228F39007DBD18 /* ViewModel */, + 3544D73E2C228EDB007DBD18 /* Service */, 6C41B8D92BE104A800274FA4 /* RecentNewsCardView.swift */, 6C41B8DB2BE1095800274FA4 /* ChatListView.swift */, ); @@ -750,6 +772,7 @@ 6C7651492BF5FDB900196536 /* WebView.swift in Sources */, 6CDB29FF2BAA08280081037B /* GPTChatListViewModel.swift in Sources */, 6CF130AD2BAB0C4400A437B6 /* AuthenticationViewModel.swift in Sources */, + 3544D7402C228EFC007DBD18 /* CreateDebateRoomService.swift in Sources */, 6CDB29F92BAA07350081037B /* GPTChat.swift in Sources */, 6C41B8DC2BE1095800274FA4 /* ChatListView.swift in Sources */, 6CDB29FD2BAA07FD0081037B /* GPTChatView.swift in Sources */, @@ -763,6 +786,7 @@ 6C76513E2BF37F1E00196536 /* Extension+OSLog.swift in Sources */, 6CC6737C2C21BA5B009FB30E /* Auth.swift in Sources */, 357FC6EA2BCE866B00AD8915 /* DetailCardNews.swift in Sources */, + 3544D7432C228F54007DBD18 /* CreateDebateRoomViewModel.swift in Sources */, 6CC4DDC92B5574670080E7E8 /* ContentView.swift in Sources */, 6C3237A52B7C37D100B699AB /* BookmarkView.swift in Sources */, 6C3237AE2B7C382E00B699AB /* DetailNewsViewModel.swift in Sources */, @@ -932,10 +956,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"RollTheDice/Preview Content\""; - DEVELOPMENT_TEAM = 4YH4UGRTMH; + DEVELOPMENT_TEAM = NTXM48C3F8; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = RollTheDice/Resources/Support/Info.plist; @@ -951,6 +976,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = jinjihan.RollTheDice; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -962,10 +988,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"RollTheDice/Preview Content\""; - DEVELOPMENT_TEAM = 4YH4UGRTMH; + DEVELOPMENT_TEAM = NTXM48C3F8; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = RollTheDice/Resources/Support/Info.plist; @@ -981,6 +1008,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = jinjihan.RollTheDice; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index 17bfa543..3ea1b27f 100644 --- a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift +++ b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift @@ -66,6 +66,8 @@ struct RollTheDiceApp: App { DebateSummaryView() case .webView(let url): WebView(urlToLoad: url) + case .createdebateroom: + GPTChatView() } }) } diff --git a/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift b/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift index 30f880a2..806b0279 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift @@ -20,4 +20,6 @@ enum PathType: Hashable { case mypageView // 마이페이지뷰 case webView(url: String) + + case createdebateroom //토론방 생성 } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift index 9fa0b186..8d5ff093 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift @@ -8,6 +8,10 @@ import SwiftUI struct RecentNewsCardView: View { + @EnvironmentObject var pathModel: PathModel + @StateObject private var viewModel = CreateDebateRoomViewModel() + @State private var topic: String = "" + var body: some View { HStack { titleView @@ -36,7 +40,9 @@ struct RecentNewsCardView: View { } .shadow(color: .basicBlack.opacity(0.1), radius: 2) Button { - + print("버튼 클릭됨 - 주제: \(topic)") + viewModel.createDebate(topic: topic) + pathModel.paths.append(.createdebateroom) } label: { Text("토론 시작하기") .foregroundStyle(.basicWhite) @@ -47,6 +53,15 @@ struct RecentNewsCardView: View { .clipShape(RoundedRectangle(cornerRadius: 16)) } } + + if let debateID = viewModel.debateID { + Text("토론방 ID: \(debateID)") + } + + if let errorMessage = viewModel.errorMessage { + Text("Error: \(errorMessage)") + .foregroundColor(.red) + } } .padding(.horizontal, 20) .padding(.top, 24) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/CreateDebateRoomService.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/CreateDebateRoomService.swift new file mode 100644 index 00000000..bd80ce2f --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/CreateDebateRoomService.swift @@ -0,0 +1,50 @@ +// +// CreateDebateRoomService.swift +// RollTheDice +// +// Created by 신예진 on 6/19/24. +// + +import Foundation +import Moya + +enum CreateDebateRoomService { + case createDebate(topic: String) +} + +extension CreateDebateRoomService: TargetType { + var baseURL: URL { + return URL(string: "http://roll-the-dice.store:8080")! + } + + var path: String { + switch self { + case .createDebate: + return "/debates" + } + } + + var method: Moya.Method { + switch self { + case .createDebate: + return .post + } + } + + var task: Task { + switch self { + case .createDebate(let topic): + let parameters: [String: Any] = ["topic": topic] + return .requestParameters(parameters: parameters, encoding: JSONEncoding.default) + } + } + + var headers: [String: String]? { + guard let token = TokenManager.shared.accessToken else { return nil } + return ["Authorization": "Bearer \(token)"] + } + + var sampleData: Data { + return Data() + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift new file mode 100644 index 00000000..3b6cfc9b --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift @@ -0,0 +1,45 @@ +// +// CreateDebateRoomViewModel.swift +// RollTheDice +// +// Created by 신예진 on 6/19/24. +// + +import Foundation +import Moya +import Combine + +class CreateDebateRoomViewModel: ObservableObject { + private let provider = MoyaProvider() + @Published var debateID: Int? + @Published var errorMessage: String? + + func createDebate(topic: String) { + print("API 호출 시작 - 토론 주제: \(topic)") + provider.request(.createDebate(topic: topic)) { result in + switch result { + case .success(let response): + print("API 호출 성공 - 응답 코드: \(response.statusCode)") + do { + let json = try JSONSerialization.jsonObject(with: response.data, options: []) as? [String: Any] + if let id = json?["id"] as? Int { + DispatchQueue.main.async { + self.debateID = id + print("토론방 생성 성공 - ID: \(id)") + } + } + } catch { + DispatchQueue.main.async { + self.errorMessage = "Failed to parse response" + print("응답 파싱 중 에러: \(error.localizedDescription)") + } + } + case .failure(let error): + DispatchQueue.main.async { + self.errorMessage = error.localizedDescription + print("API 호출 실패 - 에러: \(error.localizedDescription)") + } + } + } + } +} From 8bec2ded8dd22d378f5871e934f13fc02dea5353 Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Wed, 19 Jun 2024 13:32:31 +0900 Subject: [PATCH 19/25] =?UTF-8?q?fix=20&=20feat=20:=20ChatGPT=EC=99=80?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=EA=B0=84=EC=9D=98=20=ED=86=A0=EB=A1=A0=20API?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/.DS_Store | Bin 6148 -> 6148 bytes .../RollTheDice.xcodeproj/project.pbxproj | 12 ++++ .../Debate/ChatGPT/GPTChatListViewModel.swift | 55 +++++++++++++++--- .../View/Debate/ChatGPT/GPTChatView.swift | 2 +- .../Debate/ChatGPT/Service/ChatService.swift | 45 ++++++++++++++ 5 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/ChatService.swift diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 301a5825fd4fa17371c375e78153dfbe265e7e66..3e52fcdbeeb138923b6e9766c2a4f1e021649a7e 100644 GIT binary patch delta 58 zcmZoMXffE}&cw{b+dcUlliuVCCLY$@9Ib4x$)}kNC+|Yy*)t|=7G(a$GO>YeGdss$ FegGRW614yT delta 58 zcmZoMXffE}&cw|4(tGkbCcViOOgya757Sqvmo;~mWd5)o7p-3 G@&f>9gA~{R diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 20e34247..9d4f2cfb 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 350909192C1C1248007D76A1 /* TokenManager.swift */; }; 3544D7402C228EFC007DBD18 /* CreateDebateRoomService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */; }; 3544D7432C228F54007DBD18 /* CreateDebateRoomViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */; }; + 3544D7462C229436007DBD18 /* ChatService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3544D7452C229436007DBD18 /* ChatService.swift */; }; 357666102BBD4BF6002C226A /* ReportListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3576660F2BBD4BF6002C226A /* ReportListView.swift */; }; 357666132BBD54AA002C226A /* SplashView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357666122BBD54AA002C226A /* SplashView.swift */; }; 3576993A2C09C1EB00AD2DA4 /* KakaoSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 357699392C09C1EB00AD2DA4 /* KakaoSDK */; }; @@ -107,6 +108,7 @@ 350909192C1C1248007D76A1 /* TokenManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenManager.swift; sourceTree = ""; }; 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateDebateRoomService.swift; sourceTree = ""; }; 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateDebateRoomViewModel.swift; sourceTree = ""; }; + 3544D7452C229436007DBD18 /* ChatService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatService.swift; sourceTree = ""; }; 3576660F2BBD4BF6002C226A /* ReportListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportListView.swift; sourceTree = ""; }; 357666122BBD54AA002C226A /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = ""; }; 357699432C09C7B900AD2DA4 /* LoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginService.swift; sourceTree = ""; }; @@ -230,6 +232,14 @@ path = ViewModel; sourceTree = ""; }; + 3544D7442C229428007DBD18 /* Service */ = { + isa = PBXGroup; + children = ( + 3544D7452C229436007DBD18 /* ChatService.swift */, + ); + path = Service; + sourceTree = ""; + }; 357666112BBD5494002C226A /* Splah */ = { isa = PBXGroup; children = ( @@ -532,6 +542,7 @@ 6CDB29F72BAA06FB0081037B /* ChatGPT */ = { isa = PBXGroup; children = ( + 3544D7442C229428007DBD18 /* Service */, 6CDB29F82BAA07350081037B /* GPTChat.swift */, 6CDB29FA2BAA07B10081037B /* GPTChatViewModel.swift */, 6CDB29FC2BAA07FD0081037B /* GPTChatView.swift */, @@ -760,6 +771,7 @@ 6C454A882B9DB6C2006FD9D0 /* CustomNavigationBar.swift in Sources */, 6CF130BF2BAB783300A437B6 /* APIConstants.swift in Sources */, 357699442C09C7B900AD2DA4 /* LoginService.swift in Sources */, + 3544D7462C229436007DBD18 /* ChatService.swift in Sources */, 6C76513C2BF37ED300196536 /* Extension+Log.swift in Sources */, 6CE103102BD56A5B00498AA4 /* TypeReportViewModel.swift in Sources */, 6C5B0C8A2C1C308A00A0D5F4 /* ScoopAPIBookmarks.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift index db009df2..7d94565e 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift @@ -7,20 +7,29 @@ import Foundation import OpenAI +import Combine +import Moya class GPTChatListViewModel: ObservableObject { @Published var chatList: [GPTChat] + private var cancellables = Set() + private let provider = MoyaProvider() - // TODO: Token Hidden - /// token 추가해야 함 - let openAI = OpenAI(apiToken: "") + // OpenAI API 토큰 관리 + private let openAI: OpenAI + +// // TODO: Token Hidden +// /// token 추가해야 함 +// let openAI = OpenAI(apiToken: "") init( chatList: [GPTChat] = [ - .init(title: "111111111", messages: []), - ] + .init(title: "토론제목", messages: []), + ], + apiToken: String = "" // TokenManager를 통해 API 토큰을 관리 ) { self.chatList = chatList + self.openAI = OpenAI(apiToken: apiToken) } } @@ -38,12 +47,40 @@ extension GPTChatListViewModel { func getBotReply(index: Int) { print("call getBotReply func") + let messages = self.chatList[index].messages.map { + Chat(role: $0.isUser ? .user : .system, content: $0.content) + } + + // openAI.chats( + // query: .init( + // model: .gpt3_5Turbo, + // messages: self.chatList[index].messages.map( + // {Chat(role: .user, content: $0.content)})) + // ) { result in + // switch result { + // case .success(let success): + // guard let choice = success.choices.first else { + // return + // } + // let message = choice.message.content + // + // DispatchQueue.main.async { + // self.chatList[index].messages.append(.init(content: message ?? "Error", isUser: false)) + // print("gpt msg: \(self.chatList[index].messages[1])") + // } + // + // case .failure(let failure): + // print(failure) + // } + // } openAI.chats( query: .init( model: .gpt3_5Turbo, - messages: self.chatList[index].messages.map( - {Chat(role: .user, content: $0.content)})) - ) { result in + messages: messages + ) + ) { [weak self] result in + guard let self = self else { return } + switch result { case .success(let success): guard let choice = success.choices.first else { @@ -53,7 +90,7 @@ extension GPTChatListViewModel { DispatchQueue.main.async { self.chatList[index].messages.append(.init(content: message ?? "Error", isUser: false)) - print("gpt msg: \(self.chatList[index].messages[1])") + print("gpt msg: \(self.chatList[index].messages.last?.content ?? "Error")") } case .failure(let failure): diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift index 4fd938b0..b2ecf127 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift @@ -11,7 +11,7 @@ struct GPTChatView: View { @EnvironmentObject var pathModel: PathModel @StateObject var chatListViewModel = GPTChatListViewModel() - @State var selectedChat: GPTChat? = .init(title: "hi", messages: [.init(content: "안녕하세요", isUser: false)]) + @State var selectedChat: GPTChat? = .init(title: "토론제목입니다", messages: [.init(content: "ChatGPT와의 토론!", isUser: false)]) var body: some View { ZStack { diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/ChatService.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/ChatService.swift new file mode 100644 index 00000000..2b14f250 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/ChatService.swift @@ -0,0 +1,45 @@ +// +// ChatService.swift +// RollTheDice +// +// Created by 신예진 on 6/19/24. +// + +import Foundation +import Moya + +enum ChatService { + case sendMessageToAI(roomId: Int, message: String) + case sendMessageToHuman(roomId: Int, message: String) +} + +extension ChatService: TargetType { + var baseURL: URL { + return URL(string: "http://roll-the-dice.store:8080")! + } + + var path: String { + switch self { + case .sendMessageToAI(let roomId, _): + return "/debates/\(roomId)/ai" + case .sendMessageToHuman(let roomId, _): + return "/debates/\(roomId)/human" + } + } + + var method: Moya.Method { + return .post + } + + var task: Task { + switch self { + case .sendMessageToAI(_, let message), .sendMessageToHuman(_, let message): + return .requestParameters(parameters: ["message": message], encoding: JSONEncoding.default) + } + } + + var headers: [String: String]? { + guard let token = TokenManager.shared.accessToken else { return nil } + return ["Authorization": "Bearer \(token)"] + } +} From fb88f3219d76ebb57bde23aeb5830bc6cfefdbca Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Wed, 19 Jun 2024 16:22:58 +0900 Subject: [PATCH 20/25] =?UTF-8?q?feat=20:=20=EC=B5=9C=EA=B7=BC=20=EB=B3=B8?= =?UTF-8?q?=20=EB=89=B4=EC=8A=A4=20API=20=EC=97=B0=EB=8F=99=ED=95=98?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Source/View/Debate/ChatList/Model/News.swift | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Model/News.swift diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Model/News.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Model/News.swift new file mode 100644 index 00000000..aa9f64f6 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Model/News.swift @@ -0,0 +1,8 @@ +// +// News.swift +// RollTheDice +// +// Created by 신예진 on 6/19/24. +// + +import Foundation From 330776f901e4ec80e4897cf7c2bbe206712ec1dc Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Wed, 19 Jun 2024 19:10:06 +0900 Subject: [PATCH 21/25] =?UTF-8?q?feat=20:=20=EC=B5=9C=EA=B7=BC=20=EC=9D=BD?= =?UTF-8?q?=EC=9D=80=20=EB=89=B4=EC=8A=A4=20=EC=A1=B0=ED=9A=8C=20API=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/.DS_Store | Bin 6148 -> 6148 bytes .../RollTheDice.xcodeproj/project.pbxproj | 20 +++ .../View/Debate/ChatList/ChatListView.swift | 30 +++- .../Debate/ChatList/RecentNewsCardView.swift | 130 +++++++++++++++--- .../ChatList/RecentNewsModel/News.swift | 14 ++ .../ChatList/Service/RecentNewsService.swift | 49 +++++++ .../ViewModel/RecentNewsViewModel.swift | 38 +++++ 7 files changed, 257 insertions(+), 24 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsModel/News.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/RecentNewsService.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/RecentNewsViewModel.swift diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 3e52fcdbeeb138923b6e9766c2a4f1e021649a7e..4e131fbb4e9617b0fc37a7d0b96e248999f2f84b 100644 GIT binary patch delta 57 zcmZoMXffE}!NjybZ}K@Ny~!0!JghIzetw!i`81Q^YeGdss$ FegGyk614yT diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 9d4f2cfb..dfd76995 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -20,6 +20,9 @@ 357699422C09C1EB00AD2DA4 /* KakaoSDKCommon in Frameworks */ = {isa = PBXBuildFile; productRef = 357699412C09C1EB00AD2DA4 /* KakaoSDKCommon */; }; 357699442C09C7B900AD2DA4 /* LoginService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357699432C09C7B900AD2DA4 /* LoginService.swift */; }; 357FC6EA2BCE866B00AD8915 /* DetailCardNews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */; }; + 3586B53C2C22DF41006B1458 /* News.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53B2C22DF41006B1458 /* News.swift */; }; + 3586B53E2C22DF67006B1458 /* RecentNewsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53D2C22DF67006B1458 /* RecentNewsService.swift */; }; + 3586B5402C22DFCB006B1458 /* RecentNewsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */; }; 35C71BF22B79F39900F777D1 /* ExyteChat in Frameworks */ = {isa = PBXBuildFile; productRef = 35C71BF12B79F39900F777D1 /* ExyteChat */; }; 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C32379E2B7C376D00B699AB /* Bookmarks.swift */; }; 6C3237A12B7C377600B699AB /* BookmarkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */; }; @@ -113,6 +116,9 @@ 357666122BBD54AA002C226A /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = ""; }; 357699432C09C7B900AD2DA4 /* LoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginService.swift; sourceTree = ""; }; 357FC6E92BCE866B00AD8915 /* DetailCardNews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailCardNews.swift; sourceTree = ""; }; + 3586B53B2C22DF41006B1458 /* News.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = News.swift; sourceTree = ""; }; + 3586B53D2C22DF67006B1458 /* RecentNewsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentNewsService.swift; sourceTree = ""; }; + 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentNewsViewModel.swift; sourceTree = ""; }; 6C32379E2B7C376D00B699AB /* Bookmarks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bookmarks.swift; sourceTree = ""; }; 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkViewModel.swift; sourceTree = ""; }; 6C3237A42B7C37D100B699AB /* BookmarkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkView.swift; sourceTree = ""; }; @@ -220,6 +226,7 @@ isa = PBXGroup; children = ( 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */, + 3586B53D2C22DF67006B1458 /* RecentNewsService.swift */, ); path = Service; sourceTree = ""; @@ -228,6 +235,7 @@ isa = PBXGroup; children = ( 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */, + 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */, ); path = ViewModel; sourceTree = ""; @@ -248,6 +256,14 @@ path = Splah; sourceTree = ""; }; + 3586B5392C22DF03006B1458 /* RecentNewsModel */ = { + isa = PBXGroup; + children = ( + 3586B53B2C22DF41006B1458 /* News.swift */, + ); + path = RecentNewsModel; + sourceTree = ""; + }; 6C32379D2B7C374E00B699AB /* BookmarkCard */ = { isa = PBXGroup; children = ( @@ -279,6 +295,7 @@ 6C41B8D62BE1048500274FA4 /* ChatList */ = { isa = PBXGroup; children = ( + 3586B5392C22DF03006B1458 /* RecentNewsModel */, 3544D7412C228F39007DBD18 /* ViewModel */, 3544D73E2C228EDB007DBD18 /* Service */, 6C41B8D92BE104A800274FA4 /* RecentNewsCardView.swift */, @@ -785,6 +802,7 @@ 6CDB29FF2BAA08280081037B /* GPTChatListViewModel.swift in Sources */, 6CF130AD2BAB0C4400A437B6 /* AuthenticationViewModel.swift in Sources */, 3544D7402C228EFC007DBD18 /* CreateDebateRoomService.swift in Sources */, + 3586B53E2C22DF67006B1458 /* RecentNewsService.swift in Sources */, 6CDB29F92BAA07350081037B /* GPTChat.swift in Sources */, 6C41B8DC2BE1095800274FA4 /* ChatListView.swift in Sources */, 6CDB29FD2BAA07FD0081037B /* GPTChatView.swift in Sources */, @@ -801,6 +819,7 @@ 3544D7432C228F54007DBD18 /* CreateDebateRoomViewModel.swift in Sources */, 6CC4DDC92B5574670080E7E8 /* ContentView.swift in Sources */, 6C3237A52B7C37D100B699AB /* BookmarkView.swift in Sources */, + 3586B53C2C22DF41006B1458 /* News.swift in Sources */, 6C3237AE2B7C382E00B699AB /* DetailNewsViewModel.swift in Sources */, 6C77048F2B7229B1001B17CB /* NewsListView.swift in Sources */, 357666132BBD54AA002C226A /* SplashView.swift in Sources */, @@ -829,6 +848,7 @@ 6C77048C2B722686001B17CB /* MainTabView.swift in Sources */, 6C7704992B722A20001B17CB /* MainTabViewModel.swift in Sources */, 6C454A7C2B9DA71C006FD9D0 /* SignUpView.swift in Sources */, + 3586B5402C22DFCB006B1458 /* RecentNewsViewModel.swift in Sources */, 6C41B8DA2BE104A800274FA4 /* RecentNewsCardView.swift in Sources */, 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */, 6CF130C72BAB7B9800A437B6 /* ScoopAPINews.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift index 67ed690b..98da2c9d 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift @@ -10,7 +10,8 @@ import SwiftUI struct ChatListView: View { @EnvironmentObject var pathModel: PathModel - + @StateObject private var newsViewModel = RecentNewsViewModel() + var body: some View { ZStack { Color.backgroundDark.ignoresSafeArea(.all) @@ -31,13 +32,28 @@ struct ChatListView: View { Text("최근 본 뉴스") .foregroundStyle(.basicWhite) .font(.pretendardBold32) +// HStack { +// RecentNewsCardView() +// Spacer() +// RecentNewsCardView() +// Spacer() +// RecentNewsCardView() +// } HStack { - RecentNewsCardView() - Spacer() - RecentNewsCardView() - Spacer() - RecentNewsCardView() - } + if newsViewModel.news.isEmpty { + Text("최근 읽은 뉴스를 불러오는 중...") + .onAppear { + print("뷰가 나타남 - 최근 읽은 뉴스 조회 시작") + newsViewModel.fetchViewedHistory() + } + } else { + ForEach(newsViewModel.news.prefix(3), id: \.id) { news in + RecentNewsCardView(news: news) + Spacer() + } + } + } + .padding() } } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift index 8d5ff093..6af4af87 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift @@ -5,27 +5,124 @@ // Created by Subeen on 4/30/24. // +//import SwiftUI +// +//struct RecentNewsCardView: View { +// @EnvironmentObject var pathModel: PathModel +// @StateObject private var viewModel = CreateDebateRoomViewModel() +// @StateObject private var newsviewModel = RecentNewsViewModel() +// @State private var topic: String = "" +// +// var body: some View { +// HStack { +// titleView +// } +//// .frame(width: 260, height: 244) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } +// +// var titleView: some View { +// ZStack { +// VStack(alignment: .center, spacing: 20) { +// Text("📌") +// .font(.title) +// Text("내 안경 못 봤어?\" 핸드폰이 알려준다…구글 \'일상 AI\' 공략 [팩플]") +// .multilineTextAlignment(.center) +// .foregroundStyle(.gray07) +// .font(.pretendardBold24) +// .frame(width: 240, height: 96) +// .padding(.horizontal, 10) +// .padding(.vertical, 30) +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 2)) +// .overlay { +// RoundedRectangle(cornerRadius: 2) +// .stroke(Color.gray05, lineWidth: 1.0) +// } +// .shadow(color: .basicBlack.opacity(0.1), radius: 2) +// Button { +// print("버튼 클릭됨 - 주제: \(topic)") +// viewModel.createDebate(topic: topic) +// pathModel.paths.append(.createdebateroom) +// } label: { +// Text("토론 시작하기") +// .foregroundStyle(.basicWhite) +// .font(.pretendardRegular14) +// .padding(.horizontal, 38) +// .padding(.vertical, 10) +// .background(.primary01) +// .clipShape(RoundedRectangle(cornerRadius: 16)) +// } +// } +// +// if let debateID = viewModel.debateID { +// Text("토론방 ID: \(debateID)") +// } +// +// if let errorMessage = viewModel.errorMessage { +// Text("Error: \(errorMessage)") +// .foregroundColor(.red) +// } +// } +// .padding(.horizontal, 20) +// .padding(.top, 24) +// .padding(.bottom, 32) +// .background(.gray02) +// } +//} +// +//#Preview { +// RecentNewsCardView() +//} + +// +// RecentNewsCardView.swift +// RollTheDice +// +// Created by Subeen on 4/30/24. +// + import SwiftUI +import Combine struct RecentNewsCardView: View { + let news: News @EnvironmentObject var pathModel: PathModel - @StateObject private var viewModel = CreateDebateRoomViewModel() +// @StateObject private var newsViewModel = RecentNewsViewModel() + @StateObject private var debateRoomViewModel = CreateDebateRoomViewModel() @State private var topic: String = "" - var body: some View { - HStack { - titleView - } -// .frame(width: 260, height: 244) - .clipShape(RoundedRectangle(cornerRadius: 8)) - } +// var body: some View { +// VStack { +// if let news = newsViewModel.news.first { +// HStack { +// titleView(news: news) +// } +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } else { +// Text("최근 읽은 뉴스를 불러오는 중...") +// .onAppear { +// print("뷰가 나타남 - 최근 읽은 뉴스 조회 시작") +// newsViewModel.fetchViewedHistory() +// } +// } +// } +// } +// + var body: some View { + HStack { + titleView + } + .clipShape(RoundedRectangle(cornerRadius: 8)) + } + - var titleView: some View { + var titleView : some View { ZStack { VStack(alignment: .center, spacing: 20) { Text("📌") .font(.title) - Text("내 안경 못 봤어?\" 핸드폰이 알려준다…구글 \'일상 AI\' 공략 [팩플]") + Text(news.title) .multilineTextAlignment(.center) .foregroundStyle(.gray07) .font(.pretendardBold24) @@ -40,8 +137,9 @@ struct RecentNewsCardView: View { } .shadow(color: .basicBlack.opacity(0.1), radius: 2) Button { - print("버튼 클릭됨 - 주제: \(topic)") - viewModel.createDebate(topic: topic) + print("버튼 클릭됨 - 주제: \(news.title)") + topic = news.title + debateRoomViewModel.createDebate(topic: topic) pathModel.paths.append(.createdebateroom) } label: { Text("토론 시작하기") @@ -54,11 +152,11 @@ struct RecentNewsCardView: View { } } - if let debateID = viewModel.debateID { + if let debateID = debateRoomViewModel.debateID { Text("토론방 ID: \(debateID)") } - if let errorMessage = viewModel.errorMessage { + if let errorMessage = debateRoomViewModel.errorMessage { Text("Error: \(errorMessage)") .foregroundColor(.red) } @@ -70,6 +168,4 @@ struct RecentNewsCardView: View { } } -#Preview { - RecentNewsCardView() -} + diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsModel/News.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsModel/News.swift new file mode 100644 index 00000000..6a24e219 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsModel/News.swift @@ -0,0 +1,14 @@ +// +// News.swift +// RollTheDice +// +// Created by 신예진 on 6/19/24. +// + +import Foundation + +//MARK : 최근 읽은 뉴스 Model +struct News: Identifiable, Codable { + let id: Int + let title: String +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/RecentNewsService.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/RecentNewsService.swift new file mode 100644 index 00000000..f2fed705 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/RecentNewsService.swift @@ -0,0 +1,49 @@ +// +// RecentNewsService.swift +// RollTheDice +// +// Created by 신예진 on 6/19/24. +// + +import Foundation +import Moya + +//MARK : 최근읽은 뉴스 관련 Service +enum RecentNewsService { + case getViewedHistory +} + +extension RecentNewsService: TargetType { + var baseURL: URL { + return URL(string: "http://roll-the-dice.store:8080")! + } + + var path: String { + switch self { + case .getViewedHistory: + return "/news/viewed-history" + } + } + + var method: Moya.Method { + switch self { + case .getViewedHistory: + return .get + } + } + + var task: Task { + return .requestPlain + } + + var headers: [String : String]? { + guard let token = TokenManager.shared.accessToken else { + return nil + } + return ["Authorization": "Bearer \(token)"] + } + + var sampleData: Data { + return Data() + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/RecentNewsViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/RecentNewsViewModel.swift new file mode 100644 index 00000000..0f10153e --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/RecentNewsViewModel.swift @@ -0,0 +1,38 @@ +// +// RecentNewsViewModel.swift +// RollTheDice +// +// Created by 신예진 on 6/19/24. +// + +import Foundation +import Combine +import Moya +import Combine + +class RecentNewsViewModel: ObservableObject { + @Published var news: [News] = [] + private var cancellables = Set() + private let provider = MoyaProvider() + + func fetchViewedHistory() { + print("최근 읽은 뉴스 조회 요청 시작") + provider.requestPublisher(.getViewedHistory) + .map([News].self) + .receive(on: DispatchQueue.main) + .sink(receiveCompletion: { completion in + switch completion { + case .failure(let error): + print("최근 읽은 뉴스 조회 실패 - 에러: \(error)") + case .finished: + print("최근 읽은 뉴스 조회 완료") + } + }, receiveValue: { [weak self] news in + self?.news = news + for item in news { + print("최근 읽은 뉴스 조회 성공 - 뉴스 id: \(item.id), 뉴스 제목: \(item.title)") + } + }) + .store(in: &cancellables) + } +} From f69c2b5962bb79c3ef325ad2bfcd686cc05592cb Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Wed, 19 Jun 2024 20:28:15 +0900 Subject: [PATCH 22/25] =?UTF-8?q?fix=20:=20ChatGPT=EA=B0=80=20=EC=B1=84?= =?UTF-8?q?=ED=8C=85=20=EC=8B=9C=EC=9E=91=ED=95=98=EB=8A=94=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/.DS_Store | Bin 6148 -> 6148 bytes .../RollTheDice/RollTheDiceApp.swift | 4 +- .../Source/View/Debate/ChatGPT/GPTChat.swift | 3 +- .../Debate/ChatGPT/GPTChatListViewModel.swift | 147 +++++++++++++----- .../View/Debate/ChatGPT/GPTChatView.swift | 140 ++++++++++++++++- .../Debate/ChatList/RecentNewsCardView.swift | 8 +- .../ViewModel/CreateDebateRoomViewModel.swift | 6 +- 7 files changed, 259 insertions(+), 49 deletions(-) diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 4e131fbb4e9617b0fc37a7d0b96e248999f2f84b..87ed28ab873c1c074a10d71527c4db1760a32cc6 100644 GIT binary patch delta 18 ZcmZoMXffE}$;9|`@;N5G%@s^Nq5wi02E70P delta 18 ZcmZoMXffE}$;6m9`5cqp<_e}BQ2;!x1~LEu diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index 3ea1b27f..eb3444a7 100644 --- a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift +++ b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift @@ -46,7 +46,7 @@ struct RollTheDiceApp: App { // 각 뷰마다 .navigationBarBackButtonHidden() 설정하기! switch pathType { case .chatView(isAiMode: true) : - GPTChatView() + GPTChatView(topic: "") .navigationBarBackButtonHidden() case .chatView(isAiMode: false): @@ -67,7 +67,7 @@ struct RollTheDiceApp: App { case .webView(let url): WebView(urlToLoad: url) case .createdebateroom: - GPTChatView() + GPTChatView(topic: "") } }) } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChat.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChat.swift index 8112a66b..7e06327d 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChat.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChat.swift @@ -8,9 +8,10 @@ import Foundation -struct GPTChat: Hashable { +struct GPTChat: Hashable, Identifiable{ var title: String var messages: [Message] + var id: UUID = .init() // id 속성 추가 init( title: String = "", diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift index 7d94565e..e9e85638 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift @@ -10,31 +10,124 @@ import OpenAI import Combine import Moya +//class GPTChatListViewModel: ObservableObject { +// @Published var chatList: [GPTChat] +// private var cancellables = Set() +// private let provider = MoyaProvider() +// +// // OpenAI API 토큰 관리 +// private let openAI: OpenAI +// +//// // TODO: Token Hidden +//// /// token 추가해야 함 +//// let openAI = OpenAI(apiToken: "") +// +// init( +// topic: String, +// chatList: [GPTChat] = [], +//// .init(title: "토론제목", messages: []), +//// ], +// apiToken: String = "" // 깃허브 보안 이슈상으로 제거 +// ) { +//// self.chatList = chatList +// self.chatList = chatList.isEmpty ? [GPTChat(title: topic, messages: [])] : chatList +// self.openAI = OpenAI(apiToken: apiToken) +// } +//} +// +//extension GPTChatListViewModel { +// /// OpenAI +// func sendNewMessage(index: Int, content: String) { +// print("call sendNewMessage func") +// +// let userMessage = Message(content: content, isUser: true) +// self.chatList[index].messages.append(userMessage) +// +// getBotReply(index: index) +// } +// +// func getBotReply(index: Int) { +// print("call getBotReply func") +// +// let messages = self.chatList[index].messages.map { +// Chat(role: $0.isUser ? .user : .system, content: $0.content) +// } +// +// // openAI.chats( +// // query: .init( +// // model: .gpt3_5Turbo, +// // messages: self.chatList[index].messages.map( +// // {Chat(role: .user, content: $0.content)})) +// // ) { result in +// // switch result { +// // case .success(let success): +// // guard let choice = success.choices.first else { +// // return +// // } +// // let message = choice.message.content +// // +// // DispatchQueue.main.async { +// // self.chatList[index].messages.append(.init(content: message ?? "Error", isUser: false)) +// // print("gpt msg: \(self.chatList[index].messages[1])") +// // } +// // +// // case .failure(let failure): +// // print(failure) +// // } +// // } +// openAI.chats( +// query: .init( +// model: .gpt3_5Turbo, +// messages: messages +// ) +// ) { [weak self] result in +// guard let self = self else { return } +// +// switch result { +// case .success(let success): +// guard let choice = success.choices.first else { +// return +// } +// let message = choice.message.content +// +// DispatchQueue.main.async { +// self.chatList[index].messages.append(.init(content: message ?? "Error", isUser: false)) +// print("gpt msg: \(self.chatList[index].messages.last?.content ?? "Error")") +// } +// +// case .failure(let failure): +// print(failure) +// } +// } +// } +//} + class GPTChatListViewModel: ObservableObject { @Published var chatList: [GPTChat] private var cancellables = Set() - private let provider = MoyaProvider() - - // OpenAI API 토큰 관리 - private let openAI: OpenAI - -// // TODO: Token Hidden -// /// token 추가해야 함 -// let openAI = OpenAI(apiToken: "") + private let provider = MoyaProvider() + private let debateprovider = MoyaProvider() + private let openAI: OpenAI + @Published var topic: String = "" init( - chatList: [GPTChat] = [ - .init(title: "토론제목", messages: []), - ], - apiToken: String = "" // TokenManager를 통해 API 토큰을 관리 + topic: String, + chatList: [GPTChat] = [], + apiToken: String = "" ) { - self.chatList = chatList + self.chatList = chatList.isEmpty ? [GPTChat(title: topic, messages: [])] : chatList self.openAI = OpenAI(apiToken: apiToken) + + // CreateDebateRoomService를 통해 주제를 받아와 초기 메시지를 설정 + CreateDebateRoomViewModel().createDebate(topic: topic) { debateTopic in + let initialMessage = Message(content: "안녕하세요! 오늘의 토론 주제는 '\(debateTopic)'입니다. 이 주제에 대해 어떻게 생각하시나요?", isUser: false) + DispatchQueue.main.async { + self.chatList[0].messages.append(initialMessage) + } + } } -} -extension GPTChatListViewModel { - /// OpenAI + func sendNewMessage(index: Int, content: String) { print("call sendNewMessage func") @@ -51,28 +144,6 @@ extension GPTChatListViewModel { Chat(role: $0.isUser ? .user : .system, content: $0.content) } - // openAI.chats( - // query: .init( - // model: .gpt3_5Turbo, - // messages: self.chatList[index].messages.map( - // {Chat(role: .user, content: $0.content)})) - // ) { result in - // switch result { - // case .success(let success): - // guard let choice = success.choices.first else { - // return - // } - // let message = choice.message.content - // - // DispatchQueue.main.async { - // self.chatList[index].messages.append(.init(content: message ?? "Error", isUser: false)) - // print("gpt msg: \(self.chatList[index].messages[1])") - // } - // - // case .failure(let failure): - // print(failure) - // } - // } openAI.chats( query: .init( model: .gpt3_5Turbo, diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift index b2ecf127..b52ffa1a 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift @@ -10,8 +10,16 @@ import SwiftUI struct GPTChatView: View { @EnvironmentObject var pathModel: PathModel - @StateObject var chatListViewModel = GPTChatListViewModel() - @State var selectedChat: GPTChat? = .init(title: "토론제목입니다", messages: [.init(content: "ChatGPT와의 토론!", isUser: false)]) +// @State var selectedChat: GPTChat? = .init(title: "토론제목입니다", messages: [.init(content: "ChatGPT와의 토론!", isUser: false)]) + @State var selectedChat: GPTChat? + @StateObject var chatListViewModel = GPTChatListViewModel(topic: "토론") + @StateObject var createDebateRoomViewModel = CreateDebateRoomViewModel() + + + init(topic: String) { + _chatListViewModel = StateObject(wrappedValue: GPTChatListViewModel(topic: topic)) + _selectedChat = State(initialValue: GPTChat(title: topic, messages: [.init(content: "\(createDebateRoomViewModel.topic) ChatGPT와의 토론!", isUser: false)])) + } var body: some View { ZStack { @@ -130,6 +138,128 @@ struct GPTChatView: View { -#Preview { - GPTChatView() -} +//#Preview { +// GPTChatView() +//} + +//struct GPTChatView: View { +// +// @EnvironmentObject var pathModel: PathModel +// @State var selectedChat: GPTChat? +// @StateObject var chatListViewModel: GPTChatListViewModel +// @StateObject var createDebateRoomViewModel = CreateDebateRoomViewModel() +// +// init(topic: String) { +// _chatListViewModel = StateObject(wrappedValue: GPTChatListViewModel(topic: topic)) +// _selectedChat = State(initialValue: GPTChat(title: topic, messages: [.init(content: "\(topic)ChatGPT와의 토론!", isUser: false)])) +// } +// +// var body: some View { +// ZStack { +// Color.backgroundDark.ignoresSafeArea(.all) +// VStack { +// CustomNavigationBar(title: selectedChat?.title ?? "", isDisplayLeadingBtn: true, leadingItems: [(Image(.chevronLeft), {pathModel.paths.popLast()})]) +// MessageTitleView(chatListViewModel: chatListViewModel, selectedChat: $selectedChat) +// } +// } +// } +// +// private struct MessageTitleView: View { +// @ObservedObject var chatListViewModel: GPTChatListViewModel +// @Binding var selectedChat: GPTChat? +// @State var string: String = "" +// @State var index: Int? = 0 +// +// fileprivate var body: some View { +// if chatListViewModel.chatList.isEmpty { +// // TODO: 채팅방 생성 뷰 +// } else { +// HStack { +// ScrollView { +// ForEach(chatListViewModel.chatList.indices, id: \.self) { index in +// Button { +// selectedChat = chatListViewModel.chatList[index] +// } label: { +// TitleCellView(title: chatListViewModel.chatList[index].title) +// } +// } +// } +// if selectedChat != nil { +// VStack { +// ScrollView { +// ForEach(selectedChat?.messages ?? []) { message in +// MessageCellView(message: message) +// } +// } +// Divider() +// +// HStack { +// TextField("Message...", text: $string, axis: .vertical) +// .padding(5) +// .background(Color.gray.opacity(0.1)) +// .foregroundStyle(.basicWhite) +// .cornerRadius(15) +// Button { +// if let index = chatListViewModel.chatList.firstIndex(where: { $0.id == selectedChat?.id }) { +// chatListViewModel.sendNewMessage(index: index, content: string) +// string = "" +// print("왜 채팅하기 버튼 안 눌려?") +// } +// } label: { +// Image(systemName: "paperplane") +// } +// } +// .padding() +// } +// } else { +// // TODO: 채팅방 선택 유도 뷰 +// Spacer() +// } +// } +// } +// } +// } +// +// private struct TitleCellView: View { +// var title: String +// fileprivate var body: some View { +// HStack { +// Text(title) +// .multilineTextAlignment(.leading) +// .padding(.horizontal) +// .background(Color.basicBlack) +// .foregroundStyle(.basicWhite) +// .clipShape(RoundedRectangle(cornerRadius: 15)) +// } +// } +// } +// +// private struct MessageCellView: View { +// var message: Message +// +// fileprivate var body: some View { +// Group { +// if message.isUser { +// HStack { +// Spacer() +// Text(message.content) +// .multilineTextAlignment(.leading) +// .padding() +// .background(Color.blue) +// .foregroundStyle(.white) +// .clipShape(RoundedRectangle(cornerRadius: 15)) +// } +// } else { +// HStack { +// Text(message.content) +// .padding() +// .background(Color.orange) +// .foregroundStyle(.white) +// .clipShape(RoundedRectangle(cornerRadius: 15)) +// Spacer() +// } +// } +// } +// } +// } +//} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift index 6af4af87..74175404 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/RecentNewsCardView.swift @@ -139,8 +139,12 @@ struct RecentNewsCardView: View { Button { print("버튼 클릭됨 - 주제: \(news.title)") topic = news.title - debateRoomViewModel.createDebate(topic: topic) - pathModel.paths.append(.createdebateroom) + debateRoomViewModel.createDebate(topic: topic) { debateTopic in + pathModel.paths.append(.createdebateroom) + print("토론방 생성 완료 - 주제: \(debateTopic)") + + } +// pathModel.paths.append(.createdebateroom) } label: { Text("토론 시작하기") .foregroundStyle(.basicWhite) diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift index 3b6cfc9b..41ef52a7 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/CreateDebateRoomViewModel.swift @@ -13,9 +13,12 @@ class CreateDebateRoomViewModel: ObservableObject { private let provider = MoyaProvider() @Published var debateID: Int? @Published var errorMessage: String? + @Published var topic: String = "" + - func createDebate(topic: String) { + func createDebate(topic: String, completion: @escaping (String) -> Void) { print("API 호출 시작 - 토론 주제: \(topic)") + self.topic = topic // 토론 주제 저장 provider.request(.createDebate(topic: topic)) { result in switch result { case .success(let response): @@ -26,6 +29,7 @@ class CreateDebateRoomViewModel: ObservableObject { DispatchQueue.main.async { self.debateID = id print("토론방 생성 성공 - ID: \(id)") + completion(topic) // 주제를 반환하여 초기 메시지 설정 } } } catch { From fbfb1ebe9991a6cbec456f604f35d28a7c43f82b Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Thu, 20 Jun 2024 00:44:49 +0900 Subject: [PATCH 23/25] =?UTF-8?q?feat:=20=ED=86=A0=EB=A1=A0=20=EC=A2=85?= =?UTF-8?q?=EB=A3=8C=20API=20=EC=97=B0=EA=B2=B0=20=EB=B0=8F=20=ED=86=A0?= =?UTF-8?q?=EB=A1=A0=20=EC=9A=94=EC=95=BD=20=ED=99=94=EB=A9=B4=20=EB=84=98?= =?UTF-8?q?=EC=96=B4=EA=B0=80=EA=B8=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/.DS_Store | Bin 6148 -> 6148 bytes .../RollTheDice.xcodeproj/project.pbxproj | 20 +++++++- .../RollTheDice/RollTheDiceApp.swift | 4 +- .../Source/Model/Path/PathType.swift | 1 + .../View/Debate/ChatGPT/GPTChatView.swift | 44 ++++++++++++++++-- .../ChatGPT/Service/EndDebateService.swift | 43 +++++++++++++++++ .../ViewModel/EndDebateViewModel.swift | 26 +++++++++++ .../GPTChatListViewModel.swift | 4 +- .../{ => ViewModel}/GPTChatViewModel.swift | 0 9 files changed, 132 insertions(+), 10 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/EndDebateService.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/EndDebateViewModel.swift rename iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/{ => ViewModel}/GPTChatListViewModel.swift (97%) rename iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/{ => ViewModel}/GPTChatViewModel.swift (100%) diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 87ed28ab873c1c074a10d71527c4db1760a32cc6..1f34c3f3dc394c9ea6c001fafa3d612c16c6d457 100644 GIT binary patch delta 58 zcmZoMXffE}&cw{jBR=^YliuVCCLUISnU@`=O+L+JIC&Qm&z>=1vmo;~mWd5)o7p-3 G@&f=SViR=$ delta 56 zcmZoMXffE}&cw{L|L5d$OnQ?mn0Q!Up8fnZfAVQ2!^yjlc=nqGnZL12Y+&Ea&heKY E0IIeZ{{R30 diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index dfd76995..1e58b14f 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -23,6 +23,8 @@ 3586B53C2C22DF41006B1458 /* News.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53B2C22DF41006B1458 /* News.swift */; }; 3586B53E2C22DF67006B1458 /* RecentNewsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53D2C22DF67006B1458 /* RecentNewsService.swift */; }; 3586B5402C22DFCB006B1458 /* RecentNewsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */; }; + 3586B5422C232C00006B1458 /* EndDebateService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5412C232C00006B1458 /* EndDebateService.swift */; }; + 3586B5452C232C7C006B1458 /* EndDebateViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5442C232C7C006B1458 /* EndDebateViewModel.swift */; }; 35C71BF22B79F39900F777D1 /* ExyteChat in Frameworks */ = {isa = PBXBuildFile; productRef = 35C71BF12B79F39900F777D1 /* ExyteChat */; }; 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C32379E2B7C376D00B699AB /* Bookmarks.swift */; }; 6C3237A12B7C377600B699AB /* BookmarkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */; }; @@ -119,6 +121,8 @@ 3586B53B2C22DF41006B1458 /* News.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = News.swift; sourceTree = ""; }; 3586B53D2C22DF67006B1458 /* RecentNewsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentNewsService.swift; sourceTree = ""; }; 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentNewsViewModel.swift; sourceTree = ""; }; + 3586B5412C232C00006B1458 /* EndDebateService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndDebateService.swift; sourceTree = ""; }; + 3586B5442C232C7C006B1458 /* EndDebateViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndDebateViewModel.swift; sourceTree = ""; }; 6C32379E2B7C376D00B699AB /* Bookmarks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bookmarks.swift; sourceTree = ""; }; 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkViewModel.swift; sourceTree = ""; }; 6C3237A42B7C37D100B699AB /* BookmarkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkView.swift; sourceTree = ""; }; @@ -244,6 +248,7 @@ isa = PBXGroup; children = ( 3544D7452C229436007DBD18 /* ChatService.swift */, + 3586B5412C232C00006B1458 /* EndDebateService.swift */, ); path = Service; sourceTree = ""; @@ -264,6 +269,16 @@ path = RecentNewsModel; sourceTree = ""; }; + 3586B5432C232C44006B1458 /* ViewModel */ = { + isa = PBXGroup; + children = ( + 3586B5442C232C7C006B1458 /* EndDebateViewModel.swift */, + 6CDB29FA2BAA07B10081037B /* GPTChatViewModel.swift */, + 6CDB29FE2BAA08280081037B /* GPTChatListViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; 6C32379D2B7C374E00B699AB /* BookmarkCard */ = { isa = PBXGroup; children = ( @@ -559,11 +574,10 @@ 6CDB29F72BAA06FB0081037B /* ChatGPT */ = { isa = PBXGroup; children = ( + 3586B5432C232C44006B1458 /* ViewModel */, 3544D7442C229428007DBD18 /* Service */, 6CDB29F82BAA07350081037B /* GPTChat.swift */, - 6CDB29FA2BAA07B10081037B /* GPTChatViewModel.swift */, 6CDB29FC2BAA07FD0081037B /* GPTChatView.swift */, - 6CDB29FE2BAA08280081037B /* GPTChatListViewModel.swift */, ); path = ChatGPT; sourceTree = ""; @@ -829,6 +843,7 @@ 6C94799E2BD3C00C00D5AEEB /* Image.swift in Sources */, 6C454A842B9DAFCB006FD9D0 /* PathType.swift in Sources */, 6CF130AF2BAB0C4F00A437B6 /* AuthenticatedView.swift in Sources */, + 3586B5422C232C00006B1458 /* EndDebateService.swift in Sources */, 6C3237B52B7C433D00B699AB /* ChatTypeView.swift in Sources */, 6CF130B22BAB74BA00A437B6 /* NewsService.swift in Sources */, 6C3237B22B7C385000B699AB /* NewsListViewModel.swift in Sources */, @@ -850,6 +865,7 @@ 6C454A7C2B9DA71C006FD9D0 /* SignUpView.swift in Sources */, 3586B5402C22DFCB006B1458 /* RecentNewsViewModel.swift in Sources */, 6C41B8DA2BE104A800274FA4 /* RecentNewsCardView.swift in Sources */, + 3586B5452C232C7C006B1458 /* EndDebateViewModel.swift in Sources */, 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */, 6CF130C72BAB7B9800A437B6 /* ScoopAPINews.swift in Sources */, 6C7651402BF37F3400196536 /* Log.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift index eb3444a7..20a0cb74 100644 --- a/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift +++ b/iOS/RollTheDice/RollTheDice/RollTheDiceApp.swift @@ -46,7 +46,7 @@ struct RollTheDiceApp: App { // 각 뷰마다 .navigationBarBackButtonHidden() 설정하기! switch pathType { case .chatView(isAiMode: true) : - GPTChatView(topic: "") + GPTChatView(topic: "토픽", roomId: 74) .navigationBarBackButtonHidden() case .chatView(isAiMode: false): @@ -67,7 +67,7 @@ struct RollTheDiceApp: App { case .webView(let url): WebView(urlToLoad: url) case .createdebateroom: - GPTChatView(topic: "") + GPTChatView(topic: "", roomId: 74) } }) } diff --git a/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift b/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift index 806b0279..b464d017 100644 --- a/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift +++ b/iOS/RollTheDice/RollTheDice/Source/Model/Path/PathType.swift @@ -22,4 +22,5 @@ enum PathType: Hashable { case webView(url: String) case createdebateroom //토론방 생성 + } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift index b52ffa1a..5dd45488 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift @@ -13,10 +13,12 @@ struct GPTChatView: View { // @State var selectedChat: GPTChat? = .init(title: "토론제목입니다", messages: [.init(content: "ChatGPT와의 토론!", isUser: false)]) @State var selectedChat: GPTChat? @StateObject var chatListViewModel = GPTChatListViewModel(topic: "토론") - @StateObject var createDebateRoomViewModel = CreateDebateRoomViewModel() + @StateObject var createDebateRoomViewModel = CreateDebateRoomViewModel() + @StateObject private var viewModel = EndDebateViewModel() + var roomId: Int - - init(topic: String) { + init(topic: String, roomId: Int) { + self.roomId = roomId _chatListViewModel = StateObject(wrappedValue: GPTChatListViewModel(topic: topic)) _selectedChat = State(initialValue: GPTChat(title: topic, messages: [.init(content: "\(createDebateRoomViewModel.topic) ChatGPT와의 토론!", isUser: false)])) } @@ -26,7 +28,9 @@ struct GPTChatView: View { Color.backgroundDark.ignoresSafeArea(.all) VStack { CustomNavigationBar(title: selectedChat?.title ?? "", isDisplayLeadingBtn: true, leadingItems: [(Image(.chevronLeft), {pathModel.paths.popLast()})]) - MessageTitleView(chatListViewModel: chatListViewModel, selectedChat: $selectedChat) + + MessageTitleView(chatListViewModel: chatListViewModel, selectedChat: $selectedChat, roomId: roomId) + } } } @@ -37,6 +41,10 @@ struct GPTChatView: View { @Binding var selectedChat: GPTChat? @State var string: String = "" @State var index: Int? = 0 + @StateObject private var viewModel = EndDebateViewModel() + var roomId: Int + @EnvironmentObject var pathModel: PathModel + fileprivate var body: some View { if chatListViewModel.chatList.isEmpty { @@ -60,6 +68,32 @@ struct GPTChatView: View { MessageCellView(message: message) } } + + //MARK : 토론 종료 버튼 + Button(action: { + print("토론종료버튼 눌림!") + viewModel.endDebate(roomId: "\(roomId)") { success in + if success { + print("토론이 종료되었습니다.") + pathModel.paths.append(.debateSummaryView) + } else { + print("토론 종료에 실패했습니다.") + } + } + + + }) { + Text("토론종료") + .font(.title3.weight(.semibold)) + .foregroundColor(.white) + .padding() + .background(Color.primary01) + .cornerRadius(15) + .shadow(radius: 4, x: 0, y: 4) + } + .frame(width: 100, height: 30) + .padding(.bottom, 20) + Divider() HStack { @@ -75,6 +109,8 @@ struct GPTChatView: View { string = "" } label: { Image(systemName: "paperplane") + .foregroundColor(.primary01) + } } .padding() diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/EndDebateService.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/EndDebateService.swift new file mode 100644 index 00000000..af1fdf4f --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/Service/EndDebateService.swift @@ -0,0 +1,43 @@ +// +// EndDebateService.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation +import Moya + +enum EndDebateService { + case endDebate(roomId: String) +} + +extension EndDebateService: TargetType { + var baseURL: URL { + return URL(string: "http://roll-the-dice.store:8080")! + } + + var path: String { + switch self { + case .endDebate(let roomId): + return "/debates/\(roomId)" + } + } + + var method: Moya.Method { + return .patch + } + + var task: Task { + return .requestPlain + } + + var headers: [String : String]? { + guard let token = TokenManager.shared.accessToken else { return nil } + return ["Authorization": "Bearer \(token)"] + } + + var sampleData: Data { + return Data() + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/EndDebateViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/EndDebateViewModel.swift new file mode 100644 index 00000000..a8f42303 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/EndDebateViewModel.swift @@ -0,0 +1,26 @@ +// +// EndDebateViewModel.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation +import Moya + +class EndDebateViewModel: ObservableObject { + private let provider = MoyaProvider() + + func endDebate(roomId: String, completion: @escaping (Bool) -> Void) { + provider.request(.endDebate(roomId: roomId)) { result in + switch result { + case .success: + print("토론 종료 성공") + completion(true) + case .failure: + print("토론 종료 실패") + completion(false) + } + } + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/GPTChatListViewModel.swift similarity index 97% rename from iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift rename to iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/GPTChatListViewModel.swift index e9e85638..a723228a 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatListViewModel.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/GPTChatListViewModel.swift @@ -107,13 +107,14 @@ class GPTChatListViewModel: ObservableObject { private var cancellables = Set() private let provider = MoyaProvider() private let debateprovider = MoyaProvider() + private let enddebateprovider = MoyaProvider() private let openAI: OpenAI @Published var topic: String = "" init( topic: String, chatList: [GPTChat] = [], - apiToken: String = "" + apiToken: String = "" //깃허브 보안 이슈로 계속 제거해야됨. ) { self.chatList = chatList.isEmpty ? [GPTChat(title: topic, messages: [])] : chatList self.openAI = OpenAI(apiToken: apiToken) @@ -126,7 +127,6 @@ class GPTChatListViewModel: ObservableObject { } } } - func sendNewMessage(index: Int, content: String) { print("call sendNewMessage func") diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/GPTChatViewModel.swift similarity index 100% rename from iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatViewModel.swift rename to iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/ViewModel/GPTChatViewModel.swift From 8b3e2a903f6ff80e14dcd8c83868e582d07bda91 Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Thu, 20 Jun 2024 02:57:01 +0900 Subject: [PATCH 24/25] =?UTF-8?q?fix=20:=20=ED=86=A0=EB=A1=A0=20=EC=A2=85?= =?UTF-8?q?=EB=A3=8C=20=ED=9B=84=20=EB=8B=A4=EC=8B=9C=20=EC=9D=B4=EC=A0=84?= =?UTF-8?q?=ED=99=94=EB=A9=B4=EC=9C=BC=EB=A1=9C=20=EB=8F=8C=EC=95=84?= =?UTF-8?q?=EC=98=A4=EB=8A=94=20=EA=B2=83=EC=9C=BC=EB=A1=9C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/.DS_Store | Bin 6148 -> 6148 bytes .../View/Debate/ChatGPT/GPTChatView.swift | 4 +++- .../View/Debate/ChatList/ChatListView.swift | 7 ++++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index 1f34c3f3dc394c9ea6c001fafa3d612c16c6d457..bd6aa60bff8ecb7d6bce98f5b7d174c576a2b551 100644 GIT binary patch delta 19 acmZoMXffE}!NerkH2EBp-sTFX9#H^5lLl7+ delta 19 acmZoMXffE}!NkNPKKUGz-sTFX9#H^1E(PZR diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift index 5dd45488..296769b9 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatGPT/GPTChatView.swift @@ -75,7 +75,9 @@ struct GPTChatView: View { viewModel.endDebate(roomId: "\(roomId)") { success in if success { print("토론이 종료되었습니다.") - pathModel.paths.append(.debateSummaryView) +// pathModel.paths.append(.debateSummaryView) + pathModel.paths.popLast() + } else { print("토론 종료에 실패했습니다.") } diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift index 98da2c9d..19e20b2b 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift @@ -86,7 +86,8 @@ struct ChatListView: View { Button { pathModel.paths.append(.chatView(isAiMode: true)) } label: { - Image(.chevronRight) + Image(systemName: "quote.bubble") + .background(.gray01) } } .background(.gray01) @@ -221,8 +222,8 @@ struct ChatListView: View { Button { pathModel.paths.append(.debateSummaryView) } label: { - Image(.chevronLeft) -// .background(.gray01) + Image(systemName: "quote.bubble") + .background(.gray01) } .frame(width: 80, height: 80) From 0f82def58238753299b00676d6685aafe5b7811d Mon Sep 17 00:00:00 2001 From: yeahzxnn Date: Thu, 20 Jun 2024 10:43:39 +0900 Subject: [PATCH 25/25] =?UTF-8?q?feat:=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8CAPI=20=EC=97=B0=EB=8F=99=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/RollTheDice/.DS_Store | Bin 6148 -> 6148 bytes .../RollTheDice.xcodeproj/project.pbxproj | 44 ++ .../View/Debate/ChatList/ChatListView.swift | 413 ++++++++++-------- .../GetDebateRoomModel/GetDebateRoom.swift | 15 + .../Service/GetDebateRoomService.swift | 50 +++ .../ViewModel/GetDebateRoomViewModel.swift | 34 ++ .../Debate/Summary/DebateSummaryView.swift | 3 + .../Service/DebateSummaryService.swift | 43 ++ .../ViewModel/DebateSummaryViewModel.swift | 46 ++ 9 files changed, 471 insertions(+), 177 deletions(-) create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/GetDebateRoomModel/GetDebateRoom.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/GetDebateRoomService.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/GetDebateRoomViewModel.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/Service/DebateSummaryService.swift create mode 100644 iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/ViewModel/DebateSummaryViewModel.swift diff --git a/iOS/RollTheDice/.DS_Store b/iOS/RollTheDice/.DS_Store index bd6aa60bff8ecb7d6bce98f5b7d174c576a2b551..f7a638416b1c4e4dc2eb9c750107977c6833eaf8 100644 GIT binary patch delta 57 zcmZoMXffE}!Nim}aq>APy~!0!Jgo6so!{M_e45E{@-8HvJ>!PWg3RAoCN{8bX6N|J F4*-0g7A*h( delta 57 zcmZoMXffE}!NerkH2EBp-sB1<9#(;wmmQ`}KFwq}c^4ATo-tvwAoDkti4AO<**X65 F0{}Q~6XE~> diff --git a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj index 1e58b14f..509e4a56 100644 --- a/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj +++ b/iOS/RollTheDice/RollTheDice.xcodeproj/project.pbxproj @@ -25,6 +25,11 @@ 3586B5402C22DFCB006B1458 /* RecentNewsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */; }; 3586B5422C232C00006B1458 /* EndDebateService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5412C232C00006B1458 /* EndDebateService.swift */; }; 3586B5452C232C7C006B1458 /* EndDebateViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5442C232C7C006B1458 /* EndDebateViewModel.swift */; }; + 3586B5492C2356F2006B1458 /* DebateSummaryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5482C2356F2006B1458 /* DebateSummaryService.swift */; }; + 3586B54C2C235731006B1458 /* DebateSummaryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B54B2C235731006B1458 /* DebateSummaryViewModel.swift */; }; + 3586B54F2C23B767006B1458 /* GetDebateRoom.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B54E2C23B767006B1458 /* GetDebateRoom.swift */; }; + 3586B5512C23B79F006B1458 /* GetDebateRoomService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5502C23B79F006B1458 /* GetDebateRoomService.swift */; }; + 3586B5532C23B7DC006B1458 /* GetDebateRoomViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3586B5522C23B7DC006B1458 /* GetDebateRoomViewModel.swift */; }; 35C71BF22B79F39900F777D1 /* ExyteChat in Frameworks */ = {isa = PBXBuildFile; productRef = 35C71BF12B79F39900F777D1 /* ExyteChat */; }; 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C32379E2B7C376D00B699AB /* Bookmarks.swift */; }; 6C3237A12B7C377600B699AB /* BookmarkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */; }; @@ -123,6 +128,11 @@ 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentNewsViewModel.swift; sourceTree = ""; }; 3586B5412C232C00006B1458 /* EndDebateService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndDebateService.swift; sourceTree = ""; }; 3586B5442C232C7C006B1458 /* EndDebateViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndDebateViewModel.swift; sourceTree = ""; }; + 3586B5482C2356F2006B1458 /* DebateSummaryService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebateSummaryService.swift; sourceTree = ""; }; + 3586B54B2C235731006B1458 /* DebateSummaryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebateSummaryViewModel.swift; sourceTree = ""; }; + 3586B54E2C23B767006B1458 /* GetDebateRoom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDebateRoom.swift; sourceTree = ""; }; + 3586B5502C23B79F006B1458 /* GetDebateRoomService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDebateRoomService.swift; sourceTree = ""; }; + 3586B5522C23B7DC006B1458 /* GetDebateRoomViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDebateRoomViewModel.swift; sourceTree = ""; }; 6C32379E2B7C376D00B699AB /* Bookmarks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bookmarks.swift; sourceTree = ""; }; 6C3237A02B7C377600B699AB /* BookmarkViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkViewModel.swift; sourceTree = ""; }; 6C3237A42B7C37D100B699AB /* BookmarkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkView.swift; sourceTree = ""; }; @@ -231,6 +241,7 @@ children = ( 3544D73F2C228EFC007DBD18 /* CreateDebateRoomService.swift */, 3586B53D2C22DF67006B1458 /* RecentNewsService.swift */, + 3586B5502C23B79F006B1458 /* GetDebateRoomService.swift */, ); path = Service; sourceTree = ""; @@ -240,6 +251,7 @@ children = ( 3544D7422C228F54007DBD18 /* CreateDebateRoomViewModel.swift */, 3586B53F2C22DFCB006B1458 /* RecentNewsViewModel.swift */, + 3586B5522C23B7DC006B1458 /* GetDebateRoomViewModel.swift */, ); path = ViewModel; sourceTree = ""; @@ -279,6 +291,30 @@ path = ViewModel; sourceTree = ""; }; + 3586B5472C2356E1006B1458 /* Service */ = { + isa = PBXGroup; + children = ( + 3586B5482C2356F2006B1458 /* DebateSummaryService.swift */, + ); + path = Service; + sourceTree = ""; + }; + 3586B54A2C23571D006B1458 /* ViewModel */ = { + isa = PBXGroup; + children = ( + 3586B54B2C235731006B1458 /* DebateSummaryViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; + 3586B54D2C23B748006B1458 /* GetDebateRoomModel */ = { + isa = PBXGroup; + children = ( + 3586B54E2C23B767006B1458 /* GetDebateRoom.swift */, + ); + path = GetDebateRoomModel; + sourceTree = ""; + }; 6C32379D2B7C374E00B699AB /* BookmarkCard */ = { isa = PBXGroup; children = ( @@ -310,6 +346,7 @@ 6C41B8D62BE1048500274FA4 /* ChatList */ = { isa = PBXGroup; children = ( + 3586B54D2C23B748006B1458 /* GetDebateRoomModel */, 3586B5392C22DF03006B1458 /* RecentNewsModel */, 3544D7412C228F39007DBD18 /* ViewModel */, 3544D73E2C228EDB007DBD18 /* Service */, @@ -617,6 +654,8 @@ 6CE103182BD57A1600498AA4 /* Summary */ = { isa = PBXGroup; children = ( + 3586B54A2C23571D006B1458 /* ViewModel */, + 3586B5472C2356E1006B1458 /* Service */, 6CE103192BD57A2500498AA4 /* DebateSummaryView.swift */, ); path = Summary; @@ -836,11 +875,13 @@ 3586B53C2C22DF41006B1458 /* News.swift in Sources */, 6C3237AE2B7C382E00B699AB /* DetailNewsViewModel.swift in Sources */, 6C77048F2B7229B1001B17CB /* NewsListView.swift in Sources */, + 3586B54C2C235731006B1458 /* DebateSummaryViewModel.swift in Sources */, 357666132BBD54AA002C226A /* SplashView.swift in Sources */, 6C4F7BAD2BDE510900ED01DA /* DailyReportViewModel.swift in Sources */, 6C3237A72B7C37E500B699AB /* BookmarksListViewModel.swift in Sources */, 6C454A822B9DAFA3006FD9D0 /* Path.swift in Sources */, 6C94799E2BD3C00C00D5AEEB /* Image.swift in Sources */, + 3586B5512C23B79F006B1458 /* GetDebateRoomService.swift in Sources */, 6C454A842B9DAFCB006FD9D0 /* PathType.swift in Sources */, 6CF130AF2BAB0C4F00A437B6 /* AuthenticatedView.swift in Sources */, 3586B5422C232C00006B1458 /* EndDebateService.swift in Sources */, @@ -852,6 +893,7 @@ 6CF130C22BAB786600A437B6 /* APIHeaderManager.swift in Sources */, 6C5B0C8C2C1C32C000A0D5F4 /* BookmarksService.swift in Sources */, 6CDB29FB2BAA07B10081037B /* GPTChatViewModel.swift in Sources */, + 3586B5492C2356F2006B1458 /* DebateSummaryService.swift in Sources */, 6C32379F2B7C376D00B699AB /* Bookmarks.swift in Sources */, 6C454A7E2B9DAA3F006FD9D0 /* SignUpFinishView.swift in Sources */, 6C7704A12B722CEB001B17CB /* ProfileView.swift in Sources */, @@ -865,8 +907,10 @@ 6C454A7C2B9DA71C006FD9D0 /* SignUpView.swift in Sources */, 3586B5402C22DFCB006B1458 /* RecentNewsViewModel.swift in Sources */, 6C41B8DA2BE104A800274FA4 /* RecentNewsCardView.swift in Sources */, + 3586B5532C23B7DC006B1458 /* GetDebateRoomViewModel.swift in Sources */, 3586B5452C232C7C006B1458 /* EndDebateViewModel.swift in Sources */, 3509091A2C1C1248007D76A1 /* TokenManager.swift in Sources */, + 3586B54F2C23B767006B1458 /* GetDebateRoom.swift in Sources */, 6CF130C72BAB7B9800A437B6 /* ScoopAPINews.swift in Sources */, 6C7651402BF37F3400196536 /* Log.swift in Sources */, 6CE1031A2BD57A2500498AA4 /* DebateSummaryView.swift in Sources */, diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift index 19e20b2b..846f529d 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ChatListView.swift @@ -11,7 +11,12 @@ struct ChatListView: View { @EnvironmentObject var pathModel: PathModel @StateObject private var newsViewModel = RecentNewsViewModel() - + @StateObject private var viewModel = DebateSummaryViewModel() + @StateObject private var endDebateViewModel = EndDebateViewModel() + @State private var roomId: String = "" // EndDebateViewModel로부터 받아올 roomId + @StateObject private var getdebateroomviewModel = GetDebateRoomViewModel() + + var body: some View { ZStack { Color.backgroundDark.ignoresSafeArea(.all) @@ -32,28 +37,28 @@ struct ChatListView: View { Text("최근 본 뉴스") .foregroundStyle(.basicWhite) .font(.pretendardBold32) -// HStack { -// RecentNewsCardView() -// Spacer() -// RecentNewsCardView() -// Spacer() -// RecentNewsCardView() -// } + // HStack { + // RecentNewsCardView() + // Spacer() + // RecentNewsCardView() + // Spacer() + // RecentNewsCardView() + // } HStack { - if newsViewModel.news.isEmpty { - Text("최근 읽은 뉴스를 불러오는 중...") - .onAppear { - print("뷰가 나타남 - 최근 읽은 뉴스 조회 시작") - newsViewModel.fetchViewedHistory() - } - } else { - ForEach(newsViewModel.news.prefix(3), id: \.id) { news in - RecentNewsCardView(news: news) - Spacer() + if newsViewModel.news.isEmpty { + Text("최근 읽은 뉴스를 불러오는 중...") + .onAppear { + print("뷰가 나타남 - 최근 읽은 뉴스 조회 시작") + newsViewModel.fetchViewedHistory() } + } else { + ForEach(newsViewModel.news.prefix(3), id: \.id) { news in + RecentNewsCardView(news: news) + Spacer() } } - .padding() + } + .padding() } } @@ -63,174 +68,228 @@ struct ChatListView: View { Text("채팅방") .foregroundStyle(.basicWhite) .font(.pretendardBold32) - debateChatCellView - debateChatCellView2 - debateChatCellView3 - debateChatCellView4 - debateChatCellView5 + // debateChatCellView + // debateChatCellView2 + // debateChatCellView3 + // debateChatCellView4 + // debateChatCellView5 + ForEach(getdebateroomviewModel.debates) { debate in + DebateChatCellView(debate: debate) + } + } + .onAppear { + print("채팅방 불러와짐") + getdebateroomviewModel.fetchDebates(page: 5, size: 10) } } - var debateChatCellView: some View { - HStack { - HStack(alignment: .center, spacing: 16) { - Text("🏛️") - .padding(.leading, 26) - .font(.pretendardBold32) - Text("삼성, 갤럭시Z플립6 두뇌 전량 퀄컴칩 탑재하나") - .foregroundStyle(.gray07) - .font(.pretendardBold24) - .padding(.vertical, 24) - - Spacer() + struct DebateChatCellView: View { + let debate: GetDebateRoom + let emojis = ["🏛️", "🔥", "📌", "⭐️", "🧬", "👩🏼‍💻", "🎨", "🎬", "💌", "🔗", "👀"] + + @EnvironmentObject var pathModel: PathModel + + var body: some View { + let randomEmoji = emojis.randomElement() ?? "🏛️" // 이모지가 선택되지 않으면 기본값을 설정합니다. + + HStack { + HStack(alignment: .center, spacing: 16) { +// Text("🏛️") +// .padding(.leading, 26) +// .font(.pretendardBold32) + Text(randomEmoji) + .padding(.leading, 26) + .font(.pretendardBold32) + Text(debate.topic.isEmpty ? "토론을 시작해주세요!" : debate.topic) + .foregroundStyle(.gray07) + .font(.pretendardBold24) + .padding(.vertical, 24) + + Spacer() + Button { + pathModel.paths.append(.chatView(isAiMode: true)) + } label: { + Image(systemName: "chevronRight") + .foregroundColor(.gray01) + } + } + .background(.gray01) + .clipShape(RoundedRectangle(cornerRadius: 8)) + .padding(.trailing, 16) + Button { - pathModel.paths.append(.chatView(isAiMode: true)) + pathModel.paths.append(.debateSummaryView) } label: { - Image(systemName: "quote.bubble") - .background(.gray01) + Image("quote.bubble") + .foregroundColor(.gray01) + } + .frame(width: 80, height: 80) + .background(.gray01) + .clipShape(RoundedRectangle(cornerRadius: 8)) } - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding(.trailing, 16) - - //TODO: 버튼 영역 수정하기 - Button { - pathModel.paths.append(.debateSummaryView) - } label: { - Image(.chevronLeft) -// .background(.gray01) - - } - .frame(width: 80, height: 80) - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - } - } - var debateChatCellView2: some View { - HStack { - HStack(alignment: .center, spacing: 16) { - Text("📱") - .padding(.leading, 26) - .font(.pretendardBold32) - Text("모친 내친 한미약품 형제… 2644억 상속세 마련방안은 `아직`") - .foregroundStyle(.gray07) - .font(.pretendardBold24) - .padding(.vertical, 24) - - Spacer() - Image(.chevronRight) - } - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding(.trailing, 16) - - //TODO: 버튼 영역 수정하기 - Button { - pathModel.paths.append(.debateSummaryView) - } label: { - Image(.chevronLeft) -// .background(.gray01) - - } - .frame(width: 80, height: 80) - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - } - } - var debateChatCellView3: some View { - HStack { - HStack(alignment: .center, spacing: 16) { - Text("💌") - .padding(.leading, 26) - .font(.pretendardBold32) - Text("[ET단상]한바탕 휩쓴 방산 해킹 사건, 보안의 다른 \'답\'을 찾아야 할 때") - .foregroundStyle(.gray07) - .font(.pretendardBold24) - .padding(.vertical, 24) - - Spacer() - Image(.chevronRight) - } - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding(.trailing, 16) - - //TODO: 버튼 영역 수정하기 - Button { - pathModel.paths.append(.debateSummaryView) - } label: { - Image(.chevronLeft) -// .background(.gray01) - - } - .frame(width: 80, height: 80) - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) } } - var debateChatCellView4: some View { - HStack { - HStack(alignment: .center, spacing: 16) { - Text("📱") - .padding(.leading, 26) - .font(.pretendardBold32) - Text("삼성, 갤럭시Z플립6 두뇌 전량 퀄컴칩 탑재하나") - .foregroundStyle(.gray07) - .font(.pretendardBold24) - .padding(.vertical, 24) - - Spacer() - Image(.chevronRight) - } - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding(.trailing, 16) - - //TODO: 버튼 영역 수정하기 - Button { - pathModel.paths.append(.debateSummaryView) - } label: { - Image(.chevronLeft) +// var debateChatCellView: some View { +// HStack { +// HStack(alignment: .center, spacing: 16) { +// Text("🏛️") +// .padding(.leading, 26) +// .font(.pretendardBold32) +// Text("삼성, 갤럭시Z플립6 두뇌 전량 퀄컴칩 탑재하나") +// .foregroundStyle(.gray07) +// .font(.pretendardBold24) +// .padding(.vertical, 24) +// +// Spacer() +// Button { +// pathModel.paths.append(.chatView(isAiMode: true)) +// } label: { +// Image(systemName: "chevronRight") +// .foregroundColor(.gray01) +// } +// } +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// .padding(.trailing, 16) +// +// //TODO: 버튼 영역 수정하기 +// Button { +// pathModel.paths.append(.debateSummaryView) +// } label: { +// Image("quote.bubble") +// .foregroundColor(.gray01) +// +// } +// .frame(width: 80, height: 80) +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } +// } +// var debateChatCellView2: some View { +// HStack { +// HStack(alignment: .center, spacing: 16) { +// Text("📱") +// .padding(.leading, 26) +// .font(.pretendardBold32) +// Text("모친 내친 한미약품 형제… 2644억 상속세 마련방안은 `아직`") +// .foregroundStyle(.gray07) +// .font(.pretendardBold24) +// .padding(.vertical, 24) +// +// Spacer() +// Image(.chevronRight) +// } +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// .padding(.trailing, 16) +// +// //TODO: 버튼 영역 수정하기 +// Button { +// pathModel.paths.append(.debateSummaryView) +// } label: { +// Image(.chevronLeft) +//// .background(.gray01) +// +// } +// .frame(width: 80, height: 80) +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } +// } +// var debateChatCellView3: some View { +// HStack { +// HStack(alignment: .center, spacing: 16) { +// Text("💌") +// .padding(.leading, 26) +// .font(.pretendardBold32) +// Text("[ET단상]한바탕 휩쓴 방산 해킹 사건, 보안의 다른 \'답\'을 찾아야 할 때") +// .foregroundStyle(.gray07) +// .font(.pretendardBold24) +// .padding(.vertical, 24) +// +// Spacer() +// Image(.chevronRight) +// } +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// .padding(.trailing, 16) +// +// //TODO: 버튼 영역 수정하기 +// Button { +// pathModel.paths.append(.debateSummaryView) +// } label: { +// Image(.chevronLeft) +//// .background(.gray01) +// +// } +// .frame(width: 80, height: 80) +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } +// } +// var debateChatCellView4: some View { +// HStack { +// HStack(alignment: .center, spacing: 16) { +// Text("📱") +// .padding(.leading, 26) +// .font(.pretendardBold32) +// Text("삼성, 갤럭시Z플립6 두뇌 전량 퀄컴칩 탑재하나") +// .foregroundStyle(.gray07) +// .font(.pretendardBold24) +// .padding(.vertical, 24) +// +// Spacer() +// Image(.chevronRight) +// } +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// .padding(.trailing, 16) +// +// //TODO: 버튼 영역 수정하기 +// Button { +// pathModel.paths.append(.debateSummaryView) +// } label: { +// Image(.chevronLeft) +//// .background(.gray01) +// +// } +// .frame(width: 80, height: 80) +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } +// } +// var debateChatCellView5: some View { +// HStack { +// HStack(alignment: .center, spacing: 16) { +// Text("🏛️") +// .padding(.leading, 26) +// .font(.pretendardBold32) +// Text("삼성, 갤럭시Z플립6 두뇌 전량 퀄컴칩 탑재하나") +// .foregroundStyle(.gray07) +// .font(.pretendardBold24) +// .padding(.vertical, 24) +// +// Spacer() +// Image(.chevronRight) +// } +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// .padding(.trailing, 16) +// +// //TODO: 버튼 영역 수정하기 +// Button { +// pathModel.paths.append(.debateSummaryView) +// } label: { +// Image(systemName: "quote.bubble") // .background(.gray01) - - } - .frame(width: 80, height: 80) - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - } - } - var debateChatCellView5: some View { - HStack { - HStack(alignment: .center, spacing: 16) { - Text("🏛️") - .padding(.leading, 26) - .font(.pretendardBold32) - Text("삼성, 갤럭시Z플립6 두뇌 전량 퀄컴칩 탑재하나") - .foregroundStyle(.gray07) - .font(.pretendardBold24) - .padding(.vertical, 24) - - Spacer() - Image(.chevronRight) - } - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding(.trailing, 16) - - //TODO: 버튼 영역 수정하기 - Button { - pathModel.paths.append(.debateSummaryView) - } label: { - Image(systemName: "quote.bubble") - .background(.gray01) - - } - .frame(width: 80, height: 80) - .background(.gray01) - .clipShape(RoundedRectangle(cornerRadius: 8)) - } - } +// +// } +// .frame(width: 80, height: 80) +// .background(.gray01) +// .clipShape(RoundedRectangle(cornerRadius: 8)) +// } +// } } #Preview { diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/GetDebateRoomModel/GetDebateRoom.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/GetDebateRoomModel/GetDebateRoom.swift new file mode 100644 index 00000000..a24fbd01 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/GetDebateRoomModel/GetDebateRoom.swift @@ -0,0 +1,15 @@ +// +// GetDebateRoom.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation + + +struct GetDebateRoom: Identifiable, Codable { + let id: Int + let topic: String + let isClosed: Bool? +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/GetDebateRoomService.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/GetDebateRoomService.swift new file mode 100644 index 00000000..49601d7d --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/Service/GetDebateRoomService.swift @@ -0,0 +1,50 @@ +// +// GetDebateRoomService.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +//MARK : 토론방 전체 조회 +import Foundation +import Moya + +enum GetDebateRoomService { + case getDebates(page: Int, size: Int) +} + +extension GetDebateRoomService: TargetType { + var baseURL: URL { + return URL(string: "http://roll-the-dice.store:8080")! + } + + var path: String { + switch self { + case .getDebates: + return "/debates" + } + } + + var method: Moya.Method { + switch self { + case .getDebates: + return .get + } + } + + var task: Task { + switch self { + case let .getDebates(page, size): + return .requestParameters(parameters: ["page": page, "size": size], encoding: URLEncoding.queryString) + } + } + + var headers: [String: String]? { + guard let token = TokenManager.shared.accessToken else { return nil } + return ["Authorization": "Bearer \(token)"] + } + + var sampleData: Data { + return Data() + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/GetDebateRoomViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/GetDebateRoomViewModel.swift new file mode 100644 index 00000000..b003450b --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/ChatList/ViewModel/GetDebateRoomViewModel.swift @@ -0,0 +1,34 @@ +// +// GetDebateRoomViewModel.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation +import Combine +import Moya + +class GetDebateRoomViewModel: ObservableObject { + @Published var debates: [GetDebateRoom] = [] + private var cancellables = Set() + private let provider = MoyaProvider() + + func fetchDebates(page: Int, size: Int) { + provider.requestPublisher(.getDebates(page: page, size: size)) + .map(\.data) + .decode(type: [GetDebateRoom].self, decoder: JSONDecoder()) + .sink(receiveCompletion: { completion in + switch completion { + case .failure(let error): + print("Error fetching debates: \(error)") + case .finished: + break + } + }, receiveValue: { [weak self] debates in + self?.debates = debates + print("Fetched debates: \(debates)") // 로그 확인용 + }) + .store(in: &cancellables) + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/DebateSummaryView.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/DebateSummaryView.swift index 62319d1e..ae34da56 100644 --- a/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/DebateSummaryView.swift +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/DebateSummaryView.swift @@ -9,6 +9,9 @@ import SwiftUI struct DebateSummaryView: View { @EnvironmentObject var pathModel: PathModel + @StateObject private var viewModel = DebateSummaryViewModel() + @StateObject private var endDebateViewModel = EndDebateViewModel() + @State private var roomId: String = "" // EndDebateViewModel로부터 받아오는 roomid var body: some View { ZStack { diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/Service/DebateSummaryService.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/Service/DebateSummaryService.swift new file mode 100644 index 00000000..b161bd3d --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/Service/DebateSummaryService.swift @@ -0,0 +1,43 @@ +// +// DebateSummaryService.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation +import Moya + +enum DebateSummaryService { + case getSummary(roomId: Int) +} + +extension DebateSummaryService: TargetType { + var baseURL: URL { + return URL(string: "http://roll-the-dice.store:8080")! + } + + var path: String { + switch self { + case .getSummary(let roomId): + return "/debates/summary/\(roomId)" + } + } + + var method: Moya.Method { + return .post + } + + var task: Task { + return .requestPlain + } + + var headers: [String : String]? { + guard let token = TokenManager.shared.accessToken else { return nil } + return ["Authorization": "Bearer \(token)"] + } + + var sampleData: Data { + return Data() + } +} diff --git a/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/ViewModel/DebateSummaryViewModel.swift b/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/ViewModel/DebateSummaryViewModel.swift new file mode 100644 index 00000000..638529c4 --- /dev/null +++ b/iOS/RollTheDice/RollTheDice/Source/View/Debate/Summary/ViewModel/DebateSummaryViewModel.swift @@ -0,0 +1,46 @@ +// +// DebateSummaryViewModel.swift +// RollTheDice +// +// Created by 신예진 on 6/20/24. +// + +import Foundation +import Combine +import Moya + +class DebateSummaryViewModel: ObservableObject { + @Published var summary: String? + @Published var roomId: Int? + @Published var isLoading: Bool = false + @Published var errorMessage: String? + + private let provider = MoyaProvider() + + func fetchSummary(roomId: Int) { + isLoading = true + provider.request(.getSummary(roomId: roomId)) { result in + self.isLoading = false + switch result { + case .success(let response): + do { + let json = try JSONSerialization.jsonObject(with: response.data, options: []) + if let dict = json as? [String: Any], let summary = dict["summary"] as? String { + self.summary = summary + self.roomId = roomId + print("토론 요약 성공") + } else { + self.errorMessage = "Invalid response format" + print("토론 요약 유효하지 않은 포맷") + } + } catch { + self.errorMessage = "Failed to parse response" + print("토론 요약 reponse 못 받아옴") + } + case .failure(let error): + self.errorMessage = error.localizedDescription + print("토론 요약 오류/실패") + } + } + } +}