Skip to content
Snippets Groups Projects
Commit 4120cff8 authored by cruxfilm's avatar cruxfilm
Browse files

UI polish to MailListView and SearchView

parent 2c3be5a2
Branches
Tags
1 merge request!76Resolve "InboxView & MailListView improvements"
...@@ -15,64 +15,56 @@ struct MailListView: View { ...@@ -15,64 +15,56 @@ struct MailListView: View {
@Environment(\.managedObjectContext) var managedObjectContext @Environment(\.managedObjectContext) var managedObjectContext
var fetchRequest: FetchRequest<MailRecord> var fetchRequest: FetchRequest<MailRecord>
var mails: FetchedResults<MailRecord>{fetchRequest.wrappedValue} var mails: FetchedResults<MailRecord>{fetchRequest.wrappedValue}
var folderPath: String
var folderName: String
var folderpath: String @State private var updating = false
var name: String @State private var showUser = false
@State private var searchText = ""
@State var updating = false @State private var searchType = SearchType.All
@State var showUser = false @State private var composeMail = false
@State var searchText = ""
@State var searchField = SearchType.All
// @State var searchNow = false
@State var composeMail = false
init(folderpath: String, name: String) { init(folderpath: String, name: String) {
fetchRequest = MailRecord.mailsInFolderFetchRequest(folderpath: folderpath) fetchRequest = MailRecord.mailsInFolderFetchRequest(folderpath: folderpath)
self.folderpath = folderpath self.folderPath = folderpath
self.name = name self.folderName = name
} }
var body: some View { var body: some View {
mainView VStack(alignment: .leading) {
.navigationBarTitle(name, displayMode: .inline) SearchView(searchText: $searchText, searchType: $searchType).padding()
.onAppear {
self.updateMails() mailList.padding(-12)
}
.sheet(isPresented: $composeMail) {
ComposeView()
} }
.navigationBarTitle(folderName, displayMode: .inline)
.onAppear { updateMails() }
.sheet(isPresented: $composeMail) { ComposeView() }
.toolbar {
ToolbarItem(placement: .status) {
lastUpdate
} }
private var mainView: some View { ToolbarItemGroup(placement: .bottomBar) {
VStack (alignment: .leading){
SearchView(searchText: $searchText, searchType: $searchField)
.padding(6)
mailList
.padding(-12)
// Toolbar
HStack {
Spacer()
self.lastUpdate
Spacer() Spacer()
self.composeButton composeButton
} }
.padding(6)
} }
} }
private var mailList: some View { private var mailList: some View {
List(self.mails.filter(filterKeyRecord), id: \.self) { record in List(self.mails.filter(filterKeyRecord), id: \.self) { record in
NavigationLink( NavigationLink(destination: ReadMainView(model: ReadModel(mail: record))) {
destination: ReadMainView(model: ReadModel(mail: record))) {
MailRowView(mail: record) MailRowView(mail: record)
} }
} }
.listStyle(InsetGroupedListStyle())
.resignKeyboardOnDragGesture() // hide keyboard when dragging .resignKeyboardOnDragGesture() // hide keyboard when dragging
} }
private var composeButton: some View { private var composeButton: some View {
Button(action: { Button {
composeMail = true composeMail = true
}) { } label: {
Image(systemName: "square.and.pencil").imageScale(.large) Image(systemName: "square.and.pencil").imageScale(.large)
} }
} }
...@@ -99,22 +91,20 @@ struct MailListView: View { ...@@ -99,22 +91,20 @@ struct MailListView: View {
guard !updating else { guard !updating else {
return return
} }
LetterboxModel LetterboxModel
.instance .instance
.mailHandler .mailHandler
.updateFolder(folderpath: folderpath, .updateFolder(folderpath: folderPath) { error in
completionCallback: { error in
if error == nil { if error == nil {
self.updating = false self.updating = false
} }
// TODO: Add error message // TODO: Add error message
}) }
updating = true updating = true
} }
func filterKeyRecord(keyRecord: MailRecord) -> Bool { func filterKeyRecord(keyRecord: MailRecord) -> Bool {
// let searchType = SearchType.findType(i: searchField)
let searchType = searchField
if self.searchText.isEmpty if self.searchText.isEmpty
|| self.searchText == NSLocalizedString("Searchbar.Title", comment: "Search") { || self.searchText == NSLocalizedString("Searchbar.Title", comment: "Search") {
return true return true
......
...@@ -9,70 +9,60 @@ ...@@ -9,70 +9,60 @@
import SwiftUI import SwiftUI
import Combine import Combine
/**
Where are we looking for? Used in the search footer.
*/
enum SearchType: LocalizedStringKey, CaseIterable {
case All = "All"
case Sender = "Sender"
case Subject = "Subject"
case Body = "Body"
}
/** /**
A SearchView for mails with a search segmented Picker to choose the search area. A SearchView for mails with a search segmented Picker to choose the search area.
Open Problems: Deplay the search, s.t. we do not start a search after each input. Open Problems: Deplay the search, s.t. we do not start a search after each input.
*/ */
struct SearchView: View { struct SearchView: View {
@Binding var searchText: String @Binding var searchText: String
@Binding var searchType: SearchType @Binding var searchType: SearchType
@State private var showCancelButton: Bool = false @State private var editingSearchField: Bool = false
var body: some View { var body: some View {
VStack { VStack {
HStack { HStack {
searchFieldView searchFieldView
if showCancelButton { if editingSearchField {
Button("Cancel") { Button("Cancel") {
UIApplication.shared.endEditing(true) UIApplication.shared.endEditing(true)
self.searchText = "" searchText = ""
self.showCancelButton = false
} }
.foregroundColor(Color(.systemBlue)) .foregroundColor(.accentColor)
} }
} }
if showCancelButton { if editingSearchField {
searchTypePicker searchTypePicker
} }
} }
.padding(.horizontal)
} }
var searchFieldView: some View { var searchFieldView: some View {
HStack { HStack {
Image(systemName: "magnifyingglass") Image(systemName: "magnifyingglass")
TextField(NSLocalizedString("Searchbar.Title", comment: "Search"),
text: $searchText) { _ in TextField("Searchbar.Title", text: $searchText) { isEditing in
self.showCancelButton = true withAnimation {
editingSearchField = isEditing
}
} }
.foregroundColor(.primary) .foregroundColor(.primary)
Button { Button {
self.searchText = "" searchText = ""
} label: { } label: {
Image(systemName: "xmark.circle.fill") Image(systemName: "xmark.circle.fill")
.opacity(searchText == "" ? 0 : 1) .opacity(searchText == "" ? 0 : 1)
} }
} }
.padding(EdgeInsets(top: 8, leading: 6, bottom: 8, trailing: 6)) .padding(8)
.foregroundColor(.secondary) .foregroundColor(.secondary)
.background(Color(.secondarySystemBackground)) .background(Color(.secondarySystemBackground))
.cornerRadius(10.0) .cornerRadius(10.0)
} }
var searchTypePicker: some View { var searchTypePicker: some View {
Picker("Hellooo", selection: $searchType) { Picker("Search Filter", selection: $searchType) {
ForEach(SearchType.allCases, id: \.self) { searchType in ForEach(SearchType.allCases, id: \.self) { searchType in
Text(searchType.rawValue) Text(searchType.rawValue)
} }
...@@ -108,3 +98,13 @@ extension View { ...@@ -108,3 +98,13 @@ extension View {
return modifier(ResignKeyboardOnDragGesture()) return modifier(ResignKeyboardOnDragGesture())
} }
} }
/**
Where are we looking for? Used in the search footer.
*/
enum SearchType: LocalizedStringKey, CaseIterable {
case All = "All"
case Sender = "Sender"
case Subject = "Subject"
case Body = "Body"
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment