diff --git a/app/components/ui/anime-card/AnimeCard.vue b/app/components/ui/anime-card/AnimeCard.vue
index a88899b..5f6a8b3 100644
--- a/app/components/ui/anime-card/AnimeCard.vue
+++ b/app/components/ui/anime-card/AnimeCard.vue
@@ -56,7 +56,7 @@ onMounted(async () => {
{{ props.item.material_data?.description }}
diff --git a/app/components/ui/button/index.ts b/app/components/ui/button/index.ts
index 337ec95..84e2e9f 100644
--- a/app/components/ui/button/index.ts
+++ b/app/components/ui/button/index.ts
@@ -18,6 +18,7 @@ export const buttonVariants = cva(
ghost:
'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
link: 'text-primary underline-offset-4 hover:underline',
+ borderless: 'border-0 cursor-pointer size-20'
},
size: {
default: 'h-9 px-4 py-2 has-[>svg]:px-3',
diff --git a/app/components/ui/player/ChangeEpisodeButton.vue b/app/components/ui/player/ChangeEpisodeButton.vue
new file mode 100644
index 0000000..ae507d7
--- /dev/null
+++ b/app/components/ui/player/ChangeEpisodeButton.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/components/ui/player/Player.vue b/app/components/ui/player/Player.vue
index b220fac..cbee975 100644
--- a/app/components/ui/player/Player.vue
+++ b/app/components/ui/player/Player.vue
@@ -1,10 +1,13 @@
diff --git a/app/components/util/player-control.js b/app/components/util/player-control.js
new file mode 100644
index 0000000..80f835a
--- /dev/null
+++ b/app/components/util/player-control.js
@@ -0,0 +1,42 @@
+import { createApp, h } from 'vue'
+
+export function createVueControlSmart(component, props = {}, events = {}) {
+ let vueApp = null
+
+ return {
+ name: props.name || 'vue-control',
+ index: props.index || 0,
+ position: props.position || 'left',
+ html: ``,
+ tooltip: props.tooltip || '',
+
+ mounted: function ($control) {
+ const container = $control.querySelector('.vue-control-wrapper')
+
+ if (container && !vueApp) {
+ vueApp = createApp({
+ render() {
+ return h(component, {
+ ...props,
+ ...Object.entries(events).reduce((acc, [eventName, handler]) => {
+ acc[`on${eventName.charAt(0).toUpperCase() + eventName.slice(1)}`] = handler
+ return acc
+ }, {})
+ })
+ }
+ })
+
+ vueApp.mount(container)
+ $control._vueApp = vueApp
+ }
+ },
+
+ destroy: function ($control) {
+ if ($control._vueApp) {
+ $control._vueApp.unmount()
+ $control._vueApp = null
+ vueApp = null
+ }
+ }
+ }
+}
diff --git a/app/components/util/route.js b/app/components/util/route.js
new file mode 100644
index 0000000..92ef81f
--- /dev/null
+++ b/app/components/util/route.js
@@ -0,0 +1,9 @@
+export const updateUrlParameter = async (route, paramName, newValue) => {
+ await navigateTo({
+ path: route.path,
+ query: {
+ ...route.query,
+ [paramName]: newValue
+ }
+ }, { replace: true })
+}
diff --git a/app/pages/watch.vue b/app/pages/watch.vue
index e338908..8e090ce 100644
--- a/app/pages/watch.vue
+++ b/app/pages/watch.vue
@@ -8,7 +8,7 @@
Episode: {{ episode }}
@@ -24,49 +24,29 @@