Compare commits
12 Commits
tyiu/fix-t
...
tyiu/fix-r
| Author | SHA1 | Date | |
|---|---|---|---|
|
1f634e6e9a
|
|||
|
|
ed36a8c062 | ||
|
|
2f81a144c1 | ||
|
|
4adb26e784 | ||
|
|
707f31fca1 | ||
| 9e9077bab5 | |||
|
|
7242c0bca3 | ||
| badbd8a92e | |||
|
|
aec61906ae | ||
| 4f4557e4b6 | |||
|
|
9c6b802f19 | ||
|
|
4c7b8dc10b |
@@ -2,7 +2,7 @@
|
||||
|
||||
### Added
|
||||
|
||||
- Parse links in profiles (William Casarin)
|
||||
- Parse links in profiles (Lionello Lunesu)
|
||||
- Added Breez wallet to wallet selector (Lee Salminen)
|
||||
- Added Bitcoin Beach wallet to wallet selector (Lee Salminen)
|
||||
- Added ability to copy relay urls (Matt Ward)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
3169CAE6294E69C000EE4006 /* EmptyTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3169CAE5294E69C000EE4006 /* EmptyTimelineView.swift */; };
|
||||
3169CAED294FCCFC00EE4006 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3169CAEC294FCCFC00EE4006 /* Constants.swift */; };
|
||||
31D2E847295218AF006D67F8 /* Shimmer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D2E846295218AF006D67F8 /* Shimmer.swift */; };
|
||||
3A4325A82961E11400BFCD9D /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 3A4325AA2961E11400BFCD9D /* Localizable.stringsdict */; };
|
||||
3ACBCB78295FE5C70037388A /* TimeAgoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACBCB77295FE5C70037388A /* TimeAgoTests.swift */; };
|
||||
4C06670128FC7C5900038D2A /* RelayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C06670028FC7C5900038D2A /* RelayView.swift */; };
|
||||
4C06670428FC7EC500038D2A /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 4C06670328FC7EC500038D2A /* Kingfisher */; };
|
||||
@@ -164,6 +165,7 @@
|
||||
3169CAE5294E69C000EE4006 /* EmptyTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyTimelineView.swift; sourceTree = "<group>"; };
|
||||
3169CAEC294FCCFC00EE4006 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Constants.swift; path = damus/Util/Constants.swift; sourceTree = SOURCE_ROOT; };
|
||||
31D2E846295218AF006D67F8 /* Shimmer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shimmer.swift; sourceTree = "<group>"; };
|
||||
3A4325A92961E11400BFCD9D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
3ACBCB77295FE5C70037388A /* TimeAgoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeAgoTests.swift; sourceTree = "<group>"; };
|
||||
4C06670028FC7C5900038D2A /* RelayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayView.swift; sourceTree = "<group>"; };
|
||||
4C06670528FCB08600038D2A /* ImageCarousel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCarousel.swift; sourceTree = "<group>"; };
|
||||
@@ -593,6 +595,7 @@
|
||||
4CE6DEE827F7A08100C66700 /* ContentView.swift */,
|
||||
4CE6DEEA27F7A08200C66700 /* Assets.xcassets */,
|
||||
4CE6DEEC27F7A08200C66700 /* Preview Content */,
|
||||
3A4325AA2961E11400BFCD9D /* Localizable.stringsdict */,
|
||||
);
|
||||
path = damus;
|
||||
sourceTree = "<group>";
|
||||
@@ -755,6 +758,7 @@
|
||||
files = (
|
||||
4CE6DEEE27F7A08200C66700 /* Preview Assets.xcassets in Resources */,
|
||||
4CE6DEEB27F7A08200C66700 /* Assets.xcassets in Resources */,
|
||||
3A4325A82961E11400BFCD9D /* Localizable.stringsdict in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -938,6 +942,17 @@
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
3A4325AA2961E11400BFCD9D /* Localizable.stringsdict */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
3A4325A92961E11400BFCD9D /* en */,
|
||||
);
|
||||
name = Localizable.stringsdict;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
4CE6DF0527F7A08200C66700 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
@@ -989,7 +1004,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.3;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
@@ -1044,7 +1059,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.3;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.3;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
@@ -1070,6 +1085,7 @@
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = damus/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Damus;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||
@@ -1109,6 +1125,7 @@
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = damus/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Damus;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||
|
||||
21
damus/Assets.xcassets/blixt-wallet.imageset/Contents.json
vendored
Normal file
21
damus/Assets.xcassets/blixt-wallet.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "blixt-wallet.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/blixt-wallet.imageset/blixt-wallet.png
vendored
Normal file
BIN
damus/Assets.xcassets/blixt-wallet.imageset/blixt-wallet.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 215 KiB |
21
damus/Assets.xcassets/river.imageset/Contents.json
vendored
Normal file
21
damus/Assets.xcassets/river.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "river.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/river.imageset/river.png
vendored
Normal file
BIN
damus/Assets.xcassets/river.imageset/river.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -11,9 +11,20 @@ func open_with_wallet(wallet: Wallet.Model, invoice: String) {
|
||||
if let url = URL(string: "\(wallet.link)\(invoice)"), UIApplication.shared.canOpenURL(url) {
|
||||
UIApplication.shared.open(url)
|
||||
} else {
|
||||
if let url = URL(string: wallet.appStoreLink), UIApplication.shared.canOpenURL(url) {
|
||||
UIApplication.shared.open(url)
|
||||
guard let store_link = wallet.appStoreLink else {
|
||||
// TODO: do something here if we don't have an appstore link
|
||||
return
|
||||
}
|
||||
|
||||
guard let url = URL(string: store_link) else {
|
||||
return
|
||||
}
|
||||
|
||||
guard UIApplication.shared.canOpenURL(url) else {
|
||||
return
|
||||
}
|
||||
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ var BOOTSTRAP_RELAYS = [
|
||||
"wss://relay.nostr.bg",
|
||||
"wss://nostr.oxtr.dev",
|
||||
"wss://nostr.v0l.io",
|
||||
"wss://nostr-2.zebedee.cloud",
|
||||
"wss://brb.io",
|
||||
]
|
||||
|
||||
struct TimestampedProfile {
|
||||
@@ -82,17 +82,14 @@ struct ContentView: View {
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
var PostingTimelineView: some View {
|
||||
VStack{
|
||||
ZStack {
|
||||
if let damus = self.damus_state {
|
||||
TimelineView(events: $home.events, loading: $home.loading, damus: damus, show_friend_icon: false, filter: filter_event)
|
||||
}
|
||||
if privkey != nil {
|
||||
PostButtonContainer {
|
||||
self.active_sheet = .post
|
||||
}
|
||||
}
|
||||
}.ignoresSafeArea(.keyboard, edges: .bottom)
|
||||
VStack {
|
||||
TabView(selection: $filter_state) {
|
||||
ContentTimelineView
|
||||
.tag(FilterState.posts)
|
||||
ContentTimelineView
|
||||
.tag(FilterState.posts_and_replies)
|
||||
}
|
||||
.tabViewStyle(.page(indexDisplayMode: .never))
|
||||
}
|
||||
.safeAreaInset(edge: .top) {
|
||||
VStack(spacing: 0) {
|
||||
@@ -106,6 +103,19 @@ struct ContentView: View {
|
||||
}
|
||||
}
|
||||
|
||||
var ContentTimelineView: some View {
|
||||
ZStack {
|
||||
if let damus = self.damus_state {
|
||||
TimelineView(events: $home.events, loading: $home.loading, damus: damus, show_friend_icon: false, filter: filter_event)
|
||||
}
|
||||
if privkey != nil {
|
||||
PostButtonContainer {
|
||||
self.active_sheet = .post
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var FiltersView: some View {
|
||||
VStack{
|
||||
Picker("Filter State", selection: $filter_state) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
</array>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>river</string>
|
||||
<string>bitcoinbeach</string>
|
||||
<string>breez</string>
|
||||
<string>muun</string>
|
||||
@@ -29,6 +30,7 @@
|
||||
<string>strike</string>
|
||||
<string>bluewallet</string>
|
||||
<string>walletofsatoshi</string>
|
||||
<string>blixtwallet</string>
|
||||
</array>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
|
||||
@@ -61,7 +61,7 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
profile_filter.authors = [pubkey]
|
||||
|
||||
text_filter.authors = [pubkey]
|
||||
text_filter.limit = 1000
|
||||
text_filter.limit = 500
|
||||
|
||||
print("subscribing to profile \(pubkey) with sub_id \(sub_id)")
|
||||
print_filters(relay_id: "profile", filters: [[text_filter], [profile_filter]])
|
||||
@@ -70,12 +70,18 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
}
|
||||
|
||||
func handle_profile_contact_event(_ ev: NostrEvent) {
|
||||
process_contact_event(pool: damus.pool, contacts: damus.contacts, pubkey: damus.pubkey, ev: ev)
|
||||
|
||||
// only use new stuff
|
||||
if let current_ev = self.contacts {
|
||||
guard ev.created_at > current_ev.created_at else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
self.contacts = ev
|
||||
self.following = count_pubkeys(ev.tags)
|
||||
self.relays = decode_json_relays(ev.content)
|
||||
if damus.contacts.is_friend(ev.pubkey) {
|
||||
self.damus.contacts.add_friend_contact(ev)
|
||||
}
|
||||
}
|
||||
|
||||
func add_event(_ ev: NostrEvent) {
|
||||
@@ -90,6 +96,8 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
let _ = insert_uniq_sorted_event(events: &self.events, new_ev: ev, cmp: { $0.created_at > $1.created_at})
|
||||
} else if ev.known_kind == .contacts {
|
||||
handle_profile_contact_event(ev)
|
||||
} else if ev.known_kind == .metadata {
|
||||
process_metadata_event(profiles: damus.profiles, ev: ev)
|
||||
}
|
||||
seen_event.insert(ev.id)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ enum Wallet: String, CaseIterable, Identifiable {
|
||||
var tag: String
|
||||
var displayName : String
|
||||
var link : String
|
||||
var appStoreLink : String
|
||||
var appStoreLink : String?
|
||||
var image: String
|
||||
}
|
||||
|
||||
@@ -33,44 +33,53 @@ enum Wallet: String, CaseIterable, Identifiable {
|
||||
case phoenix
|
||||
case breez
|
||||
case bitcoinbeach
|
||||
case blixtwallet
|
||||
case river
|
||||
|
||||
var model: Model {
|
||||
switch self {
|
||||
case .system_default_wallet:
|
||||
return .init(index: -1, tag: "systemdefaultwallet", displayName: "Local default",
|
||||
return .init(index: -1, tag: "systemdefaultwallet", displayName: NSLocalizedString("Local default", comment: "Dropdown option label for system default for Lightning wallet."),
|
||||
link: "lightning:", appStoreLink: "lightning:", image: "")
|
||||
case .strike:
|
||||
return .init(index: 0, tag: "strike", displayName: "Strike", link: "strike:",
|
||||
return .init(index: 0, tag: "strike", displayName: NSLocalizedString("Strike", comment: "Dropdown option label for Lightning wallet, Strike."), link: "strike:",
|
||||
appStoreLink: "https://apps.apple.com/us/app/strike-bitcoin-payments/id1488724463", image: "strike")
|
||||
case .cashapp:
|
||||
return .init(index: 1, tag: "cashapp", displayName: "Cash App", link: "squarecash://",
|
||||
return .init(index: 1, tag: "cashapp", displayName: NSLocalizedString("Cash App", comment: "Dropdown option label for Lightning wallet, Cash App."), link: "squarecash://",
|
||||
appStoreLink: "https://apps.apple.com/us/app/cash-app/id711923939", image: "cashapp")
|
||||
case .muun:
|
||||
return .init(index: 2, tag: "muun", displayName: "Muun", link: "muun:", appStoreLink: "https://apps.apple.com/us/app/muun-wallet/id1482037683", image: "muun")
|
||||
return .init(index: 2, tag: "muun", displayName: NSLocalizedString("Muun", comment: "Dropdown option label for Lightning wallet, Muun."), link: "muun:", appStoreLink: "https://apps.apple.com/us/app/muun-wallet/id1482037683", image: "muun")
|
||||
case .bluewallet:
|
||||
return .init(index: 3, tag: "bluewallet", displayName: "Blue Wallet", link: "bluewallet:lightning:",
|
||||
return .init(index: 3, tag: "bluewallet", displayName: NSLocalizedString("Blue Wallet", comment: "Dropdown option label for Lightning wallet, Blue Wallet."), link: "bluewallet:lightning:",
|
||||
appStoreLink: "https://apps.apple.com/us/app/bluewallet-bitcoin-wallet/id1376878040", image: "bluewallet")
|
||||
case .walletofsatoshi:
|
||||
return .init(index: 4, tag: "walletofsatoshi", displayName: "Wallet Of Satoshi", link: "walletofsatoshi:lightning:",
|
||||
return .init(index: 4, tag: "walletofsatoshi", displayName: NSLocalizedString("Wallet Of Satoshi", comment: "Dropdown option label for Lightning wallet, Wallet Of Satoshi."), link: "walletofsatoshi:lightning:",
|
||||
appStoreLink: "https://apps.apple.com/us/app/wallet-of-satoshi/id1438599608", image: "walletofsatoshi")
|
||||
case .zebedee:
|
||||
return .init(index: 5, tag: "zebedee", displayName: "Zebedee", link: "zebedee:lightning:",
|
||||
return .init(index: 5, tag: "zebedee", displayName: NSLocalizedString("Zebedee", comment: "Dropdown option label for Lightning wallet, Zebedee."), link: "zebedee:lightning:",
|
||||
appStoreLink: "https://apps.apple.com/us/app/zebedee-wallet/id1484394401", image: "zebedee")
|
||||
case .zeusln:
|
||||
return .init(index: 6, tag: "zeusln", displayName: "Zeus LN", link: "zeusln:lightning:",
|
||||
return .init(index: 6, tag: "zeusln", displayName: NSLocalizedString("Zeus LN", comment: "Dropdown option label for Lightning wallet, Zeus LN."), link: "zeusln:lightning:",
|
||||
appStoreLink: "https://apps.apple.com/us/app/zeus-ln/id1456038895", image: "zeusln")
|
||||
case .lnlink:
|
||||
return .init(index: 7, tag: "lnlink", displayName: "LNLink", link: "lnlink:lightning:",
|
||||
return .init(index: 7, tag: "lnlink", displayName: NSLocalizedString("LNLink", comment: "Dropdown option label for Lightning wallet, LNLink."), link: "lnlink:lightning:",
|
||||
appStoreLink: "https://testflight.apple.com/join/aNY4yuuZ", image: "lnlink")
|
||||
case .phoenix:
|
||||
return .init(index: 8, tag: "phoenix", displayName: "Phoenix", link: "phoenix://",
|
||||
return .init(index: 8, tag: "phoenix", displayName: NSLocalizedString("Phoenix", comment: "Dropdown option label for Lightning wallet, Phoenix."), link: "phoenix://",
|
||||
appStoreLink: "https://apps.apple.com/us/app/phoenix-wallet/id1544097028", image: "phoenix")
|
||||
case .breez:
|
||||
return .init(index: 9, tag: "breez", displayName: "Breez", link: "breez:",
|
||||
return .init(index: 9, tag: "breez", displayName: NSLocalizedString("Breez", comment: "Dropdown option label for Lightning wallet, Breez."), link: "breez:",
|
||||
appStoreLink: "https://apps.apple.com/us/app/breez-lightning-client-pos/id1463604142", image: "breez")
|
||||
case .bitcoinbeach:
|
||||
return .init(index: 10, tag: "bitcoinbeach", displayName: "Bitcoin Beach", link: "bitcoinbeach://",
|
||||
return .init(index: 10, tag: "bitcoinbeach", displayName: NSLocalizedString("Bitcoin Beach", comment: "Dropdown option label for Lightning wallet, Bitcoin Beach."), link: "bitcoinbeach://",
|
||||
appStoreLink: "https://apps.apple.com/sv/app/bitcoin-beach-wallet/id1531383905", image: "bbw")
|
||||
case .blixtwallet:
|
||||
return .init(index: 11, tag: "blixtwallet", displayName: NSLocalizedString("Blixt Wallet", comment: "Dropdown option label for Lightning wallet, Blixt Wallet"), link: "blixtwallet:lightning:",
|
||||
appStoreLink: nil, image: "blixt-wallet")
|
||||
case .river:
|
||||
return .init(index: 12, tag: "river", displayName: NSLocalizedString("River", comment: "Dropdown option label for Lightning wallet, River"), link: "river://",
|
||||
appStoreLink: "https://apps.apple.com/us/app/river-buy-mine-bitcoin/id1536176542", image: "river")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -448,7 +448,7 @@ func hex_encode(_ data: Data) -> String {
|
||||
func random_bytes(count: Int) -> Data {
|
||||
var data = Data(count: count)
|
||||
_ = data.withUnsafeMutableBytes { mutableBytes in
|
||||
SecRandomCopyBytes(kSecRandomDefault, count, mutableBytes)
|
||||
SecRandomCopyBytes(kSecRandomDefault, count, mutableBytes.baseAddress!)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public func time_ago_since(_ date: Date) -> String {
|
||||
public func time_ago_since(_ date: Date, _ calendar: Calendar = Calendar.current) -> String {
|
||||
|
||||
let calendar = Calendar.current
|
||||
let now = Date()
|
||||
let unitFlags: NSCalendar.Unit = [.second, .minute, .hour, .day, .weekOfMonth, .month, .year]
|
||||
|
||||
|
||||
@@ -40,26 +40,26 @@ struct CreateAccountView: View {
|
||||
}
|
||||
VStack {
|
||||
SignupForm {
|
||||
FormLabel("Username")
|
||||
FormLabel(NSLocalizedString("Username", comment: "Label to prompt username entry."))
|
||||
HStack(spacing: 0.0) {
|
||||
Text("@")
|
||||
.foregroundColor(.white)
|
||||
.padding(.leading, -25.0)
|
||||
|
||||
FormTextInput("satoshi", text: $account.nick_name)
|
||||
FormTextInput(NSLocalizedString("satoshi", comment: "Example username of Bitcoin creator(s), Satoshi Nakamoto."), text: $account.nick_name)
|
||||
.autocorrectionDisabled(true)
|
||||
.textInputAutocapitalization(.never)
|
||||
|
||||
}
|
||||
|
||||
FormLabel("Display Name", optional: true)
|
||||
FormTextInput("Satoshi Nakamoto", text: $account.real_name)
|
||||
FormLabel(NSLocalizedString("Display Name", comment: "Label to prompt display name entry."), optional: true)
|
||||
FormTextInput(NSLocalizedString("Satoshi Nakamoto", comment: "Name of Bitcoin creator(s)."), text: $account.real_name)
|
||||
.textInputAutocapitalization(.words)
|
||||
|
||||
FormLabel("About", optional: true)
|
||||
FormTextInput("Creator(s) of Bitcoin. Absolute legend.", text: $account.about)
|
||||
FormLabel(NSLocalizedString("About", comment: "Label to prompt for about text entry for user to describe about themself."), optional: true)
|
||||
FormTextInput(NSLocalizedString("Creator(s) of Bitcoin. Absolute legend.", comment: "Example description about Bitcoin creator(s), Satoshi Nakamoto."), text: $account.about)
|
||||
|
||||
FormLabel("Account ID")
|
||||
FormLabel(NSLocalizedString("Account ID", comment: "Label to indicate the public ID of the account."))
|
||||
.onTapGesture {
|
||||
regen_key()
|
||||
}
|
||||
@@ -75,7 +75,7 @@ struct CreateAccountView: View {
|
||||
NavigationLink(destination: SaveKeysView(account: account), isActive: $is_done) {
|
||||
EmptyView()
|
||||
}
|
||||
DamusWhiteButton("Create") {
|
||||
DamusWhiteButton(NSLocalizedString("Create", comment: "Button to create account.")) {
|
||||
self.is_done = true
|
||||
}
|
||||
.padding()
|
||||
|
||||
@@ -142,7 +142,7 @@ struct EditMetadataView: View {
|
||||
}
|
||||
|
||||
Section("About Me") {
|
||||
let placeholder = "Absolute Boss"
|
||||
let placeholder = NSLocalizedString("Absolute Boss", comment: "Placeholder text for About Me description.")
|
||||
ZStack(alignment: .topLeading) {
|
||||
TextEditor(text: $about)
|
||||
.textInputAutocapitalization(.sentences)
|
||||
@@ -169,9 +169,9 @@ struct EditMetadataView: View {
|
||||
Text("NIP-05 Verification")
|
||||
}, footer: {
|
||||
if let parts = nip05_parts {
|
||||
Text("'\(parts.username)' at '\(parts.host)' will be used for verification")
|
||||
Text(String.localizedStringWithFormat("'%@' at '%@' will be used for verification", parts.username, parts.host))
|
||||
} else {
|
||||
Text("'\(nip05)' is an invalid nip05 identifier. It should look like an email.")
|
||||
Text(String.localizedStringWithFormat("'%@' is an invalid nip05 identifier. It should look like an email.", nip05))
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -401,7 +401,7 @@ func reply_desc(profiles: Profiles, event: NostrEvent) -> String {
|
||||
let n = desc.others
|
||||
|
||||
if desc.pubkeys.count == 0 {
|
||||
return "Reply to self"
|
||||
return NSLocalizedString("Reply to self", comment: "Label to indicate that the user is replying to themself.")
|
||||
}
|
||||
|
||||
let names: [String] = pubkeys.map {
|
||||
@@ -411,20 +411,14 @@ func reply_desc(profiles: Profiles, event: NostrEvent) -> String {
|
||||
|
||||
if names.count == 2 {
|
||||
if n > 2 {
|
||||
let and_other = reply_others_desc(n: n, n_pubkeys: pubkeys.count)
|
||||
return "Replying to \(names[0]), \(names[1])\(and_other)"
|
||||
let othersCount = n - pubkeys.count
|
||||
return String(format: NSLocalizedString("replying_to_two_and_others", comment: "Label to indicate that the user is replying to 2 users and others."), othersCount, names[0], names[1])
|
||||
}
|
||||
return "Replying to \(names[0]) & \(names[1])"
|
||||
return String.localizedStringWithFormat("Replying to %@ & %@", names[0], names[1])
|
||||
}
|
||||
|
||||
let and_other = reply_others_desc(n: n, n_pubkeys: pubkeys.count)
|
||||
return "Replying to \(names[0])\(and_other)"
|
||||
}
|
||||
|
||||
func reply_others_desc(n: Int, n_pubkeys: Int) -> String {
|
||||
let other = n - n_pubkeys
|
||||
let plural = other == 1 ? "" : "s"
|
||||
return n > 1 ? " & \(other) other\(plural)" : ""
|
||||
let othersCount = n - pubkeys.count
|
||||
return String(format: NSLocalizedString("replying_to_one_and_others", comment: "Label to indicate that the user is replying to 1 user and others."), othersCount, names[0])
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ enum NostrPostResult {
|
||||
case cancel
|
||||
}
|
||||
|
||||
let POST_PLACEHOLDER = "Type your post here..."
|
||||
let POST_PLACEHOLDER = NSLocalizedString("Type your post here...", comment: "Text box prompt to ask user to type their post.")
|
||||
|
||||
struct PostView: View {
|
||||
@State var post: String = ""
|
||||
|
||||
@@ -22,13 +22,13 @@ enum FollowState {
|
||||
func follow_btn_txt(_ fs: FollowState) -> String {
|
||||
switch fs {
|
||||
case .follows:
|
||||
return "Unfollow"
|
||||
return NSLocalizedString("Unfollow", comment: "Button to unfollow a user.")
|
||||
case .following:
|
||||
return "Following..."
|
||||
return NSLocalizedString("Following...", comment: "Label to indicate that the user is in the process of following another user.")
|
||||
case .unfollowing:
|
||||
return "Unfollowing..."
|
||||
return NSLocalizedString("Unfollowing...", comment: "Label to indicate that the user is in the process of unfollowing another user.")
|
||||
case .unfollows:
|
||||
return "Follow"
|
||||
return NSLocalizedString("Follow", comment: "Button to follow a user.")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ struct SaveKeysView: View {
|
||||
complete_account_creation(account)
|
||||
}
|
||||
} else {
|
||||
DamusWhiteButton("Let's go!") {
|
||||
DamusWhiteButton(NSLocalizedString("Let's go!", comment: "Button to complete account creation and start using the app.")) {
|
||||
complete_account_creation(account)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,14 +38,8 @@ struct SelectWalletView: View {
|
||||
Section("Select a lightning wallet"){
|
||||
List{
|
||||
Button() {
|
||||
let walletModel = user_settings.default_wallet.model
|
||||
if let url = URL(string: "\(walletModel.link)\(invoice)"), UIApplication.shared.canOpenURL(url) {
|
||||
openURL(url)
|
||||
} else {
|
||||
if let url = URL(string: walletModel.appStoreLink), UIApplication.shared.canOpenURL(url) {
|
||||
openURL(url)
|
||||
}
|
||||
}
|
||||
let wallet_model = user_settings.default_wallet.model
|
||||
open_with_wallet(wallet: wallet_model, invoice: invoice)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Default Wallet").font(.body).foregroundColor(.blue)
|
||||
@@ -54,13 +48,7 @@ struct SelectWalletView: View {
|
||||
List($allWalletModels) { $wallet in
|
||||
if wallet.index >= 0 {
|
||||
Button() {
|
||||
if let url = URL(string: "\(wallet.link)\(invoice)"), UIApplication.shared.canOpenURL(url) {
|
||||
openURL(url)
|
||||
} else {
|
||||
if let url = URL(string: wallet.appStoreLink), UIApplication.shared.canOpenURL(url) {
|
||||
openURL(url)
|
||||
}
|
||||
}
|
||||
open_with_wallet(wallet: wallet, invoice: invoice)
|
||||
} label: {
|
||||
HStack {
|
||||
Image(wallet.image).resizable().frame(width: 32.0, height: 32.0,alignment: .center).cornerRadius(5)
|
||||
|
||||
@@ -60,7 +60,7 @@ struct SetupView: View {
|
||||
|
||||
CarouselView()
|
||||
|
||||
DamusWhiteButton("Create Account") {
|
||||
DamusWhiteButton(NSLocalizedString("Create Account", comment: "Button to create an account.")) {
|
||||
self.state = .create_account
|
||||
}
|
||||
|
||||
|
||||
42
damus/en.lproj/Localizable.stringsdict
Normal file
42
damus/en.lproj/Localizable.stringsdict
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>replying_to_one_and_others</key>
|
||||
<dict>
|
||||
<key>NSStringLocalizedFormatKey</key>
|
||||
<string>Replying to %2$@%#@others@</string>
|
||||
<key>others</key>
|
||||
<dict>
|
||||
<key>NSStringFormatSpecTypeKey</key>
|
||||
<string>NSStringPluralRuleType</string>
|
||||
<key>NSStringFormatValueTypeKey</key>
|
||||
<string>d</string>
|
||||
<key>zero</key>
|
||||
<string></string>
|
||||
<key>one</key>
|
||||
<string> & 1 other</string>
|
||||
<key>other</key>
|
||||
<string> & %d others</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>replying_to_two_and_others</key>
|
||||
<dict>
|
||||
<key>NSStringLocalizedFormatKey</key>
|
||||
<string>Replying to %2$@, %3$@%#@others@</string>
|
||||
<key>others</key>
|
||||
<dict>
|
||||
<key>NSStringFormatSpecTypeKey</key>
|
||||
<string>NSStringPluralRuleType</string>
|
||||
<key>NSStringFormatValueTypeKey</key>
|
||||
<string>d</string>
|
||||
<key>zero</key>
|
||||
<string></string>
|
||||
<key>one</key>
|
||||
<string> & 1 other</string>
|
||||
<key>other</key>
|
||||
<string> & %d others</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -11,24 +11,27 @@ import XCTest
|
||||
final class TimeAgoTests: XCTestCase {
|
||||
|
||||
func testTimeAgoSince() {
|
||||
XCTAssertEqual(time_ago_since(Date.now), "now")
|
||||
XCTAssertEqual(time_ago_since(Date.now.addingTimeInterval(-2)), "now")
|
||||
XCTAssertEqual(time_ago_since(Date.now.addingTimeInterval(-3)), "3s")
|
||||
XCTAssertEqual(time_ago_since(Date.now.addingTimeInterval(-59)), "59s")
|
||||
XCTAssertEqual(time_ago_since(Date.now.addingTimeInterval(-60)), "1min")
|
||||
XCTAssertEqual(time_ago_since(Date.now.addingTimeInterval(-3599)), "59min")
|
||||
XCTAssertEqual(time_ago_since(Date.now.addingTimeInterval(-3600)), "1h")
|
||||
XCTAssertEqual(time_ago_since(Date.now.addingTimeInterval(-86399)), "23h")
|
||||
XCTAssertEqual(time_ago_since(Date.now.addingTimeInterval(-86400)), "1d")
|
||||
XCTAssertEqual(time_ago_since(Calendar.current.date(byAdding: .weekOfMonth, value: -1, to: Date.now)!.addingTimeInterval(1)), "6d")
|
||||
XCTAssertEqual(time_ago_since(Calendar.current.date(byAdding: .weekOfMonth, value: -1, to: Date.now)!), "1w")
|
||||
XCTAssertEqual(time_ago_since(Calendar.current.date(byAdding: .weekOfMonth, value: -2, to: Date.now)!), "2w")
|
||||
XCTAssertEqual(time_ago_since(Calendar.current.date(byAdding: .weekOfMonth, value: -3, to: Date.now)!), "3w")
|
||||
let locale = Locale(identifier: "en_US")
|
||||
let calendar = locale.calendar
|
||||
|
||||
XCTAssertEqual(time_ago_since(Date.now, calendar), "now")
|
||||
XCTAssertEqual(time_ago_since(Date.now.addingTimeInterval(-2), calendar), "now")
|
||||
XCTAssertEqual(time_ago_since(Date.now.addingTimeInterval(-3), calendar), "3s")
|
||||
XCTAssertEqual(time_ago_since(Date.now.addingTimeInterval(-59), calendar), "59s")
|
||||
XCTAssertEqual(time_ago_since(Date.now.addingTimeInterval(-60), calendar), "1m")
|
||||
XCTAssertEqual(time_ago_since(calendar.date(byAdding: .hour, value: -1, to: Date.now)!.addingTimeInterval(1), calendar), "59m")
|
||||
XCTAssertEqual(time_ago_since(calendar.date(byAdding: .hour, value: -1, to: Date.now)!, calendar), "1h")
|
||||
XCTAssertEqual(time_ago_since(calendar.date(byAdding: .day, value: -1, to: Date.now)!.addingTimeInterval(1), calendar), "23h")
|
||||
XCTAssertEqual(time_ago_since(calendar.date(byAdding: .day, value: -1, to: Date.now)!, calendar), "1d")
|
||||
XCTAssertEqual(time_ago_since(calendar.date(byAdding: .weekOfMonth, value: -1, to: Date.now)!.addingTimeInterval(1), calendar), "6d")
|
||||
XCTAssertEqual(time_ago_since(calendar.date(byAdding: .weekOfMonth, value: -1, to: Date.now)!, calendar), "1w")
|
||||
XCTAssertEqual(time_ago_since(calendar.date(byAdding: .weekOfMonth, value: -2, to: Date.now)!, calendar), "2w")
|
||||
XCTAssertEqual(time_ago_since(calendar.date(byAdding: .weekOfMonth, value: -3, to: Date.now)!, calendar), "3w")
|
||||
// Not testing the 4-5 week boundary since how it is formatted depends on which month and year it is currently when this test executes.
|
||||
XCTAssertEqual(time_ago_since(Calendar.current.date(byAdding: .month, value: -1, to: Date.now)!), "1mo")
|
||||
XCTAssertEqual(time_ago_since(Calendar.current.date(byAdding: .year, value: -1, to: Date.now)!.addingTimeInterval(1)), "11mo")
|
||||
XCTAssertEqual(time_ago_since(Calendar.current.date(byAdding: .year, value: -1, to: Date.now)!), "1y")
|
||||
XCTAssertEqual(time_ago_since(Calendar.current.date(byAdding: .year, value: -1000, to: Date.now)!), "1,000y")
|
||||
XCTAssertEqual(time_ago_since(calendar.date(byAdding: .month, value: -1, to: Date.now)!, calendar), "1mo")
|
||||
XCTAssertEqual(time_ago_since(calendar.date(byAdding: .year, value: -1, to: Date.now)!.addingTimeInterval(1), calendar), "11mo")
|
||||
XCTAssertEqual(time_ago_since(calendar.date(byAdding: .year, value: -1, to: Date.now)!, calendar), "1y")
|
||||
XCTAssertEqual(time_ago_since(calendar.date(byAdding: .year, value: -1000, to: Date.now)!, calendar), "1,000y")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,6 +33,13 @@ class damusTests: XCTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
func testRandomBytes() {
|
||||
let bytes = random_bytes(count: 32)
|
||||
|
||||
print("testRandomBytes \(hex_encode(bytes))")
|
||||
XCTAssertEqual(bytes.count, 32)
|
||||
}
|
||||
|
||||
func testParseMentionWithMarkdown() {
|
||||
let md = """
|
||||
Testing markdown in damus
|
||||
|
||||
Reference in New Issue
Block a user