mirror of
https://github.com/NoCrypt/migu.git
synced 2026-04-20 16:12:31 +00:00
feat: more responsive view anime page
fix: click listener behavior with touch feat: bottom nabar feat: hide android nav and status bars feat: gamepad controls logic
This commit is contained in:
parent
3b5acf019b
commit
80050fa6e1
12 changed files with 393 additions and 58 deletions
|
|
@ -36,6 +36,8 @@
|
|||
"@capacitor/cli": "^5.5.1",
|
||||
"@capacitor/core": "^5.5.1",
|
||||
"@capacitor/ios": "^5.5.1",
|
||||
"@capacitor/status-bar": "^5.0.6",
|
||||
"@mauricewegner/capacitor-navigation-bar": "^2.0.3",
|
||||
"@superfrogbe/cordova-plugin-chrome-apps-sockets-udp": "github:superfrogbe/cordova-plugin-chrome-apps-sockets-udp",
|
||||
"common": "workspace:*",
|
||||
"cordova-plugin-chrome-apps-common": "^1.0.7",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,23 @@
|
|||
import TorrentClient from 'common/modules/webtorrent.js'
|
||||
import { ipcRendererWebTorrent } from './ipc.js'
|
||||
import { StatusBar, Style } from '@capacitor/status-bar'
|
||||
import { NavigationBar } from '@mauricewegner/capacitor-navigation-bar'
|
||||
|
||||
StatusBar.hide()
|
||||
StatusBar.setStyle({ style: Style.Dark })
|
||||
StatusBar.setOverlaysWebView({ overlay: true })
|
||||
|
||||
NavigationBar.setColor({ color: '#17191c' })
|
||||
function hideAndroidNavBar () {
|
||||
NavigationBar.hide()
|
||||
// NavigationBar.setTransparency({ isTransparent: true })
|
||||
}
|
||||
|
||||
screen.orientation.addEventListener('change', () => {
|
||||
hideAndroidNavBar()
|
||||
})
|
||||
|
||||
hideAndroidNavBar()
|
||||
|
||||
globalThis.chrome.runtime = { lastError: false, id: 'something' }
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,12 @@
|
|||
import IspBlock from './views/IspBlock.svelte'
|
||||
import { Toaster } from 'svelte-sonner'
|
||||
import Logout from './components/Logout.svelte'
|
||||
import Navbar from './components/Navbar.svelte'
|
||||
|
||||
setContext('view', view)
|
||||
</script>
|
||||
|
||||
<div class='page-wrapper with-sidebar with-transitions bg-dark' data-sidebar-type='overlayed-all'>
|
||||
<div class='page-wrapper with-transitions bg-dark position-relative' data-sidebar-type='overlayed-all'>
|
||||
<IspBlock />
|
||||
<Menubar bind:page={$page} />
|
||||
<ViewAnime />
|
||||
|
|
@ -40,6 +41,7 @@
|
|||
<RSSView />
|
||||
<Router bind:page={$page} />
|
||||
</div>
|
||||
<Navbar bind:page={$page} />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
|
@ -50,8 +52,15 @@
|
|||
|
||||
.page-wrapper > .content-wrapper {
|
||||
margin-left: var(--sidebar-minimised) !important;
|
||||
position: unset !important;
|
||||
width: calc(100% - var(--sidebar-minimised)) !important;
|
||||
transition: none !important;
|
||||
}
|
||||
.page-wrapper {
|
||||
height: calc(100% - var(--navbar-height)) !important;
|
||||
}
|
||||
@media (min-width: 769px) {
|
||||
.page-wrapper {
|
||||
padding-left: env(safe-area-inset-left) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
export let page = 'home'
|
||||
</script>
|
||||
|
||||
<div class='wrapper h-full position-absolute overflow-hidden'>
|
||||
<div class='w-full h-full position-absolute overflow-hidden'>
|
||||
<Miniplayer active={page !== 'player'} class='bg-dark-light z-10 {page === 'player' ? 'h-full' : ''}' minwidth='35rem' maxwidth='60rem' width='300px' padding='2rem'>
|
||||
<MediaHandler miniplayer={page !== 'player'} bind:page />
|
||||
</Miniplayer>
|
||||
|
|
@ -26,12 +26,3 @@
|
|||
{:else if page === 'watchtogether'}
|
||||
<WatchTogether />
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.wrapper {
|
||||
width: calc(100% - var(--sidebar-minimised));
|
||||
}
|
||||
:global(:fullscreen) .wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
<div class='w-full z-101 navbar bg-transparent border-0 p-0 d-flex'>
|
||||
<div class='d-flex h-full draggable align-items-center text-center'>
|
||||
{#if window.version.platform !== 'darwin'}
|
||||
<img src='./logo.ico' class='position-absolute w-50 h-50 m-10 pointer' alt='ico' use:click={close} />
|
||||
<img src='./logo.ico' class='position-absolute w-50 h-50 m-10 pointer d-md-block d-none' alt='ico' use:click={close} />
|
||||
{/if}
|
||||
</div>
|
||||
<div class='h-full bg-dark flex-grow-1'>
|
||||
|
|
@ -56,4 +56,7 @@
|
|||
path {
|
||||
fill: currentColor;
|
||||
}
|
||||
.navbar {
|
||||
left: unset !important
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
199
common/components/Navbar.svelte
Normal file
199
common/components/Navbar.svelte
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
<script>
|
||||
import { getContext } from 'svelte'
|
||||
import { alID } from '@/modules/anilist.js'
|
||||
import { media } from '../views/Player/MediaHandler.svelte'
|
||||
import { platformMap } from '../views/Settings.svelte'
|
||||
import { toast } from 'svelte-sonner'
|
||||
import { click } from '@/modules/click.js'
|
||||
import { logout } from './Logout.svelte'
|
||||
import IPC from '@/modules/ipc.js'
|
||||
const view = getContext('view')
|
||||
export let page
|
||||
const links = [
|
||||
{
|
||||
click: () => {
|
||||
if (alID) {
|
||||
$logout = true
|
||||
} else {
|
||||
IPC.emit('open', 'https://anilist.co/api/v2/oauth/authorize?client_id=4254&response_type=token') // Change redirect_url to miru://auth
|
||||
if (platformMap[window.version.platform] === 'Linux') {
|
||||
toast('Support Notification', {
|
||||
description: "If your linux distribution doesn't support custom protocol handlers, you can simply paste the full URL into the app.",
|
||||
duration: 300000
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
icon: 'login',
|
||||
text: 'Login With AniList',
|
||||
css: 'ml-auto'
|
||||
},
|
||||
{
|
||||
click: () => {
|
||||
page = 'home'
|
||||
},
|
||||
page: 'home',
|
||||
icon: 'home',
|
||||
text: 'Home'
|
||||
},
|
||||
{
|
||||
click: () => {
|
||||
page = 'search'
|
||||
},
|
||||
page: 'search',
|
||||
icon: 'search',
|
||||
text: 'Search'
|
||||
},
|
||||
{
|
||||
click: () => {
|
||||
page = 'schedule'
|
||||
},
|
||||
page: 'schedule',
|
||||
icon: 'schedule',
|
||||
text: 'Schedule'
|
||||
},
|
||||
{
|
||||
click: () => {
|
||||
if ($media) $view = $media.media
|
||||
},
|
||||
icon: 'queue_music',
|
||||
text: 'Now Playing'
|
||||
},
|
||||
{
|
||||
click: () => {
|
||||
page = 'watchtogether'
|
||||
},
|
||||
page: 'watchtogether',
|
||||
icon: 'groups',
|
||||
text: 'Watch Together'
|
||||
},
|
||||
{
|
||||
click: () => {
|
||||
IPC.emit('open', 'https://github.com/sponsors/ThaUnknown/')
|
||||
},
|
||||
icon: 'favorite',
|
||||
text: 'Support This App',
|
||||
css: 'ml-auto donate'
|
||||
},
|
||||
{
|
||||
click: () => {
|
||||
page = 'settings'
|
||||
},
|
||||
page: 'settings',
|
||||
icon: 'settings',
|
||||
text: 'Settings'
|
||||
}
|
||||
]
|
||||
if (alID) {
|
||||
alID.then(result => {
|
||||
if (result?.data?.Viewer) {
|
||||
links[0].image = result.data.Viewer.avatar.medium
|
||||
links[0].text = 'Logout'
|
||||
}
|
||||
})
|
||||
}
|
||||
function close () {
|
||||
$view = null
|
||||
page = 'home'
|
||||
}
|
||||
</script>
|
||||
|
||||
<nav class='navbar navbar-fixed-bottom d-block d-md-none border-0 bg-dark'>
|
||||
<div class='navbar-menu h-full d-flex flex-row justify-content-center align-items-center m-0 pb-5' class:animate={page !== 'player'}>
|
||||
<img src='./logo.ico' class='w-50 h-50 m-10 pointer' alt='ico' use:click={close} />
|
||||
{#each links as { click: _click, icon, text, image, css, page: _page }, i (i)}
|
||||
<div
|
||||
class='navbar-link navbar-link-with-icon pointer overflow-hidden {css}'
|
||||
use:click={_click}>
|
||||
{#if image}
|
||||
<span class='material-symbols-outlined rounded' class:filled={page === _page}>
|
||||
<img src={image} class='h-30 rounded' alt='logo' />
|
||||
</span>
|
||||
{:else}
|
||||
<span class='material-symbols-outlined rounded' class:filled={page === _page}>{icon}</span>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
nav {
|
||||
height: var(--navbar-height);
|
||||
}
|
||||
@keyframes glow {
|
||||
from {
|
||||
text-shadow: 0 0 2rem #fa68b6;
|
||||
}
|
||||
to {
|
||||
text-shadow: 0 0 1rem #fa68b6;
|
||||
}
|
||||
}
|
||||
.animate .donate .material-symbols-outlined {
|
||||
animation: glow 1s ease-in-out infinite alternate;
|
||||
}
|
||||
.donate:hover .material-symbols-outlined {
|
||||
background: #fff;
|
||||
color: #fa68b6 !important;
|
||||
}
|
||||
.donate .material-symbols-outlined {
|
||||
font-variation-settings: 'FILL' 1;
|
||||
color: #fa68b6;
|
||||
text-shadow: 0 0 1rem #fa68b6;
|
||||
}
|
||||
/* .sidebar-menu {
|
||||
padding-top: 10rem;
|
||||
} */
|
||||
.text {
|
||||
opacity: 1;
|
||||
transition: opacity 0.8s cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.navbar-link > span {
|
||||
color: #fff;
|
||||
border-radius: 0.3rem;
|
||||
}
|
||||
|
||||
.material-symbols-outlined {
|
||||
color: #fff;
|
||||
transition: background .8s cubic-bezier(0.25, 0.8, 0.25, 1), color .8s cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
}
|
||||
|
||||
.navbar-link:hover > span {
|
||||
background: #fff;
|
||||
color: var(--dark-color);
|
||||
}
|
||||
|
||||
.navbar-link {
|
||||
font-size: 1.4rem;
|
||||
padding: 0.75rem;
|
||||
height: 5.5rem;
|
||||
}
|
||||
|
||||
.material-symbols-outlined {
|
||||
font-size: 2.2rem;
|
||||
min-width: 4rem;
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.navbar-link img {
|
||||
font-size: 2.2rem;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
margin: 0.5rem;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
img {
|
||||
margin-right: var(--sidebar-brand-image-margin-right);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -95,7 +95,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class='sidebar z-30' class:animated={$settings.expandingSidebar}>
|
||||
<div class='sidebar z-30 d-md-block' class:animated={$settings.expandingSidebar}>
|
||||
<div class='sidebar-overlay pointer-events-none h-full position-absolute' />
|
||||
<div class='sidebar-menu h-full d-flex flex-column justify-content-center align-items-center m-0 pb-5' class:animate={page !== 'player'}>
|
||||
{#each links as { click: _click, icon, text, image, css, page: _page }, i (i)}
|
||||
|
|
@ -200,7 +200,8 @@
|
|||
transition: width .8s cubic-bezier(0.25, 0.8, 0.25, 1), left .8s cubic-bezier(0.25, 0.8, 0.25, 1) !important;
|
||||
background: none !important;
|
||||
overflow-y: unset;
|
||||
overflow-x: visible
|
||||
overflow-x: visible;
|
||||
left: unset;
|
||||
}
|
||||
.sidebar.animated:hover {
|
||||
width: 22rem
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@
|
|||
--card-border-width: 0;
|
||||
--sidebar-border-width: 0;
|
||||
--input-border-width: 0;
|
||||
--sidebar-minimised: 7rem;
|
||||
--sidebar-width: 7rem;
|
||||
--sidebar-minimised: 0px;
|
||||
--sidebar-width: 0px;
|
||||
--navbar-height: 7rem;
|
||||
--dark-color-base-hue: 220deg !important;
|
||||
--dark-color-base-saturation: 10% !important;
|
||||
--dark-color-hsl: var(--dark-color-base-hue), var(--dark-color-base-saturation), 10% !important;
|
||||
|
|
@ -24,6 +25,14 @@
|
|||
color-scheme: dark;
|
||||
}
|
||||
|
||||
@media (min-width: 769px) {
|
||||
:root {
|
||||
--sidebar-minimised: 7rem;
|
||||
--sidebar-width: 7rem;
|
||||
--navbar-height: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
--dm-button-secondary-bg-color: #fff !important;
|
||||
--dm-button-secondary-bg-color-hover: #ddd !important;
|
||||
|
|
|
|||
|
|
@ -1,19 +1,30 @@
|
|||
let lastTapElement = null
|
||||
let lastHoverElement = null
|
||||
|
||||
const noop = _ => {}
|
||||
|
||||
document.addEventListener('pointerup', () => {
|
||||
lastTapElement?.(false)
|
||||
lastTapElement = null
|
||||
setTimeout(() => {
|
||||
lastTapElement?.(false)
|
||||
lastTapElement = null
|
||||
lastHoverElement?.(false)
|
||||
lastHoverElement = null
|
||||
})
|
||||
})
|
||||
|
||||
export function click (node, cb = noop) {
|
||||
node.tabIndex = 0
|
||||
node.role = 'button'
|
||||
node.addEventListener('pointerdown', e => {
|
||||
node.addEventListener('click', e => {
|
||||
e.stopPropagation()
|
||||
cb(e)
|
||||
})
|
||||
node.addEventListener('pointerup', e => {
|
||||
e.stopPropagation()
|
||||
})
|
||||
node.addEventListener('pointerleave', e => {
|
||||
e.stopPropagation()
|
||||
})
|
||||
node.addEventListener('keydown', e => { if (e.key === 'Enter') cb(e) })
|
||||
}
|
||||
|
||||
|
|
@ -22,11 +33,13 @@ export function hoverClick (node, [cb = noop, hoverUpdate = noop]) {
|
|||
node.tabIndex = 0
|
||||
node.role = 'button'
|
||||
node.addEventListener('pointerenter', e => {
|
||||
lastHoverElement?.(false)
|
||||
hoverUpdate(true)
|
||||
lastTapElement?.(false)
|
||||
lastHoverElement = hoverUpdate
|
||||
pointerType = e.pointerType
|
||||
})
|
||||
node.addEventListener('pointerdown', e => {
|
||||
node.addEventListener('click', e => {
|
||||
e.stopPropagation()
|
||||
if (pointerType === 'mouse') return cb(e)
|
||||
lastTapElement?.(false)
|
||||
if (lastTapElement === hoverUpdate) {
|
||||
|
|
@ -39,9 +52,67 @@ export function hoverClick (node, [cb = noop, hoverUpdate = noop]) {
|
|||
node.addEventListener('keydown', e => { if (e.key === 'Enter') cb(e) })
|
||||
node.addEventListener('pointerup', e => {
|
||||
e.stopPropagation()
|
||||
if (e.pointerType === 'mouse') hoverUpdate(false)
|
||||
if (e.pointerType === 'mouse') setTimeout(() => hoverUpdate(false))
|
||||
})
|
||||
node.addEventListener('pointerleave', e => {
|
||||
setTimeout(() => { lastTapElement = hoverUpdate })
|
||||
if (e.pointerType === 'mouse') hoverUpdate(false)
|
||||
})
|
||||
}
|
||||
|
||||
const Directions = { up: 1, right: 2, down: 3, left: 4 }
|
||||
|
||||
function getDirection (anchor, relative) {
|
||||
return Math.round((Math.atan2(relative.y - anchor.y, relative.x - anchor.x) * 180 / Math.PI + 180) / 90)
|
||||
}
|
||||
|
||||
function getDistance (anchor, relative) {
|
||||
return Math.hypot(relative.x - anchor.x, relative.y - anchor.y)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets keyboard-focusable elements within a specified element
|
||||
* @param {Element} [element=document.body] element
|
||||
* @returns {Element[]}
|
||||
*/
|
||||
function getKeyboardFocusableElements (element = document.body) {
|
||||
return [...element.querySelectorAll('a[href], button:not([disabled]), fieldset:not([disabled]), input:not([disabled]), optgroup:not([disabled]), option:not([disabled]), select:not([disabled]), textarea:not([disabled]), details, [tabindex]:not([tabindex="-1"]), [contenteditable], [controls]')].filter(
|
||||
el => !el.getAttribute('aria-hidden')
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} element
|
||||
*/
|
||||
function getElementPosition (element) {
|
||||
const { x, y, width, height } = element.getBoundingClientRect()
|
||||
if (width || height) {
|
||||
return { element, x: x + width * 0.5, y: y + height * 0.5 }
|
||||
}
|
||||
}
|
||||
|
||||
function getFocusableElementPositions () {
|
||||
const elements = []
|
||||
for (const element of getKeyboardFocusableElements()) {
|
||||
const position = getElementPosition(element)
|
||||
if (position) elements.push(position)
|
||||
}
|
||||
return elements
|
||||
}
|
||||
|
||||
function navigateDPad (direction = 'up') {
|
||||
const keyboardFocusable = getFocusableElementPositions()
|
||||
const currentElement = !document.activeElement || document.activeElement === document.body ? keyboardFocusable[0] : getElementPosition(document.activeElement)
|
||||
|
||||
const elementsInDesiredDirection = keyboardFocusable.filter(position => {
|
||||
return position.element !== currentElement.element && getDirection(currentElement, position) === Directions[direction]
|
||||
})
|
||||
|
||||
const closestElement = elementsInDesiredDirection.reduce((reducer, position) => {
|
||||
const distance = getDistance(currentElement, position)
|
||||
if (distance < reducer.distance) return { distance, element: position.element }
|
||||
return reducer
|
||||
}, { distance: Infinity, element: null })
|
||||
|
||||
closestElement.element.focus()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
</script>
|
||||
|
||||
{#if block}
|
||||
<div class='w-full h-full left-0 z-50 position-absolute content-wrapper bg-dark d-flex align-items-center justify-content-center flex-column'>
|
||||
<div class='w-full h-full left-0 z-50 px-10 position-absolute content-wrapper bg-dark d-flex align-items-center justify-content-center flex-column'>
|
||||
<div>
|
||||
<h1 class='font-weight-bold'>Could not connect to Tosho!</h1>
|
||||
<div class='font-size-16'>This happens either because Tosho is down, or because your ISP blocks Tosho, the latter being more likely.</div>
|
||||
|
|
|
|||
|
|
@ -82,39 +82,47 @@
|
|||
<img class='w-full cover-img banner position-absolute' alt='banner' src={media.bannerImage || ' '} />
|
||||
<div class='row'>
|
||||
<div class='col-lg-7 col-12 pb-10'>
|
||||
<div class='d-flex flex-md-row flex-column align-items-end pb-20 mb-15'>
|
||||
<div class='d-flex flex-md-row flex-column align-items-md-end pb-20 mb-15'>
|
||||
<div class='cover d-flex flex-row align-items-md-end align-items-center mw-full w-full mb-md-0 mb-20'>
|
||||
<img class='rounded cover-img w-full overflow-hidden h-full' alt='cover-art' src={media.coverImage?.extraLarge || media.coverImage?.medium} />
|
||||
</div>
|
||||
<div class='pl-md-20 ml-md-20'>
|
||||
<h1 class='font-weight-very-bold text-white select-all'>{media.title.userPreferred}</h1>
|
||||
<p class='d-flex flex-row font-size-18'>
|
||||
<h1 class='font-weight-very-bold text-white select-all mb-0'>{media.title.userPreferred}</h1>
|
||||
<div class='d-flex flex-row font-size-18 flex-wrap mt-5'>
|
||||
{#if media.averageScore}
|
||||
<span class='material-symbols-outlined mx-10 font-size-24'> trending_up </span>
|
||||
<span class='mr-20'>
|
||||
Rating: {media.averageScore + '%'}
|
||||
</span>
|
||||
<div class='d-flex flex-row mt-10'>
|
||||
<span class='material-symbols-outlined mx-10 font-size-24'> trending_up </span>
|
||||
<span class='mr-20'>
|
||||
Rating: {media.averageScore + '%'}
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
{#if media.format}
|
||||
<span class='material-symbols-outlined mx-10 font-size-24'> monitor </span>
|
||||
<span class='mr-20 text-capitalize'>
|
||||
Format: {formatMap[media.format]}
|
||||
</span>
|
||||
<div class='d-flex flex-row mt-10'>
|
||||
<span class='material-symbols-outlined mx-10 font-size-24'> monitor </span>
|
||||
<span class='mr-20 text-capitalize'>
|
||||
Format: {formatMap[media.format]}
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
{#if media.episodes !== 1 && getMediaMaxEp(media)}
|
||||
<span class='material-symbols-outlined mx-10 font-size-24'> theaters </span>
|
||||
<span class='mr-20'>
|
||||
Episodes: {getMediaMaxEp(media)}
|
||||
</span>
|
||||
<div class='d-flex flex-row mt-10'>
|
||||
<span class='material-symbols-outlined mx-10 font-size-24'> theaters </span>
|
||||
<span class='mr-20'>
|
||||
Episodes: {getMediaMaxEp(media)}
|
||||
</span>
|
||||
</div>
|
||||
{:else if media.duration}
|
||||
<span class='material-symbols-outlined mx-10 font-size-24'> timer </span>
|
||||
<span class='mr-20'>
|
||||
Length: {media.duration + ' min'}
|
||||
</span>
|
||||
<div class='d-flex flex-row mt-10'>
|
||||
<span class='material-symbols-outlined mx-10 font-size-24'> timer </span>
|
||||
<span class='mr-20'>
|
||||
Length: {media.duration + ' min'}
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
</p>
|
||||
<div class='d-flex flex-row pt-5'>
|
||||
<button class='btn btn-lg btn-secondary w-250 text-dark font-weight-bold shadow-none border-0 d-flex align-items-center justify-content-center'
|
||||
</div>
|
||||
<div class='d-flex flex-row flex-wrap'>
|
||||
<button class='btn btn-lg btn-secondary w-250 text-dark font-weight-bold shadow-none border-0 d-flex align-items-center justify-content-center mr-10 mt-20'
|
||||
use:click={() => play()}
|
||||
disabled={media.status === 'NOT_YET_RELEASED'}>
|
||||
<span class='material-symbols-outlined font-size-24 filled pr-10'>
|
||||
|
|
@ -122,18 +130,20 @@
|
|||
</span>
|
||||
{playButtonText}
|
||||
</button>
|
||||
<button class='btn bg-dark btn-lg btn-square ml-10 material-symbols-outlined font-size-20 shadow-none border-0' class:filled={media.isFavourite} use:click={toggleFavourite}>
|
||||
favorite
|
||||
</button>
|
||||
<button class='btn bg-dark btn-lg btn-square ml-10 material-symbols-outlined font-size-20 shadow-none border-0' class:filled={media.mediaListEntry} use:click={toggleStatus}>
|
||||
bookmark
|
||||
</button>
|
||||
<button class='btn bg-dark btn-lg btn-square ml-10 material-symbols-outlined font-size-20 shadow-none border-0' use:click={() => copyToClipboard(`https://miru.watch/anime/${media.id}`)}>
|
||||
share
|
||||
</button>
|
||||
<button class='btn bg-dark btn-lg btn-square ml-10 material-symbols-outlined font-size-20 shadow-none border-0' use:click={() => openInBrowser(`https://anilist.co/anime/${media.id}`)}>
|
||||
open_in_new
|
||||
</button>
|
||||
<div class='mt-20'>
|
||||
<button class='btn bg-dark btn-lg btn-square material-symbols-outlined font-size-20 shadow-none border-0' class:filled={media.isFavourite} use:click={toggleFavourite}>
|
||||
favorite
|
||||
</button>
|
||||
<button class='btn bg-dark btn-lg btn-square ml-10 material-symbols-outlined font-size-20 shadow-none border-0' class:filled={media.mediaListEntry} use:click={toggleStatus}>
|
||||
bookmark
|
||||
</button>
|
||||
<button class='btn bg-dark btn-lg btn-square ml-10 material-symbols-outlined font-size-20 shadow-none border-0' use:click={() => copyToClipboard(`https://miru.watch/anime/${media.id}`)}>
|
||||
share
|
||||
</button>
|
||||
<button class='btn bg-dark btn-lg btn-square ml-10 material-symbols-outlined font-size-20 shadow-none border-0' use:click={() => openInBrowser(`https://anilist.co/anime/${media.id}`)}>
|
||||
open_in_new
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -68,6 +68,12 @@ importers:
|
|||
'@capacitor/ios':
|
||||
specifier: ^5.5.1
|
||||
version: 5.5.1(@capacitor/core@5.5.1)
|
||||
'@capacitor/status-bar':
|
||||
specifier: ^5.0.6
|
||||
version: 5.0.6(@capacitor/core@5.5.1)
|
||||
'@mauricewegner/capacitor-navigation-bar':
|
||||
specifier: ^2.0.3
|
||||
version: 2.0.3(@capacitor/core@5.5.1)
|
||||
'@superfrogbe/cordova-plugin-chrome-apps-sockets-udp':
|
||||
specifier: github:superfrogbe/cordova-plugin-chrome-apps-sockets-udp
|
||||
version: github.com/superfrogbe/cordova-plugin-chrome-apps-sockets-udp/4b740017299c81cfc7d5b49c7d6122a6650b57d4
|
||||
|
|
@ -292,6 +298,14 @@ packages:
|
|||
'@capacitor/core': 5.5.1
|
||||
dev: false
|
||||
|
||||
/@capacitor/status-bar@5.0.6(@capacitor/core@5.5.1):
|
||||
resolution: {integrity: sha512-7od8CxsBnot1XMK3IeOkproFL4hgoKoWAc3pwUvmDOkQsXoxwQm4SR9mLwQavv1XfxtHbFV9Ukd7FwMxOPSViw==}
|
||||
peerDependencies:
|
||||
'@capacitor/core': ^5.0.0
|
||||
dependencies:
|
||||
'@capacitor/core': 5.5.1
|
||||
dev: false
|
||||
|
||||
/@develar/schema-utils@2.6.5:
|
||||
resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==}
|
||||
engines: {node: '>= 8.9.0'}
|
||||
|
|
@ -592,6 +606,14 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@mauricewegner/capacitor-navigation-bar@2.0.3(@capacitor/core@5.5.1):
|
||||
resolution: {integrity: sha512-E8HTcVkZEqm4tLJ7MpkTlqc93mboUSbJL41fFbvEaVwBhpgenEezkK268RxwQDij5hkudZmo4/eRXG3aJQwrzQ==}
|
||||
peerDependencies:
|
||||
'@capacitor/core': ^4.0.1 || ^5.0.0
|
||||
dependencies:
|
||||
'@capacitor/core': 5.5.1
|
||||
dev: false
|
||||
|
||||
/@nodelib/fs.scandir@2.1.5:
|
||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||
engines: {node: '>= 8'}
|
||||
|
|
|
|||
Loading…
Reference in a new issue