mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-06 01:09:30 +00:00
Custom emojis in display name
This commit is contained in:
parent
ae9f78e737
commit
c2a2fe1f86
11 changed files with 75 additions and 20 deletions
|
@ -98,7 +98,7 @@ struct AccountDetailHeaderView: View {
|
|||
accountAvatarView
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
Text(account.displayName)
|
||||
account.displayNameWithEmojis
|
||||
.font(.headline)
|
||||
Text(account.acct)
|
||||
.font(.callout)
|
||||
|
|
|
@ -25,6 +25,7 @@ public struct Account: Codable, Identifiable, Equatable, Hashable {
|
|||
public let lastStatusAt: String?
|
||||
public let fields: [Field]
|
||||
public let locked: Bool
|
||||
public let emojis: [Emoji]
|
||||
|
||||
public static func placeholder() -> Account {
|
||||
.init(id: UUID().uuidString,
|
||||
|
@ -40,6 +41,7 @@ public struct Account: Codable, Identifiable, Equatable, Hashable {
|
|||
statusesCount: 10,
|
||||
lastStatusAt: nil,
|
||||
fields: [],
|
||||
locked: false)
|
||||
locked: false,
|
||||
emojis: [])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,11 @@ extension HTMLString {
|
|||
|
||||
public var asSafeAttributedString: AttributedString {
|
||||
do {
|
||||
// Add space between hashtags that follow each other
|
||||
let markdown = asMarkdown.replacingOccurrences(of: ")[#", with: ") [#")
|
||||
let options = AttributedString.MarkdownParsingOptions(allowsExtendedAttributes: true,
|
||||
interpretedSyntax: .inlineOnlyPreservingWhitespace)
|
||||
return try AttributedString(markdown: asMarkdown, options: options)
|
||||
return try AttributedString(markdown: markdown, options: options)
|
||||
} catch {
|
||||
return AttributedString(stringLiteral: self)
|
||||
}
|
||||
|
|
17
Packages/Models/Sources/Models/Emoji.swift
Normal file
17
Packages/Models/Sources/Models/Emoji.swift
Normal file
|
@ -0,0 +1,17 @@
|
|||
import Foundation
|
||||
|
||||
public struct Emoji: Codable, Hashable, Identifiable {
|
||||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(shortcode)
|
||||
}
|
||||
|
||||
public var id: String {
|
||||
shortcode
|
||||
}
|
||||
|
||||
public let shortcode: String
|
||||
public let url: URL
|
||||
public let staticUrl: URL
|
||||
public let visibleInPicker: Bool
|
||||
}
|
27
Packages/Models/Sources/Models/Ext/AccountExt.swift
Normal file
27
Packages/Models/Sources/Models/Ext/AccountExt.swift
Normal file
|
@ -0,0 +1,27 @@
|
|||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
extension Account {
|
||||
public var displayNameWithEmojis: some View {
|
||||
let splittedDisplayName = displayName.split(separator: ":")
|
||||
return HStack(spacing: 0) {
|
||||
ForEach(splittedDisplayName, id: \.self) { part in
|
||||
if let emoji = emojis.first(where: { $0.shortcode == part }) {
|
||||
AsyncImage(
|
||||
url: emoji.url,
|
||||
content: { image in
|
||||
image.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(maxWidth: 20, maxHeight: 20)
|
||||
},
|
||||
placeholder: {
|
||||
ProgressView()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
Text(part)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ public struct Notification: Codable, Identifiable {
|
|||
}
|
||||
|
||||
public static func placeholders() -> [Notification] {
|
||||
[.placeholder(), .placeholder(), .placeholder(), .placeholder(), .placeholder()]
|
||||
[.placeholder(), .placeholder(), .placeholder(), .placeholder(), .placeholder(), .placeholder(), .placeholder(), .placeholder()]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ public protocol AnyStatus {
|
|||
var favourited: Bool { get }
|
||||
var reblogged: Bool { get }
|
||||
var pinned: Bool? { get }
|
||||
var emojis: [Emoji] { get }
|
||||
}
|
||||
|
||||
public struct Status: AnyStatus, Codable, Identifiable {
|
||||
|
@ -31,6 +32,7 @@ public struct Status: AnyStatus, Codable, Identifiable {
|
|||
public let favourited: Bool
|
||||
public let reblogged: Bool
|
||||
public let pinned: Bool?
|
||||
public let emojis: [Emoji]
|
||||
|
||||
public static func placeholder() -> Status {
|
||||
.init(id: UUID().uuidString,
|
||||
|
@ -46,7 +48,8 @@ public struct Status: AnyStatus, Codable, Identifiable {
|
|||
card: nil,
|
||||
favourited: false,
|
||||
reblogged: false,
|
||||
pinned: false)
|
||||
pinned: false,
|
||||
emojis: [])
|
||||
}
|
||||
|
||||
public static func placeholders() -> [Status] {
|
||||
|
@ -68,4 +71,5 @@ public struct ReblogStatus: AnyStatus, Codable, Identifiable {
|
|||
public let favourited: Bool
|
||||
public let reblogged: Bool
|
||||
public let pinned: Bool?
|
||||
public let emojis: [Emoji]
|
||||
}
|
||||
|
|
|
@ -25,12 +25,12 @@ struct NotificationRowView: View {
|
|||
.aspectRatio(contentMode: .fit)
|
||||
.padding(.horizontal, 4)
|
||||
if type.displayAccountName() {
|
||||
Text(notification.account.displayName)
|
||||
.font(.headline) +
|
||||
notification.account.displayNameWithEmojis
|
||||
.font(.subheadline)
|
||||
Text(" ")
|
||||
}
|
||||
Text(type.label())
|
||||
.font(.body)
|
||||
.font(.subheadline)
|
||||
Spacer()
|
||||
}
|
||||
if let status = notification.status {
|
||||
|
@ -91,7 +91,7 @@ extension Models.Notification.NotificationType {
|
|||
case .status:
|
||||
return "pencil"
|
||||
case .mention:
|
||||
return "at"
|
||||
return "at.circle.fill"
|
||||
case .reblog:
|
||||
return "arrow.left.arrow.right.circle.fill"
|
||||
case .follow, .follow_request:
|
||||
|
|
|
@ -7,7 +7,6 @@ import DesignSystem
|
|||
public struct NotificationsListView: View {
|
||||
@EnvironmentObject private var client: Client
|
||||
@StateObject private var viewModel = NotificationsViewModel()
|
||||
@State private var didAppear: Bool = false
|
||||
|
||||
public init() { }
|
||||
|
||||
|
@ -25,15 +24,13 @@ public struct NotificationsListView: View {
|
|||
.padding(.top, DS.Constants.layoutPadding)
|
||||
}
|
||||
.task {
|
||||
if !didAppear {
|
||||
didAppear = true
|
||||
viewModel.client = client
|
||||
await viewModel.fetchNotifications()
|
||||
}
|
||||
}
|
||||
.refreshable {
|
||||
Task {
|
||||
await viewModel.fetchNotifications()
|
||||
}
|
||||
}
|
||||
.navigationTitle(Text("Notifications"))
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
|
|
|
@ -22,7 +22,9 @@ class NotificationsViewModel: ObservableObject {
|
|||
func fetchNotifications() async {
|
||||
guard let client else { return }
|
||||
do {
|
||||
if notifications.isEmpty {
|
||||
state = .loading
|
||||
}
|
||||
notifications = try await client.get(endpoint: Notifications.notifications(maxId: nil))
|
||||
state = .display(notifications: notifications, nextPageState: .hasNextPage)
|
||||
} catch {
|
||||
|
|
|
@ -31,11 +31,15 @@ public struct StatusRowView: View {
|
|||
if viewModel.status.reblog != nil {
|
||||
HStack(spacing: 2) {
|
||||
Image(systemName:"arrow.left.arrow.right.circle")
|
||||
Text("\(viewModel.status.account.displayName) reblogged")
|
||||
viewModel.status.account.displayNameWithEmojis
|
||||
Text("boosted")
|
||||
}
|
||||
.font(.footnote)
|
||||
.foregroundColor(.gray)
|
||||
.fontWeight(.semibold)
|
||||
.onTapGesture {
|
||||
routeurPath.navigate(to: .accountDetailWithAccount(account: viewModel.status.account))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,8 +75,8 @@ public struct StatusRowView: View {
|
|||
@ViewBuilder
|
||||
private func makeAccountView(status: AnyStatus) -> some View {
|
||||
AvatarView(url: status.account.avatar)
|
||||
VStack(alignment: .leading) {
|
||||
Text(status.account.displayName)
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
status.account.displayNameWithEmojis
|
||||
.font(.subheadline)
|
||||
.fontWeight(.semibold)
|
||||
Group {
|
||||
|
|
Loading…
Reference in a new issue