Update toolbar items

This commit is contained in:
Jackson Harper 2023-12-08 14:30:20 +08:00
parent 53a355f3cb
commit 8c0db16d9a
10 changed files with 208 additions and 60 deletions

View file

@ -53,7 +53,8 @@ struct AnimatingCellHeight: AnimatableModifier {
}
var showFeatureCards: Bool {
viewModel.listConfig.hasFeatureCards &&
isEditMode == .inactive &&
viewModel.listConfig.hasFeatureCards &&
!viewModel.hideFeatureSection &&
viewModel.fetcher.items.count > 0 &&
viewModel.searchTerm.isEmpty &&
@ -204,14 +205,6 @@ struct AnimatingCellHeight: AnimatableModifier {
}
.frame(maxWidth: .infinity, alignment: .bottomLeading)
}
ToolbarItem(placement: .barTrailing) {
if UIDevice.isIPad, viewModel.folder == "inbox" {
Button(action: { addLinkPresented = true }, label: {
Label("Add Link", systemImage: "plus")
})
}
}
ToolbarItem(placement: UIDevice.isIPhone ? .barLeading : .barTrailing) {
if enableGrid {
Button(
@ -226,26 +219,31 @@ struct AnimatingCellHeight: AnimatableModifier {
Button(
action: { searchPresented = true },
label: {
Image(systemName: "magnifyingglass")
Image.magnifyingGlass
.foregroundColor(Color.appGrayTextContrast)
}
)
}
ToolbarItem(placement: .barTrailing) {
if UIDevice.isIPhone {
Menu(content: {
Button(action: {
isEditMode = isEditMode == .inactive ? .active : .inactive
}, label: {
Text(isEditMode == .inactive ? "Select Multiple" : "End Multiselect")
})
Button(action: { addLinkPresented = true }, label: {
Label("Add Link", systemImage: "plus.circle")
})
}, label: {
Image.utilityMenu
})
.foregroundColor(.appGrayTextContrast)
Button(
action: { isEditMode = isEditMode == .active ? .inactive : .active },
label: {
Image.selectMultiple
.foregroundColor(Color.appGrayTextContrast)
}
)
}
ToolbarItem(placement: .barTrailing) {
if viewModel.folder == "inbox" {
Button(
action: { addLinkPresented = true },
label: {
Image.addLink
.foregroundColor(Color.appGrayTextContrast)
}
)
} else {
EmptyView()
}
}
ToolbarItemGroup(placement: .bottomBar) {
@ -594,8 +592,45 @@ struct AnimatingCellHeight: AnimatableModifier {
}
}
var listItems: some View {
ForEach(Array(viewModel.fetcher.items.enumerated()), id: \.1.unwrappedID) { _, item in
let horizontalInset = CGFloat(UIDevice.isIPad ? 20 : 10)
FeedCardNavigationLink(
item: item,
isInMultiSelectMode: viewModel.isInMultiSelectMode,
viewModel: viewModel
)
.background(GeometryReader { geometry in
Color.clear
.preference(key: ScrollOffsetPreferenceKey.self, value: geometry.frame(in: .named("scroll")).origin)
})
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
if value.y < 100, value.y > 0 {
if item.savedAt != nil, topItem != item {
setTopItem(item)
}
}
}
.listRowSeparatorTint(Color.thBorderColor)
.listRowInsets(.init(top: 0, leading: horizontalInset, bottom: 10, trailing: horizontalInset))
.contextMenu {
menuItems(for: item)
}
.swipeActions(edge: .leading, allowsFullSwipe: true) {
ForEach(viewModel.listConfig.leadingSwipeActions, id: \.self) { action in
swipeActionButton(action: action, item: item)
}
}
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
ForEach(viewModel.listConfig.trailingSwipeActions, id: \.self) { action in
swipeActionButton(action: action, item: item)
}
}
}
}
var body: some View {
let horizontalInset = CGFloat(UIDevice.isIPad ? 20 : 10)
VStack(spacing: 0) {
Color.systemBackground.frame(height: 1)
ScrollViewReader { reader in
@ -634,38 +669,14 @@ struct AnimatingCellHeight: AnimatableModifier {
}
}
ForEach(Array(viewModel.fetcher.items.enumerated()), id: \.1.unwrappedID) { _, item in
FeedCardNavigationLink(
item: item,
isInMultiSelectMode: viewModel.isInMultiSelectMode,
viewModel: viewModel
)
.background(GeometryReader { geometry in
Color.clear
.preference(key: ScrollOffsetPreferenceKey.self, value: geometry.frame(in: .named("scroll")).origin)
})
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
if value.y < 100, value.y > 0 {
if item.savedAt != nil, topItem != item {
setTopItem(item)
}
}
}
.listRowSeparatorTint(Color.thBorderColor)
.listRowInsets(.init(top: 0, leading: horizontalInset, bottom: 10, trailing: horizontalInset))
.contextMenu {
menuItems(for: item)
}
.swipeActions(edge: .leading, allowsFullSwipe: true) {
ForEach(viewModel.listConfig.leadingSwipeActions, id: \.self) { action in
swipeActionButton(action: action, item: item)
}
}
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
ForEach(viewModel.listConfig.trailingSwipeActions, id: \.self) { action in
swipeActionButton(action: action, item: item)
}
if viewModel.showLoadingBar {
HStack(alignment: .center, spacing: 10) {
ProgressView()
}
.frame(height: 100)
.listRowSeparator(.hidden)
} else {
listItems
}
}
}, header: {

View file

@ -152,10 +152,9 @@ import Views
func loadItems(dataService: DataService, isRefresh: Bool) async {
isLoading = true
showLoadingBar = true
showLoadingBar = isRefresh
await fetcher.loadItems(dataService: dataService, filterState: filterState, isRefresh: isRefresh)
updateFeatureFilter(context: dataService.viewContext, filter: FeaturedItemFilter(rawValue: featureFilter))
isLoading = false
@ -164,12 +163,10 @@ import Views
func loadMoreItems(dataService: DataService, filterState: FetcherFilterState, isRefresh: Bool) async {
isLoading = true
showLoadingBar = true
await fetcher.loadMoreItems(dataService: dataService, filterState: filterState, isRefresh: isRefresh)
isLoading = false
showLoadingBar = false
}
func loadFeatureItems(context: NSManagedObjectContext, predicate: NSPredicate, sort: NSSortDescriptor) async -> [Models.LibraryItem] {

View file

@ -0,0 +1,31 @@
//
// File.swift
//
//
// Created by Jackson Harper on 12/8/23.
//
import Foundation
import NaturalLanguage
public func extractFirstFewWords(_ title: String) -> String {
let languageRecognizer = NLLanguageRecognizer()
languageRecognizer.processString(title)
let language = languageRecognizer.dominantLanguage ?? NLLanguage.english
let tokenizer = NLTokenizer(unit: .word)
tokenizer.setLanguage(language)
tokenizer.string = title
var words: [String] = []
tokenizer.enumerateTokens(in: title.startIndex ..< title.endIndex) { range, _ in
let word = String(title[range])
words.append(word)
return true
}
print("WORDS: ", words)
let truncatedTitle = words.prefix(2).joined(separator: " ")
return truncatedTitle
}

View file

@ -21,6 +21,10 @@ public extension Image {
static var readerSettings: Image { Image("reader-settings", bundle: .module) }
static var utilityMenu: Image { Image("utility-menu", bundle: .module) }
static var addLink: Image { Image("add-link", bundle: .module) }
static var selectMultiple: Image { Image("select-multiple", bundle: .module) }
static var magnifyingGlass: Image { Image("magnifying-glass", bundle: .module) }
static var archive: Image { Image("archive", bundle: .module) }
static var unarchive: Image { Image("unarchive", bundle: .module) }
static var remove: Image { Image("remove", bundle: .module) }

View file

@ -0,0 +1,24 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "add-link.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View file

@ -0,0 +1,11 @@
<svg width="26" height="25" viewBox="0 0 26 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_6802_32635)">
<path d="M13.3398 5.20801V19.7913" stroke="#EDEDED" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.0481 12.5H20.6314" stroke="#EDEDED" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_6802_32635">
<rect width="25" height="25" fill="white" transform="translate(0.839844)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 519 B

View file

@ -0,0 +1,24 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "magnifying-glass.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View file

@ -0,0 +1,11 @@
<svg width="26" height="25" viewBox="0 0 26 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_6802_32619)">
<path d="M5.08984 10.6667C5.08984 11.5093 5.25582 12.3437 5.57828 13.1222C5.90075 13.9007 6.3734 14.6081 6.96924 15.2039C7.56508 15.7998 8.27245 16.2724 9.05096 16.5949C9.82946 16.9174 10.6639 17.0833 11.5065 17.0833C12.3492 17.0833 13.1836 16.9174 13.9621 16.5949C14.7406 16.2724 15.4479 15.7998 16.0438 15.2039C16.6396 14.6081 17.1123 13.9007 17.4347 13.1222C17.7572 12.3437 17.9232 11.5093 17.9232 10.6667C17.9232 9.82402 17.7572 8.98962 17.4347 8.21111C17.1123 7.43261 16.6396 6.72524 16.0438 6.1294C15.4479 5.53356 14.7406 5.06091 13.9621 4.73844C13.1836 4.41597 12.3492 4.25 11.5065 4.25C10.6639 4.25 9.82946 4.41597 9.05096 4.73844C8.27245 5.06091 7.56508 5.53356 6.96924 6.1294C6.3734 6.72524 5.90075 7.43261 5.57828 8.21111C5.25582 8.98962 5.08984 9.82402 5.08984 10.6667Z" stroke="#EDEDED" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M21.5898 20.75L16.0898 15.25" stroke="#EDEDED" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_6802_32619">
<rect width="25" height="25" fill="white" transform="translate(0.839844)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,24 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "multiple-select.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View file

@ -0,0 +1,11 @@
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_6802_32631)">
<path d="M10.3398 12.2402L13.3398 15.2402L21.3398 7.24023" stroke="#EDEDED" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M21.3398 13.2402V19.2402C21.3398 19.7707 21.1291 20.2794 20.7541 20.6544C20.379 21.0295 19.8703 21.2402 19.3398 21.2402H7.33984C6.80941 21.2402 6.3007 21.0295 5.92563 20.6544C5.55056 20.2794 5.33984 19.7707 5.33984 19.2402V7.24023C5.33984 6.7098 5.55056 6.20109 5.92563 5.82602C6.3007 5.45095 6.80941 5.24023 7.33984 5.24023H16.3398" stroke="#EDEDED" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_6802_32631">
<rect width="25" height="25" fill="white" transform="translate(0.839844 0.740234)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 864 B