diff --git a/TsunDocsKit/Sources/TsundocListFeature/TsundocList/TsundocCell.swift b/TsunDocsKit/Sources/TsundocListFeature/TsundocList/TsundocCell.swift index b441cf5..05376c8 100644 --- a/TsunDocsKit/Sources/TsundocListFeature/TsundocList/TsundocCell.swift +++ b/TsunDocsKit/Sources/TsundocListFeature/TsundocList/TsundocCell.swift @@ -7,61 +7,81 @@ import ImageLoader import Smile import SwiftUI -struct TsundocCell: View { +struct TsundocCell: View where MenuContent: View { // MARK: - Properties @Environment(\.imageLoaderFactory) var imageLoaderFactory let tsundoc: Tsundoc + @ViewBuilder + let menuContent: () -> MenuContent // MARK: - View var body: some View { - HStack { + HStack(spacing: 4) { VStack { TsundocThumbnail(source: tsundoc.thumbnailSource) .padding([.top, .trailing, .bottom], 4.0) Spacer(minLength: 0) } - VStack(alignment: .leading) { - VStack(alignment: .leading) { - Text(tsundoc.title) - .font(.headline) - .lineLimit(3) - .foregroundColor(.primary) - .padding(.top, 4.0) + VStack(spacing: 0) { + HStack { + VStack(alignment: .leading) { + VStack(alignment: .leading) { + Text(tsundoc.title) + .font(.headline) + .lineLimit(3) + .foregroundColor(.primary) + .padding(.top, 4.0) + + Spacer() + .frame(height: 8.0) + + if let description = tsundoc.description { + Text(description) + .font(.caption) + .lineLimit(3) + .foregroundColor(.secondary) + } + } + + Spacer(minLength: 0) + } + .padding(.top, 4) Spacer() - .frame(height: 8.0) - if let description = tsundoc.description { - Text(description) - .font(.subheadline) - .lineLimit(3) - .foregroundColor(.secondary) + VStack { + if tsundoc.isUnread { + Circle() + .fill(Color.accentColor) + .frame(width: 8, height: 8) + .padding([.top], 8.0) + } else { + Circle() + .fill(.clear) + .frame(width: 8, height: 8) + .padding([.top], 8.0) + } + Spacer() } } - Spacer(minLength: 0) - } - .padding(.top, 4) - - Spacer() + HStack { + Spacer() - VStack { - if tsundoc.isUnread { - Circle() - .fill(Color.accentColor) - .frame(width: 8, height: 8) - .padding([.top], 8.0) - } else { - Circle() - .fill(.clear) - .frame(width: 8, height: 8) - .padding([.top], 8.0) + Menu { + menuContent() + } label: { + Image(systemName: "ellipsis") + .foregroundColor(.secondary) + .frame(minWidth: 32, minHeight: 32) + } + // HACK: Cellのタップ判定を握りつぶす + .onTapGesture {} } - Spacer() } } .listRowInsets(EdgeInsets(top: 8, leading: 12, bottom: 8, trailing: 12)) @@ -83,66 +103,34 @@ struct TsundocCell_Previews: PreviewProvider { NavigationView { List { TsundocCell(tsundoc: .makeDefault(title: "Title only", - isUnread: true)) + isUnread: true)) { EmptyView() } .environment(\.imageLoaderFactory, .init { .init(urlSession: .makeMock(SuccessMock.self)) }) TsundocCell(tsundoc: .makeDefault(title: "Title with description", - description: "This is description of website.")) + description: "This is description of website.")) { EmptyView() } .environment(\.imageLoaderFactory, .init { .init(urlSession: .makeMock(SuccessMock.self)) }) - TsundocCell(tsundoc: .makeDefault(title: "Emoji thumbnail", emojiAlias: "smile")) + TsundocCell(tsundoc: .makeDefault(title: "Emoji thumbnail", emojiAlias: "smile")) { EmptyView() } .environment(\.imageLoaderFactory, .init { .init(urlSession: .makeMock(SuccessMock.self)) }) TsundocCell(tsundoc: .makeDefault(title: "Success image thumbnail", - imageUrl: URL(string: "http://localhost"))) + imageUrl: URL(string: "http://localhost"))) { EmptyView() } .environment(\.imageLoaderFactory, .init { .init(urlSession: .makeMock(SuccessMock.self)) }) TsundocCell(tsundoc: .makeDefault(title: "Failure image thumbnail", - imageUrl: URL(string: "http://localhost"))) + imageUrl: URL(string: "http://localhost"))) { EmptyView() } .environment(\.imageLoaderFactory, .init { .init(urlSession: .makeMock(FailureMock.self)) }) TsundocCell(tsundoc: .makeDefault(title: longString, description: longString, emojiAlias: "ghost", - isUnread: true)) + isUnread: true)) { EmptyView() } .environment(\.imageLoaderFactory, .init { .init(urlSession: .makeMock(SuccessMock.self)) }) } .listStyle(GroupedListStyle()) .navigationTitle("TsundocCell") } .preferredColorScheme(.light) - - NavigationView { - List { - TsundocCell(tsundoc: .makeDefault(title: "Title only", - isUnread: true)) - .environment(\.imageLoaderFactory, .init { .init(urlSession: .makeMock(SuccessMock.self)) }) - - TsundocCell(tsundoc: .makeDefault(title: "Title with description", - description: "This is description of website.")) - .environment(\.imageLoaderFactory, .init { .init(urlSession: .makeMock(SuccessMock.self)) }) - - TsundocCell(tsundoc: .makeDefault(title: "Emoji thumbnail", emojiAlias: "smile")) - .environment(\.imageLoaderFactory, .init { .init(urlSession: .makeMock(SuccessMock.self)) }) - - TsundocCell(tsundoc: .makeDefault(title: "Success image thumbnail", - imageUrl: URL(string: "http://localhost"))) - .environment(\.imageLoaderFactory, .init { .init(urlSession: .makeMock(SuccessMock.self)) }) - - TsundocCell(tsundoc: .makeDefault(title: "Failure image thumbnail", - imageUrl: URL(string: "http://localhost"))) - .environment(\.imageLoaderFactory, .init { .init(urlSession: .makeMock(FailureMock.self)) }) - - TsundocCell(tsundoc: .makeDefault(title: longString, - description: longString, - emojiAlias: "ghost", - isUnread: true)) - .environment(\.imageLoaderFactory, .init { .init(urlSession: .makeMock(FailureMock.self)) }) - } - .listStyle(GroupedListStyle()) - .navigationTitle("TsundocCell") - } - .preferredColorScheme(.dark) } } } diff --git a/TsunDocsKit/Sources/TsundocListFeature/TsundocList/TsundocList.swift b/TsunDocsKit/Sources/TsundocListFeature/TsundocList/TsundocList.swift index 5ee32b5..9705d9b 100644 --- a/TsunDocsKit/Sources/TsundocListFeature/TsundocList/TsundocList.swift +++ b/TsunDocsKit/Sources/TsundocListFeature/TsundocList/TsundocList.swift @@ -173,7 +173,7 @@ public struct TsundocList: View { @ViewBuilder private func cell(_ tsundoc: Tsundoc) -> some View { - TsundocCell(tsundoc: tsundoc) + TsundocCell(tsundoc: tsundoc) { menu(tsundoc) } .contentShape(Rectangle()) .onTapGesture { store.execute(.select(tsundoc))