Recently used tags

This commit is contained in:
Thomas Ricouard 2024-01-05 10:57:26 +01:00
parent 3e968525ac
commit f428118fa0
5 changed files with 98 additions and 19 deletions

View file

@ -136,6 +136,7 @@ extension View {
Draft.self, Draft.self,
LocalTimeline.self, LocalTimeline.self,
TagGroup.self, TagGroup.self,
RecentTag.self,
]) ])
} }
} }

View file

@ -0,0 +1,13 @@
import Foundation
import SwiftData
import SwiftUI
@Model public class RecentTag: Equatable {
public var title: String = ""
public var lastUse: Date = Date()
public init(title: String) {
self.title = title
self.lastUse = Date()
}
}

View file

@ -38,7 +38,7 @@ struct StatusEditorAccessoryView: View {
} }
.frame(height: 24) .frame(height: 24)
.padding(16) .padding(16)
.background(.ultraThinMaterial) .background(.thinMaterial)
.cornerRadius(8) .cornerRadius(8)
#else #else
Divider() Divider()
@ -47,7 +47,7 @@ struct StatusEditorAccessoryView: View {
} }
.frame(height: 20) .frame(height: 20)
.padding(.vertical, 12) .padding(.vertical, 12)
.background(.ultraThinMaterial) .background(.thinMaterial)
#endif #endif
} }
.onAppear { .onAppear {

View file

@ -2,26 +2,54 @@ import DesignSystem
import EmojiText import EmojiText
import Foundation import Foundation
import SwiftUI import SwiftUI
import Models
import SwiftData
@MainActor @MainActor
struct StatusEditorAutoCompleteView: View { struct StatusEditorAutoCompleteView: View {
@Environment(\.modelContext) private var context
@Environment(Theme.self) private var theme @Environment(Theme.self) private var theme
var viewModel: StatusEditorViewModel var viewModel: StatusEditorViewModel
@State private var isTagSuggestionExpanded: Bool = false
@Query(sort: \RecentTag.lastUse, order: .reverse) var recentTags: [RecentTag]
var body: some View { var body: some View {
if !viewModel.mentionsSuggestions.isEmpty || !viewModel.tagsSuggestions.isEmpty { if !viewModel.mentionsSuggestions.isEmpty || !viewModel.tagsSuggestions.isEmpty {
ScrollView(.horizontal, showsIndicators: false) { VStack {
LazyHStack { HStack {
if !viewModel.mentionsSuggestions.isEmpty { ScrollView(.horizontal, showsIndicators: false) {
suggestionsMentionsView LazyHStack {
} else { if !viewModel.mentionsSuggestions.isEmpty {
suggestionsTagView suggestionsMentionsView
} else {
suggestionsTagView
}
}
.padding(.horizontal, .layoutPadding)
}
.scrollContentBackground(.hidden)
if !viewModel.tagsSuggestions.isEmpty {
Spacer()
Button {
withAnimation {
isTagSuggestionExpanded.toggle()
}
} label: {
Image(systemName: isTagSuggestionExpanded ? "chevron.down.circle" : "chevron.up.circle")
}
.padding(.trailing, 8)
} }
} }
.padding(.horizontal, .layoutPadding) .frame(height: 40)
if isTagSuggestionExpanded {
expandedTagsSuggestionView
}
} }
.frame(height: 40) .background(.thinMaterial)
.background(.ultraThinMaterial)
} }
} }
@ -38,10 +66,11 @@ struct StatusEditorAutoCompleteView: View {
.emojiSize(Font.scaledFootnoteFont.emojiSize) .emojiSize(Font.scaledFootnoteFont.emojiSize)
.emojiBaselineOffset(Font.scaledFootnoteFont.emojiBaselineOffset) .emojiBaselineOffset(Font.scaledFootnoteFont.emojiBaselineOffset)
.font(.scaledFootnote) .font(.scaledFootnote)
.fontWeight(.bold)
.foregroundColor(theme.labelColor) .foregroundColor(theme.labelColor)
Text("@\(account.acct)") Text("@\(account.acct)")
.font(.scaledCaption) .font(.scaledFootnote)
.foregroundColor(theme.tintColor) .foregroundStyle(theme.tintColor)
} }
} }
} }
@ -51,17 +80,53 @@ struct StatusEditorAutoCompleteView: View {
private var suggestionsTagView: some View { private var suggestionsTagView: some View {
ForEach(viewModel.tagsSuggestions) { tag in ForEach(viewModel.tagsSuggestions) { tag in
Button { Button {
viewModel.selectHashtagSuggestion(tag: tag) viewModel.selectHashtagSuggestion(tag: tag.name)
if let index = recentTags.firstIndex(where: { $0.title.lowercased() == tag.name.lowercased() }) {
recentTags[index].lastUse = Date()
} else {
context.insert(RecentTag(title: tag.name))
}
} label: { } label: {
VStack(alignment: .leading) { VStack(alignment: .leading) {
Text("#\(tag.name)") Text("#\(tag.name)")
.font(.scaledFootnote) .font(.scaledFootnote)
.foregroundColor(theme.tintColor) .fontWeight(.bold)
.foregroundColor(theme.labelColor)
Text("tag.suggested.mentions-\(tag.totalUses)") Text("tag.suggested.mentions-\(tag.totalUses)")
.font(.scaledCaption) .font(.scaledFootnote)
.foregroundStyle(.secondary) .foregroundStyle(theme.tintColor)
} }
} }
} }
} }
private var expandedTagsSuggestionView: some View {
ScrollView(.vertical) {
LazyVStack(alignment: .leading, spacing: 12) {
Text("status.editor.language-select.recently-used")
.font(.scaledSubheadline)
.foregroundStyle(theme.labelColor)
.fontWeight(.bold)
ForEach(recentTags) { tag in
HStack {
Button {
tag.lastUse = Date()
withAnimation {
isTagSuggestionExpanded = false
viewModel.selectHashtagSuggestion(tag: tag.title)
}
} label: {
Text("#\(tag.title)")
.font(.scaledFootnote)
.fontWeight(.bold)
.foregroundColor(theme.labelColor)
}
Spacer()
}
}
}
.padding(.horizontal, .layoutPadding)
}
.frame(height: 250)
}
} }

View file

@ -564,9 +564,9 @@ import SwiftUI
} }
} }
func selectHashtagSuggestion(tag: Tag) { func selectHashtagSuggestion(tag: String) {
if let range = currentSuggestionRange { if let range = currentSuggestionRange {
replaceTextWith(text: "#\(tag.name) ", inRange: range) replaceTextWith(text: "#\(tag) ", inRange: range)
} }
} }