Compare commits

...

16 Commits

Author SHA1 Message Date
Jason 2b7d95497d
Merge a2f346e977 into 84572f8303 2024-04-27 15:07:03 +00:00
Jason Henriquez a2f346e977 Replace proxy icon with more fitting one 2024-04-27 10:06:53 -05:00
Jason Henriquez 1d88d647be Make constant for 'active' class name 2024-04-27 01:14:16 -05:00
Jason Henriquez 938b40d194 Update to have first section active by default 2024-04-26 23:40:05 -05:00
Jason Henriquez 02567db33b Fix underline to be equal on both sides 2024-04-26 23:32:55 -05:00
Jason Henriquez 9097768d85 Increase link padding 2024-04-26 23:09:29 -05:00
Jason Henriquez 5eaf46923e Merge branch 'development' of github.com:FreeTubeApp/FreeTube into feat/add-settings-menu 2024-04-26 22:30:03 -05:00
Jason Henriquez 5bbc41a946 Implement bare minimum mobile styling 2024-04-26 21:02:48 -05:00
Jason Henriquez e16b37264e Styling & documentation improvements; remove problematized Hot Pink link underline removal experiment 2024-04-26 20:34:04 -05:00
Jason Henriquez e9c527a5d3 Ensure General Settings is always first, ignoring sorting
Solving the problem of preventing 'jumping around' when changing locales with alphabetical sorting is hard. This problem is easily solved by stickying general settings to the top of the list unconditionally. This is in line with ChunkyProgrammer's initial assessment of how to improve the settings order in https://github.com/FreeTubeApp/FreeTube/issues/1739, albeit not also moving Theme Settings to the top for the time being. The rationale from a functional level is that General Settings is a hub. Even when you change languages, change sort order, or what have you, General Settings is right at the top. I don't imagine we need to update the label of the setting, as I think this relationship is quite intuitive.
2024-04-26 18:11:31 -05:00
Jason Henriquez 8135ff2dd0 Implement dynamic scroll-based underlining of active section 2024-04-26 17:58:56 -05:00
Jason Henriquez f4d8648607 Implement short labels and fallback to longer label when translation doesn't exist 2024-04-26 12:05:36 -05:00
Jason Henriquez 97a5c7362c Merge branch 'development' of github.com:FreeTubeApp/FreeTube into feat/add-settings-menu 2024-04-25 16:58:23 -05:00
Jason Henriquez edafe33a22 Implement settings menu with icons 2024-04-25 16:07:13 -05:00
Jason Henriquez 569f561591 Make IS_ELECTRON property used directly 2024-04-24 06:28:46 -05:00
Jason Henriquez 9a75cd0dda Implement settings section sorting 2024-04-23 22:32:26 -05:00
15 changed files with 394 additions and 164 deletions

View File

@ -73,6 +73,9 @@ const SyncEvents = {
}
}
// Settings
const ACTIVE_CLASS_NAME = 'active'
// Utils
const MAIN_PROFILE_ID = 'allChannels'
@ -80,5 +83,6 @@ export {
IpcChannels,
DBActions,
SyncEvents,
ACTIVE_CLASS_NAME,
MAIN_PROFILE_ID
}

View File

@ -0,0 +1,87 @@
.settingsMenu {
position: sticky;
inset-block-start: 120px;
display: flex;
flex-direction: column;
font-size: 22px;
padding-inline-start: 0;
block-size: fit-content;
}
.header {
font-size: 26px;
}
.title {
text-decoration: none;
color: var(--tertiary-text-color);
inline-size: 220px;
padding-block: 3px;
}
/* prevent hover styling from showing on title click for mobile */
@media (hover: hover) {
.title:hover {
color: var(--primary-text-color);
}
}
.titleContent {
inline-size: fit-content;
max-inline-size: 100%;
}
.iconAndTitleText {
overflow-x: hidden;
white-space: nowrap;
text-overflow: ellipsis;
/* needed to have underline poke out */
margin-inline-start: 3px;
}
.titleUnderline {
/* have underline poke out */
inline-size: calc(100% + 6px);
/* prevent "active" border from visibly pushing the content up */
border-block-end: 4px solid transparent;
}
.title.active {
color: var(--primary-text-color);
font-weight: 600;
}
.title.active .titleUnderline {
border-block-end: 4px solid var(--primary-color);
}
.titleIcon {
inline-size: 22px;
block-size: 22px;
}
@media only screen and (width <= 950px) {
.settingsMenu {
display: none;
}
/*
TODO: integrate settings menu into mobile view
.header {
display: none;
}
.settingsMenu {
position: fixed;
flex-direction: row;
gap: 5px;
overflow-x: scroll;
}
.title {
inline-size: 100%;
} */
}

View File

@ -0,0 +1,16 @@
import { defineComponent } from 'vue'
export default defineComponent({
name: 'FtSettingsMenu',
props: {
settingsSections: {
type: Array,
required: true
},
},
methods: {
getTitleForSection: function(settingsSection) {
return settingsSection.shortTitle !== '' ? settingsSection.shortTitle : settingsSection.title
}
}
})

View File

@ -0,0 +1,30 @@
<template>
<menu
class="settingsMenu"
>
<h2 class="header">
{{ $t('Settings.Settings') }}
</h2>
<a
v-for="(settingsSection) in settingsSections"
:id="settingsSection.type + '-link'"
:key="settingsSection.type + '-link'"
:href="'#' + settingsSection.type"
class="title"
>
<div class="titleContent">
<div class="iconAndTitleText">
<font-awesome-icon
:icon="['fas', settingsSection.icon]"
class="titleIcon"
/>
{{ getTitleForSection(settingsSection) }}
</div>
<div class="titleUnderline" />
</div>
</a>
</menu>
</template>
<script src="./ft-settings-menu.js" />
<style scoped src="./ft-settings-menu.css" />

View File

@ -7,10 +7,5 @@ export default defineComponent({
type: String,
required: true
},
},
computed: {
allSettingsSectionsExpandedByDefault: function () {
return this.$store.getters.getAllSettingsSectionsExpandedByDefault
}
}
})

View File

