//
// SearchView.swift
// Bremer
//
// Created by yhornisse on 2023/07/17.
//
import SwiftUI
import AVFoundation
struct SearchView : View {
@State
private var searchText : String = ""
@State
private var showedLoginView = false
@State
private var showedUpdateAudioDialog = false
@State
private var showedErrorAlert = false
@State
private var showedSearchAudioDialog = false
@State
private var showedDeleteAudioDialog = false
@State
private var audioTargetSlug = ""
@State
private var audioTargetName = ""
@State
private var audioName = ""
@State
var artistName = ""
@State
private var albumName = ""
@State
private var localPath = ""
@State
private var tagName = ""
@State
private var errorAlertTitle = ""
@EnvironmentObject
private var audioPlayerViewModel : AudioPlayerViewModel
@EnvironmentObject
private var settingViewModel : SettingViewModel
@ObservedObject
private var searchAudioViewModel = SearchAudioViewModel()
var body : some View {
NavigationView {
VStack {
if settingViewModel.getSetting().baseUrl == "" {
Text("Base URLを設定してください")
} else if !searchAudioViewModel.messageText.isEmpty {
if (searchAudioViewModel.hasError) {
VStack {
Text(searchAudioViewModel.messageText)
.foregroundColor(.red)
if searchAudioViewModel.messageText == "ログインしてください" {
LoginButton(action: {
self.showedLoginView = true
})
}
}
} else {
Text(searchAudioViewModel.messageText)
}
}
List {
ForEach(searchAudioViewModel.result, id:\.slug) { audio in
Button(action: {
audioPlayerViewModel.playAudioList(
audioList: searchAudioViewModel.result, audio: audio, usedBy: "search")
}) {
Text("\(audio.name) - \(audio.album ?? "")")
.font(.system(size: 14))
.frame(height: 35, alignment: .center)
.aspectRatio(contentMode: .fit)
}
.swipeActions(edge: .trailing) {
Button {
self.audioTargetSlug = audio.slug
self.audioTargetName = audio.name
self.showedDeleteAudioDialog = true
} label : {
Text("削除")
}
.tint(.red)
Button {
self.audioTargetSlug = audio.slug
self.audioName = audio.name
self.artistName = audio.artist ?? ""
self.albumName = audio.album ?? ""
self.localPath = audio.localPath
self.showedUpdateAudioDialog = true
} label: {
Text("変更")
}
.tint(.green)
}
}
}
.listStyle(.plain)
.searchable(text: $searchText, prompt: "検索キーワード")
.onSubmit(of: .search) {
searchAudioViewModel.searchAudio(keyword: searchText)
}
.alert("更新", isPresented: $showedUpdateAudioDialog) {
TextField("曲名", text: $audioName)
TextField("歌手名", text: $artistName)
TextField("アルバム名", text: $albumName)
TextField("ローカルパス(変更不可)", text: $localPath)
.disabled(true) // TODO 効かないがいずれ治す
Button("OK", role: .cancel){
if audioName.isEmpty {
self.errorAlertTitle = "名前の変更に失敗しました"
self.showedErrorAlert = true
return
}
if albumName.isEmpty {
self.errorAlertTitle = "名前の変更に失敗しました"
self.showedErrorAlert = true
return
}
searchAudioViewModel.updateAudio(
slug: audioTargetSlug,
audioName: audioName,
artistName: artistName,
albumName: albumName)
}
Button("キャンセル", role: .destructive){
self.audioName = ""
self.artistName = ""
self.albumName = ""
}
} message: {
Text("新しい名前を入力してください")
}
.confirmationDialog(
"音楽削除",
isPresented: $showedDeleteAudioDialog,
actions: {
Button("OK", role: .destructive){
searchAudioViewModel.deleteAudio(audioTargetSlug)
}
Button("キャンセル", role: .cancel){
self.audioTargetSlug = ""
self.audioTargetName = ""
}
}, message: {
Text( "本当に \(audioTargetName) を削除しますか?\n一度消すとアプリからは戻せません!")
})
Spacer()
Divider()
AudioPlayerView(audioPlayerViewModel: audioPlayerViewModel)
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
self.showedSearchAudioDialog = true
}) {
Image(systemName: "text.magnifyingglass")
}
}
}
}
.onAppear {
searchAudioViewModel.bremerApiBaseUrl = settingViewModel.getSetting().baseApiUrl()
}
.sheet(isPresented: $showedLoginView) {
LoginWebView()
.onDisappear {
searchAudioViewModel.searchAudio(keyword: searchText)
}
}
.scrollDismissesKeyboard(.immediately)
.onReceive(NotificationCenter.default.publisher(for: AVAudioSession.routeChangeNotification), perform: { param in
audioPlayerViewModel.onChangeAudioSessionRoute(param)
})
.onReceive(NotificationCenter.default.publisher(for: AVAudioSession.interruptionNotification), perform: { param in
audioPlayerViewModel.onInterrupted(param)
})
.alert("詳細検索", isPresented: $showedSearchAudioDialog) {
SearchDetailAlertView(searchAction: searchAudioViewModel.searchAudio)
} message: {
Text("新しい名前を入力してください")
}
}
}