[tvOS] Various Setting Cleanup (#1473)

* Various setting cleanup

* Remove Double headers

* My gradient did nothing... So resetting back to less.

* Reduce unnecessary formatting changes.

* Revisions https://github.com/jellyfin/Swiftfin/pull/1473#pullrequestreview-2745279339

* Subtitles was missing brightness. Subtitle shouldn't mirror title but image.

* Remove TODO.
This commit is contained in:
Joe Kribs 2025-04-06 16:05:33 -06:00 committed by GitHub
parent df89832647
commit c0b875ed2a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 102 additions and 57 deletions

View File

@ -512,6 +512,8 @@ internal enum L10n {
internal static let displayOrder = L10n.tr("Localizable", "displayOrder", fallback: "Display Order") internal static let displayOrder = L10n.tr("Localizable", "displayOrder", fallback: "Display Order")
/// Done /// Done
internal static let done = L10n.tr("Localizable", "done", fallback: "Done") internal static let done = L10n.tr("Localizable", "done", fallback: "Done")
/// Double touch
internal static let doubleTouch = L10n.tr("Localizable", "doubleTouch", fallback: "Double touch")
/// Downloads /// Downloads
internal static let downloads = L10n.tr("Localizable", "downloads", fallback: "Downloads") internal static let downloads = L10n.tr("Localizable", "downloads", fallback: "Downloads")
/// Duplicate User /// Duplicate User
@ -646,6 +648,10 @@ internal enum L10n {
internal static let hint = L10n.tr("Localizable", "hint", fallback: "Hint") internal static let hint = L10n.tr("Localizable", "hint", fallback: "Hint")
/// Home /// Home
internal static let home = L10n.tr("Localizable", "home", fallback: "Home") internal static let home = L10n.tr("Localizable", "home", fallback: "Home")
/// Horizontal pan
internal static let horizontalPan = L10n.tr("Localizable", "horizontalPan", fallback: "Horizontal pan")
/// Horizontal swipe
internal static let horizontalSwipe = L10n.tr("Localizable", "horizontalSwipe", fallback: "Horizontal swipe")
/// Hours /// Hours
internal static let hours = L10n.tr("Localizable", "hours", fallback: "Hours") internal static let hours = L10n.tr("Localizable", "hours", fallback: "Hours")
/// ID /// ID
@ -724,6 +730,8 @@ internal enum L10n {
internal static let learnMoreEllipsis = L10n.tr("Localizable", "learnMoreEllipsis", fallback: "Learn more...") internal static let learnMoreEllipsis = L10n.tr("Localizable", "learnMoreEllipsis", fallback: "Learn more...")
/// Left /// Left
internal static let `left` = L10n.tr("Localizable", "left", fallback: "Left") internal static let `left` = L10n.tr("Localizable", "left", fallback: "Left")
/// Left vertical pan
internal static let leftVerticalPan = L10n.tr("Localizable", "leftVerticalPan", fallback: "Left vertical pan")
/// Letter /// Letter
internal static let letter = L10n.tr("Localizable", "letter", fallback: "Letter") internal static let letter = L10n.tr("Localizable", "letter", fallback: "Letter")
/// Letterer /// Letterer
@ -768,6 +776,8 @@ internal enum L10n {
internal static let logs = L10n.tr("Localizable", "logs", fallback: "Logs") internal static let logs = L10n.tr("Localizable", "logs", fallback: "Logs")
/// Access the Jellyfin server logs for troubleshooting and monitoring purposes. /// Access the Jellyfin server logs for troubleshooting and monitoring purposes.
internal static let logsDescription = L10n.tr("Localizable", "logsDescription", fallback: "Access the Jellyfin server logs for troubleshooting and monitoring purposes.") internal static let logsDescription = L10n.tr("Localizable", "logsDescription", fallback: "Access the Jellyfin server logs for troubleshooting and monitoring purposes.")
/// Long press
internal static let longPress = L10n.tr("Localizable", "longPress", fallback: "Long press")
/// Lyricist /// Lyricist
internal static let lyricist = L10n.tr("Localizable", "lyricist", fallback: "Lyricist") internal static let lyricist = L10n.tr("Localizable", "lyricist", fallback: "Lyricist")
/// Lyrics /// Lyrics
@ -820,12 +830,16 @@ internal enum L10n {
internal static let minutes = L10n.tr("Localizable", "minutes", fallback: "Minutes") internal static let minutes = L10n.tr("Localizable", "minutes", fallback: "Minutes")
/// Missing /// Missing
internal static let missing = L10n.tr("Localizable", "missing", fallback: "Missing") internal static let missing = L10n.tr("Localizable", "missing", fallback: "Missing")
/// Missing codec values
internal static let missingCodecValues = L10n.tr("Localizable", "missingCodecValues", fallback: "Missing codec values")
/// Missing Items /// Missing Items
internal static let missingItems = L10n.tr("Localizable", "missingItems", fallback: "Missing Items") internal static let missingItems = L10n.tr("Localizable", "missingItems", fallback: "Missing Items")
/// Mixer /// Mixer
internal static let mixer = L10n.tr("Localizable", "mixer", fallback: "Mixer") internal static let mixer = L10n.tr("Localizable", "mixer", fallback: "Mixer")
/// Movies /// Movies
internal static let movies = L10n.tr("Localizable", "movies", fallback: "Movies") internal static let movies = L10n.tr("Localizable", "movies", fallback: "Movies")
/// Multi tap
internal static let multiTap = L10n.tr("Localizable", "multiTap", fallback: "Multi tap")
/// Music /// Music
internal static let music = L10n.tr("Localizable", "music", fallback: "Music") internal static let music = L10n.tr("Localizable", "music", fallback: "Music")
/// MVC /// MVC
@ -860,6 +874,8 @@ internal enum L10n {
internal static let nextUpRewatch = L10n.tr("Localizable", "nextUpRewatch", fallback: "Rewatching in Next Up") internal static let nextUpRewatch = L10n.tr("Localizable", "nextUpRewatch", fallback: "Rewatching in Next Up")
/// No /// No
internal static let no = L10n.tr("Localizable", "no", fallback: "No") internal static let no = L10n.tr("Localizable", "no", fallback: "No")
/// No profiles defined. Playback issues may occur.
internal static let noDeviceProfileWarning = L10n.tr("Localizable", "noDeviceProfileWarning", fallback: "No profiles defined. Playback issues may occur.")
/// No episodes available /// No episodes available
internal static let noEpisodesAvailable = L10n.tr("Localizable", "noEpisodesAvailable", fallback: "No episodes available") internal static let noEpisodesAvailable = L10n.tr("Localizable", "noEpisodesAvailable", fallback: "No episodes available")
/// No local servers found /// No local servers found
@ -936,6 +952,8 @@ internal enum L10n {
internal static let permissions = L10n.tr("Localizable", "permissions", fallback: "Permissions") internal static let permissions = L10n.tr("Localizable", "permissions", fallback: "Permissions")
/// Pin /// Pin
internal static let pin = L10n.tr("Localizable", "pin", fallback: "Pin") internal static let pin = L10n.tr("Localizable", "pin", fallback: "Pin")
/// Pinch
internal static let pinch = L10n.tr("Localizable", "pinch", fallback: "Pinch")
/// Play /// Play
internal static let play = L10n.tr("Localizable", "play", fallback: "Play") internal static let play = L10n.tr("Localizable", "play", fallback: "Play")
/// Play / Pause /// Play / Pause
@ -980,6 +998,8 @@ internal enum L10n {
internal static let profile = L10n.tr("Localizable", "profile", fallback: "Profile") internal static let profile = L10n.tr("Localizable", "profile", fallback: "Profile")
/// Profile Image /// Profile Image
internal static let profileImage = L10n.tr("Localizable", "profileImage", fallback: "Profile Image") internal static let profileImage = L10n.tr("Localizable", "profileImage", fallback: "Profile Image")
/// Profile not saved
internal static let profileNotSaved = L10n.tr("Localizable", "profileNotSaved", fallback: "Profile not saved")
/// Profiles /// Profiles
internal static let profiles = L10n.tr("Localizable", "profiles", fallback: "Profiles") internal static let profiles = L10n.tr("Localizable", "profiles", fallback: "Profiles")
/// Programs /// Programs
@ -1058,6 +1078,8 @@ internal enum L10n {
internal static let replaceAll = L10n.tr("Localizable", "replaceAll", fallback: "Replace All") internal static let replaceAll = L10n.tr("Localizable", "replaceAll", fallback: "Replace All")
/// Replace all unlocked metadata and images with new information. /// Replace all unlocked metadata and images with new information.
internal static let replaceAllDescription = L10n.tr("Localizable", "replaceAllDescription", fallback: "Replace all unlocked metadata and images with new information.") internal static let replaceAllDescription = L10n.tr("Localizable", "replaceAllDescription", fallback: "Replace all unlocked metadata and images with new information.")
/// Current profile values may cause playback issues
internal static let replaceDeviceProfileWarning = L10n.tr("Localizable", "replaceDeviceProfileWarning", fallback: "Current profile values may cause playback issues")
/// Replace Images /// Replace Images
internal static let replaceImages = L10n.tr("Localizable", "replaceImages", fallback: "Replace Images") internal static let replaceImages = L10n.tr("Localizable", "replaceImages", fallback: "Replace Images")
/// Replace all images with new images. /// Replace all images with new images.
@ -1110,6 +1132,8 @@ internal enum L10n {
internal static let reviews = L10n.tr("Localizable", "reviews", fallback: "Reviews") internal static let reviews = L10n.tr("Localizable", "reviews", fallback: "Reviews")
/// Right /// Right
internal static let `right` = L10n.tr("Localizable", "right", fallback: "Right") internal static let `right` = L10n.tr("Localizable", "right", fallback: "Right")
/// Right vertical pan
internal static let rightVerticalPan = L10n.tr("Localizable", "rightVerticalPan", fallback: "Right vertical pan")
/// Role /// Role
internal static let role = L10n.tr("Localizable", "role", fallback: "Role") internal static let role = L10n.tr("Localizable", "role", fallback: "Role")
/// Rotate /// Rotate

View File

@ -25,32 +25,32 @@ struct ListRowMenu<Content: View, Subtitle: View>: View {
var body: some View { var body: some View {
Menu(content: content) { Menu(content: content) {
ZStack { HStack {
RoundedRectangle(cornerRadius: 10) title
.fill(isFocused ? Color.white : Color.clear) .foregroundStyle(isFocused ? .black : .white)
.padding(.leading, 4)
HStack { Spacer()
title
.foregroundStyle(isFocused ? Color.black : Color.white)
.padding(.leading, 4)
Spacer() if let subtitle {
subtitle
if let subtitle { .foregroundStyle(isFocused ? .black : .secondary)
subtitle
.foregroundStyle(isFocused ? Color.black : Color.secondary)
.brightness(isFocused ? 0.4 : 0)
}
Image(systemName: "chevron.up.chevron.down")
.font(.body.weight(.regular))
.foregroundStyle(isFocused ? Color.black : Color.secondary)
.brightness(isFocused ? 0.4 : 0) .brightness(isFocused ? 0.4 : 0)
} }
.padding(.horizontal)
Image(systemName: "chevron.up.chevron.down")
.font(.body.weight(.regular))
.foregroundStyle(isFocused ? .black : .secondary)
.brightness(isFocused ? 0.4 : 0)
} }
.scaleEffect(isFocused ? 1.05 : 1.0) .padding(.horizontal)
.animation(.spring(response: 0.15, dampingFraction: 0.75), value: isFocused) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
.background(
RoundedRectangle(cornerRadius: 10)
.fill(isFocused ? Color.white : Color.clear)
)
.scaleEffect(isFocused ? 1.04 : 1.0)
.animation(.easeInOut(duration: 0.125), value: isFocused)
} }
.menuStyle(.borderlessButton) .menuStyle(.borderlessButton)
.listRowInsets(.zero) .listRowInsets(.zero)

View File

@ -90,7 +90,6 @@ struct OrderedSectionSelectorView<Element: Displayable & Hashable>: View {
} }
.environment(\.editMode, editMode) .environment(\.editMode, editMode)
} }
.withDescriptionTopPadding()
.animation(.linear(duration: 0.2), value: selection.value) .animation(.linear(duration: 0.2), value: selection.value)
} }
} }

View File

@ -8,12 +8,8 @@
import SwiftUI import SwiftUI
// TODO: See if `descriptionTopPadding` is really necessary to fix the navigation bar padding, or just add all the time
struct SplitFormWindowView: View { struct SplitFormWindowView: View {
private var descriptionTopPadding: Bool = false
private var contentView: () -> any View private var contentView: () -> any View
private var descriptionView: () -> any View private var descriptionView: () -> any View
@ -28,9 +24,7 @@ struct SplitFormWindowView: View {
contentView() contentView()
.eraseToAnyView() .eraseToAnyView()
} }
.if(descriptionTopPadding) { view in .padding(.top)
view.padding(.top)
}
.scrollClipDisabled() .scrollClipDisabled()
} }
} }
@ -52,8 +46,4 @@ extension SplitFormWindowView {
func descriptionView(@ViewBuilder _ content: @escaping () -> any View) -> Self { func descriptionView(@ViewBuilder _ content: @escaping () -> any View) -> Self {
copy(modifying: \.descriptionView, with: content) copy(modifying: \.descriptionView, with: content)
} }
func withDescriptionTopPadding() -> Self {
copy(modifying: \.descriptionTopPadding, with: true)
}
} }

View File

@ -49,6 +49,5 @@ struct FontPickerView: View {
} }
} }
} }
.withDescriptionTopPadding()
} }
} }

