diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 1db3b6de..3e3b502c 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -7,6 +7,13 @@
"type": "npm",
"script": "dev",
"problemMatcher": []
+ },
+ {
+ "type": "npm",
+ "script": "dev-runner",
+ "problemMatcher": [],
+ "label": "npm: dev-runner",
+ "detail": "node _scripts/dev-runner.js"
}
]
}
\ No newline at end of file
diff --git a/src/renderer/components/ft-auto-grid/ft-auto-grid.js b/src/renderer/components/ft-auto-grid/ft-auto-grid.js
new file mode 100644
index 00000000..2befee45
--- /dev/null
+++ b/src/renderer/components/ft-auto-grid/ft-auto-grid.js
@@ -0,0 +1,11 @@
+import Vue from 'vue'
+
+export default Vue.extend({
+ name: 'FtAutoGrid',
+ props: {
+ grid: {
+ type: Boolean,
+ required: true
+ }
+ }
+})
diff --git a/src/renderer/components/ft-auto-grid/ft-auto-grid.sass b/src/renderer/components/ft-auto-grid/ft-auto-grid.sass
new file mode 100644
index 00000000..eb71df3e
--- /dev/null
+++ b/src/renderer/components/ft-auto-grid/ft-auto-grid.sass
@@ -0,0 +1,10 @@
+.ft-auto-grid
+ &.grid
+ display: grid
+ grid-template-columns: repeat(auto-fill, 240px)
+ justify-content: space-evenly
+ grid-gap: 5px
+
+ &.list
+ display: grid
+ grid-gap: 16px
diff --git a/src/renderer/components/ft-auto-grid/ft-auto-grid.vue b/src/renderer/components/ft-auto-grid/ft-auto-grid.vue
new file mode 100644
index 00000000..14e20186
--- /dev/null
+++ b/src/renderer/components/ft-auto-grid/ft-auto-grid.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
diff --git a/src/renderer/components/ft-element-list/ft-element-list.js b/src/renderer/components/ft-element-list/ft-element-list.js
index a410bd37..c9cab911 100644
--- a/src/renderer/components/ft-element-list/ft-element-list.js
+++ b/src/renderer/components/ft-element-list/ft-element-list.js
@@ -1,6 +1,6 @@
import Vue from 'vue'
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
-import FtGrid from '../ft-grid/ft-grid.vue'
+import FtAutoGrid from '../ft-auto-grid/ft-auto-grid.vue'
import FtListVideo from '../ft-list-video/ft-list-video.vue'
import FtListChannel from '../ft-list-channel/ft-list-channel.vue'
import FtListPlaylist from '../ft-list-playlist/ft-list-playlist.vue'
@@ -9,7 +9,7 @@ export default Vue.extend({
name: 'FtElementList',
components: {
'ft-flex-box': FtFlexBox,
- 'ft-grid': FtGrid,
+ 'ft-auto-grid': FtAutoGrid,
'ft-list-video': FtListVideo,
'ft-list-channel': FtListChannel,
'ft-list-playlist': FtListPlaylist
diff --git a/src/renderer/components/ft-element-list/ft-element-list.vue b/src/renderer/components/ft-element-list/ft-element-list.vue
index baef15af..465fa0fd 100644
--- a/src/renderer/components/ft-element-list/ft-element-list.vue
+++ b/src/renderer/components/ft-element-list/ft-element-list.vue
@@ -1,49 +1,29 @@
-
-
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+ />
+
+
+
diff --git a/src/renderer/components/ft-icon-button/ft-icon-button.js b/src/renderer/components/ft-icon-button/ft-icon-button.js
index 7449fbfd..c2d6b09c 100644
--- a/src/renderer/components/ft-icon-button/ft-icon-button.js
+++ b/src/renderer/components/ft-icon-button/ft-icon-button.js
@@ -19,6 +19,14 @@ export default Vue.extend({
type: Boolean,
default: true
},
+ padding: {
+ type: Number,
+ default: 10
+ },
+ size: {
+ type: Number,
+ default: 20
+ },
forceDropdown: {
type: Boolean,
default: false
diff --git a/src/renderer/components/ft-icon-button/ft-icon-button.sass b/src/renderer/components/ft-icon-button/ft-icon-button.sass
index 338e9228..0deca696 100644
--- a/src/renderer/components/ft-icon-button/ft-icon-button.sass
+++ b/src/renderer/components/ft-icon-button/ft-icon-button.sass
@@ -3,12 +3,11 @@
flex-flow: row wrap
justify-content: space-evenly
position: relative
+ user-select: none
.iconButton
width: 1em
height: 1em
- padding: 10px
- font-size: 20px
border-radius: 50%
cursor: pointer
transition: background 0.15s ease-out
diff --git a/src/renderer/components/ft-icon-button/ft-icon-button.vue b/src/renderer/components/ft-icon-button/ft-icon-button.vue
index 4b613fff..bafa0c6e 100644
--- a/src/renderer/components/ft-icon-button/ft-icon-button.vue
+++ b/src/renderer/components/ft-icon-button/ft-icon-button.vue
@@ -10,6 +10,10 @@
secondary: theme === 'secondary',
shadow: useShadow
}"
+ :style="{
+ padding: padding + 'px',
+ fontSize: size + 'px'
+ }"
@click="handleIconClick"
/>
-
+
-
- {{ videoCount }}
-
-
-
+
+
+
+
+
+
+ {{ title }}
+
+
+
+ {{ channelName }}
+
-
- {{ title }}
-
-
- {{ channelName }}
-
-
+
diff --git a/src/renderer/components/ft-list-video/ft-list-video.css b/src/renderer/components/ft-list-video/ft-list-video.css
deleted file mode 100644
index 7d8f22d8..00000000
--- a/src/renderer/components/ft-list-video/ft-list-video.css
+++ /dev/null
@@ -1,247 +0,0 @@
-.videoThumbnail {
- position: relative;
- cursor: pointer;
-}
-
-.videoThumbnail:hover .videoWatched {
- visibility: hidden;
-}
-
-.favoritesIcon {
- position: absolute;
- font-size: 15px;
- top: 0px;
- right: 0px;
- color: #FFFFFF;
- padding: 5px;
- background-color: #000000;
- opacity: 0.7;
- cursor: pointer;
-}
-
-.favorited {
- color: yellow;
-}
-
-.videoDuration {
- position: absolute;
- font-size: 13px;
- bottom: -7px;
- right: 0px;
- color: #FFFFFF;
- padding: 2px;
- background-color: #000000;
- opacity: 0.7;
- cursor: pointer;
-}
-
-.videoWatched {
- position: absolute;
- top: 0px;
- left: 0px;
- width: 100%;
- background-color: rgba(0,0,0,0.4);
- color: #FFFFFF;
- pointer-events: none;
-}
-
-.watchedProgressBar {
- background-color: var(--red-500);
- opacity: 0.8;
- height: 3px;
- position: absolute;
- bottom: 0px;
- left: 0px;
- cursor: pointer;
-}
-
-.videoTitle {
- color: var(--title-color);
- font-weight: bold;
- cursor: pointer;
-}
-
-.channelName {
- color: var(--secondary-text-color);
- cursor: pointer;
- font-size: 14px;
-}
-
-.viewCount {
- cursor: pointer;
- font-size: 13px;
-}
-
-.uploadedTime {
- cursor: pointer;
- font-size: 13px;
-}
-
-.liveText {
- color: var(--red-500);
- font-size: 13px;
- cursor: pointer;
-}
-
-/deep/ .iconButton {
- font-size: 15px;
- padding: 8px;
-}
-
-/deep/ .iconDropdown {
- margin-top: 30px;
-}
-
-.grid {
- width: 240px;
- height: 250px;
- padding: 2px;
- overflow: hidden;
-}
-
-.grid .videoThumbnail {
- width: 100%;
- height: 130px;
- margin-bottom: -5px;
-}
-
-.grid .videoThumbnail img {
- width: 100%;
- height: 130px;
-}
-
-.grid .videoWatched {
- height: 110px;
-}
-
-.grid .optionsButton {
- margin-top: 10px;
- margin-left: 210px;
- position: absolute;
-}
-
-.grid .videoTitle {
- max-height: 55px;
- width: 210px;
- overflow-y: hidden;
- margin-bottom: -15px;
-}
-
-.grid .channelName {
- width: 220px;
- height: 17px;
- margin-bottom: 10px;
- overflow-y: hidden;
-}
-
-.grid .liveText {
- float: right;
-}
-
-.list {
- height: 140px;
- width: 100%;
- margin-left: 5px;
- margin-top: 15px;
-}
-
-.list .videoThumbnail {
- float: left;
- width: 240px;
- height: 130px;
-}
-
-.list .videoThumbnail img {
- width: 100%;
- height: 130px;
-}
-
-.list .videoWatched {
- height: 130px;
-}
-
-.list .optionsButton {
- float: right;
-}
-
-.list .videoTitle {
- margin-left: 250px;
- margin-top: 5px;
- margin-bottom: -10px;
-}
-
-.list .channelName {
- margin-left: 250px;
- max-width: 275px;
-}
-
-.list .viewCount {
- margin-left: 10px;
-}
-
-.list .liveText {
- margin-left: 10px;
-}
-
-.list .description {
- margin-left: 250px;
- font-size: 13px;
- color: var(--secondary-text-color);
- height: 35px;
- overflow: hidden;
-}
-
-.videoRecommendation.list {
- height: 110px;
-}
-
-.videoRecommendation.list .videoThumbnail {
- width: 180px;
- height: 100px;
-}
-
-.videoRecommendation.list .videoThumbnail img {
- height: 100px;
-}
-
-.videoRecommendation.list .videoTitle {
- font-size: 12px;
- margin-left: 185px;
-}
-
-.videoRecommendation.list .channelName {
- margin-left: 185px;
-}
-
-.videoRecommendation.list .viewCount {
- margin-left: 5px;
-}
-
-.playlistItem .list {
- height: 60px;
- width: calc(100% - 30px);
-}
-
-.playlistItem .list .videoThumbnail {
- width: 100px;
- height: 60px;
-}
-
-.playlistItem .list .videoThumbnail img {
- height: 60px;
-}
-
-.playlistItem .list .videoTitle {
- font-size: 12px;
- margin-left: 105px;
- margin-right: 30px;
-}
-
-.playlistItem .list .channelName {
- margin-left: 105px;
- margin-right: 30px;
-}
-
-.playlistItem .list .viewCount {
- margin-left: 5px;
-}
diff --git a/src/renderer/components/ft-list-video/ft-list-video.js b/src/renderer/components/ft-list-video/ft-list-video.js
index fa63d7da..d20fba78 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.js
+++ b/src/renderer/components/ft-list-video/ft-list-video.js
@@ -1,10 +1,12 @@
import Vue from 'vue'
import FtIconButton from '../ft-icon-button/ft-icon-button.vue'
+import FtCard from "../ft-card/ft-card.vue"
export default Vue.extend({
name: 'FtListVideo',
components: {
- 'ft-icon-button': FtIconButton
+ 'ft-icon-button': FtIconButton,
+ 'ft-card': FtCard
},
props: {
data: {
@@ -18,6 +20,10 @@ export default Vue.extend({
forceListType: {
type: String,
default: null
+ },
+ appearance: {
+ type: String,
+ required: true
}
},
data: function () {
@@ -120,31 +126,6 @@ export default Vue.extend({
}
},
methods: {
- play: function () {
- const playlistInfo = {
- playlistId: this.playlistId
- }
- console.log('playlist info')
- console.log(playlistInfo)
-
- if (this.playlistId !== null) {
- console.log('Sending playlist info')
- this.$router.push(
- {
- path: `/watch/${this.id}`,
- query: playlistInfo
- }
- )
- } else {
- console.log('no playlist found')
- this.$router.push({ path: `/watch/${this.id}` })
- }
- },
-
- goToChannel: function () {
- this.$router.push({ path: `/channel/${this.channelId}` })
- },
-
toggleSave: function () {
console.log('TODO: ft-list-video method toggleSave')
},
diff --git a/src/renderer/components/ft-list-video/ft-list-video.sass b/src/renderer/components/ft-list-video/ft-list-video.sass
new file mode 100644
index 00000000..cdebfe2e
--- /dev/null
+++ b/src/renderer/components/ft-list-video/ft-list-video.sass
@@ -0,0 +1 @@
+@use "../../sass-partials/_ft-list-item"
diff --git a/src/renderer/components/ft-list-video/ft-list-video.vue b/src/renderer/components/ft-list-video/ft-list-video.vue
index 1018a95b..028da9b1 100644
--- a/src/renderer/components/ft-list-video/ft-list-video.vue
+++ b/src/renderer/components/ft-list-video/ft-list-video.vue
@@ -3,25 +3,37 @@
class="ft-list-video"
:class="{
list: (listType === 'list' || forceListType === 'list') && forceListType !== 'grid',
- grid: (listType === 'grid' || forceListType === 'list') && forceListType !== 'list'
+ grid: (listType === 'grid' || forceListType === 'list') && forceListType !== 'list',
+ [appearance]: true
}"
>
-
-
+
-
+
+
- {{ duration }}
-
-
+
@@ -29,7 +41,7 @@
v-if="watched"
class="videoWatched"
>
- WATCHED
+ Watched
-
-
- {{ title }}
-
-
- {{ channelName }}
-
-
- {{ viewCount }} views
-
-
- - {{ uploadedTime }}
-
-
- {{ viewCount }} watching
-
-
- {{ description }}
-
-
- LIVE NOW
-
+
+
+
+ {{ title }}
+
+
+ {{ channelName }}
+ • {{ viewCount }} views
+ • {{ uploadedTime }}
+ • {{ viewCount }} watching
+
+
+ {{ description }}
+
+
-
+
diff --git a/src/renderer/components/watch-playlist/watch-playlist.vue b/src/renderer/components/watch-playlist/watch-playlist.vue
index 09cddb3b..052ada01 100644
--- a/src/renderer/components/watch-playlist/watch-playlist.vue
+++ b/src/renderer/components/watch-playlist/watch-playlist.vue
@@ -14,6 +14,7 @@
/>
-
-
- {{ index + 1 }}
-
+
+
+
+ {{ index + 1 }}
+
+
diff --git a/src/renderer/components/watch-video-recommendations/watch-video-recommendations.css b/src/renderer/components/watch-video-recommendations/watch-video-recommendations.css
index e83928a1..44c3783c 100644
--- a/src/renderer/components/watch-video-recommendations/watch-video-recommendations.css
+++ b/src/renderer/components/watch-video-recommendations/watch-video-recommendations.css
@@ -1,7 +1,4 @@
-.relative {
- position: relative;
-}
-
-.videoRecommendation {
- margin-bottom: -15px;
+.watchVideoRecommendations {
+ display: grid;
+ grid-gap: 8px;
}
diff --git a/src/renderer/components/watch-video-recommendations/watch-video-recommendations.vue b/src/renderer/components/watch-video-recommendations/watch-video-recommendations.vue
index 72a12b8a..bdec1920 100644
--- a/src/renderer/components/watch-video-recommendations/watch-video-recommendations.vue
+++ b/src/renderer/components/watch-video-recommendations/watch-video-recommendations.vue
@@ -1,5 +1,5 @@
-
+
Up Next
@@ -7,8 +7,8 @@
v-for="(video, index) in data"
:key="index"
:data="video"
+ appearance="recommendation"
force-list-type="list"
- class="videoRecommendation"
/>
diff --git a/src/renderer/sass-partials/_ft-list-item.sass b/src/renderer/sass-partials/_ft-list-item.sass
new file mode 100644
index 00000000..0ba02441
--- /dev/null
+++ b/src/renderer/sass-partials/_ft-list-item.sass
@@ -0,0 +1,151 @@
+$thumbnail-overlay-opacity: 0.85
+
+@mixin is-result
+ @at-root
+ .result#{&}
+ @content
+
+@mixin is-watch-playlist-item
+ @at-root
+ .watchPlaylistItem#{&}
+ @content
+
+@mixin is-recommendation
+ @at-root
+ .recommendation#{&}
+ @content
+
+@mixin is-sidebar-item
+ @at-root
+ .watchPlaylistItem#{&}, .recommendation#{&}
+ @content
+
+.ft-list-video
+ .videoThumbnail
+ display: flex
+ position: relative
+
+ .thumbnailLink
+ display: flex
+
+ .thumbnailImage
+ height: 130px
+
+ @include is-sidebar-item
+ height: 75px
+
+ @include is-recommendation
+ width: 163px
+ height: auto
+
+ .videoDuration
+ position: absolute
+ bottom: 4px
+ right: 4px
+ padding: 3px 4px
+ line-height: 1.2
+ font-size: 15px
+ border-radius: 5px
+ margin: 0
+ opacity: $thumbnail-overlay-opacity
+ color: var(--primary-text-color)
+ background-color: var(--card-bg-color)
+
+ &.live
+ background-color: #f22
+ color: #fff
+
+ .favoritesIcon
+ position: absolute
+ top: 3px
+ right: 3px
+ font-size: 17px
+ opacity: $thumbnail-overlay-opacity
+
+ .videoCountContainer
+ position: absolute
+ right: 0
+ top: 0
+ bottom: 0
+ width: 60px
+ font-size: 20px
+
+ .background, .inner
+ position: absolute
+ top: 0
+ bottom: 0
+ left: 0
+ right: 0
+
+ .background
+ background-color: var(--bg-color)
+ opacity: 0.9
+
+ .inner
+ display: flex
+ flex-direction: column
+ justify-content: center
+ align-items: center
+ color: var(--primary-text-color)
+
+ .videoInfo
+ flex: 1
+ position: relative
+
+ .optionsButton
+ float: right // ohhhh man, float was finally the right choice for something
+
+ .title
+ font-size: 20px
+ color: var(--primary-text-color)
+ text-decoration: none
+
+ @include is-sidebar-item
+ font-size: 15px
+
+ .infoLine
+ margin-top: 5px
+ font-size: 14px
+
+ @include is-sidebar-item
+ font-size: 12px
+
+ &, .channelName
+ color: var(--secondary-text-color)
+
+ .description
+ font-size: 14px
+ color: var(--secondary-text-color)
+
+ &.list
+ display: flex
+ align-items: flex-start
+
+ .videoThumbnail
+ margin-right: 20px
+
+ @include is-sidebar-item
+ margin-right: 10px
+
+ &.grid
+ display: flex
+ flex-direction: column
+ min-height: 230px
+ padding-bottom: 20px
+
+ .videoThumbnail
+ margin-bottom: 12px
+
+ .thumbnailImage
+ width: 100%
+
+ .title
+ font-size: 18px
+
+ .infoLine
+ margin-top: 8px
+ font-size: 13px
+
+
+.videoWatched, .live
+ text-transform: uppercase
diff --git a/src/renderer/views/Playlist/Playlist.css b/src/renderer/views/Playlist/Playlist.css
index 2f19d247..66087cb7 100644
--- a/src/renderer/views/Playlist/Playlist.css
+++ b/src/renderer/views/Playlist/Playlist.css
@@ -12,4 +12,7 @@
.playlistItems {
float: right;
width: 60%;
+ padding: 10px;
+ display: grid;
+ grid-gap: 10px;
}
diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue
index 4974145c..b4c12fa1 100644
--- a/src/renderer/views/Playlist/Playlist.vue
+++ b/src/renderer/views/Playlist/Playlist.vue
@@ -13,16 +13,14 @@
v-if="!isLoading"
class="playlistItems"
>
-
-
-
+
diff --git a/src/renderer/views/Watch/Watch.sass b/src/renderer/views/Watch/Watch.sass
index 1372bbb7..e07dbf3e 100644
--- a/src/renderer/views/Watch/Watch.sass
+++ b/src/renderer/views/Watch/Watch.sass
@@ -50,8 +50,10 @@
min-width: 380px
.watchVideoPlaylist, .watchVideoSidebar, .theatrePlaylist
- height: 500px
margin: 0 8px 16px
+ .watchVideoSidebar, .theatrePlaylist
+ height: 500px
+
.watchVideoRecommendations, .theatreRecommendations
margin: 0 8px 16px