Skip to content

Commit

Permalink
Merge pull request #26933 from brave/ios-playlist-local-search
Browse files Browse the repository at this point in the history
[iOS] Add local search to Playlist
  • Loading branch information
kylehickinson authored Dec 12, 2024
2 parents 9cec895 + 51fabb7 commit 17a7985
Show file tree
Hide file tree
Showing 9 changed files with 486 additions and 210 deletions.
81 changes: 81 additions & 0 deletions ios/brave-ios/Sources/BraveUI/SwiftUI/SearchBar.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) 2024 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

import SwiftUI
import UIKit

/// A representable around `UISearchBar` using the minimal style
public struct SearchBar: UIViewRepresentable {
@Binding var text: String
var placeholder: String?
var isFocused: Binding<Bool>?
var onSubmit: (() -> Void)?

public init(
text: Binding<String>,
placeholder: String? = nil,
isFocused: Binding<Bool>? = nil,
onSubmit: (() -> Void)? = nil
) {
self._text = text
self.placeholder = placeholder
self.isFocused = isFocused
self.onSubmit = onSubmit
}

public func makeUIView(context: Context) -> UISearchBar {
let searchBar = UISearchBar(frame: .zero)
searchBar.text = text
searchBar.placeholder = placeholder
searchBar.searchBarStyle = .minimal
return searchBar
}

public func updateUIView(_ uiView: UISearchBar, context: Context) {
uiView.text = text
uiView.placeholder = placeholder
uiView.delegate = context.coordinator
if let isFocused {
if isFocused.wrappedValue {
uiView.becomeFirstResponder()
} else {
uiView.resignFirstResponder()
}
}
}

public func makeCoordinator() -> Coordinator {
Coordinator(text: $text, isFocused: isFocused, onSubmit: onSubmit)
}

public class Coordinator: NSObject, UISearchBarDelegate {
@Binding var text: String
var isFocused: Binding<Bool>?
var onSubmit: (() -> Void)?

init(text: Binding<String>, isFocused: Binding<Bool>?, onSubmit: (() -> Void)?) {
self._text = text
self.isFocused = isFocused
self.onSubmit = onSubmit
}

public func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
text = searchText
}

public func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
isFocused?.wrappedValue = true
}

public func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
isFocused?.wrappedValue = false
}

public func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
onSubmit?()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

import BraveCore
import BraveUI
import SwiftUI

struct TransactionSection: Equatable, Identifiable {
Expand Down
50 changes: 0 additions & 50 deletions ios/brave-ios/Sources/BraveWallet/SearchBar.swift

This file was deleted.

2 changes: 1 addition & 1 deletion ios/brave-ios/Sources/PlaylistUI/PlayerModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ public final class PlayerModel: ObservableObject {

@MainActor @Published var selectedItemID: PlaylistItem.ID? {
willSet {
if let selectedItem {
if selectedItem != nil {
let currentTime = currentTime
let duration = duration.seconds ?? 0
// Reset the current item's last played time if you changed videos in the last 10s
Expand Down
80 changes: 51 additions & 29 deletions ios/brave-ios/Sources/PlaylistUI/PlaylistContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ struct PlaylistContentView: View {
@State private var isEditModePresented: Bool = false
@State private var newPlaylistName: String = ""
@State private var isPopulatingNewPlaylist: Bool = false
@State private var isPresentingSearch: Bool = false

private var selectedItemID: PlaylistItem.ID? {
playerModel.selectedItemID
Expand All @@ -48,37 +49,41 @@ struct PlaylistContentView: View {
playerModel.selectedItemID.flatMap { PlaylistItem.getItem(id: $0) }
}

private var selectedItemIDBinding: Binding<PlaylistItem.ID?> {
Binding(
get: {
selectedItemID
},
set: { newValue in
// Make the item queue prior to setting the `selectedItemID`, which will start playing
// said item
withAnimation(.snappy) {
selectedDetent = .anchor(.mediaControls)
}
// FIXME: Move this into PlayerModel
playerModel.makeItemQueue(selectedItemID: newValue)
if selectedItemID == newValue {
// Already selected, restart it (based on prior behaviour)
Task {
await playerModel.seek(to: 0, accurately: true)
playerModel.play()
}
return
}
playerModel.selectedItemID = newValue
Task {
await playerModel.prepareToPlaySelectedItem(initialOffset: nil, playImmediately: true)
}
}
)
}

public var body: some View {
PlaylistSplitView(selectedDetent: $selectedDetent) {
PlaylistSidebarList(
folders: Array(folders),
folderID: selectedFolderID,
selectedItemID: Binding(
get: {
selectedItemID
},
set: { newValue in
// Make the item queue prior to setting the `selectedItemID`, which will start playing
// said item
withAnimation(.snappy) {
selectedDetent = .anchor(.mediaControls)
}
// FIXME: Move this into PlayerModel
playerModel.makeItemQueue(selectedItemID: newValue)
if selectedItemID == newValue {
// Already selected, restart it (based on prior behaviour)
Task {
await playerModel.seek(to: 0, accurately: true)
playerModel.play()
}
return
}
playerModel.selectedItemID = newValue
Task {
await playerModel.prepareToPlaySelectedItem(initialOffset: nil, playImmediately: true)
}
}
),
selectedItemID: selectedItemIDBinding,
isPlaying: playerModel.isPlaying,
onPlaylistUpdated: {
// Update the queue to reflect updated playlist
Expand Down Expand Up @@ -150,6 +155,12 @@ struct PlaylistContentView: View {
.labelStyle(.iconOnly)
.transition(.opacity.animation(.default))
}
Button {
isPresentingSearch = true
} label: {
Label(Strings.Playlist.searchTitle, braveSystemImage: "leo.search")
}
.labelStyle(.iconOnly)
}
.task {
await playerModel.prepareItemQueue()
Expand All @@ -160,9 +171,7 @@ struct PlaylistContentView: View {
}
}
.onDisappear {
if let selectedItem {
playerModel.persistPlaybackTimeForSelectedItem(playerModel.currentTime)
}
playerModel.persistPlaybackTimeForSelectedItem(playerModel.currentTime)
}
.sheet(isPresented: $isEditModePresented) {
if let selectedFolder {
Expand Down Expand Up @@ -225,6 +234,19 @@ struct PlaylistContentView: View {
.environment(\.colorScheme, .dark)
.preferredColorScheme(.dark)
}
.sheet(isPresented: $isPresentingSearch) {
SearchView(
folders: Array(folders),
selectedItemID: selectedItemIDBinding,
selectedFolderID: $playerModel.selectedFolderID,
isPlaying: playerModel.isPlaying,
onPlaylistUpdated: {
playerModel.makeItemQueue(selectedItemID: playerModel.selectedItemID)
}
)
.environment(\.colorScheme, .dark)
.preferredColorScheme(.dark)
}
.onChange(of: selectedItemID) { newValue in
if newValue == nil {
withAnimation(.snappy) {
Expand Down
Loading

0 comments on commit 17a7985

Please sign in to comment.