From af5ccc22c2054afb913eb5662a5cdf90b6664102 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 1 Sep 2024 20:26:49 +0300 Subject: [PATCH 1/9] recommendations --- .../recommended-tab-ui/recommended-tab-ui.css | 15 ++ .../recommended-tab-ui/recommended-tab-ui.js | 131 ++++++++++++++ .../recommended-tab-ui/recommended-tab-ui.vue | 72 ++++++++ .../recommended-videos/recommended-videos.js | 164 ++++++++++++++++++ .../recommended-videos/recommended-videos.vue | 12 ++ src/renderer/components/side-nav/side-nav.vue | 23 +++ src/renderer/components/top-nav/top-nav.js | 6 + src/renderer/router/index.js | 9 + .../views/Recommended/Recommended.css | 41 +++++ src/renderer/views/Recommended/Recommended.js | 118 +++++++++++++ .../views/Recommended/Recommended.vue | 42 +++++ 11 files changed, 633 insertions(+) create mode 100644 src/renderer/components/recommended-tab-ui/recommended-tab-ui.css create mode 100644 src/renderer/components/recommended-tab-ui/recommended-tab-ui.js create mode 100644 src/renderer/components/recommended-tab-ui/recommended-tab-ui.vue create mode 100644 src/renderer/components/recommended-videos/recommended-videos.js create mode 100644 src/renderer/components/recommended-videos/recommended-videos.vue create mode 100644 src/renderer/views/Recommended/Recommended.css create mode 100644 src/renderer/views/Recommended/Recommended.js create mode 100644 src/renderer/views/Recommended/Recommended.vue diff --git a/src/renderer/components/recommended-tab-ui/recommended-tab-ui.css b/src/renderer/components/recommended-tab-ui/recommended-tab-ui.css new file mode 100644 index 000000000000..a902565bb94b --- /dev/null +++ b/src/renderer/components/recommended-tab-ui/recommended-tab-ui.css @@ -0,0 +1,15 @@ +.card { + inline-size: 85%; + margin-block: 0 60px; + margin-inline: auto; +} + +.message { + color: var(--tertiary-text-color); +} + +@media only screen and (width <= 680px) { + .card { + inline-size: 90%; + } +} diff --git a/src/renderer/components/recommended-tab-ui/recommended-tab-ui.js b/src/renderer/components/recommended-tab-ui/recommended-tab-ui.js new file mode 100644 index 000000000000..55f4bc29fb5d --- /dev/null +++ b/src/renderer/components/recommended-tab-ui/recommended-tab-ui.js @@ -0,0 +1,131 @@ +import { defineComponent } from 'vue' + +import FtLoader from '../ft-loader/ft-loader.vue' +import FtButton from '../ft-button/ft-button.vue' +import FtRefreshWidget from '../ft-refresh-widget/ft-refresh-widget.vue' +import FtFlexBox from '../ft-flex-box/ft-flex-box.vue' +import FtElementList from '../FtElementList/FtElementList.vue' +import FtChannelBubble from '../ft-channel-bubble/ft-channel-bubble.vue' +import FtAutoLoadNextPageWrapper from '../ft-auto-load-next-page-wrapper/ft-auto-load-next-page-wrapper.vue' + +export default defineComponent({ + name: 'RecommededTabUI', + components: { + 'ft-loader': FtLoader, + 'ft-button': FtButton, + 'ft-refresh-widget': FtRefreshWidget, + 'ft-flex-box': FtFlexBox, + 'ft-element-list': FtElementList, + 'ft-channel-bubble': FtChannelBubble, + 'ft-auto-load-next-page-wrapper': FtAutoLoadNextPageWrapper, + }, + props: { + isLoading: { + type: Boolean, + default: false + }, + videoList: { + type: Array, + default: () => ([]) + }, + isCommunity: { + type: Boolean, + default: false + }, + errorChannels: { + type: Array, + default: () => ([]) + }, + attemptedFetch: { + type: Boolean, + default: false + }, + initialDataLimit: { + type: Number, + default: 100 + }, + lastRefreshTimestamp: { + type: String, + required: true + }, + title: { + type: String, + required: true + } + }, + emits: ['refresh'], + data: function () { + return { + dataLimit: 100, + } + }, + computed: { + activeVideoList: function () { + if (this.videoList.length < this.dataLimit) { + return this.videoList + } else { + return this.videoList.slice(0, this.dataLimit) + } + }, + + activeProfile: function () { + return this.$store.getters.getActiveProfile + }, + + recommendedList: function () { + return this.activeProfile.subscriptions + }, + + fetchSubscriptionsAutomatically: function() { + return this.$store.getters.getFetchSubscriptionsAutomatically + } + }, + created: function () { + const dataLimit = sessionStorage.getItem('subscriptionLimit') + + if (dataLimit !== null) { + this.dataLimit = dataLimit + } else { + this.dataLimit = this.initialDataLimit + } + }, + mounted: function () { + document.addEventListener('keydown', this.keyboardShortcutHandler) + }, + beforeDestroy: function () { + document.removeEventListener('keydown', this.keyboardShortcutHandler) + }, + methods: { + increaseLimit: function () { + this.dataLimit += this.initialDataLimit + sessionStorage.setItem('subscriptionLimit', this.dataLimit) + }, + + /** + * This function `keyboardShortcutHandler` should always be at the bottom of this file + * @param {KeyboardEvent} event the keyboard event + */ + keyboardShortcutHandler: function (event) { + if (event.ctrlKey || document.activeElement.classList.contains('ft-input')) { + return + } + // Avoid handling events due to user holding a key (not released) + // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat + if (event.repeat) { return } + + switch (event.key) { + case 'r': + case 'R': + case 'F5': + if (!this.isLoading && this.activeSubscriptionList.length > 0) { + this.$emit('refresh') + } + break + } + }, + + refresh: function() { + this.$emit('refresh') + } + } +}) diff --git a/src/renderer/components/recommended-tab-ui/recommended-tab-ui.vue b/src/renderer/components/recommended-tab-ui/recommended-tab-ui.vue new file mode 100644 index 000000000000..7120b59de439 --- /dev/null +++ b/src/renderer/components/recommended-tab-ui/recommended-tab-ui.vue @@ -0,0 +1,72 @@ + + +