View File

@ -78,7 +78,6 @@ struct EditServerView: View {
} }
} }
} }
.withDescriptionTopPadding()
.navigationTitle(L10n.server) .navigationTitle(L10n.server)
.alert(L10n.deleteServer, isPresented: $isPresentingConfirmDeletion) { .alert(L10n.deleteServer, isPresented: $isPresentingConfirmDeletion) {
Button(L10n.delete, role: .destructive) { Button(L10n.delete, role: .destructive) {

View File

@ -130,11 +130,11 @@ extension CustomDeviceProfileSettingsView {
.padding(.vertical) .padding(.vertical)
if !isValid { if !isValid {
Label("Current profile values may cause playback issues", systemImage: "exclamationmark.circle.fill") Label(L10n.replaceDeviceProfileWarning, systemImage: "exclamationmark.circle.fill")
} }
} }
.navigationTitle(L10n.customProfile) .navigationTitle(L10n.customProfile)
.alert("Profile not saved", isPresented: $isPresentingNotSaved) { .alert(L10n.profileNotSaved, isPresented: $isPresentingNotSaved) {
Button(L10n.close, role: .destructive) { Button(L10n.close, role: .destructive) {
router.dismissCoordinator() router.dismissCoordinator()
} }

View File

@ -58,14 +58,14 @@ struct CustomDeviceProfileSettingsView: View {
} }
if !isValid { if !isValid {
Label("No profiles defined. Playback issues may occur.", systemImage: "exclamationmark.circle.fill") Label(L10n.noDeviceProfileWarning, systemImage: "exclamationmark.circle.fill")
} }
} }
} }
Section { Section {
if customProfiles.isEmpty { if customProfiles.isEmpty {
Button("Add profile") { Button(L10n.add) {
router.route(to: \.createCustomDeviceProfile) router.route(to: \.createCustomDeviceProfile)
} }
} }

View File

@ -77,7 +77,6 @@ struct CustomizeViewsSettings: View {
HomeSection() HomeSection()
} }
.withDescriptionTopPadding()
.navigationTitle(L10n.customize) .navigationTitle(L10n.customize)
} }
} }

