Add bitcoin icon to bitcoin hashtags
Changelog-Added: Add bitcoin icon to bitcoin hashtags
This commit is contained in:
@@ -136,6 +136,8 @@
|
|||||||
4C75EFBB2804A34C0006080F /* ProofOfWork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C75EFBA2804A34C0006080F /* ProofOfWork.swift */; };
|
4C75EFBB2804A34C0006080F /* ProofOfWork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C75EFBA2804A34C0006080F /* ProofOfWork.swift */; };
|
||||||
4C7FF7D52823313F009601DB /* Mentions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7FF7D42823313F009601DB /* Mentions.swift */; };
|
4C7FF7D52823313F009601DB /* Mentions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7FF7D42823313F009601DB /* Mentions.swift */; };
|
||||||
4C8682872814DE470026224F /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8682862814DE470026224F /* ProfileView.swift */; };
|
4C8682872814DE470026224F /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8682862814DE470026224F /* ProfileView.swift */; };
|
||||||
|
4C8D00C829DF791C0036AF10 /* CompatibleAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D00C729DF791C0036AF10 /* CompatibleAttribute.swift */; };
|
||||||
|
4C8D00CA29DF80350036AF10 /* TruncatedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D00C929DF80350036AF10 /* TruncatedText.swift */; };
|
||||||
4C8EC52529D1FA6C0085D9A8 /* DamusColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */; };
|
4C8EC52529D1FA6C0085D9A8 /* DamusColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */; };
|
||||||
4C90BD162839DB54008EE7EF /* NostrMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C90BD152839DB54008EE7EF /* NostrMetadata.swift */; };
|
4C90BD162839DB54008EE7EF /* NostrMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C90BD152839DB54008EE7EF /* NostrMetadata.swift */; };
|
||||||
4C90BD18283A9EE5008EE7EF /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C90BD17283A9EE5008EE7EF /* LoginView.swift */; };
|
4C90BD18283A9EE5008EE7EF /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C90BD17283A9EE5008EE7EF /* LoginView.swift */; };
|
||||||
@@ -535,6 +537,8 @@
|
|||||||
4C75EFBA2804A34C0006080F /* ProofOfWork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProofOfWork.swift; sourceTree = "<group>"; };
|
4C75EFBA2804A34C0006080F /* ProofOfWork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProofOfWork.swift; sourceTree = "<group>"; };
|
||||||
4C7FF7D42823313F009601DB /* Mentions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mentions.swift; sourceTree = "<group>"; };
|
4C7FF7D42823313F009601DB /* Mentions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mentions.swift; sourceTree = "<group>"; };
|
||||||
4C8682862814DE470026224F /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = "<group>"; };
|
4C8682862814DE470026224F /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = "<group>"; };
|
||||||
|
4C8D00C729DF791C0036AF10 /* CompatibleAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompatibleAttribute.swift; sourceTree = "<group>"; };
|
||||||
|
4C8D00C929DF80350036AF10 /* TruncatedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TruncatedText.swift; sourceTree = "<group>"; };
|
||||||
4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusColors.swift; sourceTree = "<group>"; };
|
4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusColors.swift; sourceTree = "<group>"; };
|
||||||
4C90BD152839DB54008EE7EF /* NostrMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrMetadata.swift; sourceTree = "<group>"; };
|
4C90BD152839DB54008EE7EF /* NostrMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrMetadata.swift; sourceTree = "<group>"; };
|
||||||
4C90BD17283A9EE5008EE7EF /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; };
|
4C90BD17283A9EE5008EE7EF /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; };
|
||||||
@@ -983,6 +987,7 @@
|
|||||||
4C9BB83029C0ED4F00FC4E37 /* DisplayName.swift */,
|
4C9BB83029C0ED4F00FC4E37 /* DisplayName.swift */,
|
||||||
4CE4F0F129D4FCFA005914DB /* DebouncedOnChange.swift */,
|
4CE4F0F129D4FCFA005914DB /* DebouncedOnChange.swift */,
|
||||||
4C1A9A1929DCA17E00516EAC /* ReplyCounter.swift */,
|
4C1A9A1929DCA17E00516EAC /* ReplyCounter.swift */,
|
||||||
|
4C8D00C729DF791C0036AF10 /* CompatibleAttribute.swift */,
|
||||||
);
|
);
|
||||||
path = Util;
|
path = Util;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1102,6 +1107,7 @@
|
|||||||
4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */,
|
4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */,
|
||||||
4CE4F0F729DB7399005914DB /* ThiccDivider.swift */,
|
4CE4F0F729DB7399005914DB /* ThiccDivider.swift */,
|
||||||
4C1A9A2229DDDB8100516EAC /* IconLabel.swift */,
|
4C1A9A2229DDDB8100516EAC /* IconLabel.swift */,
|
||||||
|
4C8D00C929DF80350036AF10 /* TruncatedText.swift */,
|
||||||
);
|
);
|
||||||
path = Components;
|
path = Components;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1487,6 +1493,7 @@
|
|||||||
4C285C8A2838B985008A31F1 /* ProfilePictureSelector.swift in Sources */,
|
4C285C8A2838B985008A31F1 /* ProfilePictureSelector.swift in Sources */,
|
||||||
4C9F18E429ABDE6D008C55EC /* MaybeAnonPfpView.swift in Sources */,
|
4C9F18E429ABDE6D008C55EC /* MaybeAnonPfpView.swift in Sources */,
|
||||||
4C75EFB92804A2740006080F /* EventView.swift in Sources */,
|
4C75EFB92804A2740006080F /* EventView.swift in Sources */,
|
||||||
|
4C8D00C829DF791C0036AF10 /* CompatibleAttribute.swift in Sources */,
|
||||||
3AA247FD297E3CFF0090C62D /* RepostsModel.swift in Sources */,
|
3AA247FD297E3CFF0090C62D /* RepostsModel.swift in Sources */,
|
||||||
F75BA12F29A18EF500E10810 /* BookmarksView.swift in Sources */,
|
F75BA12F29A18EF500E10810 /* BookmarksView.swift in Sources */,
|
||||||
4CB883B6297730E400DC99E7 /* LNUrls.swift in Sources */,
|
4CB883B6297730E400DC99E7 /* LNUrls.swift in Sources */,
|
||||||
@@ -1513,6 +1520,7 @@
|
|||||||
4CE4F9DE2852768D00C00DD9 /* ConfigView.swift in Sources */,
|
4CE4F9DE2852768D00C00DD9 /* ConfigView.swift in Sources */,
|
||||||
4C285C8E28399BFE008A31F1 /* SaveKeysView.swift in Sources */,
|
4C285C8E28399BFE008A31F1 /* SaveKeysView.swift in Sources */,
|
||||||
F7F0BA25297892BD009531F3 /* SwipeToDismiss.swift in Sources */,
|
F7F0BA25297892BD009531F3 /* SwipeToDismiss.swift in Sources */,
|
||||||
|
4C8D00CA29DF80350036AF10 /* TruncatedText.swift in Sources */,
|
||||||
4C9BB83429C12D9900FC4E37 /* EventProfileName.swift in Sources */,
|
4C9BB83429C12D9900FC4E37 /* EventProfileName.swift in Sources */,
|
||||||
4CB8838F296F781C00DC99E7 /* ReactionsView.swift in Sources */,
|
4CB8838F296F781C00DC99E7 /* ReactionsView.swift in Sources */,
|
||||||
4C649844285A952100EAE2B3 /* LocalUserConfig.swift in Sources */,
|
4C649844285A952100EAE2B3 /* LocalUserConfig.swift in Sources */,
|
||||||
|
|||||||
23
damus/Assets.xcassets/bitcoin-hashtag.imageset/Contents.json
vendored
Normal file
23
damus/Assets.xcassets/bitcoin-hashtag.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "bitcoin-hashtag.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "bitcoin-hashtag.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "bitcoin-hashtag.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
43
damus/Assets.xcassets/bitcoin-hashtag.imageset/bitcoin-hashtag.svg
vendored
Normal file
43
damus/Assets.xcassets/bitcoin-hashtag.imageset/bitcoin-hashtag.svg
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
width="9.5679588"
|
||||||
|
height="12.664063"
|
||||||
|
viewBox="0 0 9.5679588 12.664063"
|
||||||
|
version="1.1"
|
||||||
|
id="svg2"
|
||||||
|
sodipodi:docname="bitcoin-hashtag.svg"
|
||||||
|
inkscape:version="1.3-dev (77bc73e, 2022-05-18)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview2"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="31.12"
|
||||||
|
inkscape:cx="4.2095116"
|
||||||
|
inkscape:cy="7.4710797"
|
||||||
|
inkscape:window-width="1571"
|
||||||
|
inkscape:window-height="957"
|
||||||
|
inkscape:window-x="1707"
|
||||||
|
inkscape:window-y="66"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="svg2" />
|
||||||
|
<g
|
||||||
|
id="surface1"
|
||||||
|
transform="translate(-4.867188,-3.484375)">
|
||||||
|
<path
|
||||||
|
style="fill:#f59119;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
d="M 14.410156,8.574219 C 14.609375,7.246094 13.59375,6.53125 12.210938,6.050781 L 12.660156,4.25 11.5625,3.976562 11.125,5.730469 C 10.835938,5.660156 10.539062,5.589844 10.246094,5.523438 L 10.6875,3.757812 9.589844,3.484375 9.140625,5.285156 C 8.902344,5.230469 8.667969,5.179688 8.4375,5.121094 L 8.441406,5.117188 6.925781,4.738281 6.636719,5.910156 c 0,0 0.8125,0.1875 0.796875,0.199219 C 7.875,6.21875 7.957031,6.511719 7.941406,6.746094 L 7.429688,8.800781 C 7.460938,8.808594 7.5,8.820312 7.546875,8.835938 l -0.117187,-0.027344 -0.71875,2.875 c -0.054688,0.136718 -0.191407,0.339844 -0.5,0.261718 0.00781,0.01563 -0.800782,-0.199218 -0.800782,-0.199218 L 4.867188,13 6.296875,13.359375 c 0.265625,0.06641 0.523437,0.132813 0.78125,0.199219 L 6.621094,15.382812 7.71875,15.65625 8.167969,13.851562 c 0.300781,0.08203 0.589843,0.15625 0.875,0.226563 L 8.59375,15.875 l 1.097656,0.273438 0.453125,-1.820313 c 1.871094,0.355469 3.28125,0.210937 3.871094,-1.480469 0.476563,-1.363281 -0.02344,-2.148437 -1.007813,-2.660156 0.71875,-0.167969 1.257813,-0.636719 1.402344,-1.613281 z m -2.507812,3.515625 C 11.5625,13.453125 9.269531,12.71875 8.523438,12.53125 l 0.605468,-2.414062 c 0.742188,0.183593 3.125,0.550781 2.773438,1.972656 z M 12.242188,8.554688 C 11.933594,9.796875 10.023438,9.164062 9.402344,9.011719 L 9.949219,6.820312 c 0.621093,0.15625 2.613281,0.441407 2.292969,1.734376 z m 0,0"
|
||||||
|
id="path2" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -65,9 +65,9 @@ struct TranslateView: View {
|
|||||||
.padding([.top, .bottom], 10)
|
.padding([.top, .bottom], 10)
|
||||||
|
|
||||||
if self.size == .selected {
|
if self.size == .selected {
|
||||||
SelectableText(attributedString: artifacts.content, size: self.size)
|
SelectableText(attributedString: artifacts.content.attributed, size: self.size)
|
||||||
} else {
|
} else {
|
||||||
Text(artifacts.content)
|
artifacts.content.text
|
||||||
.font(eventviewsize_to_font(self.size))
|
.font(eventviewsize_to_font(self.size))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
53
damus/Components/TruncatedText.swift
Normal file
53
damus/Components/TruncatedText.swift
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// TruncatedText.swift
|
||||||
|
// damus
|
||||||
|
//
|
||||||
|
// Created by William Casarin on 2023-04-06.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct TruncatedText: View {
|
||||||
|
let text: CompatibleText
|
||||||
|
let maxChars: Int = 280
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
let truncatedAttributedString: AttributedString? = getTruncatedString()
|
||||||
|
|
||||||
|
if let truncatedAttributedString {
|
||||||
|
Text(truncatedAttributedString)
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
} else {
|
||||||
|
text.text
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
if truncatedAttributedString != nil {
|
||||||
|
Spacer()
|
||||||
|
Button(NSLocalizedString("Show more", comment: "Button to show entire note.")) { }
|
||||||
|
.allowsHitTesting(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTruncatedString() -> AttributedString? {
|
||||||
|
let nsAttributedString = NSAttributedString(text.attributed)
|
||||||
|
if nsAttributedString.length < maxChars { return nil }
|
||||||
|
|
||||||
|
let range = NSRange(location: 0, length: maxChars)
|
||||||
|
let truncatedAttributedString = nsAttributedString.attributedSubstring(from: range)
|
||||||
|
|
||||||
|
return AttributedString(truncatedAttributedString) + "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TruncatedText_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
VStack(spacing: 100) {
|
||||||
|
TruncatedText(text: CompatibleText(stringLiteral: "hello\nthere\none\ntwo\nthree\nfour\nfive\nsix\nseven\neight\nnine\nten\neleven"))
|
||||||
|
.frame(width: 200, height: 200)
|
||||||
|
|
||||||
|
TruncatedText(text: CompatibleText(stringLiteral: "hello\nthere\none\ntwo\nthree\nfour"))
|
||||||
|
.frame(width: 200, height: 200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1011,7 +1011,7 @@ func process_local_notification(damus_state: DamusState, event ev: NostrEvent) {
|
|||||||
for block in ev.blocks(damus_state.keypair.privkey) {
|
for block in ev.blocks(damus_state.keypair.privkey) {
|
||||||
if case .mention(let mention) = block, mention.ref.ref_id == damus_state.keypair.pubkey,
|
if case .mention(let mention) = block, mention.ref.ref_id == damus_state.keypair.pubkey,
|
||||||
let displayName = damus_state.profiles.lookup(id: ev.pubkey)?.display_name {
|
let displayName = damus_state.profiles.lookup(id: ev.pubkey)?.display_name {
|
||||||
let justContent = NSAttributedString(render_note_content(ev: ev, profiles: damus_state.profiles, privkey: damus_state.keypair.privkey).content).string
|
let justContent = NSAttributedString(render_note_content(ev: ev, profiles: damus_state.profiles, privkey: damus_state.keypair.privkey).content.attributed).string
|
||||||
create_local_notification(displayName: displayName, conversation: justContent, type: type)
|
create_local_notification(displayName: displayName, conversation: justContent, type: type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
44
damus/Util/CompatibleAttribute.swift
Normal file
44
damus/Util/CompatibleAttribute.swift
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// CompatibleAttribute.swift
|
||||||
|
// damus
|
||||||
|
//
|
||||||
|
// Created by William Casarin on 2023-04-06.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
class CompatibleText: Equatable {
|
||||||
|
var text: Text
|
||||||
|
var attributed: AttributedString
|
||||||
|
|
||||||
|
init() {
|
||||||
|
self.text = Text("")
|
||||||
|
self.attributed = AttributedString(stringLiteral: "")
|
||||||
|
}
|
||||||
|
|
||||||
|
init(stringLiteral: String) {
|
||||||
|
self.text = Text(stringLiteral)
|
||||||
|
self.attributed = AttributedString(stringLiteral: stringLiteral)
|
||||||
|
}
|
||||||
|
|
||||||
|
init(text: Text, attributed: AttributedString) {
|
||||||
|
self.text = text
|
||||||
|
self.attributed = attributed
|
||||||
|
}
|
||||||
|
|
||||||
|
init(attributed: AttributedString) {
|
||||||
|
self.text = Text(attributed)
|
||||||
|
self.attributed = attributed
|
||||||
|
}
|
||||||
|
|
||||||
|
static func == (lhs: CompatibleText, rhs: CompatibleText) -> Bool {
|
||||||
|
return lhs.attributed == rhs.attributed
|
||||||
|
}
|
||||||
|
|
||||||
|
static func +(lhs: CompatibleText, rhs: CompatibleText) -> CompatibleText {
|
||||||
|
let combinedText = lhs.text + rhs.text
|
||||||
|
let combinedAttributes = lhs.attributed + rhs.attributed
|
||||||
|
return CompatibleText(text: combinedText, attributed: combinedAttributes)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,8 +60,15 @@ struct NoteContentView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var truncatedText: some View {
|
var truncatedText: some View {
|
||||||
TruncatedText(text: artifacts.content, maxChars: (truncate ? 280 : nil))
|
Group {
|
||||||
.font(eventviewsize_to_font(size))
|
if truncate {
|
||||||
|
TruncatedText(text: artifacts.content)
|
||||||
|
.font(eventviewsize_to_font(size))
|
||||||
|
} else {
|
||||||
|
artifacts.content.text
|
||||||
|
.font(eventviewsize_to_font(size))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var invoicesView: some View {
|
var invoicesView: some View {
|
||||||
@@ -92,10 +99,10 @@ struct NoteContentView: View {
|
|||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
if size == .selected {
|
if size == .selected {
|
||||||
if with_padding {
|
if with_padding {
|
||||||
SelectableText(attributedString: artifacts.content, size: self.size)
|
SelectableText(attributedString: artifacts.content.attributed, size: self.size)
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
} else {
|
} else {
|
||||||
SelectableText(attributedString: artifacts.content, size: self.size)
|
SelectableText(attributedString: artifacts.content.attributed, size: self.size)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if with_padding {
|
if with_padding {
|
||||||
@@ -198,27 +205,49 @@ struct NoteContentView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hashtag_str(_ htag: String) -> AttributedString {
|
enum ImageName {
|
||||||
|
case systemImage(String)
|
||||||
|
case image(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
func attributed_string_attach_icon(_ astr: inout AttributedString, img: UIImage) {
|
||||||
|
let attachment = NSTextAttachment()
|
||||||
|
attachment.image = img
|
||||||
|
let attachmentString = NSAttributedString(attachment: attachment)
|
||||||
|
let wrapped = AttributedString(attachmentString)
|
||||||
|
astr.append(wrapped)
|
||||||
|
}
|
||||||
|
|
||||||
|
func hashtag_str(_ htag: String) -> CompatibleText {
|
||||||
var attributedString = AttributedString(stringLiteral: "#\(htag)")
|
var attributedString = AttributedString(stringLiteral: "#\(htag)")
|
||||||
attributedString.link = URL(string: "damus:t:\(htag)")
|
attributedString.link = URL(string: "damus:t:\(htag)")
|
||||||
|
|
||||||
|
var text = Text(attributedString)
|
||||||
|
|
||||||
if htag.lowercased() == "bitcoin" {
|
if htag.lowercased() == "bitcoin" {
|
||||||
attributedString.foregroundColor = Color.orange
|
attributedString.foregroundColor = Color.orange
|
||||||
|
if let img = UIImage(named: "bitcoin-hashtag") {
|
||||||
|
attributedString = attributedString + " "
|
||||||
|
attributed_string_attach_icon(&attributedString, img: img)
|
||||||
|
}
|
||||||
|
let img = Image("bitcoin-hashtag")
|
||||||
|
text = text.foregroundColor(.orange) + Text(" \(img)")
|
||||||
} else {
|
} else {
|
||||||
attributedString.foregroundColor = DamusColors.purple
|
attributedString.foregroundColor = DamusColors.purple
|
||||||
}
|
}
|
||||||
|
|
||||||
return attributedString
|
return CompatibleText(text: text, attributed: attributedString)
|
||||||
}
|
}
|
||||||
|
|
||||||
func url_str(_ url: URL) -> AttributedString {
|
func url_str(_ url: URL) -> CompatibleText {
|
||||||
var attributedString = AttributedString(stringLiteral: url.absoluteString)
|
var attributedString = AttributedString(stringLiteral: url.absoluteString)
|
||||||
attributedString.link = url
|
attributedString.link = url
|
||||||
attributedString.foregroundColor = DamusColors.purple
|
attributedString.foregroundColor = DamusColors.purple
|
||||||
return attributedString
|
|
||||||
|
return CompatibleText(attributed: attributedString)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mention_str(_ m: Mention, profiles: Profiles) -> AttributedString {
|
func mention_str(_ m: Mention, profiles: Profiles) -> CompatibleText {
|
||||||
switch m.type {
|
switch m.type {
|
||||||
case .pubkey:
|
case .pubkey:
|
||||||
let pk = m.ref.ref_id
|
let pk = m.ref.ref_id
|
||||||
@@ -227,13 +256,15 @@ func mention_str(_ m: Mention, profiles: Profiles) -> AttributedString {
|
|||||||
var attributedString = AttributedString(stringLiteral: "@\(disp)")
|
var attributedString = AttributedString(stringLiteral: "@\(disp)")
|
||||||
attributedString.link = URL(string: "damus:\(encode_pubkey_uri(m.ref))")
|
attributedString.link = URL(string: "damus:\(encode_pubkey_uri(m.ref))")
|
||||||
attributedString.foregroundColor = DamusColors.purple
|
attributedString.foregroundColor = DamusColors.purple
|
||||||
return attributedString
|
|
||||||
|
return CompatibleText(attributed: attributedString)
|
||||||
case .event:
|
case .event:
|
||||||
let bevid = bech32_note_id(m.ref.ref_id) ?? m.ref.ref_id
|
let bevid = bech32_note_id(m.ref.ref_id) ?? m.ref.ref_id
|
||||||
var attributedString = AttributedString(stringLiteral: "@\(abbrev_pubkey(bevid))")
|
var attributedString = AttributedString(stringLiteral: "@\(abbrev_pubkey(bevid))")
|
||||||
attributedString.link = URL(string: "damus:\(encode_event_id_uri(m.ref))")
|
attributedString.link = URL(string: "damus:\(encode_event_id_uri(m.ref))")
|
||||||
attributedString.foregroundColor = DamusColors.purple
|
attributedString.foregroundColor = DamusColors.purple
|
||||||
return attributedString
|
|
||||||
|
return CompatibleText(attributed: attributedString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +272,8 @@ struct NoteContentView_Previews: PreviewProvider {
|
|||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let state = test_damus_state()
|
let state = test_damus_state()
|
||||||
let content = "hi there ¯\\_(ツ)_/¯ https://jb55.com/s/Oct12-150217.png 5739a762ef6124dd.jpg"
|
let content = "hi there ¯\\_(ツ)_/¯ https://jb55.com/s/Oct12-150217.png 5739a762ef6124dd.jpg"
|
||||||
let artifacts = NoteArtifacts(content: AttributedString(stringLiteral: content), images: [], invoices: [], links: [])
|
let txt = CompatibleText(attributed: AttributedString(stringLiteral: content))
|
||||||
|
let artifacts = NoteArtifacts(content: txt, images: [], invoices: [], links: [])
|
||||||
NoteContentView(damus_state: state, event: NostrEvent(content: content, pubkey: "pk"), show_images: true, size: .normal, artifacts: artifacts, options: [])
|
NoteContentView(damus_state: state, event: NostrEvent(content: content, pubkey: "pk"), show_images: true, size: .normal, artifacts: artifacts, options: [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,13 +283,14 @@ struct NoteArtifacts: Equatable {
|
|||||||
return lhs.content == rhs.content
|
return lhs.content == rhs.content
|
||||||
}
|
}
|
||||||
|
|
||||||
let content: AttributedString
|
let content: CompatibleText
|
||||||
let images: [URL]
|
let images: [URL]
|
||||||
let invoices: [Invoice]
|
let invoices: [Invoice]
|
||||||
let links: [URL]
|
let links: [URL]
|
||||||
|
|
||||||
static func just_content(_ content: String) -> NoteArtifacts {
|
static func just_content(_ content: String) -> NoteArtifacts {
|
||||||
NoteArtifacts(content: AttributedString(stringLiteral: content), images: [], invoices: [], links: [])
|
let txt = CompatibleText(attributed: AttributedString(stringLiteral: content))
|
||||||
|
return NoteArtifacts(content: txt, images: [], invoices: [], links: [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +310,7 @@ func render_blocks(blocks: [Block], profiles: Profiles, privkey: String?) -> Not
|
|||||||
.count == 1
|
.count == 1
|
||||||
|
|
||||||
var ind: Int = -1
|
var ind: Int = -1
|
||||||
let txt: AttributedString = blocks.reduce("") { str, block in
|
let txt: CompatibleText = blocks.reduce(CompatibleText()) { str, block in
|
||||||
ind = ind + 1
|
ind = ind + 1
|
||||||
|
|
||||||
switch block {
|
switch block {
|
||||||
@@ -300,7 +333,7 @@ func render_blocks(blocks: [Block], profiles: Profiles, privkey: String?) -> Not
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return str + AttributedString(stringLiteral: trimmed)
|
return str + CompatibleText(stringLiteral: trimmed)
|
||||||
case .hashtag(let htag):
|
case .hashtag(let htag):
|
||||||
return str + hashtag_str(htag)
|
return str + hashtag_str(htag)
|
||||||
case .invoice(let invoice):
|
case .invoice(let invoice):
|
||||||
@@ -349,36 +382,6 @@ func load_cached_preview(previews: PreviewCache, evid: String) -> LinkViewRepres
|
|||||||
return LinkViewRepresentable(meta: .linkmeta(meta))
|
return LinkViewRepresentable(meta: .linkmeta(meta))
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TruncatedText: View {
|
|
||||||
|
|
||||||
let text: AttributedString
|
|
||||||
let maxChars: Int?
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
let truncatedAttributedString: AttributedString? = getTruncatedString()
|
|
||||||
|
|
||||||
Text(truncatedAttributedString ?? text)
|
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
|
||||||
|
|
||||||
if truncatedAttributedString != nil {
|
|
||||||
Spacer()
|
|
||||||
Button(NSLocalizedString("Show more", comment: "Button to show entire note.")) { }
|
|
||||||
.allowsHitTesting(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTruncatedString() -> AttributedString? {
|
|
||||||
guard let maxChars = maxChars else { return nil }
|
|
||||||
let nsAttributedString = NSAttributedString(text)
|
|
||||||
if nsAttributedString.length < maxChars { return nil }
|
|
||||||
|
|
||||||
let range = NSRange(location: 0, length: maxChars)
|
|
||||||
let truncatedAttributedString = nsAttributedString.attributedSubstring(from: range)
|
|
||||||
|
|
||||||
return AttributedString(truncatedAttributedString) + "..."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// trim suffix whitespace and newlines
|
// trim suffix whitespace and newlines
|
||||||
func trim_suffix(_ str: String) -> String {
|
func trim_suffix(_ str: String) -> String {
|
||||||
|
|||||||
Reference in New Issue
Block a user