Compare commits

..

1 Commits

Author SHA1 Message Date
8ac9863765 Fix missing Mute button in profile view menu
Changelog-Fixed: Fix missing Mute button in profile view menu
2024-06-23 22:40:33 -04:00
11 changed files with 122 additions and 115 deletions

View File

@@ -12,7 +12,6 @@
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 */; };
3A0A30BB2C21397A00F8C9BC /* EmojiPicker in Frameworks */ = {isa = PBXBuildFile; productRef = 3A0A30BA2C21397A00F8C9BC /* EmojiPicker */; };
3A23838E2A297DD200E5AA2E /* ZapButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A23838D2A297DD200E5AA2E /* ZapButtonModel.swift */; };
3A3040ED29A5CB86008A0F29 /* ReplyDescriptionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A3040EC29A5CB86008A0F29 /* ReplyDescriptionTests.swift */; };
3A3040F129A8FF97008A0F29 /* LocalizationUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A3040F029A8FF97008A0F29 /* LocalizationUtil.swift */; };
@@ -33,6 +32,7 @@
3ACB685F297633BC00C46468 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ACB685D297633BC00C46468 /* Localizable.strings */; };
3ACBCB78295FE5C70037388A /* TimeAgoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACBCB77295FE5C70037388A /* TimeAgoTests.swift */; };
3AE45AF6297BB2E700C1D842 /* LibreTranslateServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE45AF5297BB2E700C1D842 /* LibreTranslateServer.swift */; };
3AFE89C32BD4156F00AD31EF /* MCEmojiPicker in Frameworks */ = {isa = PBXBuildFile; productRef = 3AFE89C22BD4156F00AD31EF /* MCEmojiPicker */; };
3CCD1E6A2A874C4E0099A953 /* Nip98HTTPAuth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CCD1E692A874C4E0099A953 /* Nip98HTTPAuth.swift */; };
4C011B5E2BD0A56A002F2F9B /* ChatEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C011B5C2BD0A56A002F2F9B /* ChatEventView.swift */; };
4C011B5F2BD0A56A002F2F9B /* ChatroomThreadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C011B5D2BD0A56A002F2F9B /* ChatroomThreadView.swift */; };
@@ -1485,10 +1485,10 @@
buildActionMask = 2147483647;
files = (
4C06670428FC7EC500038D2A /* Kingfisher in Frameworks */,
3A0A30BB2C21397A00F8C9BC /* EmojiPicker in Frameworks */,
D78DB8592C1CE9CA00F0AB12 /* SwipeActions in Frameworks */,
4C649881286E0EE300EAE2B3 /* secp256k1 in Frameworks */,
4C27C9322A64766F007DBC75 /* MarkdownUI in Frameworks */,
3AFE89C32BD4156F00AD31EF /* MCEmojiPicker in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2866,7 +2866,7 @@
4C649880286E0EE300EAE2B3 /* secp256k1 */,
4C06670328FC7EC500038D2A /* Kingfisher */,
4C27C9312A64766F007DBC75 /* MarkdownUI */,
3A0A30BA2C21397A00F8C9BC /* EmojiPicker */,
3AFE89C22BD4156F00AD31EF /* MCEmojiPicker */,
D78DB8582C1CE9CA00F0AB12 /* SwipeActions */,
);
productName = damus;
@@ -3007,7 +3007,7 @@
4CCF9AB02A1FE80B00E03CFB /* XCRemoteSwiftPackageReference "GSPlayer" */,
4C27C9302A64766F007DBC75 /* XCRemoteSwiftPackageReference "swift-markdown-ui" */,
D7A343EC2AD0D77C00CED48B /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */,
3A0A30B92C21397A00F8C9BC /* XCRemoteSwiftPackageReference "EmojiPicker" */,
3AFE89C12BD4156F00AD31EF /* XCRemoteSwiftPackageReference "MCEmojiPicker" */,
D78DB8572C1CE9CA00F0AB12 /* XCRemoteSwiftPackageReference "SwipeActions" */,
);
productRefGroup = 4CE6DEE427F7A08100C66700 /* Products */;
@@ -4316,12 +4316,12 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
3A0A30B92C21397A00F8C9BC /* XCRemoteSwiftPackageReference "EmojiPicker" */ = {
3AFE89C12BD4156F00AD31EF /* XCRemoteSwiftPackageReference "MCEmojiPicker" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/tyiu/EmojiPicker.git";
repositoryURL = "https://github.com/izyumkin/MCEmojiPicker";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.1.1;
minimumVersion = 1.2.3;
};
};
4C06670228FC7EC500038D2A /* XCRemoteSwiftPackageReference "Kingfisher" */ = {
@@ -4375,10 +4375,10 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
3A0A30BA2C21397A00F8C9BC /* EmojiPicker */ = {
3AFE89C22BD4156F00AD31EF /* MCEmojiPicker */ = {
isa = XCSwiftPackageProductDependency;
package = 3A0A30B92C21397A00F8C9BC /* XCRemoteSwiftPackageReference "EmojiPicker" */;
productName = EmojiPicker;
package = 3AFE89C12BD4156F00AD31EF /* XCRemoteSwiftPackageReference "MCEmojiPicker" */;
productName = MCEmojiPicker;
};
4C06670328FC7EC500038D2A /* Kingfisher */ = {
isa = XCSwiftPackageProductDependency;

View File

@@ -1,24 +1,6 @@
{
"originHash" : "babaf4d5748afecf49bbb702530d8e9576460692f478b0a50ee43195dd4440e2",
"pins" : [
{
"identity" : "emojikit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/tyiu/EmojiKit",
"state" : {
"revision" : "05805f72d63a6d6a2d7dc7fe14abd37c1317b11a",
"version" : "0.1.2"
}
},
{
"identity" : "emojipicker",
"kind" : "remoteSourceControl",
"location" : "https://github.com/tyiu/EmojiPicker.git",
"state" : {
"revision" : "0c28b4a1a6b8840cf2580bda59517f6d0a733dc8",
"version" : "0.1.1"
}
},
{
"identity" : "gsplayer",
"kind" : "remoteSourceControl",
@@ -37,6 +19,15 @@
"version" : "7.6.1"
}
},
{
"identity" : "mcemojipicker",
"kind" : "remoteSourceControl",
"location" : "https://github.com/izyumkin/MCEmojiPicker",
"state" : {
"revision" : "e0b4903b75ae1cc418d276d84d1cb946b8a1d73c",
"version" : "1.2.3"
}
},
{
"identity" : "secp256k1.swift",
"kind" : "remoteSourceControl",
@@ -45,15 +36,6 @@
"revision" : "40b4b38b3b1c83f7088c76189a742870e0ca06a9"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections.git",
"state" : {
"revision" : "ee97538f5b81ae89698fd95938896dec5217b148",
"version" : "1.1.1"
}
},
{
"identity" : "swift-markdown-ui",
"kind" : "remoteSourceControl",
@@ -80,15 +62,6 @@
"version" : "509.0.0"
}
},
{
"identity" : "swift-trie",
"kind" : "remoteSourceControl",
"location" : "https://github.com/tyiu/swift-trie",
"state" : {
"revision" : "4c50bff6c168f74425f70476be62a072980d2da7",
"version" : "0.1.2"
}
},
{
"identity" : "swipeactions",
"kind" : "remoteSourceControl",

View File

@@ -8,7 +8,6 @@
import SwiftUI
import AVKit
import MediaPlayer
import EmojiPicker
struct ZapSheet {
let target: ZapTarget
@@ -720,8 +719,7 @@ struct ContentView: View {
music: MusicController(onChange: music_changed),
video: VideoController(),
ndb: ndb,
quote_reposts: .init(our_pubkey: pubkey),
emoji_provider: DefaultEmojiProvider(showAllVariations: true)
quote_reposts: .init(our_pubkey: pubkey)
)
home.damus_state = self.damus_state!

View File

@@ -7,7 +7,6 @@
import Foundation
import LinkPresentation
import EmojiPicker
class DamusState: HeadlessDamusState {
let pool: RelayPool
@@ -38,9 +37,8 @@ class DamusState: HeadlessDamusState {
let ndb: Ndb
var purple: DamusPurple
var push_notification_client: PushNotificationClient
let emoji_provider: EmojiProvider
init(pool: RelayPool, keypair: Keypair, likes: EventCounter, boosts: EventCounter, contacts: Contacts, mutelist_manager: MutelistManager, profiles: Profiles, dms: DirectMessagesModel, previews: PreviewCache, zaps: Zaps, lnurls: LNUrls, settings: UserSettingsStore, relay_filters: RelayFilters, relay_model_cache: RelayModelCache, drafts: Drafts, events: EventCache, bookmarks: BookmarksManager, postbox: PostBox, bootstrap_relays: [RelayURL], replies: ReplyCounter, wallet: WalletModel, nav: NavigationCoordinator, music: MusicController?, video: VideoController, ndb: Ndb, purple: DamusPurple? = nil, quote_reposts: EventCounter, emoji_provider: EmojiProvider) {
init(pool: RelayPool, keypair: Keypair, likes: EventCounter, boosts: EventCounter, contacts: Contacts, mutelist_manager: MutelistManager, profiles: Profiles, dms: DirectMessagesModel, previews: PreviewCache, zaps: Zaps, lnurls: LNUrls, settings: UserSettingsStore, relay_filters: RelayFilters, relay_model_cache: RelayModelCache, drafts: Drafts, events: EventCache, bookmarks: BookmarksManager, postbox: PostBox, bootstrap_relays: [RelayURL], replies: ReplyCounter, wallet: WalletModel, nav: NavigationCoordinator, music: MusicController?, video: VideoController, ndb: Ndb, purple: DamusPurple? = nil, quote_reposts: EventCounter) {
self.pool = pool
self.keypair = keypair
self.likes = likes
@@ -72,7 +70,6 @@ class DamusState: HeadlessDamusState {
)
self.quote_reposts = quote_reposts
self.push_notification_client = PushNotificationClient(keypair: keypair, settings: settings)
self.emoji_provider = emoji_provider
}
@discardableResult
@@ -138,8 +135,7 @@ class DamusState: HeadlessDamusState {
music: nil,
video: VideoController(),
ndb: .empty,
quote_reposts: .init(our_pubkey: empty_pub),
emoji_provider: DefaultEmojiProvider(showAllVariations: true)
quote_reposts: .init(our_pubkey: empty_pub)
)
}
}

View File

@@ -6,7 +6,6 @@
//
import Foundation
import EmojiPicker
let test_seckey = Privkey(Data([0xe0, 0xaa, 0x60, 0x26, 0x08, 0x18, 0xac, 0x10, 0x03, 0x86, 0x4d, 0x15, 0x24, 0x9a, 0xf7, 0xa3, 0x3e, 0x4f, 0x1f, 0xc9, 0x01, 0xcf, 0xee, 0xa9, 0xb4, 0x77, 0xc7, 0x07, 0x22, 0xb7, 0x25, 0xfd]))
@@ -101,8 +100,7 @@ var test_damus_state: DamusState = ({
music: .init(onChange: {_ in }),
video: .init(),
ndb: ndb,
quote_reposts: .init(our_pubkey: our_pubkey),
emoji_provider: DefaultEmojiProvider(showAllVariations: true)
quote_reposts: .init(our_pubkey: our_pubkey)
)
/*

View File

@@ -85,7 +85,7 @@ enum Route: Hashable {
case .TranslationSettings(let settings):
TranslationSettingsView(settings: settings, damus_state: damusState)
case .ReactionsSettings(let settings):
ReactionsSettingsView(settings: settings, damus_state: damusState)
ReactionsSettingsView(settings: settings)
case .SearchSettings(let settings):
SearchSettingsView(settings: settings)
case .DeveloperSettings(let settings):

View File

@@ -6,8 +6,7 @@
//
import SwiftUI
import EmojiPicker
import EmojiKit
import MCEmojiPicker
import SwipeActions
struct EventActionBar: View {
@@ -23,7 +22,7 @@ struct EventActionBar: View {
@State var show_share_action: Bool = false
@State var show_repost_action: Bool = false
@State private var selectedEmoji: Emoji? = nil
@State private var isOnTopHalfOfScreen: Bool = false
@ObservedObject var bar: ActionBarModel
@@ -127,7 +126,7 @@ struct EventActionBar: View {
var like_button: some View {
HStack(spacing: 4) {
LikeButton(damus_state: damus_state, liked: bar.liked, liked_emoji: bar.our_like != nil ? to_reaction_emoji(ev: bar.our_like!) : nil) { emoji in
LikeButton(damus_state: damus_state, liked: bar.liked, liked_emoji: bar.our_like != nil ? to_reaction_emoji(ev: bar.our_like!) : nil, isOnTopHalfOfScreen: $isOnTopHalfOfScreen) { emoji in
if bar.liked {
//notify(.delete, bar.our_like)
} else {
@@ -258,6 +257,20 @@ struct EventActionBar: View {
self.bar.our_like = liked.event
}
}
.background(
GeometryReader { geometry in
EmptyView()
.onAppear {
let eventActionBarY = geometry.frame(in: .global).midY
let screenMidY = UIScreen.main.bounds.midY
self.isOnTopHalfOfScreen = eventActionBarY > screenMidY
}
.onChange(of: geometry.frame(in: .global).midY) { newY in
let screenMidY = UIScreen.main.bounds.midY
self.isOnTopHalfOfScreen = newY > screenMidY
}
}
)
}
func send_like(emoji: String) {
@@ -302,6 +315,7 @@ struct LikeButton: View {
let damus_state: DamusState
let liked: Bool
let liked_emoji: String?
@Binding var isOnTopHalfOfScreen: Bool
let action: (_ emoji: String) -> Void
// For reactions background
@@ -310,7 +324,7 @@ struct LikeButton: View {
@State private var isReactionsVisible = false
@State private var selectedEmoji: Emoji?
@State private var selectedEmoji: String = ""
// Following four are Shaka animation properties
let timer = Timer.publish(every: 0.10, on: .main, in: .common).autoconnect()
@@ -349,11 +363,6 @@ struct LikeButton: View {
.foregroundColor(.gray)
}
}
.sheet(isPresented: $isReactionsVisible) {
NavigationView {
EmojiPickerView(selectedEmoji: $selectedEmoji, emojiProvider: damus_state.emoji_provider)
}.presentationDetents([.medium, .large])
}
.accessibilityLabel(NSLocalizedString("Like", comment: "Accessibility Label for Like button"))
.rotationEffect(Angle(degrees: shouldAnimate ? rotationAngle : 0))
.onReceive(self.timer) { _ in
@@ -368,10 +377,14 @@ struct LikeButton: View {
amountOfAngleIncrease = 20.0
}
})
.emojiPicker(
isPresented: $isReactionsVisible,
selectedEmoji: $selectedEmoji,
arrowDirection: isOnTopHalfOfScreen ? .down : .up,
isDismissAfterChoosing: true
)
.onChange(of: selectedEmoji) { newSelectedEmoji in
if let newSelectedEmoji {
self.action(newSelectedEmoji.value)
}
self.action(newSelectedEmoji)
}
}

View File

@@ -6,8 +6,7 @@
//
import SwiftUI
import EmojiKit
import EmojiPicker
import MCEmojiPicker
import SwipeActions
fileprivate let CORNER_RADIUS: CGFloat = 10
@@ -35,8 +34,8 @@ struct ChatEventView: View {
generator.impactOccurred()
}
}
@State var selected_emoji: Emoji?
@State var selected_emoji: String = ""
@State private var isOnTopHalfOfScreen: Bool = false
@ObservedObject var bar: ActionBarModel
@@ -155,18 +154,19 @@ struct ChatEventView: View {
var event_bubble_with_long_press_interaction: some View {
ZStack(alignment: is_ours ? .bottomLeading : .bottomTrailing) {
self.event_bubble
.sheet(isPresented: Binding(get: { popover_state == .open_emoji_selector }, set: { new_state in
withAnimation(new_state == true ? .easeIn(duration: 0.5) : .easeOut(duration: 0.1)) {
popover_state = new_state == true ? .open_emoji_selector : .closed
}
})) {
NavigationView {
EmojiPickerView(selectedEmoji: $selected_emoji, emojiProvider: damus_state.emoji_provider)
}.presentationDetents([.medium, .large])
}
.emojiPicker(
isPresented: Binding(get: { popover_state == .open_emoji_selector }, set: { new_state in
withAnimation(new_state == true ? .easeIn(duration: 0.5) : .easeOut(duration: 0.1)) {
popover_state = new_state == true ? .open_emoji_selector : .closed
}
}),
selectedEmoji: $selected_emoji,
arrowDirection: isOnTopHalfOfScreen ? .down : .up,
isDismissAfterChoosing: false
)
.onChange(of: selected_emoji) { newSelectedEmoji in
if let newSelectedEmoji {
send_like(emoji: newSelectedEmoji.value)
if newSelectedEmoji != "" {
send_like(emoji: newSelectedEmoji)
popover_state = .closed
}
}

View File

@@ -70,6 +70,7 @@ struct ProfileView: View {
@State var show_share_sheet: Bool = false
@State var show_qr_code: Bool = false
@State var action_sheet_presented: Bool = false
@State var mute_dialog_presented: Bool = false
@State var filter_state : FilterState = .posts
@State var yOffset: CGFloat = 0
@@ -162,7 +163,10 @@ struct ProfileView: View {
Button(action: {
action_sheet_presented = true
}) {
navImage(img: "share3")
Image(systemName: "ellipsis")
.frame(width: 33, height: 33)
.background(Color.black.opacity(0.6))
.clipShape(Circle())
}
.confirmationDialog(NSLocalizedString("Actions", comment: "Title for confirmation dialog to either share, report, or mute a profile."), isPresented: $action_sheet_presented) {
Button(NSLocalizedString("Share", comment: "Button to share the link to a profile.")) {
@@ -196,15 +200,21 @@ struct ProfileView: View {
damus_state.postbox.send(new_ev)
}
} else {
MuteDurationMenu { duration in
notify(.mute(.user(profile.pubkey, duration?.date_from_now)))
} label: {
Text("Mute", comment: "Button to mute a profile.")
.foregroundStyle(.red)
Button(NSLocalizedString("Mute", comment: "Button to mute a profile"), role: .destructive) {
mute_dialog_presented = true
}
}
}
}
.confirmationDialog(NSLocalizedString("Mute", comment: "Title for confirmation dialog to mute a profile."), isPresented: $mute_dialog_presented) {
ForEach(DamusDuration.allCases, id: \.self) { duration in
Button {
notify(.mute(.user(profile.pubkey, duration.date_from_now)))
} label: {
Text(duration.title)
}
}
}
}
var customNavbar: some View {

View File

@@ -6,20 +6,22 @@
//
import SwiftUI
import EmojiPicker
import EmojiKit
import MCEmojiPicker
struct ReactionsSettingsView: View {
@ObservedObject var settings: UserSettingsStore
let damus_state: DamusState
@State private var isReactionsVisible: Bool = false
@State private var selectedEmoji: Emoji? = nil
var body: some View {
Form {
Section {
Text(settings.default_emoji_reaction)
.emojiPicker(
isPresented: $isReactionsVisible,
selectedEmoji: $settings.default_emoji_reaction,
arrowDirection: .up,
isDismissAfterChoosing: true
)
.onTapGesture {
isReactionsVisible = true
}
@@ -29,23 +31,43 @@ struct ReactionsSettingsView: View {
}
.navigationTitle(NSLocalizedString("Reactions", comment: "Title of emoji reactions view"))
.navigationBarTitleDisplayMode(.large)
.sheet(isPresented: $isReactionsVisible) {
NavigationView {
EmojiPickerView(selectedEmoji: $selectedEmoji, emojiProvider: damus_state.emoji_provider)
}
.presentationDetents([.medium, .large])
}
.onChange(of: selectedEmoji) { newEmoji in
guard let newEmoji else {
return
}
settings.default_emoji_reaction = newEmoji.value
}
}
}
/// From: https://stackoverflow.com/a/39425959
extension Character {
/// A simple emoji is one scalar and presented to the user as an Emoji
var isSimpleEmoji: Bool {
guard let firstScalar = unicodeScalars.first else { return false }
return firstScalar.properties.isEmoji && firstScalar.value > 0x238C
}
/// Checks if the scalars will be merged into an emoji
var isCombinedIntoEmoji: Bool { unicodeScalars.count > 1 && unicodeScalars.first?.properties.isEmoji ?? false }
var isEmoji: Bool { isSimpleEmoji || isCombinedIntoEmoji }
}
extension String {
var isSingleEmoji: Bool { count == 1 && containsEmoji }
var containsEmoji: Bool { contains { $0.isEmoji } }
var containsOnlyEmoji: Bool { !isEmpty && !contains { !$0.isEmoji } }
var emojiString: String { emojis.map { String($0) }.reduce("", +) }
var emojis: [Character] { filter { $0.isEmoji } }
var emojiScalars: [UnicodeScalar] { filter { $0.isEmoji }.flatMap { $0.unicodeScalars } }
}
func isValidEmoji(_ string: String) -> Bool {
return string.isSingleEmoji
}
struct ReactionsSettingsView_Previews: PreviewProvider {
static var previews: some View {
ReactionsSettingsView(settings: UserSettingsStore(), damus_state: test_damus_state)
ReactionsSettingsView(settings: UserSettingsStore())
}
}

View File

@@ -7,7 +7,6 @@
import Foundation
@testable import damus
import EmojiPicker
// Generates a test damus state with configurable mock parameters
func generate_test_damus_state(
@@ -51,9 +50,7 @@ func generate_test_damus_state(
music: .init(onChange: {_ in }),
video: .init(),
ndb: ndb,
quote_reposts: .init(our_pubkey: our_pubkey),
emoji_provider: DefaultEmojiProvider()
)
quote_reposts: .init(our_pubkey: our_pubkey) )
return damus
}