View File

@ -43,7 +43,6 @@ struct IndicatorSettingsView: View {
Toggle(L10n.showWatched, isOn: $showWatched) Toggle(L10n.showWatched, isOn: $showWatched)
} }
} }
.withDescriptionTopPadding()
.navigationTitle(L10n.indicators) .navigationTitle(L10n.indicators)
} }
} }

View File

@ -71,7 +71,6 @@ struct UserProfileSettingsView: View {
// Text(L10n.resetSettingsDescription) // Text(L10n.resetSettingsDescription)
// } // }
} }
.withDescriptionTopPadding()
.navigationTitle(L10n.user) .navigationTitle(L10n.user)
.confirmationDialog( .confirmationDialog(
L10n.resetSettings, L10n.resetSettings,

View File

@ -73,7 +73,6 @@ struct VideoPlayerSettingsView: View {
Toggle(L10n.pauseOnBackground, isOn: $pauseOnBackground) Toggle(L10n.pauseOnBackground, isOn: $pauseOnBackground)
Toggle(L10n.playOnActive, isOn: $playOnActive) Toggle(L10n.playOnActive, isOn: $playOnActive)
} }
.navigationTitle(L10n.videoPlayer.text)
.blurredFullScreenCover(isPresented: $isPresentingResumeOffsetStepper) { .blurredFullScreenCover(isPresented: $isPresentingResumeOffsetStepper) {
StepperView( StepperView(
title: L10n.resumeOffsetTitle, title: L10n.resumeOffsetTitle,
@ -90,5 +89,6 @@ struct VideoPlayerSettingsView: View {
} }
} }
} }
.navigationTitle(L10n.videoPlayer)
} }
} }

View File

@ -102,12 +102,13 @@ struct UserSignInView: View {
} }
viewModel.send(.signIn(username: username, password: password, policy: .none)) viewModel.send(.signIn(username: username, password: password, policy: .none))
} }
.padding(.bottom)
if case .signingIn = viewModel.state { if case .signingIn = viewModel.state {
ListRowButton(L10n.cancel, role: .cancel) { ListRowButton(L10n.cancel, role: .cancel) {
viewModel.send(.cancel) viewModel.send(.cancel)
} }
.padding(.vertical) .padding(.bottom)
} else { } else {
ListRowButton(L10n.signIn) { ListRowButton(L10n.signIn) {
viewModel.send(.signIn(username: username, password: password, policy: .none)) viewModel.send(.signIn(username: username, password: password, policy: .none))
@ -118,7 +119,7 @@ struct UserSignInView: View {
username.isEmpty ? Color.white.opacity(0.5) : accentColor username.isEmpty ? Color.white.opacity(0.5) : accentColor
) )
.opacity(username.isEmpty ? 0.5 : 1) .opacity(username.isEmpty ? 0.5 : 1)
.padding(.vertical) .padding(.bottom)
} }
if viewModel.isQuickConnectEnabled { if viewModel.isQuickConnectEnabled {

View File

@ -110,7 +110,7 @@ extension CustomDeviceProfileSettingsView {
} }
} footer: { } footer: {
if !isValid { if !isValid {
Label("Missing codec values", systemImage: "exclamationmark.circle.fill") Label(L10n.missingCodecValues, systemImage: "exclamationmark.circle.fill")
.labelStyle(.sectionFooterWithImage(imageStyle: .orange)) .labelStyle(.sectionFooterWithImage(imageStyle: .orange))
} }
} }
@ -136,7 +136,7 @@ extension CustomDeviceProfileSettingsView {
.buttonStyle(.toolbarPill) .buttonStyle(.toolbarPill)
.disabled(!isValid) .disabled(!isValid)
} }
.alert("Profile not saved", isPresented: $isPresentingNotSaved) { .alert(L10n.profileNotSaved, isPresented: $isPresentingNotSaved) {
Button(L10n.close, role: .destructive) { Button(L10n.close, role: .destructive) {
router.dismissCoordinator() router.dismissCoordinator()
} }

View File

@ -47,7 +47,7 @@ struct CustomDeviceProfileSettingsView: View {
} }
if !isValid { if !isValid {
Label("No profiles defined. Playback issues may occur.", systemImage: "exclamationmark.circle.fill") Label(L10n.noDeviceProfileWarning, systemImage: "exclamationmark.circle.fill")
.labelStyle(.sectionFooterWithImage(imageStyle: .orange)) .labelStyle(.sectionFooterWithImage(imageStyle: .orange))
} }
} }
@ -56,7 +56,7 @@ struct CustomDeviceProfileSettingsView: View {
Section(L10n.profiles) { Section(L10n.profiles) {
if customProfiles.isEmpty { if customProfiles.isEmpty {
Button("Add profile") { Button(L10n.add) {
router.route(to: \.createCustomDeviceProfile) router.route(to: \.createCustomDeviceProfile)
} }
} }

View File

@ -38,23 +38,23 @@ struct GestureSettingsView: View {
Section { Section {
CaseIterablePicker("Horizontal Pan", selection: $horizontalPanGesture) CaseIterablePicker(L10n.horizontalPan, selection: $horizontalPanGesture)
.disabled(horizontalSwipeGesture != .none && horizontalPanGesture == .none) .disabled(horizontalSwipeGesture != .none && horizontalPanGesture == .none)
CaseIterablePicker("Horizontal Swipe", selection: $horizontalSwipeGesture) CaseIterablePicker(L10n.horizontalSwipe, selection: $horizontalSwipeGesture)
.disabled(horizontalPanGesture != .none && horizontalSwipeGesture == .none) .disabled(horizontalPanGesture != .none && horizontalSwipeGesture == .none)
CaseIterablePicker("Long Press", selection: $longPressGesture) CaseIterablePicker(L10n.longPress, selection: $longPressGesture)
CaseIterablePicker("Multi Tap", selection: $multiTapGesture) CaseIterablePicker(L10n.multiTap, selection: $multiTapGesture)
CaseIterablePicker("Double Touch", selection: $doubleTouchGesture) CaseIterablePicker(L10n.doubleTouch, selection: $doubleTouchGesture)
CaseIterablePicker("Pinch", selection: $pinchGesture) CaseIterablePicker(L10n.pinch, selection: $pinchGesture)
CaseIterablePicker("Left Vertical Pan", selection: $verticalPanGestureLeft) CaseIterablePicker(L10n.leftVerticalPan, selection: $verticalPanGestureLeft)
CaseIterablePicker("Right Vertical Pan", selection: $verticalPanGestureRight) CaseIterablePicker(L10n.rightVerticalPan, selection: $verticalPanGestureRight)
} }
} }
.navigationTitle(L10n.gestures) .navigationTitle(L10n.gestures)

View File

@ -724,6 +724,9 @@
/// Done /// Done
"done" = "Done"; "done" = "Done";
/// Double touch
"doubleTouch" = "Double touch";
/// Downloads /// Downloads
"downloads" = "Downloads"; "downloads" = "Downloads";
@ -913,6 +916,12 @@
/// Home /// Home
"home" = "Home"; "home" = "Home";
/// Horizontal pan
"horizontalPan" = "Horizontal pan";
/// Horizontal swipe
"horizontalSwipe" = "Horizontal swipe";
/// Hours /// Hours
"hours" = "Hours"; "hours" = "Hours";
@ -1021,6 +1030,9 @@
/// Left /// Left
"left" = "Left"; "left" = "Left";
/// Left vertical pan
"leftVerticalPan" = "Left vertical pan";
/// Letter /// Letter
"letter" = "Letter"; "letter" = "Letter";
@ -1087,6 +1099,9 @@
/// Access the Jellyfin server logs for troubleshooting and monitoring purposes. /// Access the Jellyfin server logs for troubleshooting and monitoring purposes.
"logsDescription" = "Access the Jellyfin server logs for troubleshooting and monitoring purposes."; "logsDescription" = "Access the Jellyfin server logs for troubleshooting and monitoring purposes.";
/// Long press
"longPress" = "Long press";
/// Lyricist /// Lyricist
"lyricist" = "Lyricist"; "lyricist" = "Lyricist";
@ -1165,6 +1180,9 @@
/// Missing /// Missing
"missing" = "Missing"; "missing" = "Missing";
/// Missing codec values
"missingCodecValues" = "Missing codec values";
/// Missing Items /// Missing Items
"missingItems" = "Missing Items"; "missingItems" = "Missing Items";
@ -1174,6 +1192,9 @@
/// Movies /// Movies
"movies" = "Movies"; "movies" = "Movies";
/// Multi tap
"multiTap" = "Multi tap";
/// Music /// Music
"music" = "Music"; "music" = "Music";
@ -1225,6 +1246,9 @@
/// No /// No
"no" = "No"; "no" = "No";
/// No profiles defined. Playback issues may occur.
"noDeviceProfileWarning" = "No profiles defined. Playback issues may occur.";
/// No episodes available /// No episodes available
"noEpisodesAvailable" = "No episodes available"; "noEpisodesAvailable" = "No episodes available";
@ -1336,6 +1360,9 @@
/// Pin /// Pin
"pin" = "Pin"; "pin" = "Pin";
/// Pinch
"pinch" = "Pinch";
/// Play /// Play
"play" = "Play"; "play" = "Play";
@ -1402,6 +1429,9 @@
/// Profile Image /// Profile Image
"profileImage" = "Profile Image"; "profileImage" = "Profile Image";
/// Profile not saved
"profileNotSaved" = "Profile not saved";
/// Profiles /// Profiles
"profiles" = "Profiles"; "profiles" = "Profiles";
@ -1516,6 +1546,9 @@
/// Replace all unlocked metadata and images with new information. /// Replace all unlocked metadata and images with new information.
"replaceAllDescription" = "Replace all unlocked metadata and images with new information."; "replaceAllDescription" = "Replace all unlocked metadata and images with new information.";
/// Current profile values may cause playback issues
"replaceDeviceProfileWarning" = "Current profile values may cause playback issues";
/// Replace Images /// Replace Images
"replaceImages" = "Replace Images"; "replaceImages" = "Replace Images";
@ -1591,6 +1624,9 @@
/// Right /// Right
"right" = "Right"; "right" = "Right";
/// Right vertical pan
"rightVerticalPan" = "Right vertical pan";
/// Role /// Role
"role" = "Role"; "role" = "Role";