From 617c1bb5414b04258010cd49f38e0c0800f40356 Mon Sep 17 00:00:00 2001 From: vixer93 Date: Thu, 13 Jun 2024 23:49:03 +0900 Subject: [PATCH 1/3] Implement TimeTableDetailView UI --- .../InformationRow.swift | 48 +++++ .../Resource/Localizable.xcstrings | 175 ++++++++++++++++++ .../Media.xcassets/Avatar.imageset/Avatar.png | Bin 0 -> 8753 bytes .../Avatar.imageset/Contents.json | 21 +++ .../Background.colorset/Contents.json | 20 ++ .../Button.colorset/Contents.json | 20 ++ .../Resource/Media.xcassets/Contents.json | 6 + .../On Primary.colorset/Contents.json | 20 ++ .../On Surface.colorset/Contents.json | 20 ++ .../Outline Variant.colorset/Contents.json | 20 ++ .../Outline.colorset/Contents.json | 20 ++ .../Primary.colorset/Contents.json | 20 ++ .../Contents.json | 20 ++ .../Surface Container.colorset/Contents.json | 20 ++ .../Surface Variant.colorset/Contents.json | 20 ++ .../ic_add_calendar.imageset/Contents.json | 15 ++ .../ic_add_calendar.svg | 8 + .../ic_category.imageset/Contents.json | 15 ++ .../ic_category.imageset/ic_category.svg | 8 + .../ic_document.imageset/Contents.json | 15 ++ .../ic_document.imageset/ic_document.svg | 8 + .../ic_favorite.imageset/Contents.json | 15 ++ .../ic_favorite.imageset/ic_favorite.svg | 3 + .../ic_language.imageset/Contents.json | 15 ++ .../ic_language.imageset/ic_language.svg | 8 + .../ic_location_on.imageset/Contents.json | 15 ++ .../ic_location_on.svg | 8 + .../ic_play.imageset/Contents.json | 15 ++ .../ic_play.imageset/ic_play.svg | 8 + .../ic_schedule.imageset/Contents.json | 15 ++ .../ic_schedule.imageset/ic_schedule.svg | 8 + .../ic_share.imageset/Contents.json | 15 ++ .../ic_share.imageset/ic_share.svg | 3 + .../SessionDescriptionView.swift | 54 ++++++ .../TimetableDetailView.swift | 169 ++++++++++++++++- 35 files changed, 867 insertions(+), 3 deletions(-) create mode 100644 app-ios/Sources/TimetableDetailFeature/InformationRow.swift create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Localizable.xcstrings create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Avatar.imageset/Avatar.png create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Avatar.imageset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Background.colorset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Button.colorset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/On Primary.colorset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/On Surface.colorset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Outline Variant.colorset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Outline.colorset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Primary.colorset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Secondary Container.colorset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Surface Container.colorset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Surface Variant.colorset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_add_calendar.imageset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_add_calendar.imageset/ic_add_calendar.svg create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_category.imageset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_category.imageset/ic_category.svg create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_document.imageset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_document.imageset/ic_document.svg create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_favorite.imageset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_favorite.imageset/ic_favorite.svg create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_language.imageset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_language.imageset/ic_language.svg create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_location_on.imageset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_location_on.imageset/ic_location_on.svg create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_play.imageset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_play.imageset/ic_play.svg create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_schedule.imageset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_schedule.imageset/ic_schedule.svg create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_share.imageset/Contents.json create mode 100644 app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_share.imageset/ic_share.svg create mode 100644 app-ios/Sources/TimetableDetailFeature/SessionDescriptionView.swift diff --git a/app-ios/Sources/TimetableDetailFeature/InformationRow.swift b/app-ios/Sources/TimetableDetailFeature/InformationRow.swift new file mode 100644 index 000000000..efaff87be --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/InformationRow.swift @@ -0,0 +1,48 @@ +import SwiftUI + +public struct InformationRow: View { + private let icon: Image + private let title: String + private let content: String + + public init( + icon: Image, + title: String, + content: String + ) { + self.icon = icon + self.title = title + self.content = content + } + + public var body: some View { + HStack { + icon + HStack(spacing: 12) { + Text(title) + .font(.callout) + .foregroundStyle(Color(.surfaceVariant)) + .bold() + HStack { + Text(content) + .font(.callout) + .foregroundStyle(Color(.onSurface)) + } + + } + } + .frame(maxWidth: .infinity, alignment: .leading) + .foregroundStyle( + Color.white + ) + } +} + +#Preview { + InformationRow( + icon: Image(systemName: "clock"), + title: String(localized: "TimeTableDetailDate", bundle: .module), + content: "2023.09.14 / 11:20 ~ 12:00 (40分)" + ) +} + diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Localizable.xcstrings b/app-ios/Sources/TimetableDetailFeature/Resource/Localizable.xcstrings new file mode 100644 index 000000000..99102813d --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Localizable.xcstrings @@ -0,0 +1,175 @@ +{ + "sourceLanguage" : "en", + "strings" : { + "DroidKaigiアプリで見るアーキテクチャの変遷" : { + + }, + "name" : { + + }, + "TimeTableDetailApplicants" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Applicants" + } + }, + "ja" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "対象者" + } + } + } + }, + "TimeTableDetailArchive" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Archive" + } + }, + "ja" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "アーカイブ" + } + } + } + }, + "TimeTableDetailCategory" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Category" + } + }, + "ja" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "カテゴリ" + } + } + } + }, + "TimeTableDetailDate" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Date" + } + }, + "ja" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "日付" + } + } + } + }, + "TimeTableDetailLanguage" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Language" + } + }, + "ja" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "対応言語" + } + } + } + }, + "TimeTableDetailLocation" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Location" + } + }, + "ja" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "場所" + } + } + } + }, + "TimeTableDetailReadMore" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Read more" + } + }, + "ja" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "続きを読む" + } + } + } + }, + "TimeTableDetailSlide" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Slide" + } + }, + "ja" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "スライド" + } + } + } + }, + "TimeTableDetailSpeaker" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Speaker" + } + }, + "ja" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "スピーカー" + } + } + } + }, + "TimeTableDetailVideo" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Video" + } + }, + "ja" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "動画" + } + } + } + }, + "手を動かして実践してひとへのヒントとなります\nCoroutinesを使いたいと感じているひと\nよりモダンで効率的なAndroidアプリ開発に興味があるひと\n新しいパラダイムをいち早く知りたいひと\nアプリ開発が複雑だと感じるひと\nアプリ開発経験を前提としてあったほうが楽しめます" : { + + } + }, + "version" : "1.0" +} \ No newline at end of file diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Avatar.imageset/Avatar.png b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/Avatar.imageset/Avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..3265a59c5e44967a06164f89ff6a8e3d5c3e04c7 GIT binary patch literal 8753 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 + + + + + + + diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_category.imageset/Contents.json b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_category.imageset/Contents.json new file mode 100644 index 000000000..119b2b3d2 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_category.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "ic_category.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_category.imageset/ic_category.svg b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_category.imageset/ic_category.svg new file mode 100644 index 000000000..dbc01ee53 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_category.imageset/ic_category.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_document.imageset/Contents.json b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_document.imageset/Contents.json new file mode 100644 index 000000000..77d87ad9c --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_document.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "ic_document.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_document.imageset/ic_document.svg b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_document.imageset/ic_document.svg new file mode 100644 index 000000000..f2779e967 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_document.imageset/ic_document.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_favorite.imageset/Contents.json b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_favorite.imageset/Contents.json new file mode 100644 index 000000000..6eb84ed4e --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_favorite.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "ic_favorite.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_favorite.imageset/ic_favorite.svg b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_favorite.imageset/ic_favorite.svg new file mode 100644 index 000000000..8542f5563 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_favorite.imageset/ic_favorite.svg @@ -0,0 +1,3 @@ + + + diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_language.imageset/Contents.json b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_language.imageset/Contents.json new file mode 100644 index 000000000..cf770ff19 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_language.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "ic_language.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_language.imageset/ic_language.svg b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_language.imageset/ic_language.svg new file mode 100644 index 000000000..ee07d5014 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_language.imageset/ic_language.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_location_on.imageset/Contents.json b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_location_on.imageset/Contents.json new file mode 100644 index 000000000..0cc07bd09 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_location_on.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "ic_location_on.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_location_on.imageset/ic_location_on.svg b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_location_on.imageset/ic_location_on.svg new file mode 100644 index 000000000..b654e7574 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_location_on.imageset/ic_location_on.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_play.imageset/Contents.json b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_play.imageset/Contents.json new file mode 100644 index 000000000..059067738 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_play.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "ic_play.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_play.imageset/ic_play.svg b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_play.imageset/ic_play.svg new file mode 100644 index 000000000..f46ff6b66 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_play.imageset/ic_play.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_schedule.imageset/Contents.json b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_schedule.imageset/Contents.json new file mode 100644 index 000000000..802ffe376 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_schedule.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "ic_schedule.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_schedule.imageset/ic_schedule.svg b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_schedule.imageset/ic_schedule.svg new file mode 100644 index 000000000..5dbe7b0e2 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_schedule.imageset/ic_schedule.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_share.imageset/Contents.json b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_share.imageset/Contents.json new file mode 100644 index 000000000..070352f9a --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_share.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "ic_share.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_share.imageset/ic_share.svg b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_share.imageset/ic_share.svg new file mode 100644 index 000000000..ad9abca46 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/Resource/Media.xcassets/ic_share.imageset/ic_share.svg @@ -0,0 +1,3 @@ + + + diff --git a/app-ios/Sources/TimetableDetailFeature/SessionDescriptionView.swift b/app-ios/Sources/TimetableDetailFeature/SessionDescriptionView.swift new file mode 100644 index 000000000..f88661ab0 --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/SessionDescriptionView.swift @@ -0,0 +1,54 @@ +import SwiftUI + +struct SessionDescriptionView: View { + @State private var isDescriptionExpanded: Bool = false + @State private var canBeExpanded: Bool = false + let content: String + + init(content: String) { + self.content = content + } + + var body: some View { + VStack(alignment: .leading, spacing: 16) { + Text(content) + .textSelection(.enabled) + .lineLimit(isDescriptionExpanded ? nil : 5) + .font(.callout) + .foregroundStyle(Color(.surfaceVariant)) + .background { + ViewThatFits(in: .vertical) { + Text(content) + .hidden() + // Just for receiving onAppear event if the description exceeds its line limit + Color.clear + .onAppear { + canBeExpanded = true + } + } + } + if canBeExpanded { + Button { + isDescriptionExpanded = true + canBeExpanded = false + } label: { + Text(String(localized: "TimeTableDetailReadMore", bundle: .module)) + .foregroundStyle(Color(.primary)) + .frame(width: 120, height: 40, alignment: .center) + .overlay { + Capsule() + .stroke(Color(.outline)) + } + } + } + } + } +} + +#Preview { + VStack { + SessionDescriptionView(content: "Kotlin Coroutinesは非同期処理をシンプルに記述できるKotlinの言語機能です。実験的な機能としてこれまでも提供されてきましたがKotlin 1.3で正式にリリース予定です。Androidの誕生から10年たちアプリの利用シーンが増えたKotlin Coroutinesは非同期処理をシンプルに記述できるKotlinの言語機能です。実験的な機能としてこれまでも提供されてきましたがKotlin 1.3で正式にリリース予定です。Androidの誕生から10年たちアプリの利用シーンが増えた.") + .padding(.horizontal, 16) + } + .background(Color(.background)) +} diff --git a/app-ios/Sources/TimetableDetailFeature/TimetableDetailView.swift b/app-ios/Sources/TimetableDetailFeature/TimetableDetailView.swift index e28e153f7..128ffc0bb 100644 --- a/app-ios/Sources/TimetableDetailFeature/TimetableDetailView.swift +++ b/app-ios/Sources/TimetableDetailFeature/TimetableDetailView.swift @@ -5,10 +5,173 @@ public struct TimetableDetailView: View { private let store: StoreOf public var body: some View { - Text(store.title) - .onAppear { - store.send(.onAppear) + VStack { + ScrollView { + sessionDetail + .padding(.horizontal, 16) + + Divider().background(Color(.outlineVariant)) + + targetUser + .padding(16) + + Divider().background(Color(.outlineVariant)) + + speaker + .padding(16) + + Divider().background(Color(.outlineVariant)) + + archive + .padding(16) + } + + footer + } + .background(Color(.background)) + .frame(maxWidth: .infinity) + } + + var footer: some View { + HStack(spacing: 8) { + Button { + // do something + } label: { + Group { + Image(.icShare) + } + .frame(width: 40, height: 40) + } + Button { + // do something + } label: { + Group { + Image(.icAddCalendar) + } + .frame(width: 40, height: 40) } + Spacer() + Button { + // do something + } label: { + Group { + Image(.icFavorite) + } + .frame(width: 56, height: 56) + .background(Color(.secondaryContainer)) + .clipShape(RoundedRectangle(cornerRadius: 16)) + } + } + .frame(height: 80) + .frame(maxWidth: .infinity) + .padding(.horizontal, 16) + .background(Color(.surfaceContainer)) + } + + var sessionDetail: some View { + VStack(alignment: .leading, spacing: 20) { + Text("DroidKaigiアプリで見るアーキテクチャの変遷") + .font(.title) + .foregroundStyle(Color(.surfaceVariant)) + VStack(spacing: 16) { + InformationRow( + icon: Image(.icSchedule), + title: String(localized: "TimeTableDetailDate", bundle: .module), + content: "2023.09.14 / 11:20 ~ 12:00 (40分)" + ) + InformationRow( + icon: Image(.icLocationOn), + title: String(localized: "TimeTableDetailLocation", bundle: .module), + content: "Arctic Fox (1F)" + ) + InformationRow( + icon: Image(.icLanguage), + title: String(localized: "TimeTableDetailLanguage", bundle: .module), + content: "日本語(英語通訳あり)" + ) + InformationRow( + icon: Image(.icCategory), + title: String(localized: "TimeTableDetailCategory", bundle: .module), + content: "Jetpack Compose" + ) + } + .padding(16) + .overlay( + RoundedRectangle(cornerRadius: 12) + .stroke(Color(.onSurface), lineWidth: 1) + ) + + SessionDescriptionView(content: "Kotlin Coroutinesは非同期処理をシンプルに記述できるKotlinの言語機能です。実験的な機能としてこれまでも提供されてきましたがKotlin 1.3で正式にリリース予定です。Androidの誕生から10年たちアプリの利用シーンが増えたKotlin Coroutinesは非同期処理をシンプルに記述できるKotlinの言語機能です。実験的な機能としてこれまでも提供されてきましたがKotlin 1.3で正式にリリース予定です。Androidの誕生から10年たちアプリの利用シーンが増えた.") + .padding(.bottom, 24) + } + } + + var targetUser: some View { + VStack(alignment: .leading, spacing: 16) { + Text(String(localized: "TimeTableDetailApplicants", bundle: .module)) + .font(.title3) + .foregroundStyle(Color(.surfaceVariant)) + + Text("手を動かして実践してひとへのヒントとなります\nCoroutinesを使いたいと感じているひと\nよりモダンで効率的なAndroidアプリ開発に興味があるひと\n新しいパラダイムをいち早く知りたいひと\nアプリ開発が複雑だと感じるひと\nアプリ開発経験を前提としてあったほうが楽しめます") + .font(.callout) + .foregroundStyle(Color(.surfaceVariant)) + } + } + + var speaker: some View { + VStack(alignment: .leading, spacing: 16) { + Text(String(localized: "TimeTableDetailSpeaker", bundle: .module)) + .font(.title3) + .foregroundStyle(Color(.surfaceVariant)) + + HStack { + Image(.avatar) + .padding(.trailing, 24) + Text("name") + .font(.callout) + .foregroundStyle(Color(.onSurface)) + Spacer() + } + } + } + + var archive: some View { + VStack(alignment: .leading, spacing: 16) { + Text(String(localized: "TimeTableDetailArchive", bundle: .module)) + .font(.title3) + .foregroundStyle(Color(.surfaceVariant)) + + HStack { + Button { + // do something + } label: { + VStack { + Label( + title: { Text(String(localized: "TimeTableDetailSlide", bundle: .module)).foregroundStyle(Color(.onPrimary)) }, + icon: { Image(.icDocument) } + ) + } + .frame(height: 40) + .frame(maxWidth: .infinity) + .background(Color(.button)) + .clipShape(Capsule()) + } + Button { + // do something + } label: { + VStack { + Label( + title: { Text(String(localized: "TimeTableDetailVideo", bundle: .module)).foregroundStyle(Color(.onPrimary)) }, + icon: { Image(.icPlay) } + ) + } + .frame(height: 40) + .frame(maxWidth: .infinity) + .background(Color(.button)) + .clipShape(Capsule()) + } + } + } } public init(store: StoreOf) { From 1ca3866d7d45db9342cbe8ea4a13f2a388d75d5d Mon Sep 17 00:00:00 2001 From: vixer93 Date: Tue, 18 Jun 2024 22:36:23 +0900 Subject: [PATCH 2/3] Added file of sample data --- .../InformationRow.swift | 2 +- .../TimetableDetailFeature/SampleData.swift | 10 ++++++++ .../SessionDescriptionView.swift | 2 +- .../TimetableDetailView.swift | 24 +++++++++---------- 4 files changed, 24 insertions(+), 14 deletions(-) create mode 100644 app-ios/Sources/TimetableDetailFeature/SampleData.swift diff --git a/app-ios/Sources/TimetableDetailFeature/InformationRow.swift b/app-ios/Sources/TimetableDetailFeature/InformationRow.swift index efaff87be..958e5feb7 100644 --- a/app-ios/Sources/TimetableDetailFeature/InformationRow.swift +++ b/app-ios/Sources/TimetableDetailFeature/InformationRow.swift @@ -42,7 +42,7 @@ public struct InformationRow: View { InformationRow( icon: Image(systemName: "clock"), title: String(localized: "TimeTableDetailDate", bundle: .module), - content: "2023.09.14 / 11:20 ~ 12:00 (40分)" + content: SampleData.dateValue ) } diff --git a/app-ios/Sources/TimetableDetailFeature/SampleData.swift b/app-ios/Sources/TimetableDetailFeature/SampleData.swift new file mode 100644 index 000000000..c37c4b99b --- /dev/null +++ b/app-ios/Sources/TimetableDetailFeature/SampleData.swift @@ -0,0 +1,10 @@ +enum SampleData { + static let title = "DroidKaigiアプリで見るアーキテクチャの変遷" + static let dateValue = "2023.09.14 / 11:20 ~ 12:00 (40分)" + static let locationValue = "Arctic Fox (1F)" + static let languageValue = "日本語(英語通訳あり)" + static let categoryValue = "Jetpack Compose" + static let sessionDescription = "Kotlin Coroutinesは非同期処理をシンプルに記述できるKotlinの言語機能です。実験的な機能としてこれまでも提供されてきましたがKotlin 1.3で正式にリリース予定です。Androidの誕生から10年たちアプリの利用シーンが増えたKotlin Coroutinesは非同期処理をシンプルに記述できるKotlinの言語機能です。実験的な機能としてこれまでも提供されてきましたがKotlin 1.3で正式にリリース予定です。Androidの誕生から10年たちアプリの利用シーンが増えた." + static let applicants = "手を動かして実践してひとへのヒントとなります\nCoroutinesを使いたいと感じているひと\nよりモダンで効率的なAndroidアプリ開発に興味があるひと\n新しいパラダイムをいち早く知りたいひと\nアプリ開発が複雑だと感じるひと\nアプリ開発経験を前提としてあったほうが楽しめます" + static let name = "name" +} diff --git a/app-ios/Sources/TimetableDetailFeature/SessionDescriptionView.swift b/app-ios/Sources/TimetableDetailFeature/SessionDescriptionView.swift index f88661ab0..8e8ceaff3 100644 --- a/app-ios/Sources/TimetableDetailFeature/SessionDescriptionView.swift +++ b/app-ios/Sources/TimetableDetailFeature/SessionDescriptionView.swift @@ -47,7 +47,7 @@ struct SessionDescriptionView: View { #Preview { VStack { - SessionDescriptionView(content: "Kotlin Coroutinesは非同期処理をシンプルに記述できるKotlinの言語機能です。実験的な機能としてこれまでも提供されてきましたがKotlin 1.3で正式にリリース予定です。Androidの誕生から10年たちアプリの利用シーンが増えたKotlin Coroutinesは非同期処理をシンプルに記述できるKotlinの言語機能です。実験的な機能としてこれまでも提供されてきましたがKotlin 1.3で正式にリリース予定です。Androidの誕生から10年たちアプリの利用シーンが増えた.") + SessionDescriptionView(content: SampleData.sessionDescription) .padding(.horizontal, 16) } .background(Color(.background)) diff --git a/app-ios/Sources/TimetableDetailFeature/TimetableDetailView.swift b/app-ios/Sources/TimetableDetailFeature/TimetableDetailView.swift index 128ffc0bb..d78597c56 100644 --- a/app-ios/Sources/TimetableDetailFeature/TimetableDetailView.swift +++ b/app-ios/Sources/TimetableDetailFeature/TimetableDetailView.swift @@ -68,31 +68,31 @@ public struct TimetableDetailView: View { .background(Color(.surfaceContainer)) } - var sessionDetail: some View { + @ViewBuilder var sessionDetail: some View { VStack(alignment: .leading, spacing: 20) { - Text("DroidKaigiアプリで見るアーキテクチャの変遷") + Text(SampleData.title) .font(.title) .foregroundStyle(Color(.surfaceVariant)) VStack(spacing: 16) { InformationRow( icon: Image(.icSchedule), title: String(localized: "TimeTableDetailDate", bundle: .module), - content: "2023.09.14 / 11:20 ~ 12:00 (40分)" + content: SampleData.dateValue ) InformationRow( icon: Image(.icLocationOn), title: String(localized: "TimeTableDetailLocation", bundle: .module), - content: "Arctic Fox (1F)" + content: SampleData.locationValue ) InformationRow( icon: Image(.icLanguage), title: String(localized: "TimeTableDetailLanguage", bundle: .module), - content: "日本語(英語通訳あり)" + content: SampleData.languageValue ) InformationRow( icon: Image(.icCategory), title: String(localized: "TimeTableDetailCategory", bundle: .module), - content: "Jetpack Compose" + content: SampleData.categoryValue ) } .padding(16) @@ -101,24 +101,24 @@ public struct TimetableDetailView: View { .stroke(Color(.onSurface), lineWidth: 1) ) - SessionDescriptionView(content: "Kotlin Coroutinesは非同期処理をシンプルに記述できるKotlinの言語機能です。実験的な機能としてこれまでも提供されてきましたがKotlin 1.3で正式にリリース予定です。Androidの誕生から10年たちアプリの利用シーンが増えたKotlin Coroutinesは非同期処理をシンプルに記述できるKotlinの言語機能です。実験的な機能としてこれまでも提供されてきましたがKotlin 1.3で正式にリリース予定です。Androidの誕生から10年たちアプリの利用シーンが増えた.") + SessionDescriptionView(content: SampleData.sessionDescription) .padding(.bottom, 24) } } - var targetUser: some View { + @ViewBuilder var targetUser: some View { VStack(alignment: .leading, spacing: 16) { Text(String(localized: "TimeTableDetailApplicants", bundle: .module)) .font(.title3) .foregroundStyle(Color(.surfaceVariant)) - Text("手を動かして実践してひとへのヒントとなります\nCoroutinesを使いたいと感じているひと\nよりモダンで効率的なAndroidアプリ開発に興味があるひと\n新しいパラダイムをいち早く知りたいひと\nアプリ開発が複雑だと感じるひと\nアプリ開発経験を前提としてあったほうが楽しめます") + Text(SampleData.applicants) .font(.callout) .foregroundStyle(Color(.surfaceVariant)) } } - var speaker: some View { + @ViewBuilder var speaker: some View { VStack(alignment: .leading, spacing: 16) { Text(String(localized: "TimeTableDetailSpeaker", bundle: .module)) .font(.title3) @@ -127,7 +127,7 @@ public struct TimetableDetailView: View { HStack { Image(.avatar) .padding(.trailing, 24) - Text("name") + Text(SampleData.name) .font(.callout) .foregroundStyle(Color(.onSurface)) Spacer() @@ -135,7 +135,7 @@ public struct TimetableDetailView: View { } } - var archive: some View { + @ViewBuilder var archive: some View { VStack(alignment: .leading, spacing: 16) { Text(String(localized: "TimeTableDetailArchive", bundle: .module)) .font(.title3) From be50f0527e9ea1b391dac64c9f473191b0916bac Mon Sep 17 00:00:00 2001 From: vixer93 Date: Fri, 21 Jun 2024 00:41:36 +0900 Subject: [PATCH 3/3] Delete public accessor from InformationRow --- app-ios/Sources/TimetableDetailFeature/InformationRow.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app-ios/Sources/TimetableDetailFeature/InformationRow.swift b/app-ios/Sources/TimetableDetailFeature/InformationRow.swift index 958e5feb7..907d52b9f 100644 --- a/app-ios/Sources/TimetableDetailFeature/InformationRow.swift +++ b/app-ios/Sources/TimetableDetailFeature/InformationRow.swift @@ -1,11 +1,11 @@ import SwiftUI -public struct InformationRow: View { +struct InformationRow: View { private let icon: Image private let title: String private let content: String - public init( + init( icon: Image, title: String, content: String @@ -15,7 +15,7 @@ public struct InformationRow: View { self.content = content } - public var body: some View { + var body: some View { HStack { icon HStack(spacing: 12) {