UI update

added browse by category
This commit is contained in:
sairaj mote 2021-06-24 16:57:43 +05:30
parent b28d1e27ba
commit 5c8fc0570c
5 changed files with 191 additions and 75 deletions

View File

@ -1601,9 +1601,7 @@ stripSelect.innerHTML = `
box-sizing: border-box;
}
:host{
--background-color: inherit;
--active-option-color: inherit;
--active-option-backgroud-color: rgba(var(--text-color), .2);
--gap: 0.5rem;
}
.hide{
display: none !important;
@ -1618,32 +1616,24 @@ stripSelect.innerHTML = `
padding: 1rem 0;
}
.strip-select{
display: flex;
display: grid;
grid-auto-flow: column;
gap: var(--gap);
position: relative;
max-width: 100%;
align-items: center;
overflow: auto hidden;
}
.strip-option{
display: flex;
flex-strink: 0;
cursor: pointer;
white-space: nowrap;
border-radius: 2rem;
padding: 0.5rem 0.8rem;
}
.strip-option[active]{
color: var(--active-option-color);
background-color: var(--active-option-backgroud-color);
}
.nav-button{
position: absolute;
display: flex;
top: 50%;
z-index: 2;
border: none;
top: 50%;
padding: 0.3rem;
cursor: pointer;
background: none;
position: absolute;
align-items: center;
background: var(--background-color);
transform: translateY(-50%);
}
.nav-button--right{
@ -1657,11 +1647,11 @@ stripSelect.innerHTML = `
pointer-events: none;
}
.cover--left{
background: linear-gradient(90deg, var(--background-color) 60%, transparent);
background: linear-gradient(90deg, var(--background-color), transparent);
}
.cover--right{
right: 0;
background: linear-gradient(90deg, transparent 0%, var(--background-color) 40%);
background: linear-gradient(90deg, transparent, var(--background-color));
}
.nav-button--right::before{
background-color: red;
@ -1685,6 +1675,9 @@ stripSelect.innerHTML = `
.strip-select{
overflow: auto hidden;
}
.cover{
width: 2rem;
}
}
@media (hover: hover){
.strip-select{
@ -1716,18 +1709,11 @@ customElements.define('strip-select', class extends HTMLElement{
this.stripSelect = this.shadowRoot.querySelector('.strip-select')
this.slottedOptions
this._value
this.scrollDistance = 200
this.scrollDistance = 300
}
get value() {
return this._value
}
randString = (length) => {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < length; i++)
result += characters.charAt(Math.floor(Math.random() * characters.length));
return result;
}
fireEvent = () => {
this.dispatchEvent(
new CustomEvent("change", {
@ -1754,51 +1740,37 @@ customElements.define('strip-select', class extends HTMLElement{
}
connectedCallback() {
const slot = this.shadowRoot.querySelector('slot')
const groupName = this.randString(8)
const coverLeft = this.shadowRoot.querySelector('.cover--left')
const coverRight = this.shadowRoot.querySelector('.cover--right')
const navButtonLeft = this.shadowRoot.querySelector('.nav-button--left')
const navButtonRight = this.shadowRoot.querySelector('.nav-button--right')
slot.addEventListener('slotchange', e => {
slot.assignedElements().forEach(elem => {
const label = document.createElement('label')
const input = document.createElement('input')
label.className = 'strip-option'
label.tabIndex = 0
input.type = 'radio'
input.name = groupName
input.setAttribute('value', elem.getAttribute('value'))
label.append(input, elem)
this.stripSelect.append(label)
if (elem.hasAttribute('selected')) {
elem.setAttribute('active', '')
this._value = elem.value
}
})
slot.remove()
firstOptionObserver.observe(this.stripSelect.firstElementChild)
lastOptionObserver.observe(this.stripSelect.lastElementChild)
})
this.stripSelect.addEventListener('change', e => {
this._value = e.target.value
e.target.closest('label').scrollIntoView({behavior: "smooth", block: "start", inline: "center"})
Array.from(this.stripSelect.children).forEach(elem => elem.removeAttribute('active'))
e.target.closest('.strip-option').setAttribute('active', '')
this.fireEvent()
})
this.stripSelect.addEventListener('keyup', e => {
if (e.key === 'Enter' || e.key === 'Space') {
e.target.click()
if (slot.assignedElements().length) {
firstOptionObserver.observe(slot.assignedElements()[0])
lastOptionObserver.observe(slot.assignedElements()[slot.assignedElements().length - 1])
}
else {
navButtonLeft.classList.add('hide')
navButtonRight.classList.add('hide')
coverLeft.classList.add('hide')
coverRight.classList.add('hide')
}
})
const widthObserver = new ResizeObserver(entries => {
entries.forEach(entry => {
if(entry.contentBoxSize) {
const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize;
this.style.width = `${contentBoxSize.inlineSize}px`
} else {
this.style.width = `${contentRect.width}px`
}
})
this.stripSelect.addEventListener('change', e => {
if (this._value !== e.target.value) {
this._value = e.target.value
e.target.scrollIntoView({behavior: "smooth", block: "nearest", inline: "center"})
slot.assignedElements().forEach(elem => elem.removeAttribute('active'))
e.target.setAttribute('active', '')
this.fireEvent()
}
})
widthObserver.observe(this.parentNode)
const firstOptionObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
@ -1834,6 +1806,82 @@ customElements.define('strip-select', class extends HTMLElement{
}
})
const stripOption = document.createElement('template')
stripOption.innerHTML = `
<style>
*{
padding: 0;
margin: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
:host{
--border-radius: 2rem;
--background-color: inherit;
--active-option-color: inherit;
--active-option-backgroud-color: rgba(var(--text-color), .2);
}
.hide{
display: none !important;
}
.strip-option{
display: flex;
flex-strink: 0;
cursor: pointer;
white-space: nowrap;
border-radius: var(--border-radius);
padding: 0.5rem 0.8rem;
-webkit-tap-highlight-color: transparent;
}
:host([active]) .strip-option{
color: var(--active-option-color);
background-color: var(--active-option-backgroud-color);
}
</style>
<label class="strip-option" tabindex="0">
<slot></slot>
</label>
`
//Strip option
customElements.define('strip-option', class extends HTMLElement{
constructor() {
super()
this.attachShadow({
mode: 'open'
}).append(stripOption.content.cloneNode(true))
this._value
this.radioButton = this.shadowRoot.querySelector('input')
}
get value() {
return this._value
}
fireEvent = () => {
this.dispatchEvent(
new CustomEvent("change", {
bubbles: true,
composed: true,
detail: {
value: this._value
}
})
)
}
connectedCallback() {
this._value = this.getAttribute('value')
this.addEventListener('click', e => {
this.fireEvent()
})
this.addEventListener('keyup', e => {
if (e.key === 'Enter' || e.key === 'Space') {
this.fireEvent()
}
})
}
})
//popup
const smPopup = document.createElement('template')
smPopup.innerHTML = `

View File

@ -606,6 +606,12 @@ sm-option {
font-size: 0.9rem;
}
#page_selector strip-option {
--border-radius: 0.3rem;
--active-option-color: white;
--active-option-backgroud-color: var(--accent-color);
}
#main_footer {
padding: 3rem 0;
background-color: rgba(var(--text-color), 0.06);

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -534,6 +534,14 @@ ul{
sm-option{
font-size: 0.9rem;
}
#page_selector{
strip-option{
--border-radius: 0.3rem;
--active-option-color: white;
--active-option-backgroud-color: var(--accent-color);
}
}
#main_footer{
padding: 3rem 0;
background-color: rgba(var(--text-color), 0.06);

View File

@ -108,13 +108,13 @@
</div>
</section>
<div id="result_for"></div>
<ul id="search_result" class="torrent-container observe-empty-state"></ul>
<ul id="search_result" class="torrent-container"></ul>
</section>
<section id="browse" class="hide-completely page page-layout">
<section class="flex direction-column">
<h1 class="page__title">Browse</h1>
<strip-select id="browse_category_selector">
<strip-option value="movie">Movie</strip-option>
<strip-option value="movie" selected>Movie</strip-option>
<strip-option value="tv series">TV series</strip-option>
<strip-option value="video">Video</strip-option>
<strip-option value="music">Music</strip-option>
@ -125,6 +125,8 @@
<strip-option value="misc">Misc</strip-option>
</strip-select>
</section>
<ul id="browser_category_torrents" class="torrent-container"></ul>
<strip-select id="page_selector"></strip-select>
</section>
</main>
@ -581,11 +583,13 @@
}
function create(tagName, obj) {
const { className, text, innerHTML } = obj
const { className, textContent, innerHTML } = obj
const elem = document.createElement(tagName)
elem.className = className
elem.textContent = text
elem.innerHTML = innerHTML
if(className)
elem.className = className
elem.textContent = textContent
if(innerHTML)
elem.innerHTML = innerHTML
return elem
}
@ -901,7 +905,7 @@
}
})
function getParts(){
function getSearchParams(){
const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries());
return params
@ -963,7 +967,7 @@
}
function showPage(target){
let params = getParts()
let params = getSearchParams()
let page = target.includes('#') ? target.split('#')[1] : target
switch(page){
case 'search':
@ -978,7 +982,8 @@
}
break
case 'browse':
const category = getRef('browse_category_selector').value
showCategoryTorrents(category)
break
default:
page = 'homepage'
@ -1000,12 +1005,61 @@
}
else{
advancedSearch.isActive = false
advancedSearch.category = ''
getRef('advance_search_panel').classList.add('hide-completely')
}
advancedSearch['query'] = getRef('advance_torrent_search').value.trim()
})
getRef('category_selector').addEventListener('change', e => {
advancedSearch.category = e.detail.value
advancedSearch.category = e.detail.value
})
getRef('browse_category_selector').addEventListener('change', e => {
showCategoryTorrents(e.detail.value)
})
async function showCategoryTorrents(category){
const torrents = await getDataFromIDB()
const options = {
keys: ['type'],
threshold: 0.2,
}
const fuseSearch = new Fuse(torrents, options)
const result = fuseSearch.search(category).map(elem => elem.item)
getRef('browser_category_torrents').innerHTML = ``
getRef('browser_category_torrents').append(renderTorrents(result.slice(0, 20)))
const paginationFrag = document.createDocumentFragment()
const pages = Math.round(result.length / 20)
for(let i = 0; i < pages; i++){
const pageButton = create('strip-option', {
textContent : (i + 1)
})
pageButton.setAttribute('value', i)
if(i === 0){
pageButton.setAttribute('selected', '')
}
paginationFrag.append(pageButton)
}
getRef('page_selector').innerHTML = ''
getRef('page_selector').append(paginationFrag)
}
getRef('page_selector').addEventListener('change', async e => {
const torrents = await getDataFromIDB()
const options = {
keys: ['type'],
threshold: 0.2,
}
const fuseSearch = new Fuse(torrents, options)
const category = getRef('browse_category_selector').value
const result = fuseSearch.search(category).map(elem => elem.item)
const startIndex = parseInt(e.detail.value) * 20
const endIndex = (parseInt(e.detail.value) * 20) + 20
getRef('browser_category_torrents').innerHTML = ``
getRef('browser_category_torrents').append(renderTorrents(result.slice(startIndex, endIndex)))
getRef('browser_category_torrents').scrollIntoView({behavior: 'smooth', block: 'start'})
})
</script>
</body>