添加上传自定义铃声UI

This commit is contained in:
Fin 2024-03-29 18:00:14 +08:00
parent e8f33bc384
commit d2f134088c
9 changed files with 161 additions and 27 deletions

View File

@ -91,6 +91,7 @@
0661A54D204FDA4100965E4E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0661A54B204FDA4100965E4E /* LaunchScreen.storyboard */; };
0667D192247D162C005DE2ED /* MessageTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0667D191247D162C005DE2ED /* MessageTableViewCell.swift */; };
0667D194247D1BA0005DE2ED /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0667D193247D1BA0005DE2ED /* Date+Extension.swift */; };
066E0C8C2BB6AC9A00873838 /* AddSoundCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 066E0C8B2BB6AC9A00873838 /* AddSoundCell.swift */; };
0672CB06256903F700570C9D /* MessageListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0672CB05256903F700570C9D /* MessageListViewModel.swift */; };
06787C392A710568008ABDD7 /* GesturePassTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06787C382A710568008ABDD7 /* GesturePassTextView.swift */; };
06787C3B2AB82BDB008ABDD7 /* CrashReportViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06787C3A2AB82BDB008ABDD7 /* CrashReportViewController.swift */; };
@ -267,6 +268,7 @@
0661A54E204FDA4100965E4E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0667D191247D162C005DE2ED /* MessageTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageTableViewCell.swift; sourceTree = "<group>"; };
0667D193247D1BA0005DE2ED /* Date+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extension.swift"; sourceTree = "<group>"; };
066E0C8B2BB6AC9A00873838 /* AddSoundCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddSoundCell.swift; sourceTree = "<group>"; };
0672CB05256903F700570C9D /* MessageListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageListViewModel.swift; sourceTree = "<group>"; };
06787C382A710568008ABDD7 /* GesturePassTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GesturePassTextView.swift; sourceTree = "<group>"; };
06787C3A2AB82BDB008ABDD7 /* CrashReportViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReportViewController.swift; sourceTree = "<group>"; };
@ -405,6 +407,7 @@
06BBB8BB2567B3AD0076F63E /* ArchiveSettingCellViewModel.swift */,
060481EF250F51CA00BC9799 /* SoundCell.swift */,
065BE44F2563D939002A8CA4 /* SoundCellViewModel.swift */,
066E0C8B2BB6AC9A00873838 /* AddSoundCell.swift */,
062B98C2251B2762004562E7 /* BKButton.swift */,
06C595352481160F006B98F3 /* BKLabel.swift */,
062B98C7251B27AE004562E7 /* UINavigationItem+Extension.swift */,
@ -952,6 +955,7 @@
068EC15A27ED99E700D5D11E /* ServerListViewModel.swift in Sources */,
06172FDC27F6DB06002333A4 /* ServerListTableViewCellViewModel.swift in Sources */,
061894C729A75BEA00E001C2 /* Algorithm.swift in Sources */,
066E0C8C2BB6AC9A00873838 /* AddSoundCell.swift in Sources */,
065BE4502563D939002A8CA4 /* SoundCellViewModel.swift in Sources */,
06F08EA729B1DDFE006AB9CA /* Error+Extension.swift in Sources */,
06B1158F247BB1FB006D91FB /* Message.swift in Sources */,

View File

@ -0,0 +1,12 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"symbols" : [
{
"filename" : "music_note-music_note_symbol.svg",
"idiom" : "universal"
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -169,3 +169,7 @@ Email: to@day.app
Telegram: https://t.me/joinchat/OsCbLzovUAE0YjY1
Github Issue: https://github.com/Finb/Bark/issues
";
uploadSound = "Upload Sound";
customSounds = "Custom Sounds";
defaultSounds = "Default Sounds";

View File

@ -169,3 +169,7 @@ Email: to@day.app
Telegram: https://t.me/joinchat/OsCbLzovUAE0YjY1
Github Issue: https://github.com/Finb/Bark/issues
";
uploadSound = "Upload Sound";
customSounds = "Custom Sounds";
defaultSounds = "Default Sounds";

View File

@ -169,3 +169,7 @@ https://bark.day.app/#/faq
Telegram: https://t.me/joinchat/OsCbLzov
Github Issue: https://github.com/Finb/Bark/issues
";
uploadSound = "上传铃声";
customSounds = "自定义铃声";
defaultSounds = "默认铃声";

View File

@ -17,9 +17,10 @@ import RxSwift
class SoundsViewController: BaseViewController<SoundsViewModel> {
let tableView: UITableView = {
let tableView = UITableView()
let tableView = UITableView(frame: CGRect.zero, style: .insetGrouped)
tableView.backgroundColor = BKColor.background.primary
tableView.register(SoundCell.self, forCellReuseIdentifier: "\(SoundCell.self)")
tableView.register(AddSoundCell.self, forCellReuseIdentifier: "\(AddSoundCell.self)")
return tableView
}()
@ -27,41 +28,44 @@ class SoundsViewController: BaseViewController<SoundsViewModel> {
self.title = NSLocalizedString("notificationSound")
self.view.addSubview(self.tableView)
self.tableView.delegate = self
self.tableView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
self.tableView.tableHeaderView = {
let header = UILabel()
header.fontSize = 12
header.text = " \(NSLocalizedString("previewSound"))"
header.textColor = BKColor.grey.darken1
header.frame = CGRect(x: 0, y: 0, width: 0, height: 40)
return header
}()
}
override func bindViewModel() {
let output = viewModel.transform(
input: SoundsViewModel.Input(soundSelected: self.tableView.rx
.modelSelected(SoundCellViewModel.self)
.modelSelected(SoundItem.self)
.asDriver()))
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, SoundCellViewModel>> { _, tableView, _, item -> UITableViewCell in
guard let cell = tableView.dequeueReusableCell(withIdentifier: "\(SoundCell.self)") as? SoundCell else {
return UITableViewCell()
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, SoundItem>> { _, tableView, _, item -> UITableViewCell in
switch item {
case .sound(let model):
guard let cell = tableView.dequeueReusableCell(withIdentifier: "\(SoundCell.self)") as? SoundCell else {
return UITableViewCell()
}
cell.bindViewModel(model: model)
return cell
case .addSound:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "\(AddSoundCell.self)") else {
return UITableViewCell()
}
return cell
}
cell.bindViewModel(model: item)
return cell
} titleForHeaderInSection: { dataSource, section in
return dataSource[section].model
}
output.audios
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: rx.disposeBag)
output.copyNameAction.drive(onNext: { [weak self] name in
output.copyNameAction.drive(onNext: { [unowned self] name in
UIPasteboard.general.string = name.trimmingCharacters(in: .whitespacesAndNewlines)
self?.navigationController?.showSnackbar(text: NSLocalizedString("Copy"))
self.navigationController?.showSnackbar(text: NSLocalizedString("Copy"))
}).disposed(by: rx.disposeBag)
output.playAction.drive(onNext: { url in
@ -71,5 +75,33 @@ class SoundsViewController: BaseViewController<SoundsViewModel> {
AudioServicesDisposeSystemSoundID(soundID)
}
}).disposed(by: rx.disposeBag)
output.pickerFile.drive(onNext: { [unowned self] _ in
}).disposed(by: rx.disposeBag)
}
}
extension SoundsViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let sectionTitle = tableView.dataSource?.tableView?(tableView, titleForHeaderInSection: section) ?? ""
let view = UIView()
let label = UILabel()
label.text = NSLocalizedString(sectionTitle)
label.fontSize = 14
label.textColor = BKColor.grey.darken3
view.addSubview(label)
label.snp.makeConstraints { make in
make.left.equalTo(12)
make.centerY.equalToSuperview()
}
return view
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
}

View File

@ -12,24 +12,31 @@ import RxCocoa
import RxDataSources
import RxSwift
enum SoundItem {
case sound(model: SoundCellViewModel)
case addSound
}
class SoundsViewModel: ViewModel, ViewModelType {
struct Input {
var soundSelected: Driver<SoundCellViewModel>
var soundSelected: Driver<SoundItem>
}
struct Output {
var audios: Observable<[SectionModel<String, SoundCellViewModel>]>
var audios: Observable<[SectionModel<String, SoundItem>]>
var copyNameAction: Driver<String>
var playAction: Driver<CFURL>
var pickerFile: Driver<Void>
}
func getSounds(urls: [URL]) -> [SoundCellViewModel] {
func getSounds(urls: [URL]) -> [SoundItem] {
let urls = urls.sorted { u1, u2 -> Bool in
u1.lastPathComponent.localizedStandardCompare(u2.lastPathComponent) == ComparisonResult.orderedAscending
}
return urls
.map { AVURLAsset(url: $0) }
.map { SoundCellViewModel(model: $0) }
.map { SoundItem.sound(model: $0) }
}
///
@ -53,17 +60,22 @@ class SoundsViewModel: ViewModel, ViewModelType {
urls: Bundle.main.urls(forResourcesWithExtension: "caf", subdirectory: nil) ?? []
)
let customSounds: [SoundCellViewModel] = {
let customSounds: [SoundItem] = {
guard let soundsDirectoryUrl = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true).first?.appending("/Sounds") else {
return []
return [.addSound]
}
return getSounds(
urls: getFilesInDirectory(directory: soundsDirectoryUrl, suffix: "caf")
)
) + [.addSound]
}()
let copyAction = Driver.merge(
(defaultSounds + customSounds).map { $0.copyNameAction.asDriver(onErrorDriveWith: .empty()) }
(defaultSounds + customSounds).compactMap { item in
if case SoundItem.sound(let model) = item {
return model.copyNameAction.asDriver(onErrorDriveWith: .empty())
}
return nil
}
).asDriver()
return Output(
@ -72,7 +84,20 @@ class SoundsViewModel: ViewModel, ViewModelType {
SectionModel(model: "defaultSounds", items: defaultSounds)
]),
copyNameAction: copyAction,
playAction: input.soundSelected.map { $0.model.url as CFURL }
)
playAction: input.soundSelected
.compactMap { item in
if case SoundItem.sound(let model) = item {
return model
}
return nil
}
.map { $0.model.url as CFURL },
pickerFile: input.soundSelected
.compactMap { item in
if case SoundItem.addSound = item {
return ()
}
return nil
})
}
}

37
View/AddSoundCell.swift Normal file
View File

@ -0,0 +1,37 @@
//
// AddSoundCell.swift
// Bark
//
// Created by Fin on 2024/3/29.
// Copyright © 2024 Fin. All rights reserved.
//
import UIKit
class AddSoundCell: UITableViewCell {
let button: UIButton = {
let button = UIButton(type: .system)
button.setTitle(NSLocalizedString("uploadSound"), for: .normal)
button.setImage(UIImage(named: "music_note-music_note_symbol"), for: .normal)
button.setTitleColor(BKColor.lightBlue.darken3, for: .normal)
button.tintColor = BKColor.lightBlue.darken3
button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
// UITableView didSelectRowAt
button.isUserInteractionEnabled = false
return button
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.selectionStyle = .none
contentView.addSubview(button)
button.snp.makeConstraints { make in
make.edges.equalToSuperview()
make.height.equalTo(44)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}