mirror of
https://github.com/FreeTubeApp/FreeTube
synced 2024-11-22 01:45:40 +01:00
A new way to subscribe (#4238)
* Implement styling for new subscribe button * Implement dropdown element and styling * Implements remaining styling and logic * Correct use of aria-selected in FT Note: was able to add aria-controls to ft-profile-selector because it keeps the hidden dropdown in the DOM. The same is not true of the ft-icon-button or ft-subscribe-button. Main point: aria-expanded should go on the button opening the dropdown, not the dropdown itself. * Resolve subscribe button staying upon bug * Remove unneeded vendor-specific transition prefixes See discussion here: https://www.web-plus-plus.com/Articles/css-transition-moz-and-webkit-vs-css3
This commit is contained in:
parent
62e7b439db
commit
e68c534e6c
@ -11,17 +11,12 @@
|
||||
overflow: hidden;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
-webkit-transition: background 0.2s ease-out;
|
||||
-moz-transition: background 0.2s ease-out;
|
||||
-o-transition: background 0.2s ease-out;
|
||||
transition: background 0.2s ease-out;
|
||||
}
|
||||
|
||||
.bubblePadding:hover {
|
||||
background-color: var(--side-nav-hover-color);
|
||||
color: var(--side-nav-hover-text-color);
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
}"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
:aria-expanded="dropdownShown"
|
||||
@click="handleIconClick"
|
||||
@mousedown="handleIconMouseDown"
|
||||
@keydown.enter.prevent="handleIconClick"
|
||||
@ -33,7 +34,6 @@
|
||||
v-if="dropdownOptions.length > 0"
|
||||
class="list"
|
||||
role="listbox"
|
||||
:aria-expanded="dropdownShown"
|
||||
>
|
||||
<li
|
||||
v-for="(option, index) in dropdownOptions"
|
||||
@ -71,7 +71,6 @@
|
||||
v-if="dropdownOptions.length > 0"
|
||||
class="list"
|
||||
role="listbox"
|
||||
:aria-expanded="dropdownShown"
|
||||
>
|
||||
<li
|
||||
v-for="(option, index) in dropdownOptions"
|
||||
|
@ -57,8 +57,6 @@
|
||||
border-radius: 100%;
|
||||
color: var(--primary-text-color);
|
||||
opacity: 0;
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
@ -74,8 +72,6 @@
|
||||
.clearInputTextButton.visible:active {
|
||||
background-color: var(--tertiary-text-color);
|
||||
color: var(--side-nav-active-text-color);
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
@ -172,8 +168,6 @@
|
||||
.inputAction.enabled:hover {
|
||||
background-color: var(--side-nav-hover-color);
|
||||
color: var(--side-nav-hover-text-color);
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
@ -184,8 +178,6 @@
|
||||
.inputAction.enabled:active {
|
||||
background-color: var(--tertiary-text-color);
|
||||
color: var(--side-nav-active-text-color);
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
|
@ -4,17 +4,12 @@
|
||||
padding-block: 10px 30px;
|
||||
padding-inline: 10px;
|
||||
cursor: pointer;
|
||||
-webkit-transition: background 0.2s ease-out;
|
||||
-moz-transition: background 0.2s ease-out;
|
||||
-o-transition: background 0.2s ease-out;
|
||||
transition: background 0.2s ease-out;
|
||||
}
|
||||
|
||||
.bubblePadding:hover {
|
||||
background-color: var(--side-nav-hover-color);
|
||||
color: var(--side-nav-hover-text-color);
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
|
@ -56,17 +56,12 @@ Height adjust for profile list so it won't cover navbar. */
|
||||
.profile {
|
||||
cursor: pointer;
|
||||
block-size: 50px;
|
||||
-webkit-transition: background 0.2s ease-out;
|
||||
-moz-transition: background 0.2s ease-out;
|
||||
-o-transition: background 0.2s ease-out;
|
||||
transition: background 0.2s ease-out;
|
||||
}
|
||||
|
||||
.profile:hover {
|
||||
background-color: var(--side-nav-hover-color);
|
||||
color: var(--side-nav-hover-text-color);
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,10 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isActiveProfile: function (profile) {
|
||||
return profile._id === this.activeProfile._id
|
||||
},
|
||||
|
||||
toggleProfileList: function () {
|
||||
this.profileListShown = !this.profileListShown
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
:style="{ background: activeProfile.bgColor, color: activeProfile.textColor }"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
:aria-expanded="profileListShown"
|
||||
aria-controls="profileSelectorList"
|
||||
@click="toggleProfileList"
|
||||
@mousedown="handleIconMouseDown"
|
||||
@keydown.space.prevent="toggleProfileList"
|
||||
@ -19,6 +21,7 @@
|
||||
</div>
|
||||
<ft-card
|
||||
v-show="profileListShown"
|
||||
id="profileSelectorList"
|
||||
ref="profileList"
|
||||
class="profileList"
|
||||
tabindex="-1"
|
||||
@ -46,7 +49,7 @@
|
||||
:key="index"
|
||||
class="profile"
|
||||
:aria-labelledby="'profile-' + index + '-name'"
|
||||
aria-selected="false"
|
||||
:aria-selected="isActiveProfile(profile)"
|
||||
tabindex="0"
|
||||
role="option"
|
||||
@click="setActiveProfile(profile)"
|
||||
|
@ -1,8 +0,0 @@
|
||||
/* Ensures style here overrides style of .btn */
|
||||
.subscribeButton.btn {
|
||||
align-self: center;
|
||||
block-size: 50%;
|
||||
margin-block-end: 10px;
|
||||
min-inline-size: 150px;
|
||||
white-space: initial;
|
||||
}
|
@ -25,29 +25,54 @@ export default defineComponent({
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
hideProfileDropdownToggle: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
subscriptionCountText: {
|
||||
default: '',
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
isProfileDropdownOpen: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
profileInitials: function () {
|
||||
return this.profileDisplayList.map((profile) => {
|
||||
return profile?.name?.length > 0 ? Array.from(profile.name)[0].toUpperCase() : ''
|
||||
})
|
||||
},
|
||||
|
||||
profileList: function () {
|
||||
return this.$store.getters.getProfileList
|
||||
},
|
||||
|
||||
/* sort by 'All Channels' -> active profile -> unsubscribed channels -> subscribed channels */
|
||||
profileDisplayList: function () {
|
||||
const mainProfileAndActiveProfile = [this.profileList[0]]
|
||||
if (this.activeProfile._id !== MAIN_PROFILE_ID) {
|
||||
mainProfileAndActiveProfile.push(this.activeProfile)
|
||||
}
|
||||
|
||||
return [
|
||||
...mainProfileAndActiveProfile,
|
||||
...this.profileList.filter((profile, i) =>
|
||||
i !== 0 && !this.isActiveProfile(profile) && !this.isProfileSubscribed(profile)),
|
||||
...this.profileList.filter((profile, i) =>
|
||||
i !== 0 && !this.isActiveProfile(profile) && this.isProfileSubscribed(profile))
|
||||
]
|
||||
},
|
||||
|
||||
activeProfile: function () {
|
||||
return this.$store.getters.getActiveProfile
|
||||
},
|
||||
|
||||
subscriptionInfo: function () {
|
||||
return this.activeProfile.subscriptions.find((channel) => {
|
||||
return channel.id === this.channelId
|
||||
}) ?? null
|
||||
},
|
||||
|
||||
isSubscribed: function () {
|
||||
return this.subscriptionInfo !== null
|
||||
return this.subscriptionInfoForProfile(this.activeProfile)
|
||||
},
|
||||
|
||||
hideChannelSubscriptions: function () {
|
||||
@ -55,23 +80,27 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
subscribedText: function () {
|
||||
let subscribedValue = (this.isSubscribed ? this.$t('Channel.Unsubscribe') : this.$t('Channel.Subscribe')).toUpperCase()
|
||||
let subscribedValue = (this.isProfileSubscribed(this.activeProfile) ? this.$t('Channel.Unsubscribe') : this.$t('Channel.Subscribe')).toUpperCase()
|
||||
if (this.subscriptionCountText !== '' && !this.hideChannelSubscriptions) {
|
||||
subscribedValue += ' ' + this.subscriptionCountText
|
||||
}
|
||||
return subscribedValue
|
||||
},
|
||||
|
||||
isProfileDropdownEnabled: function () {
|
||||
return !this.hideProfileDropdownToggle && this.profileList.length > 1
|
||||
}
|
||||
|
||||
},
|
||||
methods: {
|
||||
handleSubscription: function () {
|
||||
handleSubscription: function (profile = this.activeProfile) {
|
||||
if (this.channelId === '') {
|
||||
return
|
||||
}
|
||||
|
||||
const currentProfile = deepCopy(this.activeProfile)
|
||||
const currentProfile = deepCopy(profile)
|
||||
|
||||
if (this.isSubscribed) {
|
||||
if (this.isProfileSubscribed(profile)) {
|
||||
currentProfile.subscriptions = currentProfile.subscriptions.filter((channel) => {
|
||||
return channel.id !== this.channelId
|
||||
})
|
||||
@ -79,16 +108,16 @@ export default defineComponent({
|
||||
this.updateProfile(currentProfile)
|
||||
showToast(this.$t('Channel.Channel has been removed from your subscriptions'))
|
||||
|
||||
if (this.activeProfile._id === MAIN_PROFILE_ID) {
|
||||
if (profile._id === MAIN_PROFILE_ID) {
|
||||
// Check if a subscription exists in a different profile.
|
||||
// Remove from there as well.
|
||||
let duplicateSubscriptions = 0
|
||||
|
||||
this.profileList.forEach((profile) => {
|
||||
if (profile._id === MAIN_PROFILE_ID) {
|
||||
this.profileList.forEach((profileInList) => {
|
||||
if (profileInList._id === MAIN_PROFILE_ID) {
|
||||
return
|
||||
}
|
||||
duplicateSubscriptions += this.unsubscribe(profile, this.channelId)
|
||||
duplicateSubscriptions += this.unsubscribe(profileInList, this.channelId)
|
||||
})
|
||||
|
||||
if (duplicateSubscriptions > 0) {
|
||||
@ -107,7 +136,7 @@ export default defineComponent({
|
||||
this.updateProfile(currentProfile)
|
||||
showToast(this.$t('Channel.Added channel to your subscriptions'))
|
||||
|
||||
if (this.activeProfile._id !== MAIN_PROFILE_ID) {
|
||||
if (profile._id !== MAIN_PROFILE_ID) {
|
||||
const primaryProfile = deepCopy(this.profileList.find(prof => {
|
||||
return prof._id === MAIN_PROFILE_ID
|
||||
}))
|
||||
@ -122,6 +151,34 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isProfileDropdownEnabled && !this.isProfileDropdownOpen) {
|
||||
this.toggleProfileDropdown()
|
||||
}
|
||||
},
|
||||
|
||||
handleProfileDropdownFocusOut: function () {
|
||||
if (!this.$refs.subscribeButton.matches(':focus-within')) {
|
||||
this.isProfileDropdownOpen = false
|
||||
}
|
||||
},
|
||||
|
||||
toggleProfileDropdown: function() {
|
||||
this.isProfileDropdownOpen = !this.isProfileDropdownOpen
|
||||
},
|
||||
|
||||
isActiveProfile: function (profile) {
|
||||
return profile._id === this.activeProfile._id
|
||||
},
|
||||
|
||||
subscriptionInfoForProfile: function (profile) {
|
||||
return profile.subscriptions.find((channel) => {
|
||||
return channel.id === this.channelId
|
||||
}) ?? null
|
||||
},
|
||||
|
||||
isProfileSubscribed: function (profile) {
|
||||
return this.subscriptionInfoForProfile(profile) !== null
|
||||
},
|
||||
|
||||
unsubscribe: function(profile, channelId) {
|
||||
|
@ -0,0 +1,141 @@
|
||||
.buttonList {
|
||||
margin: 5px;
|
||||
margin-block-end: 10px;
|
||||
border-radius: 4px;
|
||||
block-size: fit-content;
|
||||
box-shadow: 0px 1px 2px rgb(0 0 0 / 50%);
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
/* addresses odd clipping behavior when adjusting window size */
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.ftSubscribeButton {
|
||||
position: relative;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
/* Ensures style here overrides style of .btn */
|
||||
.subscribeButton.btn {
|
||||
min-inline-size: 150px;
|
||||
white-space: initial;
|
||||
}
|
||||
|
||||
.subscribeButton.btn, .profileDropdownToggle.btn {
|
||||
align-self: center;
|
||||
margin-block: 0;
|
||||
margin-inline: 0;
|
||||
}
|
||||
|
||||
.dropdownOpened {
|
||||
.subscribeButton, .profileDropdownToggle {
|
||||
border-end-start-radius: 0;
|
||||
border-end-end-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.profileDropdownToggle.btn {
|
||||
border-inline-start: none !important;
|
||||
border-start-start-radius: 0;
|
||||
border-end-start-radius: 0;
|
||||
display: inline-block;
|
||||
min-inline-size: 1em;
|
||||
padding-inline: 10px;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.hasProfileDropdownToggle {
|
||||
.subscribeButton.btn {
|
||||
min-inline-size: 100px;
|
||||
padding-inline: 5px;
|
||||
border-inline-end: 2px solid var(--primary-color-active) !important;
|
||||
border-start-end-radius: 0;
|
||||
border-end-end-radius: 0;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
}
|
||||
|
||||
.hasProfileDropdownToggle > .subscribeButton.btn, .profileDropdownToggle.btn {
|
||||
padding-block: 5px;
|
||||
padding-inline: 6px;
|
||||
box-shadow: none;
|
||||
flex: auto;
|
||||
block-size: 2em;
|
||||
}
|
||||
|
||||
.profileDropdown {
|
||||
background-color: var(--side-nav-color);
|
||||
box-shadow: 0 1px 2px rgb(0 0 0 / 50%);
|
||||
color: var(--secondary-text-color);
|
||||
display: inline;
|
||||
font-size: 12px;
|
||||
max-block-size: 200px;
|
||||
margin-block: -10px 0;
|
||||
margin-inline: 5px 0;
|
||||
overflow-y: scroll;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
z-index: 3;
|
||||
// accounts for parent's left and right margins
|
||||
inline-size: calc(100% - 10px);
|
||||
|
||||
.profileList {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding-inline: 0;
|
||||
}
|
||||
|
||||
.profile {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
gap: 0.5em;
|
||||
padding-inline-start: 0.5em;
|
||||
block-size: 50px;
|
||||
align-items: center;
|
||||
transition: background 0.2s ease-out;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--side-nav-hover-color);
|
||||
color: var(--side-nav-hover-text-color);
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
.colorOption {
|
||||
inline-size: 40px;
|
||||
block-size: 40px;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
border-radius: 50%;
|
||||
-webkit-border-radius: 50%;
|
||||
}
|
||||
|
||||
.initial {
|
||||
font-size: 20px;
|
||||
line-height: 1em;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.profileName {
|
||||
padding-inline-end: 1em;
|
||||
text-align: start;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&.subscribed {
|
||||
background-color: var(--primary-color);
|
||||
|
||||
.profileName {
|
||||
color: var(--text-with-main-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,83 @@
|
||||
<template>
|
||||
<ft-button
|
||||
:label="subscribedText"
|
||||
class="subscribeButton"
|
||||
background-color="var(--primary-color)"
|
||||
text-color="var(--text-with-main-color)"
|
||||
@click="handleSubscription"
|
||||
/>
|
||||
<div
|
||||
ref="subscribeButton"
|
||||
class="ftSubscribeButton"
|
||||
:class="{ dropdownOpened: isProfileDropdownOpen}"
|
||||
@focusout="handleProfileDropdownFocusOut"
|
||||
>
|
||||
<div
|
||||
class="buttonList"
|
||||
:class="{ hasProfileDropdownToggle: isProfileDropdownEnabled}"
|
||||
>
|
||||
<ft-button
|
||||
:label="subscribedText"
|
||||
:no-border="true"
|
||||
class="subscribeButton"
|
||||
background-color="var(--primary-color)"
|
||||
text-color="var(--text-with-main-color)"
|
||||
@click="handleSubscription"
|
||||
/>
|
||||
<ft-button
|
||||
v-if="isProfileDropdownEnabled"
|
||||
:no-border="true"
|
||||
:title="isProfileDropdownOpen ? $t('Profile.Close Profile Dropdown') : $t('Profile.Open Profile Dropdown')"
|
||||
class="profileDropdownToggle"
|
||||
background-color="var(--primary-color)"
|
||||
text-color="var(--text-with-main-color)"
|
||||
:aria-expanded="isProfileDropdownOpen"
|
||||
@click="toggleProfileDropdown"
|
||||
>
|
||||
<font-awesome-icon
|
||||
:icon="isProfileDropdownOpen ? ['fas', 'angle-up'] : ['fas', 'angle-down']"
|
||||
/>
|
||||
</ft-button>
|
||||
</div>
|
||||
<template v-if="isProfileDropdownOpen">
|
||||
<div
|
||||
tabindex="-1"
|
||||
class="profileDropdown"
|
||||
>
|
||||
<ul
|
||||
class="profileList"
|
||||
>
|
||||
<li
|
||||
v-for="(profile, index) in profileDisplayList"
|
||||
:id="'subscription-profile-' + index"
|
||||
:key="index"
|
||||
class="profile"
|
||||
:class="{
|
||||
subscribed: isProfileSubscribed(profile)
|
||||
}"
|
||||
:aria-labelledby="'subscription-profile-' + index + '-name'"
|
||||
:aria-selected="isActiveProfile(profile)"
|
||||
:aria-checked="isProfileSubscribed(profile)"
|
||||
tabindex="0"
|
||||
role="checkbox"
|
||||
@click.stop.prevent="handleSubscription(profile)"
|
||||
@keydown.space.stop.prevent="handleSubscription(profile)"
|
||||
>
|
||||
<div
|
||||
class="colorOption"
|
||||
:style="{ background: profile.bgColor, color: profile.textColor }"
|
||||
>
|
||||
<div
|
||||
class="initial"
|
||||
>
|
||||
{{ isProfileSubscribed(profile) ? '✓' : profileInitials[index] }}
|
||||
</div>
|
||||
</div>
|
||||
<p
|
||||
:id="'subscription-profile-' + index + '-name'"
|
||||
class="profileName"
|
||||
>
|
||||
{{ profile.name }}
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./ft-subscribe-button.js" />
|
||||
<style src="./ft-subscribe-button.css" />
|
||||
<style lang="scss" src="./ft-subscribe-button.scss" />
|
||||
|
@ -14,16 +14,12 @@
|
||||
.navOption:hover {
|
||||
background-color: var(--side-nav-hover-color);
|
||||
color: var(--side-nav-hover-text-color);
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
.navOption:active {
|
||||
background-color: var(--side-nav-active-color);
|
||||
color: var(--side-nav-active-text-color);
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
|
@ -53,16 +53,12 @@
|
||||
.navOption:hover, .navChannel:hover {
|
||||
background-color: var(--side-nav-hover-color);
|
||||
color: var(--side-nav-hover-text-color);
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
.navOption:active, .navChannel:active {
|
||||
background-color: var(--side-nav-active-color);
|
||||
color: var(--side-nav-active-text-color);
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
// to avoid code conflict and duplicate entries
|
||||
import {
|
||||
faAngleDown,
|
||||
faAngleUp,
|
||||
faArrowDown,
|
||||
faArrowLeft,
|
||||
faArrowRight,
|
||||
@ -81,6 +82,7 @@ Vue.config.productionTip = process.env.NODE_ENV === 'development'
|
||||
library.add(
|
||||
// solid icons
|
||||
faAngleDown,
|
||||
faAngleUp,
|
||||
faArrowDown,
|
||||
faArrowLeft,
|
||||
faArrowRight,
|
||||
|
@ -69,6 +69,7 @@
|
||||
display: flex;
|
||||
gap: 30px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.subscribeButton {
|
||||
|
@ -26,7 +26,7 @@
|
||||
<ft-flex-box class="channels">
|
||||
<div
|
||||
v-for="channel in channelList"
|
||||
:key="channel.key"
|
||||
:key="channel.id"
|
||||
class="channel"
|
||||
>
|
||||
<router-link
|
||||
@ -53,7 +53,6 @@
|
||||
class="unsubscribeContainer"
|
||||
>
|
||||
<ft-subscribe-button
|
||||
class="btn"
|
||||
:channel-id="channel.id"
|
||||
:channel-name="channel.name"
|
||||
:channel-thumbnail="channel.thumbnail"
|
||||
|
@ -551,6 +551,8 @@ Profile:
|
||||
Are you sure you want to delete the selected channels? This will not delete the channel from any other profile.: Are
|
||||
you sure you want to delete the selected channels? This will not delete the channel
|
||||
from any other profile.
|
||||
Close Profile Dropdown: Close Profile Dropdown
|
||||
Open Profile Dropdown: Open Profile Dropdown
|
||||
#On Channel Page
|
||||
Channel:
|
||||
Subscribe: Subscribe
|
||||
|
Loading…
Reference in New Issue
Block a user