diff --git a/src/renderer/App.js b/src/renderer/App.js index 84d9a2f296a49..417c46c65996d 100644 --- a/src/renderer/App.js +++ b/src/renderer/App.js @@ -130,7 +130,7 @@ export default defineComponent({ externalLinkOpeningPromptNames: function () { return [ - this.$t('Yes'), + this.$t('Yes, Open Link'), this.$t('No') ] }, diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js index 9cda4bad1504c..1671981f1ceaa 100644 --- a/src/renderer/components/data-settings/data-settings.js +++ b/src/renderer/components/data-settings/data-settings.js @@ -39,7 +39,8 @@ export default defineComponent({ 'youtubenew', 'youtube', 'youtubeold', - 'newpipe' + 'newpipe', + 'close' ], shouldExportPlaylistForOlderVersions: false, @@ -70,7 +71,8 @@ export default defineComponent({ `${exportYouTube} (.csv)`, `${exportYouTube} (.json)`, `${exportYouTube} (.opml)`, - `${exportNewPipe} (.json)` + `${exportNewPipe} (.json)`, + this.$t('Close') ] }, primaryProfile: function () { diff --git a/src/renderer/components/data-settings/data-settings.vue b/src/renderer/components/data-settings/data-settings.vue index 456c6d3585c57..81dcab91f6095 100644 --- a/src/renderer/components/data-settings/data-settings.vue +++ b/src/renderer/components/data-settings/data-settings.vue @@ -67,7 +67,6 @@ :label="$t('Settings.Data Settings.Select Export Type')" :option-names="exportSubscriptionsPromptNames" :option-values="subscriptionsPromptValues" - :show-close="true" @click="exportSubscriptions" /> diff --git a/src/renderer/components/experimental-settings/experimental-settings.js b/src/renderer/components/experimental-settings/experimental-settings.js index 1c313c86688e7..652c94f752b18 100644 --- a/src/renderer/components/experimental-settings/experimental-settings.js +++ b/src/renderer/components/experimental-settings/experimental-settings.js @@ -37,7 +37,7 @@ export default defineComponent({ handleReplaceHttpCache: function (value) { this.showRestartPrompt = false - if (value === null || value === 'no') { + if (value === null || value === 'cancel') { this.replaceHttpCache = !this.replaceHttpCache return } diff --git a/src/renderer/components/experimental-settings/experimental-settings.vue b/src/renderer/components/experimental-settings/experimental-settings.vue index 0e70671b8d4c3..1f0d61f64ebbe 100644 --- a/src/renderer/components/experimental-settings/experimental-settings.vue +++ b/src/renderer/components/experimental-settings/experimental-settings.vue @@ -19,8 +19,8 @@ diff --git a/src/renderer/components/ft-button/ft-button.css b/src/renderer/components/ft-button/ft-button.css index 4a0cc58edf2c5..a2a9a5f4474b6 100644 --- a/src/renderer/components/ft-button/ft-button.css +++ b/src/renderer/components/ft-button/ft-button.css @@ -7,7 +7,6 @@ block-size: fit-content; box-sizing: border-box; cursor: pointer; - display: inline-block; align-items: center; justify-content: center; text-align: center; @@ -17,6 +16,8 @@ white-space: nowrap; font-weight: 500; vertical-align: middle; + display: flex; + gap: 10px; margin: 5px; box-shadow: 0 1px 2px rgb(0 0 0 / 50%); } diff --git a/src/renderer/components/ft-button/ft-button.js b/src/renderer/components/ft-button/ft-button.js index 4aa1b12352ca6..ecb2f45286eab 100644 --- a/src/renderer/components/ft-button/ft-button.js +++ b/src/renderer/components/ft-button/ft-button.js @@ -18,6 +18,10 @@ export default defineComponent({ id: { type: String, default: '' + }, + icon: { + type: Array, + default: null } }, emits: ['click'], diff --git a/src/renderer/components/ft-button/ft-button.vue b/src/renderer/components/ft-button/ft-button.vue index 945000bbff1a6..5566ec1dce40b 100644 --- a/src/renderer/components/ft-button/ft-button.vue +++ b/src/renderer/components/ft-button/ft-button.vue @@ -10,6 +10,10 @@ @click="click" > + {{ label }} diff --git a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue index e82ca98ac1dd6..5370f2fb04501 100644 --- a/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue +++ b/src/renderer/components/ft-create-playlist-prompt/ft-create-playlist-prompt.vue @@ -25,6 +25,8 @@ /> diff --git a/src/renderer/components/ft-icon-button/ft-icon-button.scss b/src/renderer/components/ft-icon-button/ft-icon-button.scss index 6e4f3acb268f6..0e35323f49587 100644 --- a/src/renderer/components/ft-icon-button/ft-icon-button.scss +++ b/src/renderer/components/ft-icon-button/ft-icon-button.scss @@ -74,6 +74,20 @@ } } + &.destructive { + background-color: var(--destructive-color); + color: var(--destructive-text-color); + + &:hover, + &:focus-visible { + background-color: var(--destructive-hover-color); + } + + &:active { + background-color: var(--destructive-active-color); + } + } + &.favorite, &.favorite:hover, &.favorite:focus-visible { color: var(--favorite-icon-color); } diff --git a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue index 3865e0acb3e50..3ab9a13fa907b 100644 --- a/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue +++ b/src/renderer/components/ft-playlist-add-video-prompt/ft-playlist-add-video-prompt.vue @@ -73,6 +73,8 @@ /> diff --git a/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.js b/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.js index d707ebcbe85d5..6166401f85374 100644 --- a/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.js +++ b/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.js @@ -34,8 +34,8 @@ export default defineComponent({ subscriptions: [], selectedLength: 0, deletePromptValues: [ - 'yes', - 'no' + 'delete', + 'cancel' ] } }, @@ -61,8 +61,8 @@ export default defineComponent({ }, deletePromptNames: function () { return [ - this.$t('Yes'), - this.$t('No') + this.$t('Yes, Delete'), + this.$t('Cancel') ] }, locale: function () { @@ -109,7 +109,7 @@ export default defineComponent({ }, handleDeletePromptClick: function (value) { - if (value !== 'no' && value !== null) { + if (value !== 'cancel' && value !== null) { if (this.isMainProfile) { const channelsToRemove = this.subscriptions.filter((channel) => channel.selected) this.subscriptions = this.subscriptions.filter((channel) => !channel.selected) diff --git a/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.vue b/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.vue index dd33d8d5b8b13..94b92f873548f 100644 --- a/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.vue +++ b/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.vue @@ -30,8 +30,8 @@ /> @@ -41,6 +41,7 @@ :label="deletePromptMessage" :option-names="deletePromptNames" :option-values="deletePromptValues" + :is-first-option-destructive="true" @click="handleDeletePromptClick" /> diff --git a/src/renderer/components/ft-profile-edit/ft-profile-edit.js b/src/renderer/components/ft-profile-edit/ft-profile-edit.js index 240501a0f7012..5b9e5b439d036 100644 --- a/src/renderer/components/ft-profile-edit/ft-profile-edit.js +++ b/src/renderer/components/ft-profile-edit/ft-profile-edit.js @@ -42,8 +42,8 @@ export default defineComponent({ profileBgColor: '', profileTextColor: '', deletePromptValues: [ - 'yes', - 'no' + 'delete', + 'cancel' ] } }, @@ -70,8 +70,8 @@ export default defineComponent({ }, deletePromptNames: function () { return [ - this.$t('Yes'), - this.$t('No') + this.$t('Yes, Delete'), + this.$t('Cancel') ] }, editOrCreateProfileLabel: function () { @@ -101,7 +101,7 @@ export default defineComponent({ }, handleDeletePrompt: function (response) { - if (response === 'yes') { + if (response === 'delete') { this.deleteProfile() } else { this.showDeletePrompt = false diff --git a/src/renderer/components/ft-profile-edit/ft-profile-edit.vue b/src/renderer/components/ft-profile-edit/ft-profile-edit.vue index 35423f822632b..2b011ac94ff81 100644 --- a/src/renderer/components/ft-profile-edit/ft-profile-edit.vue +++ b/src/renderer/components/ft-profile-edit/ft-profile-edit.vue @@ -83,8 +83,9 @@ @@ -99,6 +100,7 @@ :label="deletePromptLabel" :option-names="deletePromptNames" :option-values="deletePromptValues" + :is-first-option-destructive="true" @click="handleDeletePrompt" /> diff --git a/src/renderer/components/ft-prompt/ft-prompt.js b/src/renderer/components/ft-prompt/ft-prompt.js index c28bb3d4cda87..ae91f31208e19 100644 --- a/src/renderer/components/ft-prompt/ft-prompt.js +++ b/src/renderer/components/ft-prompt/ft-prompt.js @@ -29,11 +29,11 @@ export default defineComponent({ type: Array, default: () => { return [] } }, - showClose: { + autosize: { type: Boolean, default: false }, - autosize: { + isFirstOptionDestructive: { type: Boolean, default: false }, @@ -52,7 +52,7 @@ export default defineComponent({ computed: { sanitizedLabel: function() { return sanitizeForHtmlId(this.label) - } + }, }, mounted: function () { this.lastActiveElement = document.activeElement @@ -72,6 +72,24 @@ export default defineComponent({ nextTick(() => this.lastActiveElement?.focus()) }, methods: { + optionButtonTextColor: function(index) { + if (index === 0 && this.isFirstOptionDestructive) { + return 'var(--destructive-text-color)' + } else if (index < this.optionNames.length - 1) { + return 'var(--text-with-accent-color)' + } else { + return null + } + }, + optionButtonBackgroundColor: function(index) { + if (index === 0 && this.isFirstOptionDestructive) { + return 'var(--destructive-color)' + } else if (index < this.optionNames.length - 1) { + return 'var(--accent-color)' + } else { + return null + } + }, click: function (value) { this.$emit('click', value) }, diff --git a/src/renderer/components/ft-prompt/ft-prompt.vue b/src/renderer/components/ft-prompt/ft-prompt.vue index 9ea9e47412fa7..1332324ca7068 100644 --- a/src/renderer/components/ft-prompt/ft-prompt.vue +++ b/src/renderer/components/ft-prompt/ft-prompt.vue @@ -36,17 +36,11 @@ :id="'prompt-' + sanitizedLabel + '-' + index" :key="index" :label="option" + :text-color="optionButtonTextColor(index)" + :background-color="optionButtonBackgroundColor(index)" + :icon="index === 0 && isFirstOptionDestructive ? ['fas', 'trash'] : null" @click="click(optionValues[index])" /> - diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue index cbdbf65bbc7ef..b2d35e849a424 100644 --- a/src/renderer/components/playlist-info/playlist-info.vue +++ b/src/renderer/components/playlist-info/playlist-info.vue @@ -155,14 +155,14 @@ v-if="!editMode && isUserPlaylist && videoCount > 0" :title="$t('User Playlists.Remove Watched Videos')" :icon="['fas', 'eye-slash']" - theme="primary" + theme="destructive" @click="showRemoveVideosOnWatchPrompt = true" /> diff --git a/src/renderer/components/privacy-settings/privacy-settings.js b/src/renderer/components/privacy-settings/privacy-settings.js index 94ec93d8f8d18..c547dfb4e9e7f 100644 --- a/src/renderer/components/privacy-settings/privacy-settings.js +++ b/src/renderer/components/privacy-settings/privacy-settings.js @@ -24,8 +24,8 @@ export default defineComponent({ showRemoveSubscriptionsPrompt: false, showRemovePlaylistsPrompt: false, promptValues: [ - 'yes', - 'no' + 'delete', + 'cancel' ] } }, @@ -48,8 +48,8 @@ export default defineComponent({ }, promptNames: function () { return [ - this.$t('Yes'), - this.$t('No') + this.$t('Yes, Delete'), + this.$t('Cancel') ] } }, @@ -57,7 +57,7 @@ export default defineComponent({ handleSearchCache: function (option) { this.showSearchCachePrompt = false - if (option === 'yes') { + if (option === 'delete') { this.clearSessionSearchHistory() showToast(this.$t('Settings.Privacy Settings.Search cache has been cleared')) } @@ -74,7 +74,7 @@ export default defineComponent({ handleRemoveHistory: function (option) { this.showRemoveHistoryPrompt = false - if (option === 'yes') { + if (option === 'delete') { this.removeAllHistory() showToast(this.$t('Settings.Privacy Settings.Watch history has been cleared')) } @@ -85,7 +85,7 @@ export default defineComponent({ this.updateActiveProfile(MAIN_PROFILE_ID) - if (option !== 'yes') { return } + if (option !== 'delete') { return } this.profileList.forEach((profile) => { if (profile._id === MAIN_PROFILE_ID) { diff --git a/src/renderer/components/privacy-settings/privacy-settings.vue b/src/renderer/components/privacy-settings/privacy-settings.vue index 53f944777729d..3fe025d4e7df1 100644 --- a/src/renderer/components/privacy-settings/privacy-settings.vue +++ b/src/renderer/components/privacy-settings/privacy-settings.vue @@ -34,26 +34,30 @@ @@ -62,6 +66,7 @@ :label="$t('Settings.Privacy Settings.Are you sure you want to clear out your search cache?')" :option-names="promptNames" :option-values="promptValues" + :is-first-option-destructive="true" @click="handleSearchCache" /> diff --git a/src/renderer/components/theme-settings/theme-settings.js b/src/renderer/components/theme-settings/theme-settings.js index 5e9d268b60e4e..6900f4db17aec 100644 --- a/src/renderer/components/theme-settings/theme-settings.js +++ b/src/renderer/components/theme-settings/theme-settings.js @@ -27,8 +27,8 @@ export default defineComponent({ disableSmoothScrollingToggleValue: false, showRestartPrompt: false, restartPromptValues: [ - 'yes', - 'no' + 'restart', + 'cancel' ], baseThemeValues: [ 'system', @@ -90,8 +90,8 @@ export default defineComponent({ restartPromptNames: function () { return [ - this.$t('Yes'), - this.$t('No') + this.$t('Yes, Restart'), + this.$t('Cancel') ] }, @@ -141,7 +141,7 @@ export default defineComponent({ handleSmoothScrolling: function (value) { this.showRestartPrompt = false - if (value === null || value === 'no') { + if (value === null || value === 'cancel') { this.disableSmoothScrollingToggleValue = !this.disableSmoothScrollingToggleValue return } diff --git a/src/renderer/themes.css b/src/renderer/themes.css index 16f35ae590fa5..406f9c1719960 100644 --- a/src/renderer/themes.css +++ b/src/renderer/themes.css @@ -8,6 +8,10 @@ .hotPink, .nordic { --primary-input-color: rgb(0 0 0 / 50%); + --destructive-color: #f44336; + --destructive-text-color: #000; + --destructive-hover-color: #e53935; + --destructive-active-color: #c62828; } .system[data-system-theme*='light'], .light, @@ -191,6 +195,25 @@ --logo-text: url("../../_icons/textBlackSmall.svg"); } +.nordic { + --primary-text-color: #EEE; + --secondary-text-color: #ddd; + --tertiary-text-color: #EEE; + --title-color: #EEE; + --bg-color: #2b2f3a; + --favorite-icon-color: #0F0; + --card-bg-color: #2e3440; + --secondary-card-bg-color: rgb(59 66 82 / 75%); + --scrollbar-color: #4b566a; + --scrollbar-color-hover: #4b566a; + --side-nav-color: #2e3440; + --side-nav-hover-color: #3b4252; + --side-nav-active-color: #3b4252; + --search-bar-color: #4b566a; + --logo-icon: url("../../_icons/iconNordicLightSmall.svg"); + --logo-text: url("../../_icons/textNordicLightSmall.svg"); +} + .hotPink { --primary-text-color: #FFFF; --secondary-text-color: #FFFF; @@ -243,25 +266,6 @@ it can be safely elided. This looks quite pleasant on this theme. */ text-decoration: underline; } -.nordic { - --primary-text-color: #EEE; - --secondary-text-color: #ddd; - --tertiary-text-color: #EEE; - --title-color: #EEE; - --bg-color: #2b2f3a; - --favorite-icon-color: #0F0; - --card-bg-color: #2e3440; - --secondary-card-bg-color: rgb(59 66 82 / 75%); - --scrollbar-color: #4b566a; - --scrollbar-color-hover: #4b566a; - --side-nav-color: #2e3440; - --side-nav-hover-color: #3b4252; - --side-nav-active-color: #3b4252; - --search-bar-color: #4b566a; - --logo-icon: url("../../_icons/iconNordicLightSmall.svg"); - --logo-text: url("../../_icons/textNordicLightSmall.svg"); -} - .mainRed, .mainPink, .mainPurple, @@ -387,6 +391,7 @@ it can be safely elided. This looks quite pleasant on this theme. */ .mainDraculaCyan, .mainDraculaGreen, .mainDraculaOrange, +.mainDraculaRed, .mainDraculaYellow { --text-with-main-color: #282A36; --logo-icon-bar-color: url("../../_icons/iconDraculaDarkSmall.svg"); @@ -394,8 +399,7 @@ it can be safely elided. This looks quite pleasant on this theme. */ } .mainDraculaPink, -.mainDraculaPurple, -.mainDraculaRed { +.mainDraculaPurple { --text-with-main-color: #F8F8F2; --logo-icon-bar-color: url("../../_icons/iconDraculaLightSmall.svg"); --logo-text-bar-color: url("../../_icons/textDraculaLightSmall.svg"); @@ -763,13 +767,13 @@ it can be safely elided. This looks quite pleasant on this theme. */ .secDraculaCyan, .secDraculaGreen, .secDraculaOrange, +.secDraculaRed, .secDraculaYellow { --text-with-accent-color: #212121; } .secDraculaPink, -.secDraculaPurple, -.secDraculaRed { +.secDraculaPurple { --text-with-accent-color: #F8F8F2; } @@ -1028,6 +1032,34 @@ it can be safely elided. This looks quite pleasant on this theme. */ --accent-color-opacity4: rgb(180 190 254 / 24%); } + /* region destructive color for red color themes + using :has(.app) to increase specificity */ + .mainRed:has(.app), .secRed:has(.app), .mainDraculaRed:has(.app), .secDraculaRed:has(.app) { + --destructive-color: #9C27B0; + --destructive-text-color: #FFF; + --destructive-hover-color: #8E24AA; + --destructive-active-color: #6A1B9A; + } + + /* Deal with theme conflict on destructive colors */ + .mainRed.secPurple, + .mainRed.secDeepPurple, + .mainRed.secDraculaPurple, + .mainDraculaRed.secPurple, + .mainDraculaRed.secDeepPurple, + .mainDraculaRed.secDraculaPurple, + .mainPurple.secRed, + .mainPurple.secDraculaRed, + .mainDeepPurple.secRed, + .mainDeepPurple.secDraculaRed, + .mainDraculaPurple.secRed, + .mainDraculaPurple.secDraculaRed { + --destructive-color: #FF9800; + --destructive-text-color: #FFF; + --destructive-hover-color: #FB8C00; + --destructive-active-color: #EF6C00; + } + body[dir='ltr'] { --ltr-or-rtl: ltr; --float-left-ltr-rtl-value: left; diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml index dde2702086089..8dfcfda7306d5 100644 --- a/static/locales/en-US.yaml +++ b/static/locales/en-US.yaml @@ -1068,6 +1068,10 @@ Moments Ago: moments ago Yes: Yes No: No Ok: Ok +Yes, Delete: Yes, Delete +Yes, Restart: Yes, Restart +Yes, Open Link: Yes, Open Link +Cancel: Cancel # symbol used to indicate that an item is correct checkmark: ✓ # French is the only language that should change this (they have a space before the colon)