Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,6 @@ extension NavigationRoute {
}
}

static func itemDeletion(viewModel: ItemEditorViewModel<BaseItemDto>) -> NavigationRoute {
NavigationRoute(
id: "itemDeletion",
style: .sheet
) {
ItemDeletionView(viewModel: viewModel)
}
}

#if os(iOS)
static func itemEditor(viewModel: ItemEditorViewModel<BaseItemDto>) -> NavigationRoute {
NavigationRoute(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

typealias MediaPlayerItemProviderFunction = @Sendable (BaseItemDto) async throws -> MediaPlayerItem

struct MediaPlayerItemProvider: Equatable, Sendable {
struct MediaPlayerItemProvider: Equatable {

let item: BaseItemDto
let function: MediaPlayerItemProviderFunction
Expand Down
131 changes: 0 additions & 131 deletions Shared/Views/ItemEditorView/ItemDeletionView.swift

This file was deleted.

23 changes: 23 additions & 0 deletions Shared/Views/ItemView/Components/ItemEditorMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Copyright (c) 2026 Jellyfin & Jellyfin Contributors
//

import Defaults
import JellyfinAPI
import SwiftUI

Expand Down Expand Up @@ -63,5 +64,27 @@ struct ItemEditorMenu: View {
#endif
}
}

// TODO: Enable & Complete Deletion for tvOS after
/* #if os(tvOS)
if StoredValues[.User.enableItemDeletion] && viewModel.item.canDelete == true {
Button(L10n.delete, systemImage: "trash", role: .destructive) {
isPresentingDeleteConfirmation.wrappedValue = true
}
.confirmationDialog(
L10n.deleteItemConfirmationMessage,
isPresented: $isPresentingDeleteConfirmation,
titleVisibility: .visible
) {
Button(
L10n.confirm,
role: .destructive,
action: viewModel.delete
)

Button(L10n.cancel, role: .cancel) {}
}
}
#endif */
}
}
59 changes: 33 additions & 26 deletions Shared/Views/SettingsView/CustomizeSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,6 @@ struct CustomizeSettingsView: View {
private var shouldShowMissingSeasons
@Default(.Customization.shouldShowMissingEpisodes)
private var shouldShowMissingEpisodes
@StoredValue(.User.enableCollectionManagement)
private var enableCollectionManagement
@StoredValue(.User.enableItemEditing)
private var enableItemEditing
@StoredValue(.User.enableItemDeletion)
private var enableItemDeletion

// MARK: - Item View Defaults

Expand All @@ -101,6 +95,15 @@ struct CustomizeSettingsView: View {
@Default(.Customization.Episodes.useSeriesLandscapeBackdrop)
private var useSeriesLandscapeBackdrop

// MARK: - Item Management Defaults

@StoredValue(.User.enableCollectionManagement)
private var enableCollectionManagement
@StoredValue(.User.enableItemEditing)
private var enableItemEditing
@StoredValue(.User.enableItemDeletion)
private var enableItemDeletion

// MARK: - User Permissions

@Injected(\.currentUserSession)
Expand Down Expand Up @@ -129,9 +132,7 @@ struct CustomizeSettingsView: View {

itemViewSettings

#if os(iOS)
itemManagementSettings
#endif
}
.navigationTitle(L10n.customize)
}
Expand Down Expand Up @@ -298,26 +299,32 @@ struct CustomizeSettingsView: View {

@ViewBuilder
private var itemManagementSettings: some View {
Section(L10n.itemManagement) {

/// Collections can be edited by users or by setting
if userPolicy?.isAdministrator == true ||
userPolicy?.enableCollectionManagement == true
{
Toggle(L10n.editCollections, isOn: $enableCollectionManagement)
}
if userPolicy?.isAdministrator == true ||
userPolicy?.enableCollectionManagement == true ||
userPolicy?.enableContentDeletion == true ||
userPolicy?.enableContentDeletionFromFolders?.isNotEmpty == true
{
Section(L10n.itemManagement) {

if userPolicy?.isAdministrator == true ||
userPolicy?.enableCollectionManagement == true
{
Toggle(L10n.editCollections, isOn: $enableCollectionManagement)
}

/// Only allow editing if administrator
/// - Does NOT include subtitle / lyric editing
if userPolicy?.isAdministrator == true {
Toggle(L10n.editMedia, isOn: $enableItemEditing)
}
// Does NOT include subtitle / lyric editing
if userPolicy?.isAdministrator == true {
Toggle(L10n.editMedia, isOn: $enableItemEditing)
}

/// Only allow deletion if there is someting to delete from
if userPolicy?.enableContentDeletion == true ||
userPolicy?.enableContentDeletionFromFolders?.isNotEmpty == true
{
Toggle(L10n.deleteMedia, isOn: $enableItemDeletion)
if userPolicy?.enableContentDeletion == true ||
userPolicy?.enableContentDeletionFromFolders?.isNotEmpty == true
{
// TODO: Enable when tvOS Deletion is available
if !UIDevice.isTV {
Toggle(L10n.deleteMedia, isOn: $enableItemDeletion)
}
}
}
}
}
Expand Down
27 changes: 24 additions & 3 deletions Swiftfin/Views/ItemEditorView/ItemEditorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Copyright (c) 2026 Jellyfin & Jellyfin Contributors
//

import Engine
import Factory
import JellyfinAPI
import SwiftUI
Expand Down Expand Up @@ -41,6 +42,11 @@ struct ItemEditorView: View {
.refreshable {
viewModel.refreshItem(sendNotification: false)
}
.onNotification(.didDeleteItem) { _ in
UIDevice.feedback(.success)
router.dismiss()
}
.errorMessage($viewModel.error)
}

private var contentView: some View {
Expand Down Expand Up @@ -89,10 +95,25 @@ struct ItemEditorView: View {
}

if viewModel.item.canDelete == true {
Button(L10n.delete, role: .destructive) {
router.route(to: .itemDeletion(viewModel: viewModel))
StateAdapter(initialValue: false) { isPresentingDeleteConfirmation in
Button(L10n.delete, role: .destructive) {
isPresentingDeleteConfirmation.wrappedValue = true
}
.buttonStyle(.primary)
.confirmationDialog(
L10n.deleteItemConfirmationMessage,
isPresented: isPresentingDeleteConfirmation,
titleVisibility: .visible
) {
Button(
L10n.confirm,
role: .destructive,
action: viewModel.delete
)

Button(L10n.cancel, role: .cancel) {}
}
}
.buttonStyle(.primary)
}
}
}
Expand Down
Loading