From ef68e4a84d6b7f2a9ce7aafb77fbe430df50f4b3 Mon Sep 17 00:00:00 2001 From: bivashy Date: Mon, 23 Jun 2025 00:53:12 +0500 Subject: [PATCH] WIP Implement search and watch prototype --- bun.lock | 54 ++++++- components/ui/dialog/Dialog.vue | 17 ++ components/ui/dialog/DialogClose.vue | 14 ++ components/ui/dialog/DialogContent.vue | 47 ++++++ components/ui/dialog/DialogDescription.vue | 22 +++ components/ui/dialog/DialogFooter.vue | 15 ++ components/ui/dialog/DialogHeader.vue | 17 ++ components/ui/dialog/DialogOverlay.vue | 20 +++ components/ui/dialog/DialogScrollContent.vue | 56 +++++++ components/ui/dialog/DialogTitle.vue | 22 +++ components/ui/dialog/DialogTrigger.vue | 14 ++ components/ui/dialog/index.ts | 10 ++ components/ui/label/Label.vue | 25 +++ components/ui/label/index.ts | 1 + openapi/extractor.json | 1 + openapi/extractor.ts | 96 ++++++++++++ orval.config.js | 8 + package.json | 6 +- pages/anime/[slug].vue | 71 +++++++++ pages/index.vue | 120 ++++++++------- pages/search.vue | 154 +++++-------------- pages/watch.vue | 125 +++++++++++++++ 22 files changed, 737 insertions(+), 178 deletions(-) create mode 100644 components/ui/dialog/Dialog.vue create mode 100644 components/ui/dialog/DialogClose.vue create mode 100644 components/ui/dialog/DialogContent.vue create mode 100644 components/ui/dialog/DialogDescription.vue create mode 100644 components/ui/dialog/DialogFooter.vue create mode 100644 components/ui/dialog/DialogHeader.vue create mode 100644 components/ui/dialog/DialogOverlay.vue create mode 100644 components/ui/dialog/DialogScrollContent.vue create mode 100644 components/ui/dialog/DialogTitle.vue create mode 100644 components/ui/dialog/DialogTrigger.vue create mode 100644 components/ui/dialog/index.ts create mode 100644 components/ui/label/Label.vue create mode 100644 components/ui/label/index.ts create mode 100644 openapi/extractor.json create mode 100644 openapi/extractor.ts create mode 100644 pages/anime/[slug].vue create mode 100644 pages/watch.vue diff --git a/bun.lock b/bun.lock index 85122cf..ceba584 100644 --- a/bun.lock +++ b/bun.lock @@ -7,18 +7,20 @@ "@nuxt/eslint": "1.4.1", "@nuxt/image": "1.10.0", "@tailwindcss/vite": "^4.1.7", - "@vueuse/core": "^13.2.0", + "@videojs-player/vue": "^1.0.0", + "@vueuse/core": "^13.4.0", "axios": "^1.10.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "eslint": "^9.0.0", "lucide-vue-next": "^0.511.0", "nuxt": "^3.17.4", - "reka-ui": "^2.2.1", + "reka-ui": "^2.3.1", "shadcn-nuxt": "2.1.0", "tailwind-merge": "^3.3.0", "tailwindcss": "^4.1.7", "tw-animate-css": "^1.3.0", + "video.js": "^8.23.3", "vue": "^3.5.14", "vue-router": "^4.5.1", "vue-sonner": "^2.0.0", @@ -89,6 +91,8 @@ "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Q5sT5+O4QUebHdbwKedFBEwRLb02zJ7r4A5Gg2hUoLuU3FjdMcyqcywqUrLCaDsFCxzokf7u9kuy7qz51YUuAg=="], + "@babel/runtime": ["@babel/runtime@7.27.6", "", {}, "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q=="], + "@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], "@babel/traverse": ["@babel/traverse@7.27.1", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.1", "@babel/parser": "^7.27.1", "@babel/template": "^7.27.1", "@babel/types": "^7.27.1", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg=="], @@ -569,6 +573,8 @@ "@types/urijs": ["@types/urijs@1.19.25", "", {}, "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg=="], + "@types/video.js": ["@types/video.js@7.3.58", "", {}, "sha512-1CQjuSrgbv1/dhmcfQ83eVyYbvGyqhTvb2Opxr0QCV+iJ4J6/J+XWQ3Om59WiwCd1MN3rDUHasx5XRrpUtewYQ=="], + "@types/web-bluetooth": ["@types/web-bluetooth@0.0.21", "", {}, "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="], "@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="], @@ -627,6 +633,14 @@ "@vercel/nft": ["@vercel/nft@0.29.3", "", { "dependencies": { "@mapbox/node-pre-gyp": "^2.0.0", "@rollup/pluginutils": "^5.1.3", "acorn": "^8.6.0", "acorn-import-attributes": "^1.9.5", "async-sema": "^3.1.1", "bindings": "^1.4.0", "estree-walker": "2.0.2", "glob": "^10.4.5", "graceful-fs": "^4.2.9", "node-gyp-build": "^4.2.2", "picomatch": "^4.0.2", "resolve-from": "^5.0.0" }, "bin": { "nft": "out/cli.js" } }, "sha512-aVV0E6vJpuvImiMwU1/5QKkw2N96BRFE7mBYGS7FhXUoS6V7SarQ+8tuj33o7ofECz8JtHpmQ9JW+oVzOoB7MA=="], + "@videojs-player/vue": ["@videojs-player/vue@1.0.0", "", { "peerDependencies": { "@types/video.js": "7.x", "video.js": "7.x", "vue": "3.x" } }, "sha512-WonTezRfKu3fYdQLt/ta+nuKH6gMZUv8l40Jke/j4Lae7IqeO/+lLAmBnh3ni88bwR+vkFXIlZ2Ci7VKInIYJg=="], + + "@videojs/http-streaming": ["@videojs/http-streaming@3.17.0", "", { "dependencies": { "@babel/runtime": "^7.12.5", "@videojs/vhs-utils": "^4.1.1", "aes-decrypter": "^4.0.2", "global": "^4.4.0", "m3u8-parser": "^7.2.0", "mpd-parser": "^1.3.1", "mux.js": "7.1.0", "video.js": "^7 || ^8" } }, "sha512-Ch1P3tvvIEezeZXyK11UfWgp4cWKX4vIhZ30baN/lRinqdbakZ5hiAI3pGjRy3d+q/Epyc8Csz5xMdKNNGYpcw=="], + + "@videojs/vhs-utils": ["@videojs/vhs-utils@4.1.1", "", { "dependencies": { "@babel/runtime": "^7.12.5", "global": "^4.4.0" } }, "sha512-5iLX6sR2ownbv4Mtejw6Ax+naosGvoT9kY+gcuHzANyUZZ+4NpeNdKMUhb6ag0acYej1Y7cmr/F2+4PrggMiVA=="], + + "@videojs/xhr": ["@videojs/xhr@2.7.0", "", { "dependencies": { "@babel/runtime": "^7.5.5", "global": "~4.4.0", "is-function": "^1.0.1" } }, "sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ=="], + "@vitejs/plugin-vue": ["@vitejs/plugin-vue@5.2.4", "", { "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA=="], "@vitejs/plugin-vue-jsx": ["@vitejs/plugin-vue-jsx@4.2.0", "", { "dependencies": { "@babel/core": "^7.27.1", "@babel/plugin-transform-typescript": "^7.27.1", "@rolldown/pluginutils": "^1.0.0-beta.9", "@vue/babel-plugin-jsx": "^1.4.0" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.0.0" } }, "sha512-DSTrmrdLp+0LDNF77fqrKfx7X0ErRbOcUAgJL/HbSesqQwoUvUQ4uYQqaex+rovqgGcoPqVk+AwUh3v9CuiYIw=="], @@ -665,11 +679,11 @@ "@vue/shared": ["@vue/shared@3.5.14", "", {}, "sha512-oXTwNxVfc9EtP1zzXAlSlgARLXNC84frFYkS0HHz0h3E4WZSP9sywqjqzGCP9Y34M8ipNmd380pVgmMuwELDyQ=="], - "@vueuse/core": ["@vueuse/core@13.2.0", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "13.2.0", "@vueuse/shared": "13.2.0" }, "peerDependencies": { "vue": "^3.5.0" } }, "sha512-n5TZoIAxbWAQ3PqdVPDzLgIRQOujFfMlatdI+f7ditSmoEeNpPBvp7h2zamzikCmrhFIePAwdEQB6ENccHr7Rg=="], + "@vueuse/core": ["@vueuse/core@13.4.0", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "13.4.0", "@vueuse/shared": "13.4.0" }, "peerDependencies": { "vue": "^3.5.0" } }, "sha512-OnK7zW3bTq/QclEk17+vDFN3tuAm8ONb9zQUIHrYQkkFesu3WeGUx/3YzpEp+ly53IfDAT9rsYXgGW6piNZC5w=="], - "@vueuse/metadata": ["@vueuse/metadata@13.2.0", "", {}, "sha512-kPpzuQCU0+D8DZCzK0iPpIcXI+6ufWSgwnjJ6//GNpEn+SHViaCtR+XurzORChSgvpHO9YC8gGM97Y1kB+UabA=="], + "@vueuse/metadata": ["@vueuse/metadata@13.4.0", "", {}, "sha512-CPDQ/IgOeWbqItg1c/pS+Ulum63MNbpJ4eecjFJqgD/JUCJ822zLfpw6M9HzSvL6wbzMieOtIAW/H8deQASKHg=="], - "@vueuse/shared": ["@vueuse/shared@13.2.0", "", { "peerDependencies": { "vue": "^3.5.0" } }, "sha512-vx9ZPDF5HcU9up3Jgt3G62dMUfZEdk6tLyBAHYAG4F4n73vpaA7J5hdncDI/lS9Vm7GA/FPlbOmh9TrDZROTpg=="], + "@vueuse/shared": ["@vueuse/shared@13.4.0", "", { "peerDependencies": { "vue": "^3.5.0" } }, "sha512-+AxuKbw8R1gYy5T21V5yhadeNM7rJqb4cPaRI9DdGnnNl3uqXh+unvQ3uCaA2DjYLbNr1+l7ht/B4qEsRegX6A=="], "@whatwg-node/disposablestack": ["@whatwg-node/disposablestack@0.0.6", "", { "dependencies": { "@whatwg-node/promise-helpers": "^1.0.0", "tslib": "^2.6.3" } }, "sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw=="], @@ -681,6 +695,8 @@ "@whatwg-node/server": ["@whatwg-node/server@0.9.71", "", { "dependencies": { "@whatwg-node/disposablestack": "^0.0.6", "@whatwg-node/fetch": "^0.10.5", "@whatwg-node/promise-helpers": "^1.2.2", "tslib": "^2.6.3" } }, "sha512-ueFCcIPaMgtuYDS9u0qlUoEvj6GiSsKrwnOLPp9SshqjtcRaR1IEHRjoReq3sXNydsF5i0ZnmuYgXq9dV53t0g=="], + "@xmldom/xmldom": ["@xmldom/xmldom@0.8.10", "", {}, "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw=="], + "abbrev": ["abbrev@3.0.1", "", {}, "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg=="], "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], @@ -691,6 +707,8 @@ "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + "aes-decrypter": ["aes-decrypter@4.0.2", "", { "dependencies": { "@babel/runtime": "^7.12.5", "@videojs/vhs-utils": "^4.1.1", "global": "^4.4.0", "pkcs7": "^1.0.4" } }, "sha512-lc+/9s6iJvuaRe5qDlMTpCFjnwpkeOXp8qP3oiZ5jsj1MRg+SBVUmmICrhxHvc8OELSmc+fEyyxAuppY6hrWzw=="], + "agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="], "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], @@ -995,6 +1013,8 @@ "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], + "dom-walk": ["dom-walk@0.1.2", "", {}, "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="], + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], @@ -1231,6 +1251,8 @@ "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + "global": ["global@4.4.0", "", { "dependencies": { "min-document": "^2.19.0", "process": "^0.11.10" } }, "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w=="], + "global-directory": ["global-directory@4.0.1", "", { "dependencies": { "ini": "4.1.1" } }, "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q=="], "globals": ["globals@16.1.0", "", {}, "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g=="], @@ -1343,6 +1365,8 @@ "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + "is-function": ["is-function@1.0.2", "", {}, "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ=="], + "is-generator-function": ["is-generator-function@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "get-proto": "^1.0.0", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ=="], "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], @@ -1543,6 +1567,8 @@ "luxon": ["luxon@3.6.1", "", {}, "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ=="], + "m3u8-parser": ["m3u8-parser@7.2.0", "", { "dependencies": { "@babel/runtime": "^7.12.5", "@videojs/vhs-utils": "^4.1.1", "global": "^4.4.0" } }, "sha512-CRatFqpjVtMiMaKXxNvuI3I++vUumIXVVT/JpCpdU/FynV/ceVw1qpPyyBNindL+JlPMSesx+WX1QJaZEJSaMQ=="], + "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], "magic-string-ast": ["magic-string-ast@0.7.1", "", { "dependencies": { "magic-string": "^0.30.17" } }, "sha512-ub9iytsEbT7Yw/Pd29mSo/cNQpaEu67zR1VVcXDiYjSFwzeBxNdTd0FMnSslLQXiRj8uGPzwsaoefrMD5XAmdw=="], @@ -1579,6 +1605,8 @@ "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], + "min-document": ["min-document@2.19.0", "", { "dependencies": { "dom-walk": "^0.1.0" } }, "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ=="], + "min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="], "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], @@ -1601,10 +1629,14 @@ "module-definition": ["module-definition@5.0.1", "", { "dependencies": { "ast-module-types": "^5.0.0", "node-source-walk": "^6.0.1" }, "bin": { "module-definition": "bin/cli.js" } }, "sha512-kvw3B4G19IXk+BOXnYq/D/VeO9qfHaapMeuS7w7sNUqmGaA6hywdFHMi+VWeR9wUScXM7XjoryTffCZ5B0/8IA=="], + "mpd-parser": ["mpd-parser@1.3.1", "", { "dependencies": { "@babel/runtime": "^7.12.5", "@videojs/vhs-utils": "^4.0.0", "@xmldom/xmldom": "^0.8.3", "global": "^4.4.0" }, "bin": { "mpd-to-m3u8-json": "bin/parse.js" } }, "sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw=="], + "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "mux.js": ["mux.js@7.1.0", "", { "dependencies": { "@babel/runtime": "^7.11.2", "global": "^4.4.0" }, "bin": { "muxjs-transmux": "bin/transmux.js" } }, "sha512-NTxawK/BBELJrYsZThEulyUMDVlLizKdxyAsMuzoCD1eFj97BVaA8D/CvKsKu6FOLYkFojN5CbM9h++ZTZtknA=="], + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "nanotar": ["nanotar@0.2.0", "", {}, "sha512-9ca1h0Xjvo9bEkE4UOxgAzLV0jHKe6LMaxo37ND2DAhhAtd0j8pR1Wxz+/goMrZO8AEZTWCmyaOsFI/W5AdpCQ=="], @@ -1765,6 +1797,8 @@ "picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], + "pkcs7": ["pkcs7@1.0.4", "", { "dependencies": { "@babel/runtime": "^7.5.5" }, "bin": { "pkcs7": "bin/cli.js" } }, "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ=="], + "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], "pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="], @@ -1905,7 +1939,7 @@ "regjsparser": ["regjsparser@0.12.0", "", { "dependencies": { "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ=="], - "reka-ui": ["reka-ui@2.2.1", "", { "dependencies": { "@floating-ui/dom": "^1.6.13", "@floating-ui/vue": "^1.1.6", "@internationalized/date": "^3.5.0", "@internationalized/number": "^3.5.0", "@tanstack/vue-virtual": "^3.12.0", "@vueuse/core": "^12.5.0", "@vueuse/shared": "^12.5.0", "aria-hidden": "^1.2.4", "defu": "^6.1.4", "ohash": "^2.0.11" }, "peerDependencies": { "vue": ">= 3.2.0" } }, "sha512-oLHiyBn6gTIQGnTnv8G5LQuFp9j8HuUNl0qdnW3XPhFb/07hrxzFpjo2kt/jxOZive+n/XWDbOjSj2h9Hih3qA=="], + "reka-ui": ["reka-ui@2.3.1", "", { "dependencies": { "@floating-ui/dom": "^1.6.13", "@floating-ui/vue": "^1.1.6", "@internationalized/date": "^3.5.0", "@internationalized/number": "^3.5.0", "@tanstack/vue-virtual": "^3.12.0", "@vueuse/core": "^12.5.0", "@vueuse/shared": "^12.5.0", "aria-hidden": "^1.2.4", "defu": "^6.1.4", "ohash": "^2.0.11" }, "peerDependencies": { "vue": ">= 3.2.0" } }, "sha512-2SjGeybd7jvD8EQUkzjgg7GdOQdf4cTwdVMq/lDNTMqneUFNnryGO43dg8WaM/jaG9QpSCZBvstfBFWlDdb2Zg=="], "remove-trailing-separator": ["remove-trailing-separator@1.1.0", "", {}, "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="], @@ -2223,6 +2257,14 @@ "validator": ["validator@13.15.15", "", {}, "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A=="], + "video.js": ["video.js@8.23.3", "", { "dependencies": { "@babel/runtime": "^7.12.5", "@videojs/http-streaming": "^3.17.0", "@videojs/vhs-utils": "^4.1.1", "@videojs/xhr": "2.7.0", "aes-decrypter": "^4.0.2", "global": "4.4.0", "m3u8-parser": "^7.2.0", "mpd-parser": "^1.3.1", "mux.js": "^7.0.1", "videojs-contrib-quality-levels": "4.1.0", "videojs-font": "4.2.0", "videojs-vtt.js": "0.15.5" } }, "sha512-Toe0VLlDZcUhiaWfcePS1OEdT3ATfktm0hk/PELfD7zUoPDHeT+cJf/wZmCy5M5eGVwtGUg25RWPCj1L/1XufA=="], + + "videojs-contrib-quality-levels": ["videojs-contrib-quality-levels@4.1.0", "", { "dependencies": { "global": "^4.4.0" }, "peerDependencies": { "video.js": "^8" } }, "sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA=="], + + "videojs-font": ["videojs-font@4.2.0", "", {}, "sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ=="], + + "videojs-vtt.js": ["videojs-vtt.js@0.15.5", "", { "dependencies": { "global": "^4.3.1" } }, "sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ=="], + "vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="], "vite-dev-rpc": ["vite-dev-rpc@1.0.7", "", { "dependencies": { "birpc": "^2.0.19", "vite-hot-client": "^2.0.4" }, "peerDependencies": { "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1" } }, "sha512-FxSTEofDbUi2XXujCA+hdzCDkXFG1PXktMjSk1efq9Qb5lOYaaM9zNSvKvPPF7645Bak79kSp1PTooMW2wktcA=="], diff --git a/components/ui/dialog/Dialog.vue b/components/ui/dialog/Dialog.vue new file mode 100644 index 0000000..bb8bf72 --- /dev/null +++ b/components/ui/dialog/Dialog.vue @@ -0,0 +1,17 @@ + + + diff --git a/components/ui/dialog/DialogClose.vue b/components/ui/dialog/DialogClose.vue new file mode 100644 index 0000000..7574168 --- /dev/null +++ b/components/ui/dialog/DialogClose.vue @@ -0,0 +1,14 @@ + + + diff --git a/components/ui/dialog/DialogContent.vue b/components/ui/dialog/DialogContent.vue new file mode 100644 index 0000000..39a1f0d --- /dev/null +++ b/components/ui/dialog/DialogContent.vue @@ -0,0 +1,47 @@ + + + diff --git a/components/ui/dialog/DialogDescription.vue b/components/ui/dialog/DialogDescription.vue new file mode 100644 index 0000000..cc81b1d --- /dev/null +++ b/components/ui/dialog/DialogDescription.vue @@ -0,0 +1,22 @@ + + + diff --git a/components/ui/dialog/DialogFooter.vue b/components/ui/dialog/DialogFooter.vue new file mode 100644 index 0000000..c3b4b55 --- /dev/null +++ b/components/ui/dialog/DialogFooter.vue @@ -0,0 +1,15 @@ + + + diff --git a/components/ui/dialog/DialogHeader.vue b/components/ui/dialog/DialogHeader.vue new file mode 100644 index 0000000..0fc2f5f --- /dev/null +++ b/components/ui/dialog/DialogHeader.vue @@ -0,0 +1,17 @@ + + + diff --git a/components/ui/dialog/DialogOverlay.vue b/components/ui/dialog/DialogOverlay.vue new file mode 100644 index 0000000..e2bef33 --- /dev/null +++ b/components/ui/dialog/DialogOverlay.vue @@ -0,0 +1,20 @@ + + + diff --git a/components/ui/dialog/DialogScrollContent.vue b/components/ui/dialog/DialogScrollContent.vue new file mode 100644 index 0000000..5173953 --- /dev/null +++ b/components/ui/dialog/DialogScrollContent.vue @@ -0,0 +1,56 @@ + + + diff --git a/components/ui/dialog/DialogTitle.vue b/components/ui/dialog/DialogTitle.vue new file mode 100644 index 0000000..7db6de6 --- /dev/null +++ b/components/ui/dialog/DialogTitle.vue @@ -0,0 +1,22 @@ + + + diff --git a/components/ui/dialog/DialogTrigger.vue b/components/ui/dialog/DialogTrigger.vue new file mode 100644 index 0000000..a870f66 --- /dev/null +++ b/components/ui/dialog/DialogTrigger.vue @@ -0,0 +1,14 @@ + + + diff --git a/components/ui/dialog/index.ts b/components/ui/dialog/index.ts new file mode 100644 index 0000000..baa7d61 --- /dev/null +++ b/components/ui/dialog/index.ts @@ -0,0 +1,10 @@ +export { default as Dialog } from './Dialog.vue' +export { default as DialogClose } from './DialogClose.vue' +export { default as DialogContent } from './DialogContent.vue' +export { default as DialogDescription } from './DialogDescription.vue' +export { default as DialogFooter } from './DialogFooter.vue' +export { default as DialogHeader } from './DialogHeader.vue' +export { default as DialogOverlay } from './DialogOverlay.vue' +export { default as DialogScrollContent } from './DialogScrollContent.vue' +export { default as DialogTitle } from './DialogTitle.vue' +export { default as DialogTrigger } from './DialogTrigger.vue' diff --git a/components/ui/label/Label.vue b/components/ui/label/Label.vue new file mode 100644 index 0000000..3199723 --- /dev/null +++ b/components/ui/label/Label.vue @@ -0,0 +1,25 @@ + + + diff --git a/components/ui/label/index.ts b/components/ui/label/index.ts new file mode 100644 index 0000000..572c2f0 --- /dev/null +++ b/components/ui/label/index.ts @@ -0,0 +1 @@ +export { default as Label } from './Label.vue' diff --git a/openapi/extractor.json b/openapi/extractor.json new file mode 100644 index 0000000..e62da6e --- /dev/null +++ b/openapi/extractor.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"http://localhost:8081","description":"Generated server url"}],"paths":{"/metadata/shikimori":{"get":{"tags":["metadata-controller"],"operationId":"shikimori","parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/KodikMetadata"}}}}}}},"/metadata/kodik":{"get":{"tags":["metadata-controller"],"operationId":"kodik","parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/KodikMetadata"}}}}}}},"/extract/video":{"get":{"tags":["extract-controller"],"operationId":"video","parameters":[{"name":"translationDTO","in":"query","required":true,"schema":{"$ref":"#/components/schemas/KodikTranslationDTO"}},{"name":"quality","in":"query","required":true,"schema":{"type":"string"}},{"name":"episode","in":"query","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/KodikVideoLinks"}}}}}}}},"components":{"schemas":{"KodikMetadata":{"type":"object","properties":{"title":{"type":"string"},"translations":{"type":"array","items":{"$ref":"#/components/schemas/KodikTranslation"}}}},"KodikTranslation":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"mediaId":{"type":"string"},"mediaHash":{"type":"string"},"mediaType":{"type":"string"},"translationType":{"type":"string"},"episodeCount":{"type":"integer","format":"int32"}}},"KodikTranslationDTO":{"type":"object","properties":{"mediaType":{"type":"string"},"mediaId":{"type":"string"},"mediaHash":{"type":"string"}}},"KodikVideoLinks":{"type":"object","properties":{"links":{"type":"object","additionalProperties":{"type":"array","items":{"$ref":"#/components/schemas/Link"}}}}},"Link":{"type":"object","properties":{"type":{"type":"string"},"src":{"type":"string"}}}}}} \ No newline at end of file diff --git a/openapi/extractor.ts b/openapi/extractor.ts new file mode 100644 index 0000000..6b25cd4 --- /dev/null +++ b/openapi/extractor.ts @@ -0,0 +1,96 @@ +/** + * Generated by orval v7.10.0 🍺 + * Do not edit manually. + * OpenAPI definition + * OpenAPI spec version: v0 + */ +import axios from 'axios'; +import type { + AxiosRequestConfig, + AxiosResponse +} from 'axios'; + +export interface KodikMetadata { + title?: string; + translations?: KodikTranslation[]; +} + +export interface KodikTranslation { + id?: string; + title?: string; + mediaId?: string; + mediaHash?: string; + mediaType?: string; + translationType?: string; + episodeCount?: number; +} + +export interface KodikTranslationDTO { + mediaType?: string; + mediaId?: string; + mediaHash?: string; +} + +export type KodikVideoLinksLinks = { [key: string]: Link[] }; + +export interface KodikVideoLinks { + links?: KodikVideoLinksLinks; +} + +export interface Link { + type?: string; + src?: string; +} + +export type ShikimoriParams = { + id: string; +}; + +export type KodikParams = { + id: string; +}; + +export type VideoParams = { + mediaType: string; + mediaId: string; + mediaHash: string; + quality: string; + episode: number; +}; + +export const shikimori = >( + params: ShikimoriParams, options?: AxiosRequestConfig +): Promise => { + return axios.get( + `http://localhost:8081/metadata/shikimori`, { + ...options, + params: { ...params, ...options?.params }, + } + ); +} + +export const kodik = >( + params: KodikParams, options?: AxiosRequestConfig +): Promise => { + return axios.get( + `http://localhost:8081/metadata/kodik`, { + ...options, + params: { ...params, ...options?.params }, + } + ); +} + +export const video = >( + params: VideoParams, options?: AxiosRequestConfig +): Promise => { + return axios.get( + `http://localhost:8081/extract/video`, { + ...options, + params: { ...params, ...options?.params }, + } + ); +} + +export type ShikimoriResult = AxiosResponse +export type KodikResult = AxiosResponse +export type VideoResult = AxiosResponse diff --git a/orval.config.js b/orval.config.js index 5d362dd..f297782 100644 --- a/orval.config.js +++ b/orval.config.js @@ -5,3 +5,11 @@ export const search = { baseUrl: 'http://localhost:8080' }, }; + +export const extractor = { + input: './openapi/extractor.json', + output: { + target: './openapi/extractor.ts', + baseUrl: 'http://localhost:8081' + }, +} diff --git a/package.json b/package.json index ca8625e..8b552a7 100644 --- a/package.json +++ b/package.json @@ -13,18 +13,20 @@ "@nuxt/eslint": "1.4.1", "@nuxt/image": "1.10.0", "@tailwindcss/vite": "^4.1.7", - "@vueuse/core": "^13.2.0", + "@videojs-player/vue": "^1.0.0", + "@vueuse/core": "^13.4.0", "axios": "^1.10.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "eslint": "^9.0.0", "lucide-vue-next": "^0.511.0", "nuxt": "^3.17.4", - "reka-ui": "^2.2.1", + "reka-ui": "^2.3.1", "shadcn-nuxt": "2.1.0", "tailwind-merge": "^3.3.0", "tailwindcss": "^4.1.7", "tw-animate-css": "^1.3.0", + "video.js": "^8.23.3", "vue": "^3.5.14", "vue-router": "^4.5.1", "vue-sonner": "^2.0.0" diff --git a/pages/anime/[slug].vue b/pages/anime/[slug].vue new file mode 100644 index 0000000..be81096 --- /dev/null +++ b/pages/anime/[slug].vue @@ -0,0 +1,71 @@ + + + diff --git a/pages/index.vue b/pages/index.vue index 2d95e56..1277988 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -3,13 +3,13 @@ import kodikImage from "assets/img/kodik.png"; import shikimoriImage from "assets/img/shikimori.png"; import { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectLabel, - SelectTrigger, - SelectValue + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectTrigger, + SelectValue } from "~/components/ui/select"; import { toast } from "vue-sonner"; import { Toaster } from "~/components/ui/sonner"; @@ -17,63 +17,71 @@ import { Navbar } from "~/components/ui/navbar"; import 'vue-sonner/style.css' import { Icon } from "#components"; +const router = useRouter() const searchProvider = ref('kodik') const displaySearchProvider = computed(() => { - let label = ''; - let image; - if (searchProvider.value === 'kodik') { - label = 'Kodik'; - image = kodikImage; - } - if (searchProvider.value === 'shikimori') { - label = 'Shikimori'; - image = shikimoriImage; - } - return { - label, - image - } + let label = ''; + let image; + if (searchProvider.value === 'kodik') { + label = 'Kodik'; + image = kodikImage; + } + if (searchProvider.value === 'shikimori') { + label = 'Shikimori'; + image = shikimoriImage; + } + return { + label, + image + } }) const search = defineModel("") function querySearch() { - if (!search.value || search.value.trim() === "") { - toast('Please enter a value'); - return; - } - + if (!search.value || search.value.trim() === "") { + toast('Please enter a value'); + return; + } + router.push({ path: '/search', query: { title: search.value, provider: searchProvider.value } }) + .catch(err => { + console.error('Navigation error:', err); + toast.error('Failed to navigate to search results'); + }); } diff --git a/pages/search.vue b/pages/search.vue index ad3bb0d..aa4ff44 100644 --- a/pages/search.vue +++ b/pages/search.vue @@ -1,132 +1,58 @@ - - - diff --git a/pages/watch.vue b/pages/watch.vue new file mode 100644 index 0000000..e0d048d --- /dev/null +++ b/pages/watch.vue @@ -0,0 +1,125 @@ + + + + +