Compare commits
20 Commits
reactions-
...
profile-vi
| Author | SHA1 | Date | |
|---|---|---|---|
|
1767a677bb
|
|||
|
|
dba1799df0 | ||
|
|
2db3d7310f | ||
|
|
10b1cf64ae | ||
|
|
afdd3f1d43 | ||
|
|
1b8e3fe184 | ||
|
|
8ab1c6a899 | ||
|
|
e8fae19b97 | ||
|
|
63e70605fc | ||
|
|
35df9f7ab7 | ||
|
|
605d88add1 | ||
|
|
2b0a7d126d | ||
|
|
6e2c133faa | ||
|
|
9885ff1912 | ||
|
|
abb818bbd4 | ||
|
|
f1dc023e18 | ||
|
|
4a332c7ffa | ||
|
|
616f730ae5 | ||
|
|
164cea96f3 | ||
|
|
fa70c376b1 |
76
CHANGELOG.md
76
CHANGELOG.md
@@ -1,3 +1,79 @@
|
||||
## [1.9 (14)] - 2024-07-14
|
||||
|
||||
### Added
|
||||
|
||||
- Completely new threads experience that is easier and more pleasant to use (Daniel D’Aquino)
|
||||
- Add emoji search to emoji picker (Terry Yiu)
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Added first aid contact damus support email (alltheseas)
|
||||
- Disable mutiny wallet button (William Casarin)
|
||||
- Make friends show up first when searching for profiles (Terry Yiu)
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix crash on profile page when there are profile updates (William Casarin)
|
||||
- Fix crash when adding duplicate mute items (William Casarin)
|
||||
- Fix pretty bad crash when building flatbuffer profiles (William Casarin)
|
||||
- Fix reactions view to not show reactions from replies on parent note (Terry Yiu)
|
||||
- Fix missing Mute button in profile view menu (Terry Yiu)
|
||||
- Fixed wallet not disconnecting when a user logs out (ericholguin)
|
||||
- Fix stale feed issue when follow list is too big (Daniel D’Aquino)
|
||||
|
||||
[1.9 (14)]: https://github.com/damus-io/damus/releases/tag/v1.9-14
|
||||
|
||||
## [1.8] - 2024-05-11
|
||||
|
||||
### Added
|
||||
|
||||
- Added nip10 marker replies (William Casarin)
|
||||
- Add marker nip10 support when reading notes (William Casarin)
|
||||
- Added title image and tags to longform events (ericholguin)
|
||||
- Add First Aid solution for users who do not have a contact list created for their account (Daniel D’Aquino)
|
||||
- Relay fees metadata (ericholguin)
|
||||
- Added callbackuri for a better ux when connecting mutiny wallet nwc (ericholguin)
|
||||
- Add event content preview to the full screen carousel (Daniel D’Aquino)
|
||||
- Show list of quoted reposts in threads (William Casarin)
|
||||
- Proxy Tags are now viewable on Selected Events (ericholguin)
|
||||
- Connect to Mutiny Wallet Button (ericholguin)
|
||||
- Add ability to mute words, add new mutelist interface (Charlie) (William Casarin)
|
||||
- Add ability to mute hashtag from SearchView (Charlie Fish)
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Change reactions to use a native looking emoji picker (Terry Yiu)
|
||||
- Relay detail design (ericholguin)
|
||||
- Updated Zeus logo (ericholguin)
|
||||
- Improve UX around video playback (Daniel D’Aquino)
|
||||
- Moved paste nwc button to main wallet view (ericholguin)
|
||||
- Errors with an NWC will show as an alert (ericholguin)
|
||||
- Relay config view user interface (ericholguin)
|
||||
- Always strip GPS data from images (kernelkind)
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix thread bug where a quote isn't picked up as a reply (William Casarin)
|
||||
- Fixed threads not loading sometimes (William Casarin)
|
||||
- Fixed issue where some replies were including the q tag (William Casarin)
|
||||
- Fixed issue where timeline was scrolling when it isn't supposed to (William Casarin)
|
||||
- Fix issue where bootstrap relays would inadvertently be added to the user's list on connectivity issues (Daniel D’Aquino)
|
||||
- Fix broken GIF uploads (Daniel D’Aquino)
|
||||
- Fix ghost notifications caused by Purple impending expiration notifications (Daniel D’Aquino)
|
||||
- Improve reliability of contact list creation during onboarding (Daniel D’Aquino)
|
||||
- Fix emoji reactions being cut off (ericholguin)
|
||||
- Fix image indicators to limit number of dots to not spill screen beyond visible margins (ericholguin)
|
||||
- Fix bug that would cause connection issues with relays defined with a trailing slash URL, and an inability to delete them. (Daniel D’Aquino)
|
||||
- Issue where NWC Scanner view would not dismiss after a failed scan/paste (ericholguin)
|
||||
|
||||
|
||||
|
||||
[1.8]: https://github.com/damus-io/damus/releases/tag/v1.8
|
||||
|
||||
## [1.7-rc2] - 2024-02-28
|
||||
|
||||
### Added
|
||||
|
||||
@@ -407,6 +407,7 @@
|
||||
5C7389B12B6EFA7100781E0A /* ProxyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7389B02B6EFA7100781E0A /* ProxyView.swift */; };
|
||||
5C7389B72B9E692E00781E0A /* MutinyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7389B62B9E692E00781E0A /* MutinyButton.swift */; };
|
||||
5C7389B92B9E69ED00781E0A /* MutinyGradient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7389B82B9E69ED00781E0A /* MutinyGradient.swift */; };
|
||||
5C8711DE2C460C06007879C2 /* PostingTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C8711DD2C460C06007879C2 /* PostingTimelineView.swift */; };
|
||||
5CC8529D2BD741CD0039FFC5 /* HighlightEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC8529C2BD741CD0039FFC5 /* HighlightEvent.swift */; };
|
||||
5CC8529F2BD744F60039FFC5 /* HighlightView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC8529E2BD744F60039FFC5 /* HighlightView.swift */; };
|
||||
5CC852A22BDED9B90039FFC5 /* HighlightDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC852A12BDED9B90039FFC5 /* HighlightDescription.swift */; };
|
||||
@@ -1348,6 +1349,7 @@
|
||||
5C7389B02B6EFA7100781E0A /* ProxyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyView.swift; sourceTree = "<group>"; };
|
||||
5C7389B62B9E692E00781E0A /* MutinyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MutinyButton.swift; sourceTree = "<group>"; };
|
||||
5C7389B82B9E69ED00781E0A /* MutinyGradient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MutinyGradient.swift; sourceTree = "<group>"; };
|
||||
5C8711DD2C460C06007879C2 /* PostingTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostingTimelineView.swift; sourceTree = "<group>"; };
|
||||
5CC8529C2BD741CD0039FFC5 /* HighlightEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HighlightEvent.swift; sourceTree = "<group>"; };
|
||||
5CC8529E2BD744F60039FFC5 /* HighlightView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HighlightView.swift; sourceTree = "<group>"; };
|
||||
5CC852A12BDED9B90039FFC5 /* HighlightDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HighlightDescription.swift; sourceTree = "<group>"; };
|
||||
@@ -2447,6 +2449,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4CE0E2B529A3ED5500DB4CA2 /* InnerTimelineView.swift */,
|
||||
5C8711DD2C460C06007879C2 /* PostingTimelineView.swift */,
|
||||
);
|
||||
path = Timeline;
|
||||
sourceTree = "<group>";
|
||||
@@ -3175,6 +3178,7 @@
|
||||
4CE6DEE927F7A08100C66700 /* ContentView.swift in Sources */,
|
||||
4CEE2AF5280B29E600AB5EEF /* TimeAgo.swift in Sources */,
|
||||
4CC14FF12A73FCDB007AEB17 /* Pubkey.swift in Sources */,
|
||||
5C8711DE2C460C06007879C2 /* PostingTimelineView.swift in Sources */,
|
||||
4CA9275D2A28FF630098A105 /* LongformView.swift in Sources */,
|
||||
4C75EFAD28049CFB0006080F /* PostButton.swift in Sources */,
|
||||
D7EDED1E2B11797D0018B19C /* LongformEvent.swift in Sources */,
|
||||
@@ -4096,7 +4100,7 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
MARKETING_VERSION = 1.10;
|
||||
MARKETING_VERSION = 1.11;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jb55.damus2;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
@@ -4147,7 +4151,7 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
MARKETING_VERSION = 1.10;
|
||||
MARKETING_VERSION = 1.11;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jb55.damus2;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
|
||||
@@ -12,31 +12,25 @@ let RECTANGLE_GRADIENT = LinearGradient(gradient: Gradient(colors: [
|
||||
DamusColors.blue
|
||||
]), startPoint: .leading, endPoint: .trailing)
|
||||
|
||||
struct CustomPicker<SelectionValue: Hashable, Content: View>: View {
|
||||
struct CustomPicker<SelectionValue: Hashable>: View {
|
||||
|
||||
let tabs: [(String, SelectionValue)]
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
|
||||
@Namespace var picker
|
||||
@Binding var selection: SelectionValue
|
||||
@ViewBuilder let content: Content
|
||||
|
||||
|
||||
public var body: some View {
|
||||
let contentMirror = Mirror(reflecting: content)
|
||||
let blocksCount = Mirror(reflecting: contentMirror.descendant("value")!).children.count
|
||||
HStack {
|
||||
ForEach(0..<blocksCount, id: \.self) { index in
|
||||
let tupleBlock = contentMirror.descendant("value", ".\(index)")
|
||||
let text = Mirror(reflecting: tupleBlock!).descendant("content") as! Text
|
||||
let tag = Mirror(reflecting: tupleBlock!).descendant("modifier", "value", "tagged") as! SelectionValue
|
||||
|
||||
ForEach(tabs, id: \.1) { (text, tag) in
|
||||
Button {
|
||||
withAnimation(.spring()) {
|
||||
selection = tag
|
||||
}
|
||||
} label: {
|
||||
text
|
||||
.padding(EdgeInsets(top: 15, leading: 0, bottom: 10, trailing: 0))
|
||||
Text(text).padding(EdgeInsets(top: 15, leading: 0, bottom: 10, trailing: 0))
|
||||
.font(.system(size: 14, weight: .heavy))
|
||||
.tag(tag)
|
||||
}
|
||||
.background(
|
||||
Group {
|
||||
|
||||
@@ -79,71 +79,15 @@ struct ContentView: View {
|
||||
@State var hide_bar: Bool = false
|
||||
@State var user_muted_confirm: Bool = false
|
||||
@State var confirm_overwrite_mutelist: Bool = false
|
||||
@SceneStorage("ContentView.filter_state") var filter_state : FilterState = .posts_and_replies
|
||||
@State private var isSideBarOpened = false
|
||||
var home: HomeModel = HomeModel()
|
||||
@StateObject var navigationCoordinator: NavigationCoordinator = NavigationCoordinator()
|
||||
@AppStorage("has_seen_suggested_users") private var hasSeenOnboardingSuggestions = false
|
||||
let sub_id = UUID().description
|
||||
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
// connect retry timer
|
||||
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
|
||||
|
||||
var mystery: some View {
|
||||
Text("Are you lost?", comment: "Text asking the user if they are lost in the app.")
|
||||
.id("what")
|
||||
}
|
||||
|
||||
func content_filter(_ fstate: FilterState) -> ((NostrEvent) -> Bool) {
|
||||
var filters = ContentFilters.defaults(damus_state: damus_state!)
|
||||
filters.append(fstate.filter)
|
||||
return ContentFilters(filters: filters).filter
|
||||
}
|
||||
|
||||
var PostingTimelineView: some View {
|
||||
VStack {
|
||||
ZStack {
|
||||
TabView(selection: $filter_state) {
|
||||
// This is needed or else there is a bug when switching from the 3rd or 2nd tab to first. no idea why.
|
||||
mystery
|
||||
|
||||
contentTimelineView(filter: content_filter(.posts))
|
||||
.tag(FilterState.posts)
|
||||
.id(FilterState.posts)
|
||||
contentTimelineView(filter: content_filter(.posts_and_replies))
|
||||
.tag(FilterState.posts_and_replies)
|
||||
.id(FilterState.posts_and_replies)
|
||||
}
|
||||
.tabViewStyle(.page(indexDisplayMode: .never))
|
||||
|
||||
if privkey != nil {
|
||||
PostButtonContainer(is_left_handed: damus_state?.settings.left_handed ?? false) {
|
||||
self.active_sheet = .post(.posting(.none))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.safeAreaInset(edge: .top, spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
CustomPicker(selection: $filter_state, content: {
|
||||
Text("Notes", comment: "Label for filter for seeing only notes (instead of notes and replies).").tag(FilterState.posts)
|
||||
Text("Notes & Replies", comment: "Label for filter for seeing notes and replies (instead of only notes).").tag(FilterState.posts_and_replies)
|
||||
})
|
||||
Divider()
|
||||
.frame(height: 1)
|
||||
}
|
||||
.background(colorScheme == .dark ? Color.black : Color.white)
|
||||
}
|
||||
}
|
||||
|
||||
func contentTimelineView(filter: (@escaping (NostrEvent) -> Bool)) -> some View {
|
||||
TimelineView(events: home.events, loading: .constant(false), damus: damus_state, show_friend_icon: false, filter: filter) {
|
||||
PullDownSearchView(state: damus_state, on_cancel: {})
|
||||
}
|
||||
}
|
||||
|
||||
func navIsAtRoot() -> Bool {
|
||||
return navigationCoordinator.isAtRoot()
|
||||
}
|
||||
@@ -171,7 +115,7 @@ struct ContentView: View {
|
||||
}
|
||||
|
||||
case .home:
|
||||
PostingTimelineView
|
||||
PostingTimelineView(damus_state: damus_state!, home: home, active_sheet: $active_sheet)
|
||||
|
||||
case .notifications:
|
||||
NotificationsView(state: damus, notifications: home.notifications)
|
||||
|
||||
@@ -16,7 +16,7 @@ enum FilterState : Int {
|
||||
func filter(ev: NostrEvent) -> Bool {
|
||||
switch self {
|
||||
case .posts:
|
||||
return ev.known_kind == .boost || !ev.is_reply()
|
||||
return ev.known_kind == .boost || ev.known_kind == .highlight || !ev.is_reply()
|
||||
case .posts_and_replies:
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -111,12 +111,16 @@ class MutelistManager {
|
||||
private func add_mute_item(_ item: MuteItem) {
|
||||
switch item {
|
||||
case .user(_, _):
|
||||
guard !users.contains(item) else { return }
|
||||
users.insert(item)
|
||||
case .hashtag(_, _):
|
||||
guard !hashtags.contains(item) else { return }
|
||||
hashtags.insert(item)
|
||||
case .word(_, _):
|
||||
guard !words.contains(item) else { return }
|
||||
words.insert(item)
|
||||
case .thread(_, _):
|
||||
guard !threads.contains(item) else { return }
|
||||
threads.insert(item)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,15 @@ import Foundation
|
||||
class ThreadModel: ObservableObject {
|
||||
@Published var event: NostrEvent
|
||||
let original_event: NostrEvent
|
||||
let highlight: String?
|
||||
var event_map: Set<NostrEvent>
|
||||
|
||||
init(event: NostrEvent, damus_state: DamusState) {
|
||||
init(event: NostrEvent, damus_state: DamusState, highlight: String? = nil) {
|
||||
self.damus_state = damus_state
|
||||
self.event_map = Set()
|
||||
self.event = event
|
||||
self.original_event = event
|
||||
self.highlight = highlight
|
||||
add_event(event, keypair: damus_state.keypair)
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,13 @@ let test_short_note =
|
||||
createdAt: UInt32(Date().timeIntervalSince1970 - 100)
|
||||
)!
|
||||
|
||||
let test_super_short_note =
|
||||
NostrEvent(
|
||||
content: "A",
|
||||
keypair: jack_keypair,
|
||||
createdAt: UInt32(Date().timeIntervalSince1970 - 100)
|
||||
)!
|
||||
|
||||
let test_note_json_with_escaped_slash = "{\"tags\":[],\"pubkey\":\"f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9\",\"content\":\"https:\\/\\/cdn.nostr.build\\/i\\/5c1d3296f66c2630131bf123106486aeaf051ed8466031c0e0532d70b33cddb2.jpg\",\"created_at\":1691864981,\"kind\":1,\"sig\":\"fc0033aa3d4df50b692a5b346fa816fdded698de2045e36e0642a021391468c44ca69c2471adc7e92088131872d4aaa1e90ea6e1ad97f3cc748f4aed96dfae18\",\"id\":\"e8f6eca3b161abba034dac9a02bb6930ecde9fd2fb5d6c5f22a05526e11382cb\"}"
|
||||
let test_encoded_note_with_image = NostrEvent.owned_from_json(json: test_note_json_with_escaped_slash)
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ struct ChatEventView: View {
|
||||
@State var long_press_bounce_work_item: DispatchWorkItem?
|
||||
@State var popover_state: PopoverState = .closed {
|
||||
didSet {
|
||||
let generator = UIImpactFeedbackGenerator(style: popover_state == .open_emoji_selector ? .heavy : .light)
|
||||
let generator = UIImpactFeedbackGenerator(style: popover_state.some_sheet_open() ? .heavy : .light)
|
||||
generator.impactOccurred()
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,11 @@ struct ChatEventView: View {
|
||||
enum PopoverState: String {
|
||||
case closed
|
||||
case open_emoji_selector
|
||||
case open_zap_sheet
|
||||
|
||||
func some_sheet_open() -> Bool {
|
||||
return self == .open_zap_sheet || self == .open_emoji_selector
|
||||
}
|
||||
}
|
||||
|
||||
var just_started: Bool {
|
||||
@@ -90,9 +95,22 @@ struct ChatEventView: View {
|
||||
var by_other_user: Bool {
|
||||
return event.pubkey != damus_state.pubkey
|
||||
}
|
||||
|
||||
|
||||
var is_ours: Bool { return !by_other_user }
|
||||
|
||||
|
||||
// MARK: Zapping properties
|
||||
|
||||
var lnurl: String? {
|
||||
damus_state.profiles.lookup_with_timestamp(event.pubkey)?.map({ pr in
|
||||
pr?.lnurl
|
||||
}).value
|
||||
}
|
||||
var zap_target: ZapTarget {
|
||||
ZapTarget.note(id: event.id, author: event.pubkey)
|
||||
}
|
||||
|
||||
// MARK: Views
|
||||
|
||||
var event_bubble: some View {
|
||||
ChatBubble(
|
||||
direction: is_ours ? .right : .left,
|
||||
@@ -107,6 +125,7 @@ struct ChatEventView: View {
|
||||
.onTapGesture {
|
||||
show_profile_action_sheet_if_enabled(damus_state: damus_state, pubkey: event.pubkey)
|
||||
}
|
||||
.lineLimit(1)
|
||||
Text(verbatim: "\(format_relative_time(event.created_at))")
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
@@ -124,13 +143,18 @@ struct ChatEventView: View {
|
||||
}
|
||||
|
||||
let blur_images = should_blur_images(settings: damus_state.settings, contacts: damus_state.contacts, ev: event, our_pubkey: damus_state.pubkey)
|
||||
NoteContentView(damus_state: damus_state, event: event, blur_images: blur_images, size: .normal, options: [])
|
||||
NoteContentView(damus_state: damus_state, event: event, blur_images: blur_images, size: .normal, options: [.truncate_content])
|
||||
.padding(2)
|
||||
if let mention = first_eref_mention(ev: event, keypair: damus_state.keypair) {
|
||||
MentionView(damus_state: damus_state, mention: mention)
|
||||
.background(DamusColors.adaptableWhite)
|
||||
.clipShape(RoundedRectangle(cornerSize: CGSize(width: 10, height: 10)))
|
||||
}
|
||||
}
|
||||
.frame(minWidth: 150, alignment: is_ours ? .trailing : .leading)
|
||||
.frame(minWidth: 5, alignment: is_ours ? .trailing : .leading)
|
||||
.padding(10)
|
||||
}
|
||||
.tint(is_ours ? Color.white : Color.accentColor)
|
||||
.tint(Color.accentColor)
|
||||
.overlay(
|
||||
ZStack(alignment: is_ours ? .bottomLeading : .bottomTrailing) {
|
||||
VStack {
|
||||
@@ -164,6 +188,14 @@ struct ChatEventView: View {
|
||||
EmojiPickerView(selectedEmoji: $selected_emoji, emojiProvider: damus_state.emoji_provider)
|
||||
}.presentationDetents([.medium, .large])
|
||||
}
|
||||
.sheet(isPresented: Binding(get: { popover_state == .open_zap_sheet }, set: { new_state in
|
||||
withAnimation(new_state == true ? .easeIn(duration: 0.5) : .easeOut(duration: 0.1)) {
|
||||
popover_state = new_state == true ? .open_zap_sheet : .closed
|
||||
}
|
||||
})) {
|
||||
ZapSheetViewIfPossible(damus_state: damus_state, target: zap_target, lnurl: lnurl)
|
||||
.presentationDetents([.medium, .large])
|
||||
}
|
||||
.onChange(of: selected_emoji) { newSelectedEmoji in
|
||||
if let newSelectedEmoji {
|
||||
send_like(emoji: newSelectedEmoji.value)
|
||||
@@ -171,8 +203,8 @@ struct ChatEventView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.scaleEffect(self.popover_state == .open_emoji_selector ? 1.08 : is_pressing ? 1.02 : 1)
|
||||
.shadow(color: (is_pressing || self.popover_state == .open_emoji_selector) ? .black.opacity(0.1) : .black.opacity(0.3), radius: (is_pressing || self.popover_state == .open_emoji_selector) ? 8 : 0, y: (is_pressing || self.popover_state == .open_emoji_selector) ? 15 : 0)
|
||||
.scaleEffect(self.popover_state.some_sheet_open() ? 1.08 : is_pressing ? 1.02 : 1)
|
||||
.shadow(color: (is_pressing || self.popover_state.some_sheet_open()) ? .black.opacity(0.1) : .black.opacity(0.3), radius: (is_pressing || self.popover_state.some_sheet_open()) ? 8 : 0, y: (is_pressing || self.popover_state.some_sheet_open()) ? 15 : 0)
|
||||
.onLongPressGesture(minimumDuration: 0.5, maximumDistance: 10, perform: {
|
||||
long_press_bounce_work_item?.cancel()
|
||||
}, onPressingChanged: { is_pressing in
|
||||
@@ -186,7 +218,8 @@ struct ChatEventView: View {
|
||||
// Ensure the action is performed only if the condition is still valid
|
||||
if self.is_pressing {
|
||||
withAnimation(.bouncy(duration: 0.2, extraBounce: 0.35)) {
|
||||
popover_state = .open_emoji_selector
|
||||
let should_show_zap_sheet = !damus_state.settings.nozaps && damus_state.settings.onlyzaps_mode
|
||||
popover_state = should_show_zap_sheet ? .open_zap_sheet : .open_emoji_selector
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,13 +287,25 @@ struct ChatEventView: View {
|
||||
SwipeView {
|
||||
self.event_bubble_with_long_press_interaction
|
||||
} leadingActions: { context in
|
||||
EventActionBar(
|
||||
damus_state: damus_state,
|
||||
event: event,
|
||||
bar: bar,
|
||||
options: is_ours ? [.swipe_action_menu_reverse] : [.swipe_action_menu],
|
||||
swipe_context: context
|
||||
)
|
||||
if !is_ours {
|
||||
EventActionBar(
|
||||
damus_state: damus_state,
|
||||
event: event,
|
||||
bar: bar,
|
||||
options: is_ours ? [.swipe_action_menu_reverse] : [.swipe_action_menu],
|
||||
swipe_context: context
|
||||
)
|
||||
}
|
||||
} trailingActions: { context in
|
||||
if is_ours {
|
||||
EventActionBar(
|
||||
damus_state: damus_state,
|
||||
event: event,
|
||||
bar: bar,
|
||||
options: is_ours ? [.swipe_action_menu_reverse] : [.swipe_action_menu],
|
||||
swipe_context: context
|
||||
)
|
||||
}
|
||||
}
|
||||
.swipeSpacing(-20)
|
||||
.swipeActionsStyle(.mask)
|
||||
@@ -322,3 +367,8 @@ extension Notification.Name {
|
||||
let bar = make_actionbar_model(ev: test_note.id, damus: test_damus_state)
|
||||
return ChatEventView(event: test_short_note, selected_event: test_note, prev_ev: nil, next_ev: nil, damus_state: test_damus_state, thread: ThreadModel(event: test_note, damus_state: test_damus_state), scroll_to_event: nil, focus_event: nil, highlight_bubble: true, bar: bar)
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let bar = make_actionbar_model(ev: test_note.id, damus: test_damus_state)
|
||||
return ChatEventView(event: test_super_short_note, selected_event: test_note, prev_ev: nil, next_ev: nil, damus_state: test_damus_state, thread: ThreadModel(event: test_note, damus_state: test_damus_state), scroll_to_event: nil, focus_event: nil, highlight_bubble: false, bar: bar)
|
||||
}
|
||||
|
||||
@@ -72,13 +72,11 @@ struct DirectMessagesView: View {
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
CustomPicker(selection: $dm_type, content: {
|
||||
Text("DMs", comment: "Picker option for DM selector for seeing only DMs that have been responded to. DM is the English abbreviation for Direct Message.")
|
||||
.tag(DMType.friend)
|
||||
Text("Requests", comment: "Picker option for DM selector for seeing only message requests (DMs that someone else sent the user which has not been responded to yet). DM is the English abbreviation for Direct Message.")
|
||||
.tag(DMType.rando)
|
||||
})
|
||||
|
||||
CustomPicker(tabs: [
|
||||
(NSLocalizedString("DMs", comment: "Picker option for DM selector for seeing only DMs that have been responded to. DM is the English abbreviation for Direct Message."), DMType.friend),
|
||||
(NSLocalizedString("Requests", comment: "Picker option for DM selector for seeing only message requests (DMs that someone else sent the user which has not been responded to yet"), DMType.rando),
|
||||
], selection: $dm_type)
|
||||
|
||||
Divider()
|
||||
.frame(height: 1)
|
||||
|
||||
|
||||
@@ -15,18 +15,12 @@ struct ReplyPart: View {
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if let reply_ref = event.thread_reply()?.reply {
|
||||
if event.known_kind == .highlight {
|
||||
let highlighted_note = event.highlighted_note_id().flatMap { events.lookup($0) }
|
||||
HighlightDescription(event: event, highlighted_event: highlighted_note, ndb: ndb)
|
||||
} else if let reply_ref = event.thread_reply()?.reply {
|
||||
let replying_to = events.lookup(reply_ref.note_id)
|
||||
if event.known_kind != .highlight {
|
||||
ReplyDescription(event: event, replying_to: replying_to, ndb: ndb)
|
||||
} else if event.known_kind == .highlight {
|
||||
HighlightDescription(event: event, highlighted_event: replying_to, ndb: ndb)
|
||||
}
|
||||
else {
|
||||
EmptyView()
|
||||
}
|
||||
} else {
|
||||
EmptyView()
|
||||
ReplyDescription(event: event, replying_to: replying_to, ndb: ndb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,12 @@ struct EventBody: View {
|
||||
}
|
||||
} else if event.known_kind == .highlight {
|
||||
HighlightBodyView(state: damus_state, ev: event, options: options)
|
||||
.onTapGesture {
|
||||
if let highlighted_note = event.highlighted_note_id().flatMap({ damus_state.events.lookup($0) }) {
|
||||
let thread = ThreadModel(event: highlighted_note, damus_state: damus_state, highlight: event.content)
|
||||
damus_state.nav.push(route: Route.Thread(thread: thread))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
note_content
|
||||
}
|
||||
|
||||
@@ -29,8 +29,7 @@ struct HighlightPostView: View {
|
||||
Spacer()
|
||||
|
||||
Button(NSLocalizedString("Post", comment: "Button to post a highlight.")) {
|
||||
var tags: [[String]] = [ ["e", "\(self.event.id)"] ]
|
||||
tags.append(["context", self.event.content])
|
||||
let tags: [[String]] = [ ["e", "\(self.event.id)"] ]
|
||||
|
||||
let kind = NostrKind.highlight.rawValue
|
||||
guard let ev = NostrEvent(content: selectedText, keypair: damus_state.keypair, kind: kind, tags: tags) else {
|
||||
@@ -53,7 +52,7 @@ struct HighlightPostView: View {
|
||||
|
||||
HStack {
|
||||
var attributedString: AttributedString {
|
||||
var attributedString = AttributedString(self.event.content)
|
||||
var attributedString = AttributedString(selectedText)
|
||||
|
||||
if let range = attributedString.range(of: selectedText) {
|
||||
attributedString[range].backgroundColor = DamusColors.highlight
|
||||
|
||||
@@ -39,21 +39,10 @@ struct SelectedEventView: View {
|
||||
.padding(.horizontal)
|
||||
.minimumScaleFactor(0.75)
|
||||
.lineLimit(1)
|
||||
|
||||
if let reply_ref = event.thread_reply()?.reply {
|
||||
let replying_to = damus.events.lookup(reply_ref.note_id)
|
||||
if event.known_kind == .highlight {
|
||||
HighlightDescription(event: event, highlighted_event: replying_to, ndb: damus.ndb)
|
||||
.padding(.horizontal)
|
||||
} else {
|
||||
ReplyDescription(event: event, replying_to: replying_to, ndb: damus.ndb)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
} else if event.known_kind == .highlight {
|
||||
HighlightDescription(event: event, highlighted_event: nil, ndb: damus.ndb)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
|
||||
|
||||
ReplyPart(events: damus.events, event: event, keypair: damus.keypair, ndb: damus.ndb)
|
||||
.padding(.horizontal)
|
||||
|
||||
ProxyView(event: event)
|
||||
.padding(.top, 5)
|
||||
.padding(.horizontal)
|
||||
|
||||
@@ -160,10 +160,10 @@ struct FollowingView: View {
|
||||
.navigationBarTitle(NSLocalizedString("Following", comment: "Navigation bar title for view that shows who a user is following."))
|
||||
.safeAreaInset(edge: .top, spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
CustomPicker(selection: $tab_selection, content: {
|
||||
Text("People", comment: "Label for filter for seeing only people follows.").tag(FollowingViewTabSelection.people)
|
||||
Text("Hashtags", comment: "Label for filter for seeing only hashtag follows.").tag(FollowingViewTabSelection.hashtags)
|
||||
})
|
||||
CustomPicker(tabs: [
|
||||
(NSLocalizedString("People", comment: "Label for filter for seeing only people follows."), FollowingViewTabSelection.people),
|
||||
(NSLocalizedString("Hashtags", comment: "Label for filter for seeing only hashtag follows."), FollowingViewTabSelection.hashtags)
|
||||
], selection: $tab_selection)
|
||||
Divider()
|
||||
.frame(height: 1)
|
||||
}
|
||||
|
||||
@@ -390,7 +390,12 @@ struct NoteContentView_Previews: PreviewProvider {
|
||||
NoteContentView(damus_state: state, event: test_note, blur_images: false, size: .normal, options: [])
|
||||
}
|
||||
.previewDisplayName("Short note")
|
||||
|
||||
|
||||
VStack {
|
||||
NoteContentView(damus_state: state, event: test_super_short_note, blur_images: true, size: .normal, options: [])
|
||||
}
|
||||
.previewDisplayName("Super short note")
|
||||
|
||||
VStack {
|
||||
NoteContentView(damus_state: state, event: test_encoded_note_with_image!, blur_images: false, size: .normal, options: [])
|
||||
}
|
||||
|
||||
@@ -117,17 +117,11 @@ struct NotificationsView: View {
|
||||
}
|
||||
.safeAreaInset(edge: .top, spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
CustomPicker(selection: $filter_state, content: {
|
||||
Text("All", comment: "Label for filter for all notifications.")
|
||||
.tag(NotificationFilterState.all)
|
||||
|
||||
Text("Zaps", comment: "Label for filter for zap notifications.")
|
||||
.tag(NotificationFilterState.zaps)
|
||||
|
||||
Text("Mentions", comment: "Label for filter for seeing mention notifications (replies, etc).")
|
||||
.tag(NotificationFilterState.replies)
|
||||
|
||||
})
|
||||
CustomPicker(tabs: [
|
||||
(NSLocalizedString("All", comment: "Label for filter for all notifications."), NotificationFilterState.all),
|
||||
(NSLocalizedString("Zaps", comment: "Label for filter for zap notifications."), NotificationFilterState.zaps),
|
||||
(NSLocalizedString("Mentions", comment: "Label for filter for seeing mention notifications (replies, etc)."), NotificationFilterState.replies),
|
||||
], selection: $filter_state)
|
||||
Divider()
|
||||
.frame(height: 1)
|
||||
}
|
||||
|
||||
@@ -125,31 +125,34 @@ struct ProfileName: View {
|
||||
return
|
||||
}
|
||||
|
||||
var profile: Profile!
|
||||
var profile_txn: NdbTxn<Profile?>!
|
||||
|
||||
switch update {
|
||||
case .remote(let pubkey):
|
||||
profile_txn = damus_state.profiles.lookup(id: pubkey)
|
||||
guard let prof = profile_txn.unsafeUnownedValue else { return }
|
||||
profile = prof
|
||||
guard let profile_txn = damus_state.profiles.lookup(id: pubkey),
|
||||
let prof = profile_txn.unsafeUnownedValue else {
|
||||
return
|
||||
}
|
||||
handle_profile_update(profile: prof)
|
||||
case .manual(_, let prof):
|
||||
profile = prof
|
||||
handle_profile_update(profile: prof)
|
||||
}
|
||||
|
||||
let display_name = Profile.displayName(profile: profile, pubkey: pubkey)
|
||||
if self.display_name != display_name {
|
||||
self.display_name = display_name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let nip05 = damus_state.profiles.is_validated(pubkey)
|
||||
if nip05 != self.nip05 {
|
||||
self.nip05 = nip05
|
||||
}
|
||||
@MainActor
|
||||
func handle_profile_update(profile: Profile) {
|
||||
let display_name = Profile.displayName(profile: profile, pubkey: pubkey)
|
||||
if self.display_name != display_name {
|
||||
self.display_name = display_name
|
||||
}
|
||||
|
||||
if donation != profile.damus_donation {
|
||||
donation = profile.damus_donation
|
||||
}
|
||||
let nip05 = damus_state.profiles.is_validated(pubkey)
|
||||
if nip05 != self.nip05 {
|
||||
self.nip05 = nip05
|
||||
}
|
||||
|
||||
if donation != profile.damus_donation {
|
||||
donation = profile.damus_donation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,16 +217,6 @@ struct ProfileView: View {
|
||||
}
|
||||
}
|
||||
|
||||
var customNavbar: some View {
|
||||
HStack {
|
||||
navBackButton
|
||||
Spacer()
|
||||
navActionSheetButton
|
||||
}
|
||||
.padding(.top, 5)
|
||||
.accentColor(DamusColors.white)
|
||||
}
|
||||
|
||||
func lnButton(unownedProfile: Profile?, record: ProfileRecord?) -> some View {
|
||||
return ProfileZapLinkView(unownedProfileRecord: record, profileModel: self.profile) { reactions_enabled, lud16, lnurl in
|
||||
Image(reactions_enabled ? "zap.fill" : "zap")
|
||||
@@ -434,10 +424,10 @@ struct ProfileView: View {
|
||||
aboutSection
|
||||
|
||||
VStack(spacing: 0) {
|
||||
CustomPicker(selection: $filter_state, content: {
|
||||
Text("Notes", comment: "Label for filter for seeing only your notes (instead of notes and replies).").tag(FilterState.posts)
|
||||
Text("Notes & Replies", comment: "Label for filter for seeing your notes and replies (instead of only your notes).").tag(FilterState.posts_and_replies)
|
||||
})
|
||||
CustomPicker(tabs: [
|
||||
(NSLocalizedString("Notes", comment: "Label for filter for seeing only notes (instead of notes and replies)."), FilterState.posts),
|
||||
(NSLocalizedString("Notes & Replies", comment: "Label for filter for seeing notes and replies (instead of only notes)."), FilterState.posts_and_replies)
|
||||
], selection: $filter_state)
|
||||
Divider()
|
||||
.frame(height: 1)
|
||||
}
|
||||
@@ -458,8 +448,15 @@ struct ProfileView: View {
|
||||
.navigationTitle("")
|
||||
.navigationBarBackButtonHidden()
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .principal) {
|
||||
customNavbar
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
navBackButton
|
||||
.padding(.top, 5)
|
||||
.accentColor(DamusColors.white)
|
||||
}
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
navActionSheetButton
|
||||
.padding(.top, 5)
|
||||
.accentColor(DamusColors.white)
|
||||
}
|
||||
}
|
||||
.toolbarBackground(.hidden)
|
||||
|
||||
80
damus/Views/Timeline/PostingTimelineView.swift
Normal file
80
damus/Views/Timeline/PostingTimelineView.swift
Normal file
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// PostingTimelineView.swift
|
||||
// damus
|
||||
//
|
||||
// Created by eric on 7/15/24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct PostingTimelineView: View {
|
||||
|
||||
let damus_state: DamusState
|
||||
var home: HomeModel
|
||||
@State var search: String = ""
|
||||
@State var results: [NostrEvent] = []
|
||||
@State var initialOffset: CGFloat?
|
||||
@State var offset: CGFloat?
|
||||
@State var showSearch: Bool = true
|
||||
@Binding var active_sheet: Sheets?
|
||||
@FocusState private var isSearchFocused: Bool
|
||||
@State private var contentOffset: CGFloat = 0
|
||||
@State private var indicatorWidth: CGFloat = 0
|
||||
@State private var indicatorPosition: CGFloat = 0
|
||||
@SceneStorage("PostingTimelineView.filter_state") var filter_state : FilterState = .posts_and_replies
|
||||
|
||||
var mystery: some View {
|
||||
Text("Are you lost?", comment: "Text asking the user if they are lost in the app.")
|
||||
.id("what")
|
||||
}
|
||||
|
||||
func content_filter(_ fstate: FilterState) -> ((NostrEvent) -> Bool) {
|
||||
var filters = ContentFilters.defaults(damus_state: damus_state)
|
||||
filters.append(fstate.filter)
|
||||
return ContentFilters(filters: filters).filter
|
||||
}
|
||||
|
||||
func contentTimelineView(filter: (@escaping (NostrEvent) -> Bool)) -> some View {
|
||||
TimelineView(events: home.events, loading: .constant(false), damus: damus_state, show_friend_icon: false, filter: filter) {
|
||||
PullDownSearchView(state: damus_state, on_cancel: {})
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
ZStack {
|
||||
TabView(selection: $filter_state) {
|
||||
// This is needed or else there is a bug when switching from the 3rd or 2nd tab to first. no idea why.
|
||||
mystery
|
||||
|
||||
contentTimelineView(filter: content_filter(.posts))
|
||||
.tag(FilterState.posts)
|
||||
.id(FilterState.posts)
|
||||
contentTimelineView(filter: content_filter(.posts_and_replies))
|
||||
.tag(FilterState.posts_and_replies)
|
||||
.id(FilterState.posts_and_replies)
|
||||
}
|
||||
.tabViewStyle(.page(indexDisplayMode: .never))
|
||||
|
||||
if damus_state.keypair.privkey != nil {
|
||||
PostButtonContainer(is_left_handed: damus_state.settings.left_handed) {
|
||||
self.active_sheet = .post(.posting(.none))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.safeAreaInset(edge: .top, spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
CustomPicker(tabs: [
|
||||
(NSLocalizedString("Notes", comment: "Label for filter for seeing only notes (instead of notes and replies)."), FilterState.posts),
|
||||
(NSLocalizedString("Notes & Replies", comment: "Label for filter for seeing notes and replies (instead of only notes)."), FilterState.posts_and_replies)
|
||||
],
|
||||
selection: $filter_state)
|
||||
|
||||
Divider()
|
||||
.frame(height: 1)
|
||||
}
|
||||
.background(DamusColors.adaptableWhite)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,6 +295,64 @@ struct CustomizeZapView: View {
|
||||
}
|
||||
}
|
||||
|
||||
struct ZapSheetViewIfPossible: View {
|
||||
let damus_state: DamusState
|
||||
let target: ZapTarget
|
||||
let lnurl: String?
|
||||
var zap_sheet: ZapSheet? {
|
||||
guard let lnurl else { return nil }
|
||||
return ZapSheet(target: target, lnurl: lnurl)
|
||||
}
|
||||
|
||||
@Environment(\.dismiss) var dismiss
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
var body: some View {
|
||||
if let zap_sheet {
|
||||
CustomizeZapView(state: damus_state, target: zap_sheet.target, lnurl: zap_sheet.lnurl)
|
||||
}
|
||||
else {
|
||||
zap_sheet_not_possible
|
||||
}
|
||||
}
|
||||
|
||||
var zap_sheet_not_possible: some View {
|
||||
VStack(alignment: .center, spacing: 20) {
|
||||
Image(systemName: "bolt.trianglebadge.exclamationmark.fill")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 70)
|
||||
Text("User not zappable", comment: "Headline indicating a user cannot be zapped")
|
||||
.font(.headline)
|
||||
Text("This user cannot be zapped because they have not configured zaps on their account yet. Time to orange-pill?", comment: "Comment explaining why a user cannot be zapped.")
|
||||
.multilineTextAlignment(.center)
|
||||
.opacity(0.6)
|
||||
self.dm_button
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
|
||||
var dm_button: some View {
|
||||
let dm_model = damus_state.dms.lookup_or_create(target.pubkey)
|
||||
return VStack(alignment: .center, spacing: 10) {
|
||||
Button(
|
||||
action: {
|
||||
damus_state.nav.push(route: Route.DMChat(dms: dm_model))
|
||||
dismiss()
|
||||
},
|
||||
label: {
|
||||
Image("messages")
|
||||
.profile_button_style(scheme: colorScheme)
|
||||
}
|
||||
)
|
||||
.buttonStyle(NeutralButtonShape.circle.style)
|
||||
Text("Orange-pill", comment: "Button label that allows the user to start a direct message conversation with the user shown on-screen, to orange-pill them (i.e. help them to setup zaps)")
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
func hideKeyboard() {
|
||||
let resign = #selector(UIResponder.resignFirstResponder)
|
||||
@@ -302,9 +360,25 @@ extension View {
|
||||
}
|
||||
}
|
||||
|
||||
struct CustomizeZapView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
CustomizeZapView(state: test_damus_state, target: ZapTarget.note(id: test_note.id, author: test_note.pubkey), lnurl: "")
|
||||
.frame(width: 400, height: 600)
|
||||
}
|
||||
|
||||
|
||||
fileprivate func test_zap_sheet() -> ZapSheet {
|
||||
let zap_target = ZapTarget.note(id: test_note.id, author: test_note.pubkey)
|
||||
let lnurl = ""
|
||||
return ZapSheet(target: zap_target, lnurl: lnurl)
|
||||
}
|
||||
|
||||
#Preview {
|
||||
CustomizeZapView(state: test_damus_state, target: test_zap_sheet().target, lnurl: test_zap_sheet().lnurl)
|
||||
.frame(width: 400, height: 600)
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ZapSheetViewIfPossible(damus_state: test_damus_state, target: test_zap_sheet().target, lnurl: test_zap_sheet().lnurl)
|
||||
.frame(width: 400, height: 600)
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ZapSheetViewIfPossible(damus_state: test_damus_state, target: test_zap_sheet().target, lnurl: nil)
|
||||
.frame(width: 400, height: 600)
|
||||
}
|
||||
|
||||
@@ -341,7 +341,14 @@ extension NdbNote {
|
||||
}
|
||||
|
||||
func thread_reply() -> ThreadReply? {
|
||||
ThreadReply(tags: self.tags)
|
||||
if self.known_kind != .highlight {
|
||||
return ThreadReply(tags: self.tags)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func highlighted_note_id() -> NoteId? {
|
||||
return ThreadReply(tags: self.tags)?.reply.note_id
|
||||
}
|
||||
|
||||
func get_content(_ keypair: Keypair) -> String {
|
||||
|
||||
@@ -82,7 +82,7 @@ extern "C" {
|
||||
* Note: some internal assertion will remain if disabled.
|
||||
*/
|
||||
#ifndef FLATCC_BUILDER_ASSERT_ON_ERROR
|
||||
#define FLATCC_BUILDER_ASSERT_ON_ERROR 1
|
||||
#define FLATCC_BUILDER_ASSERT_ON_ERROR 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user