diff --git a/common/components/Logout.svelte b/common/components/Logout.svelte
index a8ccad2..5b58012 100644
--- a/common/components/Logout.svelte
+++ b/common/components/Logout.svelte
@@ -5,7 +5,7 @@
export const logout = writable(false)
function confirm () {
- localStorage.removeItem('ALtoken')
+ localStorage.removeItem('ALviewer')
location.hash = ''
location.reload()
}
diff --git a/common/components/Sidebar.svelte b/common/components/Sidebar.svelte
index 8f9aa5c..a821d91 100644
--- a/common/components/Sidebar.svelte
+++ b/common/components/Sidebar.svelte
@@ -13,7 +13,7 @@
const links = [
{
click: () => {
- if (anilistClient.userID) {
+ if (anilistClient.userID?.viewer?.data?.Viewer) {
$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
@@ -85,13 +85,9 @@
text: 'Settings'
}
]
- if (anilistClient.userID) {
- anilistClient.userID.then(result => {
- if (result?.data?.Viewer) {
- links[0].image = result.data.Viewer.avatar.medium
- links[0].text = 'Logout'
- }
- })
+ if (anilistClient.userID?.viewer?.data?.Viewer) {
+ links[0].image = anilistClient.userID.viewer.data.Viewer.avatar.medium
+ links[0].text = 'Logout'
}
diff --git a/common/components/banner/Banner.svelte b/common/components/banner/Banner.svelte
index 69e0dfa..cd30086 100644
--- a/common/components/banner/Banner.svelte
+++ b/common/components/banner/Banner.svelte
@@ -22,6 +22,8 @@
+
+
.
{#await data}
{:then { data }}
@@ -33,4 +35,7 @@
.gradient {
background: linear-gradient(0deg, #17191D 0%, #0000 15%, #0000 100%), linear-gradient(90deg, #17191D 0%, rgba(23, 25, 29, 0.885417) 15%, rgba(25, 28, 32, 0) 72%);
}
+ .opacity-0 {
+ opacity: 0;
+ }
diff --git a/common/modules/al.d.ts b/common/modules/al.d.ts
index 38c7ec4..15543da 100644
--- a/common/modules/al.d.ts
+++ b/common/modules/al.d.ts
@@ -92,21 +92,21 @@ export type Media = {
}
}[]
}
- recommendations?: {
- edges?: {
- node: {
- media: {
- id: number
- title: {
- userPreferred: string
- }
- coverImage?: {
- medium: string
- }
- }
- }
- }[]
- }
+ // recommendations?: {
+ // edges?: {
+ // node: {
+ // media: {
+ // id: number
+ // title: {
+ // userPreferred: string
+ // }
+ // coverImage?: {
+ // medium: string
+ // }
+ // }
+ // }
+ // }[]
+ // }
}
export type Following = {
diff --git a/common/modules/anilist.js b/common/modules/anilist.js
index 3328299..4dce16e 100644
--- a/common/modules/anilist.js
+++ b/common/modules/anilist.js
@@ -150,23 +150,24 @@ relations {
}
}
}
-},
-recommendations{
- edges{
- node{
- mediaRecommendation{
- id,
- title{
- userPreferred
- },
- coverImage{
- medium
- }
- }
- }
- }
}`
+// recommendations{
+// edges{
+// node{
+// mediaRecommendation{
+// id,
+// title{
+// userPreferred
+// },
+// coverImage{
+// medium
+// }
+// }
+// }
+// }
+// }
+
class AnilistClient {
limiter = new Bottleneck({
reservoir: 90,
@@ -181,7 +182,7 @@ class AnilistClient {
/** @type {import('simple-store-svelte').Writable
>} */
userLists = writable()
- userID
+ userID = alToken
/** @type {Record} */
mediaCache = {}
@@ -201,14 +202,7 @@ class AnilistClient {
return time
})
- if (alToken) {
- this.userID = this.viewer({ token: alToken }).then(result => {
- const lists = result?.data?.Viewer?.mediaListOptions?.animeList?.customLists || []
- if (!lists.includes('Watched using Miru')) {
- this.customList({ lists })
- }
- return result
- })
+ if (this.userID?.viewer?.data?.Viewer) {
this.userLists.value = this.getUserLists()
// update userLists every 15 mins
setInterval(() => { this.userLists.value = this.getUserLists() }, 1000 * 60 * 15)
@@ -250,8 +244,10 @@ class AnilistClient {
* @param {Record} variables
*/
alRequest (query, variables) {
+ /** @type {RequestInit} */
const options = {
method: 'POST',
+ credentials: 'omit',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json'
@@ -267,7 +263,8 @@ class AnilistClient {
}
})
}
- if (alToken) options.headers.Authorization = alToken
+ // @ts-ignore
+ if (alToken?.token) options.headers.Authorization = alToken.token
return this.handleRequest(options)
}
@@ -440,7 +437,6 @@ class AnilistClient {
/** @returns {Promise>} */
viewer (variables = {}) {
- variables.id = alToken
const query = /* js */`
query{
Viewer{
@@ -462,7 +458,7 @@ class AnilistClient {
/** @returns {Promise>} */
async getUserLists (variables = {}) {
- const userId = (await this.userID)?.data?.Viewer.id
+ const userId = this.userID?.viewer?.data?.Viewer.id
variables.id = userId
const query = /* js */`
query($id: Int){
@@ -499,7 +495,7 @@ class AnilistClient {
/** @returns {Promise>} */
async searchIDStatus (variables = {}) {
- const userId = (await this.userID)?.data?.Viewer.id
+ const userId = this.userID?.viewer?.data?.Viewer.id
variables.id = userId
const query = /* js */`
query($id: Int, $mediaId: Int){
diff --git a/common/modules/settings.js b/common/modules/settings.js
index 73df77a..018333a 100644
--- a/common/modules/settings.js
+++ b/common/modules/settings.js
@@ -1,7 +1,10 @@
import { writable } from 'simple-store-svelte'
import { defaults } from './util.js'
import IPC from '@/modules/ipc.js'
-export let alToken = localStorage.getItem('ALtoken') || null
+import { anilistClient } from './anilist.js'
+import { toast } from 'svelte-sonner'
+/** @type {{viewer: import('./al').Query<{Viewer: import('./al').Viewer}>, token: string} | null} */
+export let alToken = JSON.parse(localStorage.getItem('ALviewer')) || null
let storedSettings = { ...defaults }
@@ -46,8 +49,18 @@ window.addEventListener('paste', ({ clipboardData }) => {
}
})
IPC.on('altoken', handleToken)
-function handleToken (data) {
- localStorage.setItem('ALtoken', data)
- alToken = data
+async function handleToken (token) {
+ alToken = { token, viewer: null }
+ const viewer = await anilistClient.viewer({ token })
+ if (!viewer.data?.Viewer) {
+ toast.error('Failed to sign in with AniList. Please try again.', { description: JSON.stringify(viewer) })
+ console.error(viewer)
+ return
+ }
+ const lists = viewer?.data?.Viewer?.mediaListOptions?.animeList?.customLists || []
+ if (!lists.includes('Watched using Miru')) {
+ await anilistClient.customList({ lists })
+ }
+ localStorage.setItem('ALviewer', JSON.stringify({ token, viewer }))
location.reload()
}
diff --git a/common/views/Home/Home.svelte b/common/views/Home/Home.svelte
index a3247c2..a55f34d 100644
--- a/common/views/Home/Home.svelte
+++ b/common/views/Home/Home.svelte
@@ -1,6 +1,6 @@
{#await following then res}
- {@const following = res.data.Page.mediaList}
- {#if following?.length && alToken}
+ {@const following = res?.data?.Page?.mediaList}
+ {#if following?.length}
Following
diff --git a/common/views/ViewAnime/ViewAnime.svelte b/common/views/ViewAnime/ViewAnime.svelte
index 388239f..bfd1771 100644
--- a/common/views/ViewAnime/ViewAnime.svelte
+++ b/common/views/ViewAnime/ViewAnime.svelte
@@ -166,13 +166,13 @@
- edge.node.mediaRecommendation)} let:item title='Recommendations'>
+
Episodes
diff --git a/common/views/WatchTogether/WatchTogether.svelte b/common/views/WatchTogether/WatchTogether.svelte
index 6172b93..e9f8f91 100644
--- a/common/views/WatchTogether/WatchTogether.svelte
+++ b/common/views/WatchTogether/WatchTogether.svelte
@@ -26,10 +26,10 @@
atob('d3NzOi8vdHJhY2tlci5maWxlcy5mbTo3MDczL2Fubm91bmNl'),
atob('d3NzOi8vdHJhY2tlci5idG9ycmVudC54eXov')
], code)
- p2pt.on('peerconnect', async peer => {
+ p2pt.on('peerconnect', peer => {
console.log(peer.id)
console.log('connect')
- const user = (await anilistClient.userID)?.data?.Viewer || {}
+ const user = anilistClient.userID?.viewer?.data?.Viewer || {}
p2pt.send(peer,
JSON.stringify({
type: 'init',
diff --git a/electron/package.json b/electron/package.json
index 7e8dffc..6007889 100644
--- a/electron/package.json
+++ b/electron/package.json
@@ -1,6 +1,6 @@
{
"name": "Miru",
- "version": "5.0.7",
+ "version": "5.0.8",
"private": true,
"author": "ThaUnknown_
",
"description": "Stream anime torrents, real-time with no waiting for downloads.",
diff --git a/electron/src/main/main.js b/electron/src/main/main.js
index a7040b5..e9319d1 100644
--- a/electron/src/main/main.js
+++ b/electron/src/main/main.js
@@ -18,6 +18,8 @@ function createWindow () {
webtorrentWindow = new BrowserWindow({
show: development,
webPreferences: {
+ webSecurity: false,
+ allowRunningInsecureContent: false,
nodeIntegration: true,
contextIsolation: false,
backgroundThrottling: false
@@ -36,6 +38,8 @@ function createWindow () {
backgroundColor: '#17191c',
autoHideMenuBar: true,
webPreferences: {
+ webSecurity: false,
+ allowRunningInsecureContent: false,
enableBlinkFeatures: 'FontAccess, AudioVideoTracks',
backgroundThrottling: false,
preload: path.join(__dirname, '/preload.js')
@@ -53,12 +57,6 @@ function createWindow () {
return { action: 'deny' }
})
- mainWindow.webContents.session.webRequest.onHeadersReceived(({ responseHeaders }, fn) => {
- delete responseHeaders['Access-Control-Allow-Origin']
- responseHeaders['access-control-allow-origin'] = ['*']
- fn({ responseHeaders })
- })
-
const torrentLoad = webtorrentWindow.loadURL(development ? 'http://localhost:5000/background.html' : `file://${path.join(__dirname, '/background.html')}`)
mainWindow.loadURL(development ? 'http://localhost:5000/app.html' : `file://${path.join(__dirname, '/app.html')}`)
@@ -94,8 +92,8 @@ function createWindow () {
mainWindow.webContents.on('render-process-gone', (e, { reason }) => {
if (reason === 'crashed') {
if (++crashcount > 10) {
- dialog.showMessageBox({ message: 'Crashed too many times.', title: 'Miru', detail: 'App crashed too many times. For a fix visit https://github.com/ThaUnknown/miru/blob/master/docs/faq.md#miru-crashed-too-many-times', icon: '/renderer/public/logo_filled.png' }).then(() => {
- shell.openExternal('https://github.com/ThaUnknown/miru/blob/master/docs/faq.md#miru-crashed-too-many-times')
+ dialog.showMessageBox({ message: 'Crashed too many times.', title: 'Miru', detail: 'App crashed too many times. For a fix visit https://miru.watch/faq/', icon: '/renderer/public/logo_filled.png' }).then(() => {
+ shell.openExternal('https://miru.watch/faq/')
app.quit()
})
} else {
diff --git a/electron/src/main/util.js b/electron/src/main/util.js
index e38161b..16c551b 100644
--- a/electron/src/main/util.js
+++ b/electron/src/main/util.js
@@ -5,20 +5,13 @@ export const development = process.env.NODE_ENV?.trim() === 'development'
const flags = [
// not sure if safe?
- ['disable-gpu-sandbox'],
- // not sure if safe?
- ['disable-direct-composition-video-overlays'],
- // not sure if safe?
- ['double-buffer-compositing'],
- // not sure if safe?
- ['enable-zero-copy'],
- // not sure if safe?
- ['ignore-gpu-blocklist'],
+ ['disable-gpu-sandbox'], ['disable-direct-composition-video-overlays'], ['double-buffer-compositing'], ['enable-zero-copy'], ['ignore-gpu-blocklist'],
+ // should be safe
['enable-hardware-overlays', 'single-fullscreen,single-on-top,underlay'],
- // dv, drdc display compositor uses 2 gpu threads instead of 1, rest is safe performance
- ['enable-features', 'PlatformEncryptedDolbyVision,EnableDrDc,CanvasOopRasterization,ThrottleDisplayNoneAndVisibilityHiddenCrossOriginIframes,UseSkiaRenderer,WebAssemblyLazyCompilation'],
- // disabling shit, vulkan rendering, native window occlusion calculation, widget layering aka right click context menus [I think] for macOS [I think]
- ['disable-features', 'Vulkan,CalculateNativeWinOcclusion,WidgetLayering'],
+ // safe performance stuff
+ ['enable-features', 'PlatformEncryptedDolbyVision,CanvasOopRasterization,ThrottleDisplayNoneAndVisibilityHiddenCrossOriginIframes,UseSkiaRenderer,WebAssemblyLazyCompilation'],
+ // disabling shit, vulkan rendering, widget layering aka right click context menus [I think] for macOS [I think]
+ ['disable-features', 'Vulkan,WidgetLayering'],
// utility stuff, aka website security that's useless for a native app:
['autoplay-policy', 'no-user-gesture-required'], ['disable-notifications'], ['disable-logging'], ['disable-permissions-api'], ['no-sandbox'], ['no-zygote'], ['bypasscsp-schemes']
]