From 8e0663377bbc526c5a1ed27b4234e382d16f2557 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 9 May 2023 20:11:43 +0400 Subject: [PATCH] read more less wip --- .../Shared/Views/Chat/ChatItemInfoView.swift | 96 ++++++++++++++++++- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift b/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift index 4e5861f46..b0508e100 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift @@ -76,13 +76,12 @@ struct ChatItemInfoView: View { set: { _ in } ) VStack(alignment: .leading, spacing: 4) { - messageText(itemVersion.msgContent.text, parseSimpleXMarkdown(itemVersion.msgContent.text), nil) - .allowsHitTesting(false) + ExpandableText(itemVersion.msgContent.text, lineLimit: 3) .padding(.horizontal, 12) .padding(.vertical, 6) .background(ciDirFrameColor(chatItemSent: chatItemSent, colorScheme: colorScheme)) .cornerRadius(18) - .uiKitContextMenu(menu: uiMenu) + // .uiKitContextMenu(menu: uiMenu) Text(localTimestamp(itemVersion.itemVersionTs) + (current ? " (Current)" : "")) .foregroundStyle(.secondary) .font(.caption) @@ -128,6 +127,97 @@ struct ChatItemInfoView: View { } } +struct ExpandableText: View { + @State private var expanded: Bool = false + @State private var truncated: Bool = false + @State private var shrinkText: String + + private var text: String + let font: UIFont + let lineLimit: Int + + init(_ text: String, lineLimit: Int, font: UIFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)) { + self.text = text + _shrinkText = State(wrappedValue: text) + self.lineLimit = lineLimit + self.font = font + } + + var body: some View { + ZStack(alignment: .bottomLeading) { + Group { + let t = self.expanded ? text : shrinkText + messageText(t, parseSimpleXMarkdown(t), nil) + + moreLessText() + } + .lineLimit(expanded ? nil : lineLimit) + .background( + Text(text) + .lineLimit(lineLimit) + .background(GeometryReader { visibleTextGeometry in + Color.clear.onAppear() { + let size = CGSize(width: visibleTextGeometry.size.width, height: .greatestFiniteMagnitude) + let attributes:[NSAttributedString.Key:Any] = [NSAttributedString.Key.font: font] + + var low = 0 + var high = shrinkText.count + var mid = high + while ((high - low) > 1) { + let attributedText = NSAttributedString(string: shrinkText + moreLessStr, attributes: attributes) + let boundingRect = attributedText.boundingRect(with: size, options: NSStringDrawingOptions.usesLineFragmentOrigin, context: nil) + if boundingRect.size.height > visibleTextGeometry.size.height { + truncated = true + high = mid + mid = (high + low) / 2 + } else { + if mid == text.count { + break + } else { + low = mid + mid = (low + high) / 2 + } + } + shrinkText = String(text.prefix(mid)).trimmingCharacters(in: .whitespaces) + } + } + }) + .hidden() + ) + .font(Font(font)) + if truncated { + Button(action: { + expanded.toggle() + }, label: { + HStack { + Spacer() + Text("") + }.opacity(0) + }) + } + } + } + + private var moreLessStr: String { + if !truncated { + return "" + } else { + return self.expanded + ? "\n" + NSLocalizedString("Read less", comment: "long text button") + : "… " + NSLocalizedString("Read more", comment: "long text button") + } + } + + private func moreLessText() -> Text { + if !truncated { + return Text("") + } else { + return self.expanded + ? Text("\n") + Text("Read less").foregroundColor(.accentColor) + : Text("… ") + Text("Read more").foregroundColor(.accentColor) + } + } +} + func localTimestamp(_ date: Date) -> String { let localDateFormatter = DateFormatter() localDateFormatter.dateStyle = .medium