mirror of
https://github.com/lumaa-dev/BubbleApp.git
synced 2025-02-03 11:57:57 +01:00
direct messages tip + tip style
This commit is contained in:
parent
9503a4d4ab
commit
fc90c766d9
@ -1,6 +1,64 @@
|
||||
//Made by Lumaa
|
||||
|
||||
import SwiftUI
|
||||
import TipKit
|
||||
|
||||
struct HeadlineTipViewStyle: TipViewStyle {
|
||||
var headlineType: HeadlineType = .tip
|
||||
|
||||
func makeBody(configuration: TipViewStyle.Configuration) -> some View {
|
||||
VStack(alignment: .leading) {
|
||||
if headlineType != .none {
|
||||
HStack {
|
||||
Text(String(localized: LocalizedStringResource(stringLiteral: headlineType.rawValue)).uppercased())
|
||||
.font(.headline.smallCaps())
|
||||
.foregroundStyle(Color.gray)
|
||||
|
||||
Spacer()
|
||||
|
||||
Button(action: { configuration.tip.invalidate(reason: .tipClosed) }) {
|
||||
Image(systemName: "xmark")
|
||||
.scaledToFit()
|
||||
}
|
||||
}
|
||||
|
||||
Divider()
|
||||
.frame(height: 1.0)
|
||||
}
|
||||
|
||||
|
||||
HStack(alignment: .top) {
|
||||
configuration.image?
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 48.0, height: 48.0)
|
||||
|
||||
|
||||
VStack(alignment: .leading, spacing: 8.0) {
|
||||
configuration.title?.font(.headline)
|
||||
configuration.message?.font(.subheadline)
|
||||
|
||||
|
||||
ForEach(configuration.actions) { action in
|
||||
Button(action: action.handler) {
|
||||
action.label().foregroundStyle(.blue)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 5)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
|
||||
public enum HeadlineType: String {
|
||||
case tip = "tip.headline.tip" // tip
|
||||
case new = "tip.headline.new" // new
|
||||
case update = "tip.headline.update" // updated
|
||||
case meta = "tip.headline.meta" // just like meta
|
||||
case none = ""
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
func listThreaded(tint: Color = Color(uiColor: UIColor.label)) -> some View {
|
||||
|
@ -9,6 +9,9 @@
|
||||
},
|
||||
"%@" : {
|
||||
|
||||
},
|
||||
"%lld" : {
|
||||
|
||||
},
|
||||
"•" : {
|
||||
|
||||
@ -52,6 +55,12 @@
|
||||
"state" : "translated",
|
||||
"value" : "Threaded is a very simple Mastodon client, that is meant to look like the newest social media Threads made by Meta Platforms. It integrates perfectly with your Mastodon account, and matches the Threads vibe, while having Mastodon-only features.\n\nThreaded is a 100% free, made in France using SwiftUI, [open-source](https://github.com/lumaa-dev/ThreadedApp), and doesn't violate [your privacy](https://apps.lumaa.fr/legal/privacy).\n\nThreaded is not related or affiliated to Meta Platforms."
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Threaded is a very simple Mastodon client, that is meant to look like the newest social media Threads made by Meta Platforms. It integrates perfectly with your Mastodon account, and matches the Threads vibe, while having Mastodon-only features.\n\nThreaded is a 100% free, made in France using SwiftUI, [open-source](https://github.com/lumaa-dev/ThreadedApp), and doesn't violate [your privacy](https://apps.lumaa.fr/legal/privacy).\n\nThreaded is not related or affiliated to Meta Platforms."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -62,6 +71,12 @@
|
||||
"state" : "translated",
|
||||
"value" : "Threaded uses third-party open-source libraries and code:\n- [IceCubesApp](https://github.com/dimillian/IceCubesApp)\n- [SwiftSoup](https://github.com/scinfu/SwiftSoup)\n- [Nuke](https://github.com/kean/Nuke)\n- [EmojiText](https://github.com/divadretlaw/EmojiText)\n- [KeychainSwift](https://github.com/evgenyneu/keychain-swift)"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Threaded uses third-party open-source libraries and code:\n- [IceCubesApp](https://github.com/dimillian/IceCubesApp)\n- [SwiftSoup](https://github.com/scinfu/SwiftSoup)\n- [Nuke](https://github.com/kean/Nuke)\n- [EmojiText](https://github.com/divadretlaw/EmojiText)\n- [KeychainSwift](https://github.com/evgenyneu/keychain-swift)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -212,7 +227,7 @@
|
||||
},
|
||||
"other" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"state" : "translated",
|
||||
"value" : "%lld followers"
|
||||
}
|
||||
}
|
||||
@ -381,6 +396,78 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"activity.status.attachments-%lld" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"variations" : {
|
||||
"plural" : {
|
||||
"one" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%lld attachment"
|
||||
}
|
||||
},
|
||||
"other" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%lld attachments"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"variations" : {
|
||||
"plural" : {
|
||||
"one" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%lld pièce-jointe"
|
||||
}
|
||||
},
|
||||
"other" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%lld pièces-jointe"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"activity.tip.messages.desc" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Your direct messages and mentions are separated, access your direct messages using the upper-right corner button"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Vos messages privés et mentions sont séparés, accédez à vos messages privés en utilisant le bouton au coin supérieur droit"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"activity.tip.messages.title" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Direct Messages"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Messages privés"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"activity.unknown" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@ -900,6 +987,12 @@
|
||||
"state" : "translated",
|
||||
"value" : "Threaded+ - Description"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Threaded+ - Description"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -945,12 +1038,12 @@
|
||||
"one" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%lld likes"
|
||||
"value" : "%lld like"
|
||||
}
|
||||
},
|
||||
"other" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"state" : "translated",
|
||||
"value" : "%lld likes"
|
||||
}
|
||||
}
|
||||
@ -1349,6 +1442,50 @@
|
||||
},
|
||||
"timeline.trending" : {
|
||||
|
||||
},
|
||||
"tip.headline.meta" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Just like Meta!"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tip.headline.tip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Tip"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tip.headline.update" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Updated"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tip.healine.new" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "New!"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"version" : "1.0"
|
||||
|
@ -1,6 +1,7 @@
|
||||
//Made by Lumaa
|
||||
|
||||
import SwiftUI
|
||||
import TipKit
|
||||
|
||||
@main
|
||||
struct ThreadedApp: App {
|
||||
@ -11,6 +12,14 @@ struct ThreadedApp: App {
|
||||
.onAppear {
|
||||
HapticManager.prepareHaptics()
|
||||
}
|
||||
.task {
|
||||
Tips.showAllTipsForTesting()
|
||||
|
||||
try? Tips.configure([
|
||||
.displayFrequency(.immediate),
|
||||
.datastoreLocation(.applicationDefault)
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,23 @@
|
||||
//Made by Lumaa
|
||||
|
||||
import SwiftUI
|
||||
import TipKit
|
||||
|
||||
struct NotificationsView: View {
|
||||
@Environment(AccountManager.self) private var accountManager
|
||||
|
||||
@State private var navigator: Navigator = Navigator()
|
||||
@State private var notifications: [Notification] = []
|
||||
@State private var loadingNotifs: Bool = false
|
||||
@State private var loadingNotifs: Bool = true
|
||||
@State private var lastId: Int? = nil
|
||||
private let notifLimit = 50
|
||||
|
||||
@State private var messages: [Notification] = []
|
||||
private var msgBadge: Int {
|
||||
messages.map({ $0.account.id }).uniqued().count
|
||||
}
|
||||
|
||||
private let msgTip: MsgTip = .init()
|
||||
|
||||
var body: some View {
|
||||
NavigationStack(path: $navigator.path) {
|
||||
@ -47,6 +54,29 @@ struct NotificationsView: View {
|
||||
await fetchNotifications(lastId: nil)
|
||||
}
|
||||
.navigationTitle(String(localized: "activity"))
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
Button {
|
||||
msgTip.invalidate(reason: .actionPerformed)
|
||||
} label: {
|
||||
Image(systemName: "paperplane")
|
||||
.foregroundStyle(Color(uiColor: UIColor.label))
|
||||
.overlay(alignment: .topTrailing) {
|
||||
if msgBadge > 0 {
|
||||
Text("\(msgBadge)")
|
||||
.foregroundStyle(Color.white)
|
||||
.font(.caption)
|
||||
.padding(5)
|
||||
.background(Color.red)
|
||||
.clipShape(Circle())
|
||||
.offset(x: 5, y: -7)
|
||||
}
|
||||
}
|
||||
}
|
||||
.popoverTip(msgTip, arrowEdge: .top)
|
||||
.tipViewStyle(HeadlineTipViewStyle(headlineType: .meta))
|
||||
}
|
||||
}
|
||||
} else if loadingNotifs == false && notifications.isEmpty {
|
||||
ZStack {
|
||||
Color.appBackground
|
||||
@ -87,8 +117,30 @@ struct NotificationsView: View {
|
||||
} else {
|
||||
notifications.append(contentsOf: notifs)
|
||||
}
|
||||
|
||||
filterMessages()
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
func filterMessages() {
|
||||
guard !notifications.isEmpty else { return }
|
||||
messages = notifications.filter({ $0.status?.visibility == .direct })
|
||||
notifications.removeAll(where: { $0.status?.visibility == .direct })
|
||||
}
|
||||
|
||||
struct MsgTip: Tip {
|
||||
var title: Text = Text("activity.tip.messages.title")
|
||||
var message: Text? = Text("activity.tip.messages.desc")
|
||||
var id: String = "fr.lumaa.Threaded.MsgTip"
|
||||
var image: Image? = Image(systemName: "paperplane")
|
||||
}
|
||||
}
|
||||
|
||||
public extension Array where Element: Hashable {
|
||||
func uniqued() -> [Element] {
|
||||
var seen = Set<Element>()
|
||||
return filter { seen.insert($0).inserted }
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user