@ -1,16 +1,21 @@
.settingsSection {
background-color: var(--card-bg-color);
margin-block: 0;
margin-inline: auto;
inline-size: 85%;
@media only screen and (width <= 800px) {
inline-size: 100%;
}
}
&[open] {
padding-block-end: 15px;
}
.sectionHeader {
cursor: pointer;
display: block;
padding: 1px;
}
.sectionBody {
background-color: var(--card-bg-color);
border-radius: 20px;
padding-block: 10px;
> div {
box-sizing: border-box;
@ -26,19 +31,6 @@
}
}
.sectionLine {
border: 0;
border-block-start: 2px solid var(--primary-color);
margin-block-start: -1px;
inline-size: 100%;
}
.sectionHeader {
cursor: pointer;
display: block;
padding: 1px;
}
.sectionTitle {
user-select: none;
margin-inline-start: 2%;

View File

@ -1,16 +1,14 @@
<template>
<details
:open="allSettingsSectionsExpandedByDefault"
<div
class="settingsSection"
>
<summary class="sectionHeader">
<h3 class="sectionTitle">
{{ title }}
</h3>
</summary>
<hr class="sectionLine">
<slot />
</details>
<h3 class="sectionTitle">
{{ title }}
</h3>
<div class="sectionBody">
<slot />
</div>
</div>
</template>
<script src="./ft-settings-section.js" />

View File

@ -19,7 +19,7 @@
:select-names="protocolNames"
:select-values="protocolValues"
class="protocol-dropdown"
:icon="['fas', 'microchip']"
:icon="['fas', 'network-wired']"
@change="handleUpdateProxyProtocol"
/>
</ft-flex-box>

View File

@ -20,14 +20,19 @@ import {
faArrowRight,
faArrowUp,
faBars,
faBorderAll,
faBookmark,
faCheck,
faChevronRight,
faCirclePlay,
faCircleUser,
faClapperboard,
faClone,
faComment,
faCommentDots,
faCopy,
faDatabase,
faDisplay,
faDownload,
faEdit,
faEllipsisH,
@ -42,6 +47,7 @@ import {
faFileImage,
faFileVideo,
faFilter,
faFlask,
faFire,
faForward,
faGauge,
@ -52,12 +58,14 @@ import {
faHistory,
faImages,
faInfoCircle,
faKey,
faLanguage,
faLink,
faLinkSlash,
faList,
faLocationDot,
faMicrochip,
faLock,
faNetworkWired,
faNewspaper,
faPalette,
faPause,
@ -73,6 +81,7 @@ import {
faSearch,
faServer,
faShareAlt,
faShield,
faSlidersH,
faSortAlphaDown,
faSortAlphaDownAlt,
@ -86,7 +95,8 @@ import {
faTimes,
faTimesCircle,
faTrash,
faUsers,
faUserLock,
faUsers
} from '@fortawesome/free-solid-svg-icons'
import {
faBitcoin,
@ -113,14 +123,19 @@ library.add(
faArrowRight,
faArrowUp,
faBars,
faBorderAll,
faBookmark,
faCheck,
faChevronRight,
faCirclePlay,
faCircleUser,
faClapperboard,
faClone,
faComment,
faCommentDots,
faCopy,
faDatabase,
faDisplay,
faDownload,
faEdit,
faEllipsisH,
@ -135,6 +150,7 @@ library.add(
faFileImage,
faFileVideo,
faFilter,
faFlask,
faFire,
faForward,
faGauge,
@ -145,12 +161,14 @@ library.add(
faHistory,
faImages,
faInfoCircle,
faKey,
faLanguage,
faLink,
faLinkSlash,
faList,
faLocationDot,
faMicrochip,
faLock,
faNetworkWired,
faNewspaper,
faPalette,
faPause,
@ -167,6 +185,7 @@ library.add(
faSearch,
faServer,
faShareAlt,
faShield,
faSlidersH,
faSortAlphaDown,
faSortAlphaDownAlt,
@ -180,6 +199,7 @@ library.add(
faTimes,
faTimesCircle,
faTrash,
faUserLock,
faUsers,
// brand icons

View File

@ -162,7 +162,6 @@ const defaultSideEffectsTriggerId = settingId =>
/*****/
const state = {
allSettingsSectionsExpandedByDefault: false,
autoplayPlaylists: true,
autoplayVideos: true,
backendFallback: process.env.SUPPORTS_LOCAL_API,

View File

@ -232,17 +232,6 @@
--accent-color-opacity4: rgb(255 255 255 / 24%) !important;
}
/* Given that the Hot Pink theme does not need link underlining due to meeting
WCAG 2 Level AA (https://webaim.org/resources/linkcontrastchecker/?fcolor=FFFFFF&bcolor=DE1C85&lcolor=000000),
it can be safely elided. This looks quite pleasant on this theme. */
.hotPink a:not(:hover, :focus), .hotPink .navOption:hover, .hotPink .navOption:focus, .hotPink *:not(:hover, :focus) {
text-decoration: none;
}
.hotPink a:hover, .hotPink a:focus {
text-decoration: underline;
}
.nordic {
--primary-text-color: #EEE;
--secondary-text-color: #ddd;

View File

@ -1,24 +1,47 @@
hr {
inline-size: 85%;
margin-block: 0;
margin-inline: auto;
border: 0;
border-block-start: 2px solid var(--scrollbar-color-hover);
.settingsPage {
display: flex;
gap: 20px;
}
@media only screen and (width <= 800px) {
hr {
inline-size: 100%;
}
.settingsSections {
overflow-x: hidden;
max-inline-size: 90%;
}
.settingsSections:last-child {
/* Add enough blank space to have the last setting section be active on the FtSettingsMenu when scrolled to */
margin-block-end: calc(76vh - 150px)
}
.switchRow {
inline-size: 85%;
margin-inline: auto;
display: flex;
margin-inline-end: auto;
}
.settingsToggle {
padding-block: 0;
margin-block: 10px 5px;
margin-block: 0;
}
.section {
/* enables anchor link clicks to land with the section title in the top quarter of the page */
scroll-margin-top: 24vh;
}
.section + .section {
padding-block-start: 20px;
}
@media only screen and (width <= 950px) {
.settingsPage {
flex-direction: column;
}
.switchRow, .settingsSections {
margin-inline: auto;
}
.settingsSections:last-child {
margin-block-end: 0;
}
}

View File

@ -16,6 +16,8 @@ import ExperimentalSettings from '../../components/experimental-settings/experim
import PasswordSettings from '../../components/password-settings/password-settings.vue'
import PasswordDialog from '../../components/password-dialog/password-dialog.vue'
import FtToggleSwitch from '../../components/ft-toggle-switch/ft-toggle-switch.vue'
import FtSettingsMenu from '../../components/ft-settings-menu/ft-settings-menu.vue'
import { ACTIVE_CLASS_NAME } from '../../../constants'
export default defineComponent({
name: 'Settings',
@ -35,73 +37,12 @@ export default defineComponent({
'experimental-settings': ExperimentalSettings,
'password-settings': PasswordSettings,
'password-dialog': PasswordDialog,
'ft-toggle-switch': FtToggleSwitch
'ft-toggle-switch': FtToggleSwitch,
'ft-settings-menu': FtSettingsMenu,
},
data: function () {
return {
unlocked: false,
settingsComponentsData: [
{
type: 'general-settings',
title: this.$t('Settings.General Settings.General Settings')
},
{
type: 'theme-settings',
title: this.$t('Settings.Theme Settings.Theme Settings')
},
{
type: 'player-settings',
title: this.$t('Settings.Player Settings.Player Settings')
},
{
type: 'external-player-settings',
title: this.$t('Settings.External Player Settings.External Player Settings'),
usingElectron: true
},
{
type: 'subscription-settings',
title: this.$t('Settings.Subscription Settings.Subscription Settings')
},
{
type: 'distraction-settings',
title: this.$t('Settings.Distraction Free Settings.Distraction Free Settings')
},
{
type: 'privacy-settings',
title: this.$t('Settings.Privacy Settings.Privacy Settings')
},
{
type: 'data-settings',
title: this.$t('Settings.Data Settings.Data Settings')
},
{
type: 'proxy-settings',
title: this.$t('Settings.Proxy Settings.Proxy Settings'),
usingElectron: true
},
{
type: 'download-settings',
title: this.$t('Settings.Download Settings.Download Settings'),
usingElectron: true
},
{
type: 'parental-control-settings',
title: this.$t('Settings.Parental Control Settings.Parental Control Settings')
},
{
type: 'sponsor-block-settings',
title: this.$t('Settings.SponsorBlock Settings.SponsorBlock Settings'),
},
{
type: 'experimental-settings',
title: this.$t('Settings.Experimental Settings.Experimental Settings'),
usingElectron: true
},
{
type: 'password-settings',
title: this.$t('Settings.Password Settings.Password Settings')
},
]
unlocked: false
}
},
computed: {
@ -113,14 +54,98 @@ export default defineComponent({
return this.$store.getters.getSettingsPassword
},
allSettingsSectionsExpandedByDefault: function () {
return this.$store.getters.getAllSettingsSectionsExpandedByDefault
},
settingsSectionSortEnabled: function () {
return this.$store.getters.getSettingsSectionSortEnabled
},
settingsComponentsData: function () {
return [
{
type: 'theme-settings',
title: this.$t('Settings.Theme Settings.Theme Settings'),
shortTitle: this.$te('Settings.Theme Settings.Theme Settings Short Label') ? this.$t('Settings.Theme Settings.Theme Settings Short Label') : '',
icon: 'display'
},
{
type: 'player-settings',
title: this.$t('Settings.Player Settings.Player Settings'),
shortTitle: this.$te('Settings.Player Settings.Player Settings Short Label') ? this.$t('Settings.Player Settings.Player Settings Short Label') : '',
icon: 'circle-play'
},
{
type: 'external-player-settings',
title: this.$t('Settings.External Player Settings.External Player Settings'),
shortTitle: this.$te('Settings.External Player Settings.External Player') ? this.$t('Settings.External Player Settings.External Player') : '',
icon: 'clapperboard',
usingElectron: true
},
{
type: 'subscription-settings',
title: this.$t('Settings.Subscription Settings.Subscription Settings'),
shortTitle: this.$te('Settings.Subscription Settings.Subscription Settings Short Label') ? this.$t('Settings.Subscription Settings.Subscription Settings Short Label') : '',
icon: 'play'
},
{
type: 'distraction-settings',
title: this.$t('Settings.Distraction Free Settings.Distraction Free Settings'),
shortTitle: this.$te('Settings.Distraction Free Settings.Distraction Free Settings Short Label') ? this.$t('Settings.Distraction Free Settings.Distraction Free Settings Short Label') : '',
icon: 'eye-slash'
},
{
type: 'privacy-settings',
title: this.$t('Settings.Privacy Settings.Privacy Settings'),
shortTitle: this.$te('Settings.Privacy Settings.Privacy Settings Short Label') ? this.$t('Settings.Privacy Settings.Privacy Settings Short Label') : '',
icon: 'lock'
},
{
type: 'data-settings',
title: this.$t('Settings.Data Settings.Data Settings'),
shortTitle: this.$te('Settings.Data Settings.Data Settings Short Label') ? this.$t('Settings.Data Settings.Data Settings Short Label') : '',
icon: 'database'
},
{
type: 'proxy-settings',
title: this.$t('Settings.Proxy Settings.Proxy Settings'),
shortTitle: this.$te('Settings.Proxy Settings.Proxy Settings Short Label') ? this.$t('Settings.Proxy Settings.Proxy Settings Short Label') : '',
icon: 'network-wired',
usingElectron: true
},
{
type: 'download-settings',
title: this.$t('Settings.Download Settings.Download Settings'),
shortTitle: this.$te('Settings.Download Settings.Download Settings Short Label') ? this.$t('Settings.Download Settings.Download Settings Short Label') : '',
icon: 'download',
usingElectron: true
},
{
type: 'parental-control-settings',
title: this.$t('Settings.Parental Control Settings.Parental Control Settings'),
shortTitle: this.$te('Settings.Parental Control Settings.Parental Control Settings Short Label') ? this.$t('Settings.Parental Control Settings.Parental Control Settings Short Label') : '',
icon: 'user-lock'
},
{
type: 'sponsor-block-settings',
title: this.$t('Settings.SponsorBlock Settings.SponsorBlock Settings'),
shortTitle: this.$te('Settings.SponsorBlock Settings.SponsorBlock Settings Short Label') ? this.$t('Settings.SponsorBlock Settings.SponsorBlock Settings Short Label') : '',
// TODO: replace with SponsorBlock icon
icon: 'shield'
},
{
type: 'experimental-settings',
title: this.$t('Settings.Experimental Settings.Experimental Settings'),
shortTitle: this.$te('Settings.Experimental Settings.Experimental Settings Short Label') ? this.$t('Settings.Experimental Settings.Experimental Settings Short Label') : '',
icon: 'flask',
usingElectron: true
},
{
type: 'password-settings',
title: this.$t('Settings.Password Settings.Password Settings'),
shortTitle: this.$te('Settings.Password Settings.Password Settings Short Label') ? this.$t('Settings.Password Settings.Password Settings Short Label') : '',
icon: 'key'
},
]
},
settingsSectionComponents: function () {
let settingsSections
if (!process.env.IS_ELECTRON) {
@ -130,12 +155,22 @@ export default defineComponent({
}
if (this.settingsSectionSortEnabled) {
return settingsSections.toSorted((a, b) =>
a.title.toLowerCase().localeCompare(b.title.toLowerCase(), this.locale)
)
settingsSections = settingsSections.toSorted((a, b) => {
const aTitle = a.shortTitle !== '' ? a.shortTitle : a.title
const bTitle = b.shortTitle !== '' ? b.shortTitle : b.title
return aTitle.toLowerCase().localeCompare(bTitle.toLowerCase(), this.locale)
})
}
return settingsSections
// ensure General Settings is placed first regardless of sorting
const generalSettingsEntry = {
type: 'general-settings',
title: this.$t('Settings.General Settings.General Settings'),
shortTitle: this.$te('Settings.General Settings.General Settings Short Label') ? this.$t('Settings.General Settings.General Settings Short Label') : '',
icon: 'border-all'
}
return [generalSettingsEntry, ...settingsSections]
},
},
created: function () {
@ -143,9 +178,38 @@ export default defineComponent({
this.unlocked = true
}
},
mounted: function () {
document.addEventListener('scroll', this.markScrolledToSectionAsActive)
// mark first section as active before any scrolling has taken place
if (this.settingsSectionComponents.length > 0) {
const firstSection = document.getElementById(`${this.settingsSectionComponents[0].type}-link`)
firstSection.classList.add(ACTIVE_CLASS_NAME)
}
},
beforeDestroy: function () {
document.removeEventListener('scroll', this.markScrolledToSectionAsActive)
},
methods: {
/* Set the current section to be shown as active in the Settings Menu
* if it is the lowest section within the top quarter of the viewport (25vh) */
markScrolledToSectionAsActive: function() {
const scrollY = window.scrollY + innerHeight / 4
this.settingsSectionComponents.forEach((section) => {
const sectionElement = document.getElementById(section.type)
const sectionHeight = sectionElement.offsetHeight
const sectionTop = sectionElement.offsetTop
const correspondingMenuLink = document.getElementById(`${section.type}-link`)
if (scrollY > sectionTop && scrollY <= sectionTop + sectionHeight) {
correspondingMenuLink.classList.add(ACTIVE_CLASS_NAME)
} else {
correspondingMenuLink.classList.remove(ACTIVE_CLASS_NAME)
}
})
},
...mapActions([
'updateAllSettingsSectionsExpandedByDefault',
'updateSettingsSectionSortEnabled'
])
}

View File

@ -1,34 +1,33 @@
<template>
<div>
<div class="settingsPage">
<template v-if="unlocked">
<div class="switchRow">
<ft-toggle-switch
class="settingsToggle"
:label="$t('Settings.Expand All Settings Sections')"
:default-value="allSettingsSectionsExpandedByDefault"
:compact="false"
@change="updateAllSettingsSectionsExpandedByDefault"
/>
<ft-toggle-switch
class="settingsToggle"
:label="$t('Settings.Sort Settings Sections (A-Z)')"
:default-value="settingsSectionSortEnabled"
:compact="false"
@change="updateSettingsSectionSortEnabled"
/>
<ft-settings-menu
:settings-sections="settingsSectionComponents"
/>
<div class="settingsContent">
<div class="switchRow">
<ft-toggle-switch
class="settingsToggle"
:label="$t('Settings.Sort Settings Sections (A-Z)')"
:default-value="settingsSectionSortEnabled"
:compact="false"
@change="updateSettingsSectionSortEnabled"
/>
</div>
<div class="settingsSections">
<template
v-for="(settingsComponent) in settingsSectionComponents"
ref=""
>
<component
:is="settingsComponent.type"
:id="settingsComponent.type"
:key="settingsComponent.type + '-component'"
class="section"
/>
</template>
</div>
</div>
<template
v-for="(settingsComponent, i) in settingsSectionComponents"
>
<hr
v-if="i !== 0"
:key="settingsComponent.type + 'hr'"
>
<component
:is="settingsComponent.type"
:key="settingsComponent.type + 'component'"
/>
</template>
</template>
<password-dialog
v-else

View File

@ -247,6 +247,7 @@ Settings:
app needs to restart for changes to take effect. Restart and apply change?
General Settings:
General Settings: General Settings
General Settings Short Label: General
Check for Updates: Check for Updates
Check for Latest Blog Posts: Check for Latest Blog Posts
Fallback to Non-Preferred Backend on Failure: Fallback to Non-Preferred Backend
@ -290,6 +291,7 @@ Settings:
No Action: No Action
Theme Settings:
Theme Settings: Theme Settings
Theme Settings Short Label: Theme
Match Top Bar with Main Color: Match Top Bar with Main Color
Expand Side Bar by Default: Expand Side Bar by Default
Disable Smooth Scrolling: Disable Smooth Scrolling
@ -350,6 +352,7 @@ Settings:
#* Main Color Theme
Player Settings:
Player Settings: Player Settings
Player Settings Short Label: Player
Force Local Backend for Legacy Formats: Force Local Backend for Legacy Formats
Play Next Video: Play Next Video
Turn on Subtitles by Default: Turn on Subtitles by Default
@ -412,6 +415,7 @@ Settings:
Name: None
Privacy Settings:
Privacy Settings: Privacy Settings
Privacy Settings Short Label: Privacy
Remember History: Remember History
Save Watched Progress: Save Watched Progress
Save Watched Videos With Last Viewed Playlist: Save Watched Videos With Last Viewed Playlist
@ -432,6 +436,7 @@ Settings:
Are you sure you want to remove all your playlists?: Are you sure you want to remove all your playlists?
Subscription Settings:
Subscription Settings: Subscription Settings
Subscription Settings Short Label: Subscription
Hide Videos on Watch: Hide Videos on Watch
Fetch Feeds from RSS: Fetch Feeds from RSS
Manage Subscriptions: Manage Subscriptions
@ -439,6 +444,7 @@ Settings:
Only Show Latest Video for Each Channel: Only Show Latest Video for Each Channel
Distraction Free Settings:
Distraction Free Settings: Distraction Free Settings
Distraction Free Settings Short Label: Distraction Free
Sections:
Side Bar: Side Bar
Subscriptions Page: Subscriptions Page
@ -483,6 +489,7 @@ Settings:
Hide Subscriptions Community: Hide Subscriptions Community
Data Settings:
Data Settings: Data Settings
Data Settings Short Label: Data
Select Import Type: Select Import Type
Select Export Type: Select Export Type
Import Subscriptions: Import Subscriptions
@ -538,6 +545,7 @@ Settings:
Manage Subscriptions: Manage Subscriptions
Proxy Settings:
Proxy Settings: Proxy Settings
Proxy Settings Short Label: Proxy
Enable Tor / Proxy: Enable Tor / Proxy
Proxy Protocol: Proxy Protocol
Proxy Host: Proxy Host
@ -552,6 +560,7 @@ Settings:
Error getting network information. Is your proxy configured properly?: Error getting network information. Is your proxy configured properly?
SponsorBlock Settings:
SponsorBlock Settings: SponsorBlock Settings
SponsorBlock Settings Short Label: SponsorBlock
Enable SponsorBlock: Enable SponsorBlock
'SponsorBlock API Url (Default is https://sponsor.ajay.app)': SponsorBlock API Url (Default is https://sponsor.ajay.app)
Notify when sponsor segment is skipped: Notify when sponsor segment is skipped
@ -567,11 +576,13 @@ Settings:
Category Color: Category Color
Parental Control Settings:
Parental Control Settings: Parental Control Settings
Parental Control Settings Short Label: Parental Control
Hide Unsubscribe Button: Hide Unsubscribe Button
Show Family Friendly Only: Show Family Friendly Only
Hide Search Bar: Hide Search Bar
Download Settings:
Download Settings: Download Settings
Download Settings Short Label: Download
Ask Download Path: Ask for download path
Choose Path: Choose Path
Download Behavior: Download Behavior
@ -579,6 +590,7 @@ Settings:
Open in web browser: Open in web browser
Experimental Settings:
Experimental Settings: Experimental Settings
Experimental Settings Short Label: Experimental
Warning: These settings are experimental, they may cause crashes while enabled. Making backups is highly recommended. Use at your own risk!
Replace HTTP Cache: Replace HTTP Cache
Password Dialog:
@ -588,6 +600,7 @@ Settings:
Unlock: Unlock
Password Settings:
Password Settings: Password Settings
Password Settings Short Label: Password
Set Password To Prevent Access: Set a password to prevent access to settings
Set Password: Set Password
Remove Password: Remove Password
@ -622,6 +635,7 @@ About:
Profile:
Profile Settings: Profile Settings
Profile Settings Short Label: Profile
Toggle Profile List: Toggle Profile List
Profile Select: Profile Select
Profile Filter: Profile Filter