diff --git a/package.json b/package.json index 3e6ec71e..ae781f8c 100644 --- a/package.json +++ b/package.json @@ -32,11 +32,13 @@ "electron-store": "^8.0.1", "electron-updater": "^4.6.1", "electron-window-state": "^5.0.3", - "es6-promise": "^4.2.8", "express": "^4.17.2", "get-port": "^5.1.1", "lastfmapi": "^0.1.1", "mpris-service": "^2.1.2", + "music-metadata": "^7.11.4", + "react": "^17.0.2", + "react-dom": "^17.0.2", "source-map-support": "^0.5.21", "v8-compile-cache": "^2.3.0", "ws": "^8.4.0", @@ -76,9 +78,9 @@ } ], "build": { - "electronVersion": "15.3.4", + "electronVersion": "16.0.6", "electronDownload": { - "version": "15.3.4-wvvmp", + "version": "16.0.6+wvcus", "mirror": "https://github.com/castlabs/electron-releases/releases/download/v" }, "appId": "cider", @@ -102,7 +104,10 @@ ], "linux": { "target": [ - "AppImage" + "AppImage", + "deb", + "snap", + "rpm" ], "synopsis": "A new look into listening and enjoying music in style and performance. ", "category": "AudioVideo", diff --git a/src/main/base/win.js b/src/main/base/win.js deleted file mode 100644 index ad3ec6a3..00000000 --- a/src/main/base/win.js +++ /dev/null @@ -1,407 +0,0 @@ -const { BrowserWindow, ipcMain, shell, app, screen } = require("electron") -const { join } = require("path") -const getPort = require("get-port"); -const express = require("express"); -const path = require("path"); -const windowStateKeeper = require("electron-window-state"); -const os = require('os'); -const yt = require('youtube-search-without-api-key'); -const discord = require('./discordrpc'); -const lastfm = require('./lastfm'); -const { writeFile, writeFileSync, existsSync, mkdirSync } = require('fs'); -const fs = require('fs'); -const mpris = require('./mpris'); -const mm = require('music-metadata'); -const fetch = require('electron-fetch').default; -const { Stream } = require('stream'); - -// Analytics for debugging. -const ElectronSentry = require("@sentry/electron"); -ElectronSentry.init({ dsn: "https://68c422bfaaf44dea880b86aad5a820d2@o954055.ingest.sentry.io/6112214" }); - -const CiderBase = { - win: null, - requests: [], - audiostream: new Stream.PassThrough(), - async Start() { - this.clientPort = await getPort({ port: 9000 }); - this.win = this.CreateBrowserWindow() - }, - clientPort: 0, - CreateBrowserWindow() { - this.VerifyFiles() - // Set default window sizes - const mainWindowState = windowStateKeeper({ - defaultWidth: 1024, - defaultHeight: 600 - }); - - let win = null - const options = { - icon: join(__dirname, `../../resources/icons/icon.ico`), - width: mainWindowState.width, - height: mainWindowState.height, - x: mainWindowState.x, - y: mainWindowState.y, - minWidth: 844, - minHeight: 410, - frame: false, - title: "Cider", - vibrancy: 'dark', - // transparent: true, - hasShadow: false, - webPreferences: { - webviewTag: true, - plugins: true, - nodeIntegration: true, - nodeIntegrationInWorker: false, - webSecurity: false, - allowRunningInsecureContent: true, - enableRemoteModule: true, - sandbox: true, - nativeWindowOpen: true, - contextIsolation: false, - preload: join(__dirname, '../preload/cider-preload.js') - } - } - - CiderBase.InitWebServer() - - // Create the BrowserWindow - if (process.platform === "darwin" || process.platform === "linux") { - win = new BrowserWindow(options) - } else { - if (app.cfg.get("visual.window_transparency") !== "disabled") { - const { BrowserWindow } = require("electron-acrylic-window"); - } - win = new BrowserWindow(options) - win.setVibrancy("dark") - } - - // intercept "https://js-cdn.music.apple.com/hls.js/2.141.0/hls.js/hls.js" and redirect to local file "./apple-hls.js" instead - win.webContents.session.webRequest.onBeforeRequest( - { - urls: ["https://*/*.js"] - }, - (details, callback) => { - if (details.url.includes("hls.js")) { - callback({ - redirectURL: `http://localhost:${CiderBase.clientPort}/apple-hls.js` - }) - } else { - callback({ - cancel: false - }) - } - } - ) - - win.webContents.session.webRequest.onBeforeSendHeaders(async (details, callback) => { - if (details.url === "https://buy.itunes.apple.com/account/web/info") { - details.requestHeaders['sec-fetch-site'] = 'same-site'; - details.requestHeaders['DNT'] = '1'; - let itspod = await win.webContents.executeJavaScript(`window.localStorage.getItem("music.ampwebplay.itspod")`) - if (itspod != null) - details.requestHeaders['Cookie'] = `itspod=${itspod}` - } - callback({ requestHeaders: details.requestHeaders }) - }) - - let location = `http://localhost:${CiderBase.clientPort}/` - win.loadURL(location) - win.on("closed", () => { - win = null - }) - - // Register listeners on Window to track size and position of the Window. - mainWindowState.manage(win); - - // IPC stuff (senders) - ipcMain.on("cider-platform", (event) => { - event.returnValue = process.platform - }) - - ipcMain.on("get-gpu-mode", (event) => { - event.returnValue = process.platform - }) - - ipcMain.on("is-dev", (event) => { - event.returnValue = !app.isPackaged - }) - - // IPC stuff (listeners) - ipcMain.on('close', () => { // listen for close event - win.close(); - }) - - ipcMain.on('put-library-songs', (event, arg) => { - fs.writeFileSync(join(app.paths.ciderCache, "library-songs.json"), JSON.stringify(arg)) - }) - - ipcMain.on('put-library-artists', (event, arg) => { - fs.writeFileSync(join(app.paths.ciderCache, "library-artists.json"), JSON.stringify(arg)) - }) - - ipcMain.on('put-library-albums', (event, arg) => { - fs.writeFileSync(join(app.paths.ciderCache, "library-albums.json"), JSON.stringify(arg)) - }) - - ipcMain.on('put-library-playlists', (event, arg) => { - fs.writeFileSync(join(app.paths.ciderCache, "library-playlists.json"), JSON.stringify(arg)) - }) - - ipcMain.on('put-library-recentlyAdded', (event, arg) => { - fs.writeFileSync(join(app.paths.ciderCache, "library-recentlyAdded.json"), JSON.stringify(arg)) - }) - - ipcMain.on('get-library-songs', (event) => { - let librarySongs = fs.readFileSync(join(app.paths.ciderCache, "library-songs.json"), "utf8") - event.returnValue = JSON.parse(librarySongs) - }) - - ipcMain.on('get-library-artists', (event) => { - let libraryArtists = fs.readFileSync(join(app.paths.ciderCache, "library-artists.json"), "utf8") - event.returnValue = JSON.parse(libraryArtists) - }) - - ipcMain.on('get-library-albums', (event) => { - let libraryAlbums = fs.readFileSync(join(app.paths.ciderCache, "library-albums.json"), "utf8") - event.returnValue = JSON.parse(libraryAlbums) - }) - - ipcMain.on('get-library-playlists', (event) => { - let libraryPlaylists = fs.readFileSync(join(app.paths.ciderCache, "library-playlists.json"), "utf8") - event.returnValue = JSON.parse(libraryPlaylists) - }) - - ipcMain.on('get-library-recentlyAdded', (event) => { - let libraryRecentlyAdded = fs.readFileSync(join(app.paths.ciderCache, "library-recentlyAdded.json"), "utf8") - event.returnValue = JSON.parse(libraryRecentlyAdded) - }) - - ipcMain.handle('getYTLyrics', async (event, track, artist) => { - var u = track + " " + artist + " official video"; - const videos = await yt.search(u); - return videos - }) - - ipcMain.handle('getStoreValue', (event, key, defaultValue) => { - return (defaultValue ? app.cfg.get(key, true) : app.cfg.get(key)); - }); - - ipcMain.handle('setStoreValue', (event, key, value) => { - app.cfg.set(key, value); - }); - - ipcMain.on('getStore', (event) => { - event.returnValue = app.cfg.store - }) - - ipcMain.on('setStore', (event, store) => { - app.cfg.store = store - }) - - ipcMain.handle('setVibrancy', (event, key, value) => { - win.setVibrancy(value) - }); - - ipcMain.on('maximize', () => { // listen for maximize event - if (win.isMaximized()) { - win.unmaximize() - } else { - win.maximize() - } - }) - - ipcMain.on('minimize', () => { // listen for minimize event - win.minimize(); - }) - - if (process.platform === "win32") { - let WND_STATE = { - MINIMIZED: 0, - NORMAL: 1, - MAXIMIZED: 2, - FULL_SCREEN: 3 - } - let wndState = WND_STATE.NORMAL - - win.on("resize", (_event) => { - const isMaximized = win.isMaximized() - const isMinimized = win.isMinimized() - const isFullScreen = win.isFullScreen() - const state = wndState; - if (isMinimized && state !== WND_STATE.MINIMIZED) { - wndState = WND_STATE.MINIMIZED - } else if (isFullScreen && state !== WND_STATE.FULL_SCREEN) { - wndState = WND_STATE.FULL_SCREEN - } else if (isMaximized && state !== WND_STATE.MAXIMIZED) { - wndState = WND_STATE.MAXIMIZED - win.webContents.executeJavaScript(`app.chrome.maximized = true`) - } else if (state !== WND_STATE.NORMAL) { - wndState = WND_STATE.NORMAL - win.webContents.executeJavaScript(`app.chrome.maximized = false`) - } - }) - } - - // Set window Handler - win.webContents.setWindowOpenHandler(({ url }) => { - if (url.includes("apple") || url.includes("localhost")) { - return { action: "allow" } - } - shell.openExternal(url).catch(() => { - }) - return { - action: 'deny' - } - }) - - // Set scale - ipcMain.on('setScreenScale', (event, scale) => { - win.webContents.setZoomFactor(parseFloat(scale)) - }) - - win.webContents.setZoomFactor(screen.getPrimaryDisplay().scaleFactor) - - mpris.connect(win) - - lastfm.authenticate() - // Discord - discord.connect((app.cfg.get("general.discord_rpc") == 1) ? '911790844204437504' : '886578863147192350'); - ipcMain.on('playbackStateDidChange', (_event, a) => { - app.media = a; - discord.updateActivity(a) - mpris.updateState(a) - lastfm.scrobbleSong(a) - lastfm.updateNowPlayingSong(a) - }); - - ipcMain.on('nowPlayingItemDidChange', (_event, a) => { - app.media = a; - discord.updateActivity(a) - mpris.updateAttributes(a) - lastfm.scrobbleSong(a) - lastfm.updateNowPlayingSong(a) - }); - - ipcMain.on("getPreviewURL", (_event, url) => { - fetch(url) - .then(res => res.buffer()) - .then(async (buffer) => { - try { - const metadata = await mm.parseBuffer(buffer, 'audio/x-m4a'); - SoundCheckTag = metadata.native.iTunes[1].value - win.webContents.send('SoundCheckTag', SoundCheckTag) - } catch (error) { - console.error(error.message); - } - }) - }); - - ipcMain.on('writeAudio', function (event, buffer) { - CiderBase.audiostream.write(Buffer.from(buffer)); - }) - - return win - }, - VerifyFiles() { - const expectedDirectories = [ - "CiderCache" - ] - const expectedFiles = [ - "library-songs.json", - "library-artists.json", - "library-albums.json", - "library-playlists.json", - "library-recentlyAdded.json", - ] - for (let i = 0; i < expectedDirectories.length; i++) { - if (!existsSync(path.join(app.getPath("userData"), expectedDirectories[i]))) { - mkdirSync(path.join(app.getPath("userData"), expectedDirectories[i])) - } - } - for (let i = 0; i < expectedFiles.length; i++) { - const file = path.join(app.paths.ciderCache, expectedFiles[i]) - if (!existsSync(file)) { - writeFileSync(file, JSON.stringify([])) - } - } - }, - EnvironmentVariables: { - "env": { - platform: os.platform(), - dev: app.isPackaged - } - }, - LinkHandler: (startArgs) => { - if (!startArgs) return; - console.log("lfmtoken", String(startArgs)) - if (String(startArgs).includes('auth')) { - let authURI = String(startArgs).split('/auth/')[1] - if (authURI.startsWith('lastfm')) { // If we wanted more auth options - const authKey = authURI.split('lastfm?token=')[1]; - app.cfg.set('lastfm.enabled', true); - app.cfg.set('lastfm.auth_token', authKey); - CiderBase.win.webContents.send('LastfmAuthenticated', authKey); - lastfm.authenticate() - } - } else { - const formattedSongID = startArgs.replace('ame://', '').replace('/', ''); - console.warn(`[LinkHandler] Attempting to load song id: ${formattedSongID}`); - - // setQueue can be done with album, song, url, playlist id - this.win.webContents.executeJavaScript(` - MusicKit.getInstance().setQueue({ song: '${formattedSongID}'}).then(function(queue) { - MusicKit.getInstance().play(); - }); - `).catch((err) => console.error(err)); - } - - }, - - async InitWebServer() { - const webapp = express(); - const webRemotePath = path.join(__dirname, '../renderer/'); - webapp.set("views", path.join(webRemotePath, "views")); - webapp.set("view engine", "ejs"); - - webapp.use(function (req, res, next) { - // if not localhost - if (req.url.includes("audio.webm") || (req.headers.host.includes("localhost") && req.headers["user-agent"].includes("Cider"))) { - next(); - } - }); - - webapp.use(express.static(webRemotePath)); - webapp.get('/', function (req, res) { - //res.sendFile(path.join(webRemotePath, 'index_old.html')); - res.render("main", CiderBase.EnvironmentVariables) - }); - webapp.get('/audio.webm', function (req, res) { - try { - req.connection.setTimeout(Number.MAX_SAFE_INTEGER); - // CiderBase.requests.push({req: req, res: res}); - // var pos = CiderBase.requests.length - 1; - // req.on("close", () => { - // console.info("CLOSED", CiderBase.requests.length); - // requests.splice(pos, 1); - // console.info("CLOSED", CiderBase.requests.length); - // }); - CiderBase.audiostream.on('data', (data) => { - try { - res.write(data); - } catch (ex) { - console.log(ex) - } - }) - } catch (ex) { console.log(ex) } - }); - webapp.listen(CiderBase.clientPort, function () { - console.log(`Cider client port: ${CiderBase.clientPort}`); - }); - }, - -} - -module.exports = CiderBase; \ No newline at end of file diff --git a/src/main/base/win.ts b/src/main/base/win.ts index 1a6d0b3a..00389998 100644 --- a/src/main/base/win.ts +++ b/src/main/base/win.ts @@ -1,17 +1,25 @@ import * as path from "path"; import * as electron from "electron"; -import * as electronAcrylic from "electron-acrylic-window" +// import * as electronAcrylic from "electron-acrylic-window" import * as windowStateKeeper from "electron-window-state"; import * as express from "express"; import * as getPort from "get-port"; import * as yt from "youtube-search-without-api-key"; +import * as fs from "fs"; +import {Stream} from "stream"; export class Win { - win: any | undefined; + win: any | undefined = null; app: electron.App | undefined; - private srcPath: string = path.join(__dirname, "../../src"); - private resourcePath: string = path.join(__dirname, "../../resources"); + private paths: any = { + srcPath: path.join(__dirname, "../../src"), + resourcePath: path.join(__dirname, "../../resources"), + ciderCache: path.resolve(electron.app.getPath("userData"), "CiderCache"), + themes: path.resolve(electron.app.getPath("userData"), "Themes"), + plugins: path.resolve(electron.app.getPath("userData"), "Plugins"), + } + private audioStream: any = new Stream.PassThrough(); private clientPort: number = 0; private EnvironmentVariables: object = { "env": { @@ -20,16 +28,17 @@ export class Win { } }; private options: any = { - icon: path.join(this.resourcePath, `icons/icon.ico`), + icon: path.join(this.paths.resourcePath, `icons/icon.` + (process.platform === "win32" ? "ico" : "png")), width: 1024, height: 600, x: undefined, y: undefined, - minWidth: 850, - minHeight: 400, + minWidth: 844, + minHeight: 410, frame: false, title: "Cider", - transparent: process.platform === "darwin", + vibrancy: 'dark', + // transparent: true, hasShadow: false, webPreferences: { webviewTag: true, @@ -42,16 +51,14 @@ export class Win { sandbox: true, nativeWindowOpen: true, contextIsolation: false, - preload: path.join(this.srcPath, 'preload/cider-preload.js') + preload: path.join(this.paths.srcPath, './preload/cider-preload.js') } }; /** * Creates the browser window */ - async createWindow(): Promise { - this.clientPort = await getPort({port: 9000}); - + createWindow(): void { // Load the previous state with fallback to defaults const windowState = windowStateKeeper({ defaultWidth: 1024, @@ -60,61 +67,75 @@ export class Win { this.options.width = windowState.width; this.options.height = windowState.height; - this.startWebServer() - - if (process.platform === "win32") { - this.win = new electronAcrylic.BrowserWindow(this.options); - } else { - this.win = new electron.BrowserWindow(this.options); - } - - // Create the browser window. - - console.debug('Browser window created'); + // Start the webserver for the browser window to load + this.startWebServer().then(() => { + if (process.platform === "win32") { + // this.win = new electronAcrylic.BrowserWindow(this.options); + } else { + this.win = new electron.BrowserWindow(this.options); + } + }) // and load the renderer. this.startSession(this.win); this.startHandlers(this.win); + // Register listeners on Window to track size and position of the Window. + windowState.manage(this.win); + return this.win; } /** * Starts the webserver for the renderer process. */ - private startWebServer(): void { - const webapp = express(); - const webRemotePath = path.join(this.srcPath, 'renderer'); - webapp.set("views", path.join(webRemotePath, "views")); - webapp.set("view engine", "ejs"); + public async startWebServer(): Promise { + this.clientPort = await getPort({port: 9000}); + const app = express(); - webapp.use(function (req, res, next) { - // if not localhost - // @ts-ignore - if (req.url.includes("audio.webm") || (req.headers.host.includes("localhost") && req.headers["user-agent"].includes("Cider"))) { - next(); - } - }); + // app.use(express.static(path.join(this.paths.srcPath, './renderer/'))); // this breaks everything + app.set("views", path.join(this.paths.srcPath, './renderer/views')); + app.set("view engine", "ejs"); - webapp.use(express.static(webRemotePath)); - webapp.get('/', (req, res) => { - //res.sendFile(path.join(webRemotePath, 'index_old.html')); - console.log(req) + // this is also causing issues + // app.use((req, res, next) => { + // // if not localhost + // + // // @ts-ignore + // if (req.url.includes("audio.webm") || (req.headers.host.includes("localhost") && req.headers["user-agent"].includes("Cider"))) { + // next(); + // } + // }); + + app.get('/', (req, res) => { + // res.send("Hello world!"); + // res.sendFile(path.join(webRemotePath, 'index_old.html')); res.render("main", this.EnvironmentVariables) }); - // webelectron.app.get('/audio.webm', (req, res) => { + + // app.get('/audio.webm', (req, res) => { // try { // req.connection.setTimeout(Number.MAX_SAFE_INTEGER); - // this.audiostream.on('data', (data) => { + // // CiderBase.requests.push({req: req, res: res}); + // // var pos = CiderBase.requests.length - 1; + // // req.on("close", () => { + // // console.info("CLOSED", CiderBase.requests.length); + // // requests.splice(pos, 1); + // // console.info("CLOSED", CiderBase.requests.length); + // // }); + // this.audioStream.on('data', (data: any) => { // try { // res.write(data); // } catch (ex) { // console.log(ex) // } // }) - // } catch (ex) { console.log(ex) } + // } catch (ex) { + // console.log(ex) + // } // }); - webapp.listen(this.clientPort, () => { + + app.listen(this.clientPort, () => { console.log(`Cider client port: ${this.clientPort}`); }); } @@ -122,8 +143,7 @@ export class Win { /** * Starts the session for the renderer process. */ - private startSession(win: any): void {const self = this; - + private startSession(win: any): void { // intercept "https://js-cdn.music.apple.com/hls.js/2.141.0/hls.js/hls.js" and redirect to local file "./apple-hls.js" instead win.webContents.session.webRequest.onBeforeRequest( { @@ -132,7 +152,7 @@ export class Win { (details: { url: string | string[]; }, callback: (arg0: { redirectURL?: string; cancel?: boolean; }) => void) => { if (details.url.includes("hls.js")) { callback({ - redirectURL: `http://localhost:${self.clientPort}/apple-hls.js` + redirectURL: `http://localhost:${this.clientPort}/apple-hls.js` }) } else { callback({ @@ -146,20 +166,15 @@ export class Win { if (details.url === "https://buy.itunes.apple.com/account/web/info") { details.requestHeaders['sec-fetch-site'] = 'same-site'; details.requestHeaders['DNT'] = '1'; - let ItsPod = await win.webContents.executeJavaScript(`window.localStorage.getItem("music.ampwebplay.itspod")`) - if (ItsPod != null) - details.requestHeaders['Cookie'] = `itspod=${ItsPod}` + let itspod = await win.webContents.executeJavaScript(`window.localStorage.getItem("music.ampwebplay.itspod")`) + if (itspod != null) + details.requestHeaders['Cookie'] = `itspod=${itspod}` } callback({requestHeaders: details.requestHeaders}) }) - const location = `http://localhost:${this.clientPort}/` - console.log('yeah') + let location = `http://localhost:${this.clientPort}/` win.loadURL(location) - .then(() => { - console.debug(`Cider client location: ${location}`); - }) - .catch(console.error); } /** @@ -167,6 +182,116 @@ export class Win { * @param win The BrowserWindow */ private startHandlers(win: any): void { + + /********************************************************************************************************************** + * ipcMain Events + ****************************************************************************************************************** */ + electron.ipcMain.on("cider-platform", (event) => { + event.returnValue = process.platform + }) + + electron.ipcMain.on("get-gpu-mode", (event) => { + event.returnValue = process.platform + }) + + electron.ipcMain.on("is-dev", (event) => { + event.returnValue = !electron.app.isPackaged + }) + electron.ipcMain.on('close', () => { // listen for close event + win.close(); + }) + + electron.ipcMain.on('put-library-songs', (event, arg) => { + fs.writeFileSync(path.join(this.paths.ciderCache, "library-songs.json"), JSON.stringify(arg)) + }) + + electron.ipcMain.on('put-library-artists', (event, arg) => { + fs.writeFileSync(path.join(this.paths.ciderCache, "library-artists.json"), JSON.stringify(arg)) + }) + + electron.ipcMain.on('put-library-albums', (event, arg) => { + fs.writeFileSync(path.join(this.paths.ciderCache, "library-albums.json"), JSON.stringify(arg)) + }) + + electron.ipcMain.on('put-library-playlists', (event, arg) => { + fs.writeFileSync(path.join(this.paths.ciderCache, "library-playlists.json"), JSON.stringify(arg)) + }) + + electron.ipcMain.on('put-library-recentlyAdded', (event, arg) => { + fs.writeFileSync(path.join(this.paths.ciderCache, "library-recentlyAdded.json"), JSON.stringify(arg)) + }) + + electron.ipcMain.on('get-library-songs', (event) => { + let librarySongs = fs.readFileSync(path.join(this.paths.ciderCache, "library-songs.json"), "utf8") + event.returnValue = JSON.parse(librarySongs) + }) + + electron.ipcMain.on('get-library-artists', (event) => { + let libraryArtists = fs.readFileSync(path.join(this.paths.ciderCache, "library-artists.json"), "utf8") + event.returnValue = JSON.parse(libraryArtists) + }) + + electron.ipcMain.on('get-library-albums', (event) => { + let libraryAlbums = fs.readFileSync(path.join(this.paths.ciderCache, "library-albums.json"), "utf8") + event.returnValue = JSON.parse(libraryAlbums) + }) + + electron.ipcMain.on('get-library-playlists', (event) => { + let libraryPlaylists = fs.readFileSync(path.join(this.paths.ciderCache, "library-playlists.json"), "utf8") + event.returnValue = JSON.parse(libraryPlaylists) + }) + + electron.ipcMain.on('get-library-recentlyAdded', (event) => { + let libraryRecentlyAdded = fs.readFileSync(path.join(this.paths.ciderCache, "library-recentlyAdded.json"), "utf8") + event.returnValue = JSON.parse(libraryRecentlyAdded) + }) + + electron.ipcMain.handle('getYTLyrics', async (event, track, artist) => { + const u = track + " " + artist + " official video"; + return await yt.search(u) + }) + + // electron.ipcMain.handle('getStoreValue', (event, key, defaultValue) => { + // return (defaultValue ? app.cfg.get(key, true) : app.cfg.get(key)); + // }); + // + // electron.ipcMain.handle('setStoreValue', (event, key, value) => { + // app.cfg.set(key, value); + // }); + // + // electron.ipcMain.on('getStore', (event) => { + // event.returnValue = app.cfg.store + // }) + // + // electron.ipcMain.on('setStore', (event, store) => { + // app.cfg.store = store + // }) + + electron.ipcMain.handle('setVibrancy', (event, key, value) => { + win.setVibrancy(value) + }); + + electron.ipcMain.on('maximize', () => { // listen for maximize event + if (win.isMaximized()) { + win.unmaximize() + } else { + win.maximize() + } + }) + + electron.ipcMain.on('minimize', () => { // listen for minimize event + win.minimize(); + }) + + // Set scale + electron.ipcMain.on('setScreenScale', (event, scale) => { + win.webContents.setZoomFactor(parseFloat(scale)) + }) + + /* ********************************************************************************************* + * Window Events + * **********************************************************************************************/ + if (process.platform === "win32") { let WND_STATE = { MINIMIZED: 0, @@ -187,83 +312,26 @@ export class Win { wndState = WND_STATE.FULL_SCREEN } else if (isMaximized && state !== WND_STATE.MAXIMIZED) { wndState = WND_STATE.MAXIMIZED - win.webContents.executeJavaScript(`electron.app.chrome.maximized = true`) + win.webContents.executeJavaScript(`app.chrome.maximized = true`) } else if (state !== WND_STATE.NORMAL) { wndState = WND_STATE.NORMAL - win.webContents.executeJavaScript(`electron.app.chrome.maximized = false`) + win.webContents.executeJavaScript(`app.chrome.maximized = false`) } }) } + win.on("closed", () => { + this.win = null + }) + // Set window Handler win.webContents.setWindowOpenHandler((x: any) => { if (x.url.includes("apple") || x.url.includes("localhost")) { return {action: "allow"} } - electron.shell.openExternal(x.url).catch(() => { - }) - return { - action: 'deny' - } + electron.shell.openExternal(x.url).catch(console.error) + return {action: 'deny'} }) - //------------------------------------------------------------------------------- - // Renderer IPC Listeners - //------------------------------------------------------------------------------- - - electron.ipcMain.on("cider-platform", (event) => { - event.returnValue = process.platform - }) - - electron.ipcMain.on("get-gpu-mode", (event) => { - event.returnValue = process.platform - }) - - electron.ipcMain.on("is-dev", (event) => { - event.returnValue = !electron.app.isPackaged - }) - - // IPC stuff (listeners) - electron.ipcMain.on('close', () => { // listen for close event - win.close(); - }) - - electron.ipcMain.handle('getYTLyrics', async (event, track, artist) => { - const u = track + " " + artist + " official video"; - return await yt.search(u) - }) - - // electron.ipcMain.handle('getStoreValue', (event, key, defaultValue) => { - // return (defaultValue ? electron.app.cfg.get(key, true) : electron.app.cfg.get(key)); - // }); - // - // electron.ipcMain.handle('setStoreValue', (event, key, value) => { - // electron.app.cfg.set(key, value); - // }); - // - // electron.ipcMain.on('getStore', (event) => { - // event.returnValue = electron.app.cfg.store - // }) - // - // electron.ipcMain.on('setStore', (event, store) => { - // electron.app.cfg.store = store - // }) - - electron.ipcMain.on('maximize', () => { // listen for maximize event - if (win.isMaximized()) { - win.unmaximize() - } else { - win.maximize() - } - }) - - electron.ipcMain.on('minimize', () => { // listen for minimize event - win.minimize(); - }) - - // Set scale - electron.ipcMain.on('setScreenScale', (event, scale) => { - win.webContents.setZoomFactor(parseFloat(scale)) - }) } } \ No newline at end of file diff --git a/src/main/cider-base.js b/src/main/cider-base.js deleted file mode 100644 index 0b77d88d..00000000 --- a/src/main/cider-base.js +++ /dev/null @@ -1,90 +0,0 @@ -const lastfm = require('./plugins/lastfm'); -const win = require('./base/win') - -// Analytics for debugging. -const ElectronSentry = require("@sentry/electron"); -const {app} = require("electron"); -ElectronSentry.init({dsn: "https://68c422bfaaf44dea880b86aad5a820d2@o954055.ingest.sentry.io/6112214"}); - -module.exports = { - - //------------------------------------------------------------------------------- - // Public Methods - //------------------------------------------------------------------------------- - - /** - * Starts the application (called on on-ready). - Starts BrowserWindow and WebServer - */ - Start() { - app.win = win.createBrowserWindow() - }, - - /** - * Initializes the main application (run before on-ready) - */ - async Init() { - // Initialize the config. - const {init} = require("./base/store"); - await init() - - //------------------------------------------------------------------------------- - // Append Commandline Arguments - //------------------------------------------------------------------------------- - - // Hardware Acceleration - // Enable WebGPU and list adapters (EXPERIMENTAL.) - // Note: THIS HAS TO BE BEFORE ANYTHING GETS INITIALIZED. - switch (app.cfg.get("visual.hw_acceleration")) { - default: - case "default": - - break; - case "webgpu": - console.info("WebGPU is enabled."); - app.commandLine.appendSwitch('enable-unsafe-webgpu') - break; - case "disabled": - console.info("Hardware acceleration is disabled."); - app.commandLine.appendSwitch('disable-gpu') - break; - } - - if (process.platform === "linux") { - app.commandLine.appendSwitch('disable-features', 'MediaSessionService'); - } - - app.commandLine.appendSwitch('high-dpi-support', 'true'); - app.commandLine.appendSwitch('force-device-scale-factor', '1'); - app.commandLine.appendSwitch('disable-pinch'); - app.commandLine.appendSwitch('js-flags', '--max-old-space-size=1024') - }, - - /** - * Handles all links being opened in the application. - */ - LinkHandler(startArgs) { - if (!startArgs) return; - console.log("lfmtoken", String(startArgs)) - if (String(startArgs).includes('auth')) { - let authURI = String(startArgs).split('/auth/')[1] - if (authURI.startsWith('lastfm')) { // If we wanted more auth options - const authKey = authURI.split('lastfm?token=')[1]; - app.cfg.set('lastfm.enabled', true); - app.cfg.set('lastfm.auth_token', authKey); - app.win.webContents.send('LastfmAuthenticated', authKey); - lastfm.authenticate() - } - } else { - const formattedSongID = startArgs.replace('ame://', '').replace('/', ''); - console.warn(`[LinkHandler] Attempting to load song id: ${formattedSongID}`); - - // setQueue can be done with album, song, url, playlist id - this.win.webContents.executeJavaScript(` - MusicKit.getInstance().setQueue({ song: '${formattedSongID}'}).then(function(queue) { - MusicKit.getInstance().play(); - }); - `).catch((err) => console.error(err)); - } - - }, -} \ No newline at end of file diff --git a/src/main/index.ts b/src/main/index.ts index 96e4f94d..b6fd45a6 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -16,7 +16,7 @@ import {Win} from "./base/win"; const Cider = new Win() app.on("ready", () => { - Cider.createWindow(); + Cider.startWebServer(); }); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/main/plugins/discordrpc.js b/src/main/plugins/discordrpc.js deleted file mode 100644 index e9bf6871..00000000 --- a/src/main/plugins/discordrpc.js +++ /dev/null @@ -1,138 +0,0 @@ -const {app} = require('electron'), - DiscordRPC = require('discord-rpc') - -module.exports = { - - /** - * Connects to Discord RPC - * @param {string} clientId - */ - connect: function (clientId) { - app.discord = {isConnected: false}; - if (app.cfg.get('general.discord_rpc') == 0) return; - - DiscordRPC.register(clientId) // Apparently needed for ask to join, join, spectate etc. - const client = new DiscordRPC.Client({transport: "ipc"}); - app.discord = Object.assign(client, {error: false, activityCache: null, isConnected: false}); - - // Login to Discord - app.discord.login({clientId}) - .then(() => { - app.discord.isConnected = true; - }) - .catch((e) => console.error(`[DiscordRPC][connect] ${e}`)); - - app.discord.on('ready', () => { - console.log(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${client.user.username} (${client.user.id})`); - - if (app.discord.activityCache) { - client.setActivity(app.discord.activityCache).catch((e) => console.error(e)); - app.discord.activityCache = null; - } - }) - - // Handles Errors - app.discord.on('error', err => { - console.error(`[DiscordRPC] ${err}`); - this.disconnect() - app.discord.isConnected = false; - }); - }, - - /** - * Disconnects from Discord RPC - */ - disconnect: function () { - if (app.cfg.get('general.discord_rpc') == 0 || !app.discord.isConnected) return; - - try { - app.discord.destroy().then(() => { - app.discord.isConnected = false; - console.log('[DiscordRPC][disconnect] Disconnected from discord.') - }).catch((e) => console.error(`[DiscordRPC][disconnect] ${e}`)); - } catch (err) { - console.error(err) - } - }, - - /** - * Sets the activity of the client - * @param {object} attributes - */ - updateActivity: function (attributes) { - if (app.cfg.get('general.discord_rpc') == 0) return; - - if (!app.discord.isConnected) { - this.connect() - } - - if (!app.discord.isConnected) return; - - // console.log('[DiscordRPC][updateActivity] Updating Discord Activity.') - - const listenURL = `https://applemusicelectron.com/p?id=${attributes.playParams.id}` - //console.log(attributes) - let ActivityObject = { - details: attributes.name, - state: `by ${attributes.artistName}`, - startTimestamp: attributes.startTime, - endTimestamp: attributes.endTime, - largeImageKey: (attributes.artwork.url.replace('{w}', '512').replace('{h}', '512')) ?? 'cider', - largeImageText: attributes.albumName, - smallImageKey: (attributes.status ? 'play' : 'pause'), - smallImageText: (attributes.status ? 'Playing' : 'Paused'), - instance: true, - buttons: [ - {label: "Listen on Cider", url: listenURL}, - ] - }; - if (ActivityObject.largeImageKey == "" || ActivityObject.largeImageKey == null) { - ActivityObject.largeImageKey = (app.cfg.get("general.discord_rpc") == 1) ? "cider" : "logo" - } - // console.log(`[LinkHandler] Listening URL has been set to: ${listenURL}`); - - if (app.cfg.get('general.discordClearActivityOnPause') == 1) { - delete ActivityObject.smallImageKey - delete ActivityObject.smallImageText - } - - // Check all the values work - if (!((new Date(attributes.endTime)).getTime() > 0)) { - delete ActivityObject.startTimestamp - delete ActivityObject.endTimestamp - } - if (!attributes.artistName) { - delete ActivityObject.state - } - if (!ActivityObject.largeImageText || ActivityObject.largeImageText.length < 2) { - delete ActivityObject.largeImageText - } - if (ActivityObject.details.length > 128) { - AcitivityObject.details = ActivityObject.details.substring(0, 125) + '...' - } - - // Clear if if needed - if (!attributes.status) { - if (app.cfg.get('general.discordClearActivityOnPause') == 1) { - app.discord.clearActivity().catch((e) => console.error(`[DiscordRPC][clearActivity] ${e}`)); - ActivityObject = null - } else - { - delete ActivityObject.startTimestamp - delete ActivityObject.endTimestamp - ActivityObject.smallImageKey = 'pause' - ActivityObject.smallImageText = 'Paused' - } - } - - if (ActivityObject) { - try { - // console.log(`[DiscordRPC][setActivity] Setting activity to ${JSON.stringify(ActivityObject)}`); - app.discord.setActivity(ActivityObject) - } catch (err) { - console.error(`[DiscordRPC][setActivity] ${err}`) - } - - } - }, -} \ No newline at end of file diff --git a/src/main/plugins/lastfm.js b/src/main/plugins/lastfm.js deleted file mode 100644 index 541cde82..00000000 --- a/src/main/plugins/lastfm.js +++ /dev/null @@ -1,153 +0,0 @@ -const {app, Notification} = require('electron'), - fs = require('fs'), - {resolve} = require('path'), - sessionPath = resolve(app.getPath('userData'), 'session.json'), - apiCredentials = require('../../../resources/lfmApiCredentials.json'), - LastfmAPI = require('lastfmapi'); - -const lfm = { - authenticateFromFile: function () { - let sessionData = require(sessionPath) - console.log("[LastFM][authenticateFromFile] Logging in with Session Info.") - app.lastfm.setSessionCredentials(sessionData.name, sessionData.key) - console.log("[LastFM][authenticateFromFile] Logged in.") - }, - - authenticate: function () { - if (app.cfg.get('lastfm.auth_token')) { - app.cfg.set('lastfm.enabled', true); - } - - if (!app.cfg.get('lastfm.enabled') || !app.cfg.get('lastfm.auth_token')) { - app.cfg.set('lastfm.enabled', false); - return - } - - const lfmAPI = new LastfmAPI({ - 'api_key': apiCredentials.key, - 'secret': apiCredentials.secret - }); - - app.lastfm = Object.assign(lfmAPI, {cachedAttributes: false, cachedNowPlayingAttributes: false}); - - fs.stat(sessionPath, function (err) { - if (err) { - console.error("[LastFM][Session] Session file couldn't be opened or doesn't exist,", err) - console.log("[LastFM][Auth] Beginning authentication from configuration") - app.lastfm.authenticate(app.cfg.get('lastfm.auth_token'), function (err, session) { - if (err) { - throw err; - } - console.log("[LastFM] Successfully obtained LastFM session info,", session); // {"name": "LASTFM_USERNAME", "key": "THE_USER_SESSION_KEY"} - console.log("[LastFM] Saving session info to disk.") - let tempData = JSON.stringify(session) - fs.writeFile(sessionPath, tempData, (err) => { - if (err) - console.log("[LastFM][fs]", err) - else { - console.log("[LastFM][fs] File was written successfully.") - lfm.authenticateFromFile() - new Notification({ - title: app.getName(), - body: "Successfully logged into LastFM using Authentication Key." - }).show() - } - }) - }); - } else { - lfm.authenticateFromFile() - } - }) - }, - - scrobbleSong: async function (attributes) { - await new Promise(resolve => setTimeout(resolve, app.cfg.get('lastfm.scrobble_after') * 1000)); - const currentAttributes = app.media; - - if (!app.lastfm || app.lastfm.cachedAttributes === attributes ) { - return - } - - if (app.lastfm.cachedAttributes) { - if (app.lastfm.cachedAttributes.playParams.id === attributes.playParams.id) return; - } - - if (currentAttributes.status && currentAttributes === attributes) { - if (fs.existsSync(sessionPath)) { - // Scrobble playing song. - if (attributes.status === true) { - app.lastfm.track.scrobble({ - 'artist': lfm.filterArtistName(attributes.artistName), - 'track': attributes.name, - 'album': attributes.albumName, - 'albumArtist': this.filterArtistName(attributes.artistName), - 'timestamp': new Date().getTime() / 1000 - }, function (err, scrobbled) { - if (err) { - return console.error('[LastFM] An error occurred while scrobbling', err); - } - - console.log('[LastFM] Successfully scrobbled: ', scrobbled); - }); - app.lastfm.cachedAttributes = attributes - } - } else { - this.authenticate(); - } - } else { - return console.log('[LastFM] Did not add ', attributes.name , '-' , lfm.filterArtistName(attributes.artistName), 'because now playing a other song.'); - } - }, - - filterArtistName: function (artist) { - if (!app.cfg.get('lastfm.enabledRemoveFeaturingArtists')) return artist; - - artist = artist.split(' '); - if (artist.includes('&')) { - artist.length = artist.indexOf('&'); - } - if (artist.includes('and')) { - artist.length = artist.indexOf('and'); - } - artist = artist.join(' '); - if (artist.includes(',')) { - artist = artist.split(',') - artist = artist[0] - } - return artist.charAt(0).toUpperCase() + artist.slice(1); - }, - - updateNowPlayingSong: function (attributes) { - if (!app.lastfm ||app.lastfm.cachedNowPlayingAttributes === attributes | !app.cfg.get('lastfm.NowPlaying')) { - return - } - - if (app.lastfm.cachedNowPlayingAttributes) { - if (app.lastfm.cachedNowPlayingAttributes.playParams.id === attributes.playParams.id) return; - } - - if (fs.existsSync(sessionPath)) { - // update Now Playing - if (attributes.status === true) { - app.lastfm.track.updateNowPlaying({ - 'artist': lfm.filterArtistName(attributes.artistName), - 'track': attributes.name, - 'album': attributes.albumName, - 'albumArtist': this.filterArtistName(attributes.artistName) - }, function (err, nowPlaying) { - if (err) { - return console.error('[LastFM] An error occurred while updating nowPlayingSong', err); - } - - console.log('[LastFM] Successfully updated nowPlayingSong', nowPlaying); - }); - app.lastfm.cachedNowPlayingAttributes = attributes - } - - } else { - this.authenticate() - } - } -} - -module.exports = lfm; \ No newline at end of file diff --git a/src/main/plugins/mpris.js b/src/main/plugins/mpris.js deleted file mode 100644 index 3c92e322..00000000 --- a/src/main/plugins/mpris.js +++ /dev/null @@ -1,113 +0,0 @@ -let mediaPlayer = null; - -module.exports = { - - /** - * Connects to the MPRIS interface. - * @param {Object} win - The BrowserWindow. - */ - connect: (win) => { - if (process.platform !== "linux") return; - - const Player = require('mpris-service'); - - mediaPlayer = Player({ - name: 'Cider', - identity: 'Cider', - supportedUriSchemes: [], - supportedMimeTypes: [], - supportedInterfaces: ['player'] - }); - mediaPlayer = Object.assign(mediaPlayer, { canQuit: true, canControl: true, canPause: true, canPlay: true, canGoNext: true }) - - - let pos_atr = {durationInMillis: 0}; - mediaPlayer.getPosition = function () { - const durationInMicro = pos_atr.durationInMillis * 1000; - const percentage = parseFloat("0") || 0; - return durationInMicro * percentage; - } - - mediaPlayer.active = true - - mediaPlayer.on('playpause', async () => { - win.webContents.executeJavaScript('MusicKitInterop.pausePlay()').catch(err => console.error(err)) - }); - - mediaPlayer.on('play', async () => { - win.webContents.executeJavaScript('MusicKitInterop.pausePlay()').catch(err => console.error(err)) - }); - - mediaPlayer.on('pause', async () => { - win.webContents.executeJavaScript('MusicKitInterop.pausePlay()').catch(err => console.error(err)) - }); - - mediaPlayer.on('next', async () => { - win.webContents.executeJavaScript('MusicKitInterop.nextTrack()').catch(err => console.error(err)) - }); - - mediaPlayer.on('previous', async () => { - win.webContents.executeJavaScript('MusicKitInterop.previousTrack()').catch(err => console.error(err)) - }); - }, - - /** - * Updates the MPRIS interface. - * @param {Object} attributes - The attributes of the track. - */ - updateAttributes: (attributes) => { - if (process.platform !== "linux") return; - - const MetaData = { - 'mpris:trackid': mediaPlayer.objectPath(`track/${attributes.playParams.id.replace(/[.]+/g, "")}`), - 'mpris:length': attributes.durationInMillis * 1000, // In microseconds - 'mpris:artUrl': (attributes.artwork.url.replace('/{w}x{h}bb', '/512x512bb')).replace('/2000x2000bb', '/35x35bb'), - 'xesam:title': `${attributes.name}`, - 'xesam:album': `${attributes.albumName}`, - 'xesam:artist': [`${attributes.artistName}`,], - 'xesam:genre': attributes.genreNames - } - - if (mediaPlayer.metadata["mpris:trackid"] === MetaData["mpris:trackid"]) { - return - } - - mediaPlayer.metadata = MetaData - }, - - /** - * Updates the playback state of the MPRIS interface. - * @param {Object} attributes - The attributes of the track. - */ - updateState: (attributes) => { - if (process.platform !== "linux") return; - - function setPlaybackIfNeeded(status) { - if (mediaPlayer.playbackStatus === status) { - return - } - mediaPlayer.playbackStatus = status; - } - - switch (attributes.status) { - case true: // Playing - setPlaybackIfNeeded('Playing'); - break; - case false: // Paused - setPlaybackIfNeeded('Paused'); - break; - default: // Stopped - setPlaybackIfNeeded('Stopped'); - break; - } - }, - - /** - * Closes the MPRIS interface. - */ - clearActivity: () => { - if (process.platform !== "linux") return; - mediaPlayer.metadata = {'mpris:trackid': '/org/mpris/MediaPlayer2/TrackList/NoTrack'} - mediaPlayer.playbackStatus = 'Stopped'; - }, -} \ No newline at end of file diff --git a/src/renderer/ameframework.css b/src/renderer/ameframework.css index d28fe2e6..7da9b6a2 100644 --- a/src/renderer/ameframework.css +++ b/src/renderer/ameframework.css @@ -98,59 +98,7 @@ input[type=range].md-slider::-webkit-slider-runnable-track { } -.md-close-btn { - -webkit-mask-image: url("ameres://icons/webui/close.svg"); - -webkit-mask-repeat: no-repeat; - -webkit-mask-position: center; - background-color: white; - opacity: 0.75; - -webkit-mask-size: contain; - height: 18px; - width: 18px; -} -.md-btn { - background: rgba(100, 100, 100, 0.5); - padding: 8px 16px; - border-radius: 4px; - font-size: 15px; - border: 1px solid rgb(100 100 100 / 35%); - box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.3), 0px 1px 1px rgba(0, 0, 0, 0.4); -} - -.md-btn.md-btn-block { - display: block; -} - -.md-btn:active { - filter: brightness(75%); -} - -.md-select { - padding: 5px 10px; - font-size: 1em; - font-family: inherit; - border-radius: 4px; - border: 1px solid rgb(100 100 100 / 35%); - box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.3), 0px 1px 1px rgba(0, 0, 0, 0.4); - background: #363636; - color: #eee; -} - -.md-select:focus { - outline: none; -} - -.md-select > option { - font-size: 1em; - font-family: inherit; - padding: 8px 16px; -} - -.md-btn.md-btn-primary { - background: var(--keyColor); - color: white; -} .md-transparent { background: transparent; @@ -179,7 +127,6 @@ input[type=range].md-slider::-webkit-slider-runnable-track { @media (prefers-color-scheme: light) { .md-btn { - background: rgb(255 255 255); box-shadow: rgb(0 0 0 / 10%) 0px 0px 1px, rgb(0 0 0 / 20%) 0px 1px 1px; border: 1px solid rgb(0 0 0 / 15%); } diff --git a/src/renderer/assets/feather/disc.svg b/src/renderer/assets/feather/disc.svg new file mode 100644 index 00000000..2595b444 --- /dev/null +++ b/src/renderer/assets/feather/disc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/folder.svg b/src/renderer/assets/feather/folder.svg new file mode 100644 index 00000000..134458b9 --- /dev/null +++ b/src/renderer/assets/feather/folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/globe.svg b/src/renderer/assets/feather/globe.svg new file mode 100644 index 00000000..0a0586d3 --- /dev/null +++ b/src/renderer/assets/feather/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/heart.svg b/src/renderer/assets/feather/heart.svg new file mode 100644 index 00000000..a083b7e2 --- /dev/null +++ b/src/renderer/assets/feather/heart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/home.svg b/src/renderer/assets/feather/home.svg new file mode 100644 index 00000000..7bb31b23 --- /dev/null +++ b/src/renderer/assets/feather/home.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/list.svg b/src/renderer/assets/feather/list.svg new file mode 100644 index 00000000..0cf5c923 --- /dev/null +++ b/src/renderer/assets/feather/list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/music.svg b/src/renderer/assets/feather/music.svg new file mode 100644 index 00000000..7bee2f7e --- /dev/null +++ b/src/renderer/assets/feather/music.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/play-circle.svg b/src/renderer/assets/feather/play-circle.svg new file mode 100644 index 00000000..8766dc7b --- /dev/null +++ b/src/renderer/assets/feather/play-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/play.svg b/src/renderer/assets/feather/play.svg new file mode 100644 index 00000000..fd76e30d --- /dev/null +++ b/src/renderer/assets/feather/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/plus-circle.svg b/src/renderer/assets/feather/plus-circle.svg new file mode 100644 index 00000000..4291ff05 --- /dev/null +++ b/src/renderer/assets/feather/plus-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/plus.svg b/src/renderer/assets/feather/plus.svg new file mode 100644 index 00000000..703c5b7b --- /dev/null +++ b/src/renderer/assets/feather/plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/radio.svg b/src/renderer/assets/feather/radio.svg new file mode 100644 index 00000000..5abfcd13 --- /dev/null +++ b/src/renderer/assets/feather/radio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/share-2.svg b/src/renderer/assets/feather/share-2.svg new file mode 100644 index 00000000..09b1c7bc --- /dev/null +++ b/src/renderer/assets/feather/share-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/share.svg b/src/renderer/assets/feather/share.svg new file mode 100644 index 00000000..df38c14d --- /dev/null +++ b/src/renderer/assets/feather/share.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/thumbs-down.svg b/src/renderer/assets/feather/thumbs-down.svg new file mode 100644 index 00000000..3e7bcd6d --- /dev/null +++ b/src/renderer/assets/feather/thumbs-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/thumbs-up.svg b/src/renderer/assets/feather/thumbs-up.svg new file mode 100644 index 00000000..5f966cd9 --- /dev/null +++ b/src/renderer/assets/feather/thumbs-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/user.svg b/src/renderer/assets/feather/user.svg new file mode 100644 index 00000000..7bb5f291 --- /dev/null +++ b/src/renderer/assets/feather/user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/x-circle.svg b/src/renderer/assets/feather/x-circle.svg new file mode 100644 index 00000000..94aad5e5 --- /dev/null +++ b/src/renderer/assets/feather/x-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/spinner.gif b/src/renderer/assets/spinner.gif new file mode 100644 index 00000000..e1b07ea2 Binary files /dev/null and b/src/renderer/assets/spinner.gif differ diff --git a/src/renderer/audio/audio.js b/src/renderer/audio/audio.js new file mode 100644 index 00000000..64118b7c --- /dev/null +++ b/src/renderer/audio/audio.js @@ -0,0 +1,99 @@ +var CiderAudio = { + context : null, + source : null, + audioNodes : { + gainNode : null, + spatialNode : null, + spatialInput: null, + }, + init: function (cb = function () { }) { + //AudioOutputs.fInit = true; + searchInt = setInterval(function () { + if (document.getElementById("apple-music-player")) { + //AudioOutputs.eqReady = true; + document.getElementById("apple-music-player").crossOrigin = "anonymous"; + CiderAudio.connectContext(document.getElementById("apple-music-player"), 0); + + cb(); + clearInterval(searchInt); + } + }, 1000); + }, + off: function(){ + try{ + CiderAudio.audioNodes.gainNode.disconnect(); + CiderAudio.audioNodes.spatialNode.disconnect(); + CiderAudio.source.connect(CiderAudio.context.destination);} catch(e){} + }, + connectContext: function (mediaElem){ + + if (!CiderAudio.context){ + CiderAudio.context = new (window.AudioContext || window.webkitAudioContext); + } + if (!CiderAudio.source){ + CiderAudio.source = CiderAudio.context.createMediaElementSource(mediaElem); + } else {try{CiderAudio.source.disconnect(CiderAudio.context.destination)}catch(e){}} + CiderAudio.audioNodes.gainNode = CiderAudio.context.createGain() + CiderAudio.source.connect(CiderAudio.audioNodes.gainNode); + CiderAudio.audioNodes.gainNode.connect(CiderAudio.context.destination); + if(app.cfg.audio.normalization){ + CiderAudio.normalizerOn() + } + if (app.cfg.audio.spatial){ + CiderAudio.spatialOn() + } + }, + normalizerOn: function (){}, + normalizerOff: function (){ + CiderAudio.audioNodes.gainNode.gain.setTargetAtTime(1, CiderAudio.context.currentTime+ 1, 0.5); + }, + spatialOn: function (){ + try{ + CiderAudio.audioNodes.gainNode.connect(CiderAudio.context.destination);} catch(e){} + CiderAudio.audioNodes.spatialNode = new ResonanceAudio(CiderAudio.context); + CiderAudio.audioNodes.spatialNode.output.connect(CiderAudio.context.destination); + let roomDimensions = { + width: 32, + height: 12, + depth: 32, + }; + let roomMaterials = { + // Room wall materials + left: 'metal', + right: 'metal', + front: 'brick-bare', + back: 'brick-bare', + down: 'acoustic-ceiling-tiles', + up: 'acoustic-ceiling-tiles', + }; + CiderAudio.audioNodes.spatialNode.setRoomProperties(roomDimensions, roomMaterials); + CiderAudio.audioNodes.spatialInput = CiderAudio.audioNodes.spatialNode.createSource(); + CiderAudio.audioNodes.gainNode.connect(CiderAudio.audioNodes.spatialInput.input); + }, + spatialOff: function (){ + try{ + CiderAudio.audioNodes.spatialNode.output.disconnect(CiderAudio.context.destination); + CiderAudio.audioNodes.gainNode.disconnect(CiderAudio.audioNodes.spatialInput.input);} catch(e){} + CiderAudio.audioNodes.gainNode.connect(CiderAudio.context.destination); + }, + sendAudio: function (){ + var options = { + mimeType : 'audio/webm; codecs=opus' + }; + var destnode = CiderAudio.context.createMediaStreamDestination(); + CiderAudio.audioNodes.gainNode.connect(destnode) + var mediaRecorder = new MediaRecorder(destnode.stream,options); + mediaRecorder.start(1); + mediaRecorder.ondataavailable = function(e) { + e.data.arrayBuffer().then(buffer => { + ipcRenderer.send('writeAudio',buffer) + } + ); + } + } + +} +if (app.cfg.advanced.AudioContext){ + CiderAudio.init() + +} \ No newline at end of file diff --git a/src/renderer/index.js b/src/renderer/index.js index ccdcd637..7a3f817e 100644 --- a/src/renderer/index.js +++ b/src/renderer/index.js @@ -5,7 +5,7 @@ var CiderContextMenu = { Menu: function (event) { this.items = [] }, - Create(event, menudata) { + async Create(event, menudata) { var menuBackground = document.createElement("div"); var menu = document.createElement("div"); menu.classList.add("context-menu-body"); @@ -17,7 +17,7 @@ var CiderContextMenu = { menu.style.zIndex = "99909"; menu.addEventListener("animationend", function () { menu.classList.remove("context-menu-open"); - }, { once: true }); + }, {once: true}); function close() { menuBackground.style.pointerEvents = "none"; @@ -25,7 +25,7 @@ var CiderContextMenu = { menu.addEventListener("animationend", function () { menuBackground.remove(); menu.remove(); - }, { once: true }); + }, {once: true}); } // when menubackground is clicked, remove it @@ -37,13 +37,25 @@ var CiderContextMenu = { document.body.appendChild(menuBackground); + if (typeof menudata.items == "object") { + menudata.items = Object.values(menudata.items); + } + + console.log(menudata); // for each item in menudata create a menu item for (var i = 0; i < menudata.items.length; i++) { let item = document.createElement("button") + + if (menudata.items[i]["disabled"] === true) { + continue + } item.tabIndex = 0 item.classList.add("context-menu-item") - item.innerHTML = menudata.items[i].name + if(menudata.items[i]["icon"]) { + item.innerHTML += `` + } + item.innerHTML += menudata.items[i].name item.onclick = menudata.items[i].action menu.appendChild(item) } @@ -62,6 +74,18 @@ var CiderContextMenu = { } } +const MusicKitObjects = { + LibraryPlaylist: function () { + this.id = "" + this.type = "library-playlist-folders" + this.href = "" + this.attributes = { + dateAdded: "", + name: "" + } + this.playlists = [] + } +} const MusicKitTools = { getHeader() { @@ -79,27 +103,28 @@ Array.prototype.limit = function (n) { return this.slice(0, n); }; -// function msToMinSec(ms) { -// let minutes = Math.floor(ms / 60000); -// let seconds = ((ms % 60000) / 1000).toFixed(0); -// return minutes + ":" + (seconds < 10 ? '0' : '') + seconds; -// } - -class NavigationEvent { - constructor(page, onnavigate, scrollPosition) { - this.page = page; - this.onnavigate = onnavigate; - this.scrollPosition = scrollPosition; +const store = new Vuex.Store({ + state: { + library: { + songs: ipcRenderer.sendSync("get-library-songs"), + albums: ipcRenderer.sendSync("get-library-albums"), + recentlyAdded: ipcRenderer.sendSync("get-library-recentlyAdded"), + playlists: ipcRenderer.sendSync("get-library-playlists") + }, + artwork: { + playerLCD: "" + } + }, + mutations: { + setLCDArtwork(state, artwork) { + state.artwork.playerLCD = artwork + } } - - navigate() { - this.onnavigate(); - document.querySelector("#app-content").scrollTop = this.scrollPosition; - } -} +}) const app = new Vue({ el: "#app", + store: store, data: { appMode: "player", ipcRenderer: ipcRenderer, @@ -117,6 +142,7 @@ const app = new Vue({ resultsSocial: {}, limit: 10 }, + fullscreenLyrics: false, playerLCD: { playbackDuration: 0, desiredDuration: 0, @@ -161,7 +187,7 @@ const app = new Vue({ sorting: "name", sortOrder: "asc", listing: [], - meta: { total: 0, progress: 0 }, + meta: {total: 0, progress: 0}, search: "", displayListing: [], downloadState: 0 // 0 = not started, 1 = in progress, 2 = complete, 3 = empty library @@ -177,7 +203,7 @@ const app = new Vue({ sorting: ["dateAdded", "name"], // [0] = recentlyadded page, [1] = albums page sortOrder: ["desc", "asc"], // [0] = recentlyadded page, [1] = albums page listing: [], - meta: { total: 0, progress: 0 }, + meta: {total: 0, progress: 0}, search: "", displayListing: [], downloadState: 0 // 0 = not started, 1 = in progress, 2 = complete, 3 = empty library @@ -193,7 +219,7 @@ const app = new Vue({ sorting: ["dateAdded", "name"], // [0] = recentlyadded page, [1] = albums page sortOrder: ["desc", "asc"], // [0] = recentlyadded page, [1] = albums page listing: [], - meta: { total: 0, progress: 0 }, + meta: {total: 0, progress: 0}, search: "", displayListing: [], downloadState: 0 // 0 = not started, 1 = in progress, 2 = complete, 3 = empty library @@ -206,7 +232,10 @@ const app = new Vue({ id: "" }, mxmtoken: "", + mkIsReady: false, playerReady: false, + animateBackground: false, + currentArtUrl: '', lyricon: false, currentTrackID: '', currentTrackIDBG: '', @@ -230,7 +259,7 @@ const app = new Vue({ "attributes": { "name": "Cider User", "handle": "CiderUser", - "artwork": { "url": "./assets/logocut.png" } + "artwork": {"url": "./assets/logocut.png"} } }, menuOpened: false, @@ -247,7 +276,7 @@ const app = new Vue({ }, prevButtonBackIndicator: false, currentSongInfo: {}, - page: "browse", + page: "", pageHistory: [], songstest: false, hangtimer: null, @@ -255,8 +284,13 @@ const app = new Vue({ routes: ["browse", "listen_now", "radio"], musicBaseUrl: "https://api.music.apple.com/", modals: { - addToPlaylist: false + addToPlaylist: false, + spatialProperties: false }, + socialBadges: { + badgeMap: {}, + version: "" + } }, watch: { cfg: { @@ -280,7 +314,31 @@ const app = new Vue({ }, }, methods: { + async getSvgIcon(url) { + let response = await fetch(url); + let data = await response.text(); + return data; + }, + getSocialBadges(cb = () => { + }) { + let self = this + try { + app.mk.api.socialBadgingMap().then(data => { + self.socialBadges.badgeMap = data.badgingMap + cb(data.badgingMap) + }) + } catch (ex) { + this.socialBadges.badgeMap = {} + } + }, + addFavorite(id, type) { + this.cfg.home.favoriteItems.push({ + id: id, + type: type + }); + }, modularUITest(val = false) { + this.fullscreenLyrics = val; if (val) { document.querySelector("#app-main").classList.add("modular-fs") } else { @@ -299,10 +357,13 @@ const app = new Vue({ default: document.querySelector("html").style.background = ""; document.querySelector("body").style.background = ""; + document.querySelector("body").classList.remove("notransparency") break; case "disabled": document.querySelector("html").style.background = "#222"; - document.querySelector("body").style.background = "#222"; + document.querySelector("body").classList.add("notransparency") + + // document.querySelector("body").style.background = "#222"; break; } }, @@ -315,23 +376,39 @@ const app = new Vue({ promptAddToPlaylist() { app.modals.addToPlaylist = true; }, - addSelectedToPlaylist(playlist_id) { + async addSelectedToPlaylist(playlist_id) { let self = this let pl_items = [] for (let i = 0; i < self.selectedMediaItems.length; i++) { - if (self.selectedMediaItems[i].kind == "song") { + if (self.selectedMediaItems[i].kind == "song" || self.selectedMediaItems[i].kind == "songs") { self.selectedMediaItems[i].kind = "songs" - } else if (self.selectedMediaItems[i].kind == "album") { + pl_items.push({ + id: self.selectedMediaItems[i].id, + type: self.selectedMediaItems[i].kind + }) + } else if ((self.selectedMediaItems[i].kind == "album" || self.selectedMediaItems[i].kind == "albums") && self.selectedMediaItems[i].isLibrary != true ) { self.selectedMediaItems[i].kind = "albums" - } else if (self.selectedMediaItems[i].kind == "library-song") { - self.selectedMediaItems[i].kind = "library-songs" - } else if (self.selectedMediaItems[i].kind == "library-album") { + let res = await self.mk.api.albumRelationship(self.selectedMediaItems[i].id,"tracks"); + let ids = res.map(function(i) {return {id:i.id, type: i.type}}) + pl_items = pl_items.concat(ids) + } else if (self.selectedMediaItems[i].kind == "library-song" || self.selectedMediaItems[i].kind == "library-songs") { + self.selectedMediaItems[i].kind = "library-songs" + pl_items.push({ + id: self.selectedMediaItems[i].id, + type: self.selectedMediaItems[i].kind + }) + } else if ((self.selectedMediaItems[i].kind == "library-album" || self.selectedMediaItems[i].kind == "library-albums") || (self.selectedMediaItems[i].kind == "album" && self.selectedMediaItems[i].isLibrary == true )) { self.selectedMediaItems[i].kind = "library-albums" + let res = await self.mk.api.library.albumRelationship(self.selectedMediaItems[i].id,"tracks"); + let ids = res.map(function(i) {return {id:i.id, type: i.type}}) + pl_items = pl_items.concat(ids) + } else { + pl_items.push({ + id: self.selectedMediaItems[i].id, + type: self.selectedMediaItems[i].kind + }) } - pl_items.push({ - id: self.selectedMediaItems[i].id, - type: self.selectedMediaItems[i].kind - }) + } this.modals.addToPlaylist = false this.mk.api.library.appendTracksToPlaylist(playlist_id, pl_items).then(() => { @@ -344,7 +421,9 @@ const app = new Vue({ let self = this clearTimeout(this.hangtimer) this.mk = MusicKit.getInstance() - this.mk.authorize() + this.mk.authorize().then(() => { + self.mkIsReady = true + }) this.$forceUpdate() if (this.isDev) { this.mk.privateEnabled = true @@ -363,7 +442,7 @@ const app = new Vue({ "attributes": { "name": "Cider User", "handle": "CiderUser", - "artwork": { "url": "./assets/logocut.png" } + "artwork": {"url": "./assets/logocut.png"} } } } @@ -390,6 +469,22 @@ const app = new Vue({ window.localStorage.setItem("currentQueue", JSON.stringify(app.mk.queue.items)) }; + // Load saved quality + switch (app.cfg.audio.quality) { + case "extreme": + app.mk.bitrate = app.cfg.audio.quality = 990 + break; + case "high": + app.mk.bitrate = app.cfg.audio.quality = 256 + break; + case "low": + app.mk.bitrate = app.cfg.audio.quality = 64 + break; + default: + app.mk.bitrate = app.cfg.audio.quality + } + + // load last played track try { let lastItem = window.localStorage.getItem("currentTrack") @@ -399,7 +494,7 @@ const app = new Vue({ lastItem = JSON.parse(lastItem) let kind = lastItem.attributes.playParams.kind; let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind; - app.mk.setQueue({ [truekind]: [lastItem.attributes.playParams.id] }) + app.mk.setQueue({[truekind]: [lastItem.attributes.playParams.id]}) app.mk.mute() setTimeout(() => { app.mk.play().then(() => { @@ -417,8 +512,9 @@ const app = new Vue({ for (id of ids) { if (!(i == 0 && ids[0] == lastItem.attributes.playParams.id)) { try { - app.mk.playLater({ songs: [id] }) - } catch (err) { } + app.mk.playLater({songs: [id]}) + } catch (err) { + } } i++; } @@ -433,10 +529,20 @@ const app = new Vue({ } - } catch (e) { console.log(e) } + } catch (e) { + console.log(e) + } MusicKit.getInstance().videoContainerElement = document.getElementById("apple-music-video-player") + ipcRenderer.on('SoundCheckTag', (event, tag) => { + let replaygain = self.parseSCTagToRG(tag) + try { + CiderAudio.audioNodes.gainNode.gain.value = (Math.min(Math.pow(10, (replaygain.gain / 20)), (1 / replaygain.peak))) + } catch (e) { + + } + }) this.mk.addEventListener(MusicKit.Events.playbackTimeDidChange, (a) => { self.lyriccurrenttime = self.mk.currentPlaybackTime @@ -449,11 +555,35 @@ const app = new Vue({ self.$refs.queue.updateQueue(); } this.currentSongInfo = a + + + if (app.cfg.audio.normalization) { + // get unencrypted audio previews to get SoundCheck's normalization tag + try { + let previewURL = null + try { + previewURL = app.mk.nowPlayingItem.previewURL + } catch (e) { + } + if (!previewURL) { + app.mk.api.song(app.mk.nowPlayingItem._songId ?? app.mk.nowPlayingItem.relationships.catalog.data[0].id).then((response) => { + previewURL = response.attributes.previews[0].url + if (previewURL) + ipcRenderer.send('getPreviewURL', previewURL) + }) + } else { + if (previewURL) + ipcRenderer.send('getPreviewURL', previewURL) + } + + } catch (e) { + } + } + try { a = a.item.attributes; } catch (_) { } - let type = (self.mk.nowPlayingItem != null) ? self.mk.nowPlayingItem["type"] ?? '' : ''; if (type.includes("musicVideo") || type.includes("uploadedVideo") || type.includes("music-movie")) { @@ -466,20 +596,21 @@ const app = new Vue({ self.chrome.artworkReady = false self.lyrics = [] self.richlyrics = [] - app.getNowPlayingArtwork(42); + app.getCurrentArtURL(); + // app.getNowPlayingArtwork(42); app.getNowPlayingArtworkBG(32); - app.loadLyrics() + app.loadLyrics(); // Playback Notifications - if ((app.platform === "darwin" || app.platform === "linux") && !document.hasFocus()) { + if ((app.platform === "darwin" || app.platform === "linux") && !document.hasFocus() && a.artistName && a.artwork && a.name) { if (this.notification) { this.notification.close() } this.notification = new Notification(a.name, { body: a.artistName, - icon: (a.artwork.url.replace('/{w}x{h}bb', '/512x512bb')).replace('/2000x2000bb', '/35x35bb'), - silent: true - }) + icon: a.artwork.url.replace('/{w}x{h}bb', '/512x512bb').replace('/2000x2000bb', '/35x35bb'), + silent: true, + }); } }) @@ -493,9 +624,12 @@ const app = new Vue({ document.body.removeAttribute("loading") if (window.location.hash != "") { this.appRoute(window.location.hash) + } else { + this.page = "home" } setTimeout(() => { + this.getSocialBadges() this.getBrowsePage(); this.$forceUpdate() }, 500) @@ -541,10 +675,32 @@ const app = new Vue({ }) } }, + getPlaylistFolderChildren(id) { + return this.playlists.listing.filter(playlist => { + if (playlist.parent == id) { + return playlist + } + }) + }, async refreshPlaylists() { let self = this this.apiCall('https://api.music.apple.com/v1/me/library/playlist-folders/p.playlistsroot/children/', res => { self.playlists.listing = res.data + self.playlists.listing.forEach(playlist => { + playlist.parent = "p.playlistsroot" + }) + self.sortPlaylists() + }) + }, + sortPlaylists() { + this.playlists.listing.sort((a, b) => { + if (a.type === "library-playlist-folders" && b.type !== "library-playlist-folders") { + return -1 + } else if (a.type !== "library-playlist-folders" && b.type === "library-playlist-folders") { + return 1 + } else { + return 0 + } }) }, playlistHeaderContextMenu(event) { @@ -555,30 +711,54 @@ const app = new Vue({ action: () => { this.newPlaylist() } - } - ] - } - CiderContextMenu.Create(event, menu) - }, - playlistContextMenu(event, playlist_id) { - let menu = { - items: [ + }, { - name: "Delete from library", + name: "New Playlist Folder", action: () => { - this.deletePlaylist(playlist_id) + this.newPlaylistFolder() } } ] } CiderContextMenu.Create(event, menu) }, - async editPlaylist(id, name = "New Playlist") { + async editPlaylistFolder(id, name = "New Playlist") { let self = this - await app.mk.api.library.editPlaylist(id, { name: name }).then(res => { + this.mk.api.v3.music( + `/v1/me/library/playlist-folders/${id}`, + {}, + { + fetchOptions: { + method: "PATCH", + body: JSON.stringify({ + attributes: {name: name} + }) + } + } + ).then(res => { self.refreshPlaylists() }) }, + async editPlaylist(id, name = "New Playlist") { + let self = this + this.mk.api.v3.music( + `/v1/me/library/playlists/${id}`, + {}, + { + fetchOptions: { + method: "PATCH", + body: JSON.stringify({ + attributes: {name: name} + }) + } + } + ).then(res => { + self.refreshPlaylists() + }) + }, + copyToClipboard(str) { + navigator.clipboard.writeText(str) + }, newPlaylist(name = "New Playlist", tracks = []) { let self = this let request = { @@ -592,9 +772,17 @@ const app = new Vue({ self.appRoute(`playlist_` + res.id); self.showingPlaylist = []; self.getPlaylistFromID(app.page.substring(9)) + self.playlists.listing.push({ + id: res.id, + attributes: { + name: name + }, + parent: "p.playlistsroot" + }) + self.sortPlaylists() setTimeout(() => { app.refreshPlaylists() - }, 3000) + }, 8000) }) }, deletePlaylist(id) { @@ -617,11 +805,11 @@ const app = new Vue({ app.appRoute("collection-list") }, async showArtistView(artist, title, view) { - let response = await this.mk.api.artistView(artist, view, {}, { view: view, includeResponseMeta: !0 }) + let response = await this.mk.api.artistView(artist, view, {}, {view: view, includeResponseMeta: !0}) await this.showCollection(response, title, "artists") }, async showRecordLabelView(label, title, view) { - let response = await this.mk.api.recordLabelView(label, view, {}, { view: view, includeResponseMeta: !0 }) + let response = await this.mk.api.recordLabelView(label, view, {}, {view: view, includeResponseMeta: !0}) await this.showCollection(response, title, "record-labels") }, async showSearchView(term, group, title) { @@ -650,7 +838,7 @@ const app = new Vue({ omit: { resource: ["autos"] } - }, { groups: group, includeResponseMeta: !0 }) + }, {groups: group, includeResponseMeta: !0}) console.log(response) let responseFormat = { data: response[group].data.data, @@ -659,10 +847,10 @@ const app = new Vue({ } await this.showCollection(responseFormat, title, "search") }, - async getPlaylistContinuous(response) { + async getPlaylistContinuous(response, transient = false) { let self = this let playlistId = response.id - this.playlists.loadingState = 0 + if (!transient) this.playlists.loadingState = 0 this.showingPlaylist = response if (!response.relationships.tracks.next) { this.playlists.loadingState = 1 @@ -686,7 +874,7 @@ const app = new Vue({ getPlaylistTracks(response.relationships.tracks.next) }, - async getPlaylistFromID(id) { + async getPlaylistFromID(id, transient = false) { let self = this const params = { include: "tracks", @@ -697,19 +885,18 @@ const app = new Vue({ "fields[catalog]": "artistUrl,albumUrl", "fields[songs]": "artistUrl,albumUrl" } - - this.playlists.loadingState = 0 + if (!transient) {this.playlists.loadingState = 0;} let playlistId = '' try { app.mk.api.library.playlist(id, params).then(res => { - self.getPlaylistContinuous(res) + self.getPlaylistContinuous(res, transient) }) } catch (e) { console.log(e); try { app.mk.api.library.playlist(id, params).then(res => { - self.getPlaylistContinuous(res) + self.getPlaylistContinuous(res, transient) }) } catch (err) { console.log(err) @@ -726,7 +913,7 @@ const app = new Vue({ "fields[albums]": "artistName,artistUrl,artwork,contentRating,editorialArtwork,editorialVideo,name,playParams,releaseDate,url,trackCount", "limit[artists:top-songs]": 20, "art[url]": "f" - }, { includeResponseMeta: !0 }) + }, {includeResponseMeta: !0}) console.log(artistData) this.artistPage.data = artistData.data[0] this.page = "artist-page" @@ -821,7 +1008,7 @@ const app = new Vue({ kind: page, id: id, attributes: { - playParams: { kind: page, id: id } + playParams: {kind: page, id: id} } }) }, @@ -866,8 +1053,9 @@ const app = new Vue({ window.location.hash = `${kind}/${id}` document.querySelector("#app-content").scrollTop = 0 } else if (!kind.toString().includes("radioStation") && !kind.toString().includes("song") && !kind.toString().includes("musicVideo") && !kind.toString().includes("uploadedVideo") && !kind.toString().includes("music-movie")) { + let params = {extend: "editorialVideo"} app.page = (kind) + "_" + (id); - app.getTypeFromID((kind), (id), (isLibrary), { extend: "editorialVideo" }); + app.getTypeFromID((kind), (id), (isLibrary), params); window.location.hash = `${kind}/${id}` document.querySelector("#app-content").scrollTop = 0 } else { @@ -887,7 +1075,7 @@ const app = new Vue({ } }, async getNowPlayingItemDetailed(target) { - let u = await app.mkapi(app.mk.nowPlayingItem.playParams.kind, (app.mk.nowPlayingItem.songId == -1), (app.mk.nowPlayingItem.songId != -1) ? app.mk.nowPlayingItem.songId : app.mk.nowPlayingItem["id"], { "include[songs]": "albums,artists" }); + let u = await app.mkapi(app.mk.nowPlayingItem.playParams.kind, (app.mk.nowPlayingItem.songId == -1), (app.mk.nowPlayingItem.songId != -1) ? app.mk.nowPlayingItem.songId : app.mk.nowPlayingItem["id"], {"include[songs]": "albums,artists"}); app.searchAndNavigate(u, target) }, async searchAndNavigate(item, target) { @@ -986,17 +1174,13 @@ const app = new Vue({ } if (labelId != "") { app.showingPlaylist = [] - await app.getTypeFromID("recordLabel", labelId, false, { views: 'top-releases,latest-releases,top-artists' }); + await app.getTypeFromID("recordLabel", labelId, false, {views: 'top-releases,latest-releases,top-artists'}); app.page = "recordLabel_" + labelId; } break; } }, - pushNavigationEvent(item) { - let self = this - - }, exitMV() { MusicKit.getInstance().stop() document.getElementById("apple-music-video-container").style.display = "none"; @@ -1012,7 +1196,7 @@ const app = new Vue({ let isLibrary = item.attributes.playParams ? (item.attributes.playParams.isLibrary ?? false) : false; console.log(kind, id, isLibrary) if (kind.includes("artist")) { - app.mk.setStationQueue({ artist: 'a-' + id }).then(() => { + app.mk.setStationQueue({artist: 'a-' + id}).then(() => { app.mk.play() }) } else { @@ -1036,8 +1220,7 @@ const app = new Vue({ } finally { if (kind == "appleCurator") { app.appleCurator = a - } - else { + } else { this.getPlaylistContinuous(a) } } @@ -1310,11 +1493,11 @@ const app = new Vue({ } self.library.songs.downloadState = 1 if (downloaded == null) { - app.mk.api.library.songs("", params, { includeResponseMeta: !0 }).then((response) => { + app.mk.api.library.songs("", params, {includeResponseMeta: !0}).then((response) => { processChunk(response) }) } else { - downloaded.next("", params, { includeResponseMeta: !0 }).then((response) => { + downloaded.next("", params, {includeResponseMeta: !0}).then((response) => { processChunk(response) }) } @@ -1386,11 +1569,11 @@ const app = new Vue({ limit: 100, } if (downloaded == null) { - app.mk.api.library.albums("", params, { includeResponseMeta: !0 }).then((response) => { + app.mk.api.library.albums("", params, {includeResponseMeta: !0}).then((response) => { processChunk(response) }) } else { - downloaded.next("", params, { includeResponseMeta: !0 }).then((response) => { + downloaded.next("", params, {includeResponseMeta: !0}).then((response) => { processChunk(response) }) } @@ -1417,7 +1600,7 @@ const app = new Vue({ } if (downloaded.meta.total > library.length || typeof downloaded.meta.next != "undefined") { console.log(`downloading next chunk - ${library.length - } albums so far`) + } albums so far`) downloadChunk() } else { self.library.albums.listing = library @@ -1463,11 +1646,11 @@ const app = new Vue({ limit: 100, } if (downloaded == null) { - app.mk.api.library.artists("", params, { includeResponseMeta: !0 }).then((response) => { + app.mk.api.library.artists("", params, {includeResponseMeta: !0}).then((response) => { processChunk(response) }) } else { - downloaded.next("", "artists", { includeResponseMeta: !0 }).then((response) => { + downloaded.next("", "artists", {includeResponseMeta: !0}).then((response) => { processChunk(response) }) } @@ -1494,7 +1677,7 @@ const app = new Vue({ } if (downloaded.meta.total > library.length || typeof downloaded.meta.next != "undefined") { console.log(`downloading next chunk - ${library.length - } artists so far`) + } artists so far`) downloadChunk() } else { self.library.artists.listing = library @@ -1511,20 +1694,23 @@ const app = new Vue({ getTotalTime() { try { if (app.showingPlaylist.relationships.tracks.data.length > 0) { - time = Math.round([].concat(...app.showingPlaylist.relationships.tracks.data).reduce((a, { attributes: { durationInMillis } }) => a + durationInMillis, 0) / 60000); - return app.showingPlaylist.relationships.tracks.data.length + " tracks, " + time + " mins."; + let time = Math.round([].concat(...app.showingPlaylist.relationships.tracks.data).reduce((a, {attributes: {durationInMillis}}) => a + durationInMillis, 0) / 1000); + let hours = Math.floor(time / 3600) + let mins = Math.floor(time / 60) % 60 + let secs = time % 60 + return app.showingPlaylist.relationships.tracks.data.length + " tracks, " + ((hours > 0) ? (hours + (" hour" + ((hours > 1) ? "s, " : ", "))) : "") + ((mins > 0) ? (mins + (" minute" + ((mins > 1) ? "s, " : ", "))) : "") + secs + (" second" + ((secs > 1) ? "s." : ".")); } else return "" } catch (err) { return "" } }, async getLibrarySongs() { - let response = await this.mkapi("songs", true, "", { limit: 100 }, { includeResponseMeta: !0 }) + let response = await this.mkapi("songs", true, "", {limit: 100}, {includeResponseMeta: !0}) this.library.songs.listing = response.data this.library.songs.meta = response.meta }, async getLibraryAlbums() { - let response = await this.mkapi("albums", true, "", { limit: 100 }, { includeResponseMeta: !0 }) + let response = await this.mkapi("albums", true, "", {limit: 100}, {includeResponseMeta: !0}) this.library.albums.listing = response.data this.library.albums.meta = response.meta }, @@ -1554,7 +1740,7 @@ const app = new Vue({ "fields[artists]": ["name", "url"], "extend[stations]": ["airDate", "supportsAirTimeUpdates"], "meta[stations]": "inflectionPoints", - types: "artists,albums,editorial-items,library-albums,library-playlists,music-movies,music-videos,playlists,stations,uploaded-audios,uploaded-videos,activities,apple-curators,curators,tv-shows,social-profiles,social-upsells", + types: "artists,albums,editorial-items,library-albums,library-playlists,music-movies,music-videos,playlists,stations,uploaded-audios,uploaded-videos,activities,apple-curators,curators,tv-shows,social-upsells", platform: "web" }, { @@ -1618,6 +1804,35 @@ const app = new Vue({ this.getMadeForYou(attempt + 1) } }, + newPlaylistFolder(name = "New Folder") { + let self = this + this.mk.api.v3.music( + "/v1/me/library/playlist-folders/", + {}, + { + fetchOptions: { + method: "POST", + body: JSON.stringify({ + attributes: {name: name} + }) + } + } + ).then((res) => { + let playlist = (res.data.data[0]) + self.playlists.listing.push({ + id: playlist.id, + attributes: { + name: playlist.attributes.name + }, + type: "library-playlist-folders", + parent: "p.playlistsroot" + }) + self.sortPlaylists() + setTimeout(() => { + app.refreshPlaylists() + }, 13000) + }) + }, unauthorize() { this.mk.unauthorize() }, @@ -1632,7 +1847,9 @@ const app = new Vue({ } else { if (app.cfg.lyrics.enable_mxm) { this.loadMXM(); - } else { this.loadAMLyrics(); } + } else { + this.loadAMLyrics(); + } } }, loadAMLyrics() { @@ -1655,7 +1872,7 @@ const app = new Vue({ removeFromLibrary(kind, id) { let self = this let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind; - this.mk.api.library.remove({ [truekind]: id }).then((data) => { + this.mk.api.library.remove({[truekind]: id}).then((data) => { self.getLibrarySongsFull(true) }) }, @@ -1668,8 +1885,12 @@ const app = new Vue({ let ytid = result[0]['id']['videoId']; if (app.cfg.lyrics.enable_yt) { loadYT(ytid, app.cfg.lyrics.mxm_language ?? "en") - } else { app.loadMXM() } - } else { app.loadMXM() } + } else { + app.loadMXM() + } + } else { + app.loadMXM() + } function loadYT(id, lang) { let req = new XMLHttpRequest(); @@ -1945,15 +2166,15 @@ const app = new Vue({ line: "lrcInstrumental" }); } - preLrc.push({ startTime: start, endTime: end, line: element.textContent }); + preLrc.push({startTime: start, endTime: end, line: element.textContent}); endTimes.push(end); } // first line dot if (preLrc.length > 0) - preLrc.unshift({ startTime: 0, endTime: preLrc[0].startTime, line: "lrcInstrumental" }); + preLrc.unshift({startTime: 0, endTime: preLrc[0].startTime, line: "lrcInstrumental"}); } else { for (element of lyricsLines) { - preLrc.push({ startTime: 9999999, endTime: 9999999, line: element.textContent }); + preLrc.push({startTime: 9999999, endTime: 9999999, line: element.textContent}); } } this.lyrics = preLrc; @@ -2021,15 +2242,15 @@ const app = new Vue({ console.log(id, truekind, isLibrary) try { if (truekind.includes("artist")) { - app.mk.setStationQueue({ artist: 'a-' + id }).then(() => { + app.mk.setStationQueue({artist: 'a-' + id}).then(() => { app.mk.play() }) } else if (truekind == "radioStations") { - this.mk.setStationQueue({ url: raurl }).then(function (queue) { + this.mk.setStationQueue({url: raurl}).then(function (queue) { MusicKit.getInstance().play() }); } else { - this.mk.setQueue({ [truekind]: [id] }).then(function (queue) { + this.mk.setQueue({[truekind]: [id]}).then(function (queue) { MusicKit.getInstance().play() }) } @@ -2061,30 +2282,54 @@ const app = new Vue({ if (childIndex != -1) { app.mk.changeToMediaAtIndex(childIndex) } else if (item) { - app.mk.playNext({ [item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id }).then(function () { + app.mk.playNext({[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id}).then(function () { app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1) app.mk.play() }) - } else { app.mk.play() } + } else { + app.mk.play() + } }) } else { try { app.mk.stop() } catch (e) { } - this.mk.setQueue({ [truekind]: [id] }).then(function (queue) { + if (truekind == "playlists" && (id.startsWith("p.") || id.startsWith("pl.u"))){ + app.mk.playNext({[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id}).then(function () { + app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1) + app.mk.play().then(function(){ + app.mk.clearQueue().then(function () { + if ((app.showingPlaylist && app.showingPlaylist.id == id)) { + let query = app.showingPlaylist.relationships.tracks.data.map(item => new MusicKit.MediaItem(item)); + app.mk.queue.append(query) + } else { + app.getPlaylistFromID(id, true).then(function () { + let query = app.showingPlaylist.relationships.tracks.data.map(item => new MusicKit.MediaItem(item)); + app.mk.queue.append(query) + }) + } + }) + }) + + }) + } + else{ + this.mk.setQueue({[truekind]: [id]}).then(function (queue) { if (item && ((queue._itemIDs[childIndex] != item.id))) { childIndex = queue._itemIDs.indexOf(item.id) } if (childIndex != -1) { app.mk.changeToMediaAtIndex(childIndex) } else if (item) { - app.mk.playNext({ [item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id }).then(function () { + app.mk.playNext({[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id}).then(function () { app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1) app.mk.play() }) - } else { app.mk.play() } - }) + } else { + app.mk.play() + } + })} } } catch (err) { console.log(err) @@ -2166,18 +2411,39 @@ const app = new Vue({ "platform": "web", limit: 25 }).then(function (results) { - self.search.results = results - }) + self.search.results = results + }) await this.mk.api.socialSearch(this.search.term, { types: ["playlists", "social-profiles"], limit: 25, with: ["serverBubbles", "lyricSnippet"], "art[url]": "f", "art[social-profiles:url]": "c" - }, { includeResponseMeta: !0 }).then(function (results) { + }, {includeResponseMeta: !0}).then(function (results) { self.search.resultsSocial = results }) }, + async inLibrary(items = []) { + let types = [] + + for (let item of items) { + let type = item.type + if (type.slice(-1) != "s") { + type += "s" + } + let id = item.playParams.catalogId ? item.playParams.catalogId : item.id + + let index = types.findIndex(function (type) { + return type.type == this + }, type) + if (index == -1) { + types.push({type: type, id: [id]}) + } else { + types[index].id.push(id) + } + } + return await this.mk.api.catalogResources(types, {"omit[resource]": "autos", relate: "library", fields: "inLibrary"}) + }, isInLibrary(playParams) { let self = this let id = "" @@ -2213,12 +2479,22 @@ const app = new Vue({ } }, getMediaItemArtwork(url, height = 64, width) { + if(typeof url == "undefined" || url == "") { + return "https://beta.music.apple.com/assets/product/MissingArtworkMusic.svg" + } let newurl = `${url.replace('{w}', width ?? height).replace('{h}', height).replace('{f}', "webp").replace('{c}', ((width === 900) ? "sr" : "cc"))}`; - if (newurl.includes("900x516")) { newurl = newurl.replace("900x516cc", "900x516sr").replace("900x516bb", "900x516sr"); } + if (newurl.includes("900x516")) { + newurl = newurl.replace("900x516cc", "900x516sr").replace("900x516bb", "900x516sr"); + } return newurl }, + _rgbToRgb(rgb = [0,0,0]) { + // if rgb + return `rgb(${rgb[0]},${rgb[1]},${rgb[2]})` + }, getNowPlayingArtworkBG(size = 600) { + let self = this if (typeof this.mk.nowPlayingItem === "undefined") return; let bginterval = setInterval(() => { if (!this.mkReady()) { @@ -2233,7 +2509,29 @@ const app = new Vue({ this.currentTrackID = this.mk.nowPlayingItem["id"]; document.querySelector('.bg-artwork').src = ""; if (this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"]) { - document.querySelector('.bg-artwork').src = this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"].replace('{w}', size).replace('{h}', size); + getBase64FromUrl(this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"].replace('{w}', size).replace('{h}', size)).then(img =>{ + document.querySelectorAll('.bg-artwork').forEach(artwork => { + artwork.src = img; + }) + self.$store.commit("setLCDArtwork", img) + }) + + // Vibrant.from(this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"].replace('{w}', size).replace('{h}', size)).getPalette().then(palette=>{ + // let angle = "140deg" + // let gradient = "" + // let colors = Object.values(palette).filter(color=>color!=null) + // if(colors.length > 0){ + // let stops = [] + // colors.forEach(color=>{ + // stops.push(`${self._rgbToRgb(color._rgb)} 0%`) + // }) + // stops.push(`${self._rgbToRgb(colors[0]._rgb)} 100%`) + // gradient = `linear-gradient(${angle}, ${stops.join(", ")}` + // } + // + // document.querySelector("#app").style.setProperty("--bgColor", gradient) + // }).setQuantizer(Vibrant.Quantizer.WebWorker) + try { clearInterval(bginterval); } catch (err) { @@ -2258,46 +2556,72 @@ const app = new Vue({ } }, 200) }, - getNowPlayingArtwork(size = 600) { - if (typeof this.mk.nowPlayingItem === "undefined") return; - let interval = setInterval(() => { - try { - if (this.mk.nowPlayingItem && this.mk.nowPlayingItem["id"] != this.currentTrackIDBG && document.querySelector('.app-playback-controls .artwork')) { - this.currentTrackIDBG = this.mk.nowPlayingItem["id"]; - if (document.querySelector('.app-playback-controls .artwork') != null) { - clearInterval(interval); - } - document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', ''); - if (this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"]) { - document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${decodeURI((this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"])).replace('{w}', size).replace('{h}', size)}")`); - try { - clearInterval(interval); - } catch (err) { - } - } else { - this.setLibraryArt() - } - } else if (this.mk.nowPlayingItem["id"] == this.currentTrackID) { - try { - clearInterval(interval); - } catch (err) { - } - } - } catch (e) { - if (this.mk.nowPlayingItem && this.mk.nowPlayingItem["id"] && document.querySelector('.app-playback-controls .artwork')) { - this.setLibraryArt() - try { - clearInterval(interval); - } catch (err) { - } + // getNowPlayingArtwork(size = 600) { + // if (typeof this.mk.nowPlayingItem === "undefined") return; + // let interval = setInterval(() => { - } + // try { + // if (this.mk.nowPlayingItem && this.mk.nowPlayingItem["id"] != this.currentTrackIDBG && document.querySelector('.app-playback-controls .artwork')) { + // this.currentTrackIDBG = this.mk.nowPlayingItem["id"]; + // if (document.querySelector('.app-playback-controls .artwork') != null) { + // clearInterval(interval); + // } + // if (app.mk.nowPlayingItem.attributes.artwork != null && app.mk.nowPlayingItem.attributes.artwork.url != null && app.mk.nowPlayingItem.attributes.artwork.url!= '' ) { + // document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${decodeURI((this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"])).replace('{w}', size).replace('{h}', size)}")`); + // try { + // clearInterval(interval); + // } catch (err) { + // } + // } else { + // this.setLibraryArt() + // } + // } else if (this.mk.nowPlayingItem["id"] == this.currentTrackID) { + // try { + // clearInterval(interval); + // } catch (err) { + // } + // } + // } catch (e) { + // if (this.mk.nowPlayingItem && this.mk.nowPlayingItem["id"] && document.querySelector('.app-playback-controls .artwork')) { + // this.setLibraryArt() + // try { + // clearInterval(interval); + // } catch (err) { + // } + // } + + // } + // }, 200) + + + // }, + async getCurrentArtURL(){ + try{ + this.currentArtUrl = ''; + if (app.mk.nowPlayingItem != null && app.mk.nowPlayingItem.attributes != null && app.mk.nowPlayingItem.attributes.artwork != null && app.mk.nowPlayingItem.attributes.artwork.url != null && app.mk.nowPlayingItem.attributes.artwork.url!= '' ) + { + this.currentArtUrl = (this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"] ?? '').replace('{w}', 50).replace('{h}', 50); + try{ + document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);} + catch (e) {} + } else { + let data = await this.mk.api.library.song(this.mk.nowPlayingItem.id); + if (data != null && data !== "" && data.attributes != null && data.attributes.artwork != null) { + this.currentArtUrl = (data["attributes"]["artwork"]["url"] ?? '').replace('{w}', 50).replace('{h}', 50); + try{ + document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);} + catch (e) {} + } else {this.currentArtUrl = ''; + try{ + document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);} + catch (e) {} } - }, 200) - + } + }catch(e){ + } }, async setLibraryArt() { if (typeof this.mk.nowPlayingItem === "undefined") return; @@ -2320,7 +2644,12 @@ const app = new Vue({ const data = await this.mk.api.library.song(this.mk.nowPlayingItem.id) if (data != null && data !== "") { - document.querySelector('.bg-artwork').src = (data["attributes"]["artwork"]["url"]).toString(); + getBase64FromUrl((data["attributes"]["artwork"]["url"]).toString()).then(img =>{ + document.querySelector('.bg-artwork').forEach(artwork => { + artwork.src = img; + }) + self.$store.commit("setLCDArtwork", img) + }) } } catch (e) { } @@ -2328,8 +2657,8 @@ const app = new Vue({ }, quickPlay(query) { let self = this - MusicKit.getInstance().api.search(query, { limit: 2, types: 'songs' }).then(function (data) { - MusicKit.getInstance().setQueue({ song: data["songs"]['data'][0]["id"] }).then(function (queue) { + MusicKit.getInstance().api.search(query, {limit: 2, types: 'songs'}).then(function (data) { + MusicKit.getInstance().setQueue({song: data["songs"]['data'][0]["id"]}).then(function (queue) { MusicKit.getInstance().play() setTimeout(() => { self.$forceUpdate() @@ -2337,6 +2666,102 @@ const app = new Vue({ }) }) }, + async getRating(item) { + let type = item.type.slice(-1) === "s" ? item.type : item.type + "s" + let id = item.attributes.playParams.catalogId ? item.attributes.playParams.catalogId : item.id + if (item.id.startsWith("i.")) { + if(!type.startsWith("library-")) { + type = "library-" + type + } + id = item.id + } + let response = await this.mk.api.v3.music(`/v1/me/ratings/${type}?platform=web&ids=${id}`) + if(response.data.data.length != 0) { + let value = response.data.data[0].attributes.value + return value + }else{ + return 0 + } + }, + love(item) { + let type = item.type.slice(-1) === "s" ? item.type : item.type + "s" + let id = item.attributes.playParams.catalogId ? item.attributes.playParams.catalogId : item.id + if (item.id.startsWith("i.")) { + if(!type.startsWith("library-")) { + type = "library-" + type + } + id = item.id + } + this.mk.api.v3.music(`/v1/me/ratings/${type}/${id}`, {}, { + fetchOptions: + { + method: "PUT", + body: JSON.stringify( + { + "type": "rating", + "attributes": { + "value": 1 + } + } + ) + } + }) + }, + dislike(item) { + let type = item.type.slice(-1) === "s" ? item.type : item.type + "s" + let id = item.attributes.playParams.catalogId ? item.attributes.playParams.catalogId : item.id + if (item.id.startsWith("i.")) { + if(!type.startsWith("library-")) { + type = "library-" + type + } + id = item.id + } + this.mk.api.v3.music(`/v1/me/ratings/${type}/${id}`, {}, { + fetchOptions: + { + method: "PUT", + body: JSON.stringify( + { + "type": "rating", + "attributes": { + "value": -1 + } + } + ) + } + }) + }, + unlove(item) { + let type = item.type.slice(-1) === "s" ? item.type : item.type + "s" + let id = item.attributes.playParams.catalogId ? item.attributes.playParams.catalogId : item.id + if (item.id.startsWith("i.")) { + if(!type.startsWith("library-")) { + type = "library-" + type + } + id = item.id + } + this.mk.api.v3.music(`/v1/me/ratings/${type}/${id}`, {}, { + fetchOptions: + { + method: "DELETE", + } + }) + }, + volumeWheel(event) { + if (event.deltaY < 0) { + if(this.mk.volume < 1){ + if (this.mk.volume <= 0.9) { + this.mk.volume += 0.1 + } else { this.mk.volume = 1 } + } + } else if (event.deltaY > 0) { + if(this.mk.volume > 0){ + if (this.mk.volume >= 0.1){ + this.mk.volume -= 0.1 + } else {this.mk.volume = 0} + } + } + }, async apiCall(url, callback) { const xmlHttp = new XMLHttpRequest(); @@ -2374,10 +2799,12 @@ const app = new Vue({ document.querySelectorAll(".animated-artwork-video").forEach(el => { el.play() }) + this.animateBackground = true } else { document.querySelectorAll(".animated-artwork-video").forEach(el => { el.pause() }) + this.animateBackground = false } }, async nowPlayingContextMenu(event) { @@ -2388,11 +2815,11 @@ const app = new Vue({ let data_type = this.mk.nowPlayingItem.playParams.kind let item_id = this.mk.nowPlayingItem.attributes.playParams.id ?? this.mk.nowPlayingItem.id let isLibrary = this.mk.nowPlayingItem.attributes.playParams.isLibrary ?? false - let params = { "fields[songs]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library", "t": "1" } - // let res = await app.mkapi(data_type, isLibrary , item_id, params); + let params = {"fields[songs]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library", "t": "1"} + // let res = await app.mkapi(data_type, isLibrary , item_id, params); // if (res && res.relationships && res.relationships.library && res.relationships.library.data && res.relationships.library.data.length > 0) { // item_id = res.relationships.library.data[0].id - // } + // } app.selectedMediaItems = [] app.select_selectMediaItem(item_id, data_type, 0, '12344', isLibrary) let useMenu = "normal" @@ -2403,22 +2830,63 @@ const app = new Vue({ normal: { items: [ { + "icon": "./assets/feather/list.svg", "name": "Add to Playlist...", "action": function () { app.promptAddToPlaylist() } }, { + "icon": "./assets/feather/plus.svg", + "id": "addToLibrary", "name": "Add to Library...", + "disabled": false, "action": function () { app.addToLibrary(item_id); // if (!isLibrary) {app.addToLibrary(item_id); this.mk.nowPlayingItem.attributes.playParams["isLibrary"] = true} else { app.removeFromLibrary(data_type,item_id); this.mk.nowPlayingItem.attributes.playParams["isLibrary"] = false}; } }, { + "icon": "./assets/feather/heart.svg", + "id": "love", + "name": "Love", + "disabled": true, + "action": function () { + app.love(app.mk.nowPlayingItem) + } + }, + { + "icon": "./assets/feather/x-circle.svg", + "id": "unlove", + "name": "Unlove", + "disabled": true, + "action": function () { + app.unlove(app.mk.nowPlayingItem) + } + }, + { + "icon": "./assets/feather/thumbs-down.svg", + "id": "dislike", + "name": "Dislike", + "disabled": true, + "action": function () { + app.dislike(app.mk.nowPlayingItem) + } + }, + { + "icon": "./assets/feather/x-circle.svg", + "id": "undo_dislike", + "name": "Undo dislike", + "disabled": true, + "action": function () { + app.unlove(app.mk.nowPlayingItem) + } + }, + { + "icon": "./assets/feather/radio.svg", "name": "Start Radio", "action": function () { - app.mk.setStationQueue({ song: item_id }).then(() => { + app.mk.setStationQueue({song: item_id}).then(() => { app.mk.play() app.selectedMediaItems = [] }) @@ -2433,48 +2901,107 @@ const app = new Vue({ menus.normal.items = menus.normal.items.concat(this.contextExt.normal) } } + + // isLibrary = await app.inLibrary([this.mk.nowPlayingItem]) + // console.warn(isLibrary) + // if(isLibrary.length != 0) { + // if (isLibrary[0].attributes.inLibrary) { + // menus.normal.items.find(x => x.id == "addToLibrary").disabled = true + // } + // }else{ + // menus.normal.items.find(x => x.id == "addToLibrary").disabled = true + // } + + let rating = await app.getRating(app.mk.nowPlayingItem) + if(rating == 0) { + menus.normal.items.find(x => x.id == 'love').disabled = false + menus.normal.items.find(x => x.id == 'dislike').disabled = false + }else if(rating == 1) { + menus.normal.items.find(x => x.id == 'unlove').disabled = false + }else if(rating == -1) { + menus.normal.items.find(x => x.id == 'undo_dislike').disabled = false + } CiderContextMenu.Create(event, menus[useMenu]) }, - LastFMDeauthorize() { - ipcRenderer.invoke('setStoreValue', 'lastfm.enabled', false).catch((e) => console.error(e)); - ipcRenderer.invoke('setStoreValue', 'lastfm.auth_token', '').catch((e) => console.error(e)); - app.cfg.lastfm.auth_token = ""; - app.cfg.lastfm.enabled = false; - const element = document.getElementById('lfmConnect'); - element.innerHTML = 'Connect'; - element.onclick = app.LastFMAuthenticate; - }, - LastFMAuthenticate() { - console.log("wag") - const element = document.getElementById('lfmConnect'); - window.open('https://www.last.fm/api/auth?api_key=174905d201451602407b428a86e8344d&cb=ame://auth/lastfm'); - element.innerText = 'Connecting...'; + LastFMDeauthorize() { + ipcRenderer.invoke('setStoreValue', 'lastfm.enabled', false).catch((e) => console.error(e)); + ipcRenderer.invoke('setStoreValue', 'lastfm.auth_token', '').catch((e) => console.error(e)); + app.cfg.lastfm.auth_token = ""; + app.cfg.lastfm.enabled = false; + const element = document.getElementById('lfmConnect'); + element.innerHTML = 'Connect'; + element.onclick = app.LastFMAuthenticate; + }, + LastFMAuthenticate() { + console.log("wag") + const element = document.getElementById('lfmConnect'); + window.open('https://www.last.fm/api/auth?api_key=174905d201451602407b428a86e8344d&cb=ame://auth/lastfm'); + element.innerText = 'Connecting...'; - /* Just a timeout for the button */ - setTimeout(() => { - if (element.innerText === 'Connecting...') { - element.innerText = 'Connect'; - console.warn('[LastFM] Attempted connection timed out.'); - } - }, 20000); + /* Just a timeout for the button */ + setTimeout(() => { + if (element.innerText === 'Connecting...') { + element.innerText = 'Connect'; + console.warn('[LastFM] Attempted connection timed out.'); + } + }, 20000); + + ipcRenderer.on('LastfmAuthenticated', function (_event, lfmAuthKey) { + app.cfg.lastfm.auth_token = lfmAuthKey; + app.cfg.lastfm.enabled = true; + element.innerHTML = `Disconnect\n

(Authed: ${lfmAuthKey})

`; + element.onclick = app.LastFMDeauthorize; + }); + }, + parseSCTagToRG: function (tag) { + let soundcheck = tag.split(" ") + let numbers = [] + for (item of soundcheck) { + numbers.push(parseInt(item, 16)) - ipcRenderer.on('LastfmAuthenticated', function (_event, lfmAuthKey) { - app.cfg.lastfm.auth_token = lfmAuthKey; - app.cfg.lastfm.enabled = true; - element.innerHTML = `Disconnect\n

(Authed: ${lfmAuthKey})

`; - element.onclick = app.LastFMDeauthorize; - }); } - + numbers.shift() + let gain = Math.log10((Math.max(numbers[0], numbers[1]) ?? 1000) / 1000.0) * -10 + let peak = Math.max(numbers[6], numbers[7]) / 32768.0 + return { + gain: gain, + peak: peak + } + } + } }) Vue.component('sidebar-library-item', { template: '#sidebar-library-item', - props: ['name', 'page', 'cd-click'], + props: { + name: { + type: String, + required: true + }, + page: { + type: String, + required: true + }, + svgIcon: { + type: String, + required: false, + default: '' + }, + cdClick: { + type: Function, + required: false + } + }, data: function () { return { - app: app + app: app, + svgIconData: "" + } + }, + async mounted() { + if (this.svgIcon) { + this.svgIconData = await this.app.getSvgIcon(this.svgIcon) } }, methods: {} @@ -2538,6 +3065,7 @@ document.addEventListener('musickitloaded', function () { app.init() }, 1000) } + request.addEventListener("load", loadAlternateKey); request.open("GET", "https://raw.githubusercontent.com/lujjjh/LitoMusic/main/token.json"); request.send(); @@ -2556,12 +3084,12 @@ document.addEventListener('musickitloaded', function () { request.send(); }); -// if ('serviceWorker' in navigator) { -// // Use the window load event to keep the page load performant -// window.addEventListener('load', () => { -// navigator.serviceWorker.register('sw.js?v=1'); -// }); -// } +if ('serviceWorker' in navigator) { + // Use the window load event to keep the page load performant + window.addEventListener('load', () => { + navigator.serviceWorker.register('sw.js?v=1'); + }); + } const getBase64FromUrl = async (url) => { const data = await fetch(url); diff --git a/src/renderer/logo-simple.svg b/src/renderer/logo-simple.svg new file mode 100644 index 00000000..9f78bf50 --- /dev/null +++ b/src/renderer/logo-simple.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/renderer/logotmp.afdesign b/src/renderer/logotmp.afdesign new file mode 100644 index 00000000..4d426338 Binary files /dev/null and b/src/renderer/logotmp.afdesign differ diff --git a/src/renderer/logotmp.svg b/src/renderer/logotmp.svg new file mode 100644 index 00000000..61317b00 --- /dev/null +++ b/src/renderer/logotmp.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/renderer/style.less b/src/renderer/style.less index 1955353d..cb6651ae 100644 --- a/src/renderer/style.less +++ b/src/renderer/style.less @@ -1,6 +1,10 @@ @import url("ameframework.css"); @import url("assets/fonts/Inter/inter.css"); @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100;300;400;500;700;900&display=swap'); +@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@100;300;400;500;700;900&display=swap"); +@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+HK:wght@100;300;400;500;700;900&display=swap"); +@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@100;300;400;500;700;900&display=swap"); +@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100;300;400;500;700;900&display=swap"); :root { --appleEase: cubic-bezier(0.42, 0, 0.58, 1); @@ -50,6 +54,17 @@ body[platform='linux'] { background: #222; } +body.notransparency::before { + content: ""; + position: absolute; + top:0; + left:0; + right:0; + bottom:0; + opacity: 0.5; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAUVBMVEWFhYWDg4N3d3dtbW17e3t1dXWBgYGHh4d5eXlzc3OLi4ubm5uVlZWPj4+NjY19fX2JiYl/f39ra2uRkZGZmZlpaWmXl5dvb29xcXGTk5NnZ2c8TV1mAAAAG3RSTlNAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAvEOwtAAAFVklEQVR4XpWWB67c2BUFb3g557T/hRo9/WUMZHlgr4Bg8Z4qQgQJlHI4A8SzFVrapvmTF9O7dmYRFZ60YiBhJRCgh1FYhiLAmdvX0CzTOpNE77ME0Zty/nWWzchDtiqrmQDeuv3powQ5ta2eN0FY0InkqDD73lT9c9lEzwUNqgFHs9VQce3TVClFCQrSTfOiYkVJQBmpbq2L6iZavPnAPcoU0dSw0SUTqz/GtrGuXfbyyBniKykOWQWGqwwMA7QiYAxi+IlPdqo+hYHnUt5ZPfnsHJyNiDtnpJyayNBkF6cWoYGAMY92U2hXHF/C1M8uP/ZtYdiuj26UdAdQQSXQErwSOMzt/XWRWAz5GuSBIkwG1H3FabJ2OsUOUhGC6tK4EMtJO0ttC6IBD3kM0ve0tJwMdSfjZo+EEISaeTr9P3wYrGjXqyC1krcKdhMpxEnt5JetoulscpyzhXN5FRpuPHvbeQaKxFAEB6EN+cYN6xD7RYGpXpNndMmZgM5Dcs3YSNFDHUo2LGfZuukSWyUYirJAdYbF3MfqEKmjM+I2EfhA94iG3L7uKrR+GdWD73ydlIB+6hgref1QTlmgmbM3/LeX5GI1Ux1RWpgxpLuZ2+I+IjzZ8wqE4nilvQdkUdfhzI5QDWy+kw5Wgg2pGpeEVeCCA7b85BO3F9DzxB3cdqvBzWcmzbyMiqhzuYqtHRVG2y4x+KOlnyqla8AoWWpuBoYRxzXrfKuILl6SfiWCbjxoZJUaCBj1CjH7GIaDbc9kqBY3W/Rgjda1iqQcOJu2WW+76pZC9QG7M00dffe9hNnseupFL53r8F7YHSwJWUKP2q+k7RdsxyOB11n0xtOvnW4irMMFNV4H0uqwS5ExsmP9AxbDTc9JwgneAT5vTiUSm1E7BSflSt3bfa1tv8Di3R8n3Af7MNWzs49hmauE2wP+ttrq+AsWpFG2awvsuOqbipWHgtuvuaAE+A1Z/7gC9hesnr+7wqCwG8c5yAg3AL1fm8T9AZtp/bbJGwl1pNrE7RuOX7PeMRUERVaPpEs+yqeoSmuOlokqw49pgomjLeh7icHNlG19yjs6XXOMedYm5xH2YxpV2tc0Ro2jJfxC50ApuxGob7lMsxfTbeUv07TyYxpeLucEH1gNd4IKH2LAg5TdVhlCafZvpskfncCfx8pOhJzd76bJWeYFnFciwcYfubRc12Ip/ppIhA1/mSZ/RxjFDrJC5xifFjJpY2Xl5zXdguFqYyTR1zSp1Y9p+tktDYYSNflcxI0iyO4TPBdlRcpeqjK/piF5bklq77VSEaA+z8qmJTFzIWiitbnzR794USKBUaT0NTEsVjZqLaFVqJoPN9ODG70IPbfBHKK+/q/AWR0tJzYHRULOa4MP+W/HfGadZUbfw177G7j/OGbIs8TahLyynl4X4RinF793Oz+BU0saXtUHrVBFT/DnA3ctNPoGbs4hRIjTok8i+algT1lTHi4SxFvONKNrgQFAq2/gFnWMXgwffgYMJpiKYkmW3tTg3ZQ9Jq+f8XN+A5eeUKHWvJWJ2sgJ1Sop+wwhqFVijqWaJhwtD8MNlSBeWNNWTa5Z5kPZw5+LbVT99wqTdx29lMUH4OIG/D86ruKEauBjvH5xy6um/Sfj7ei6UUVk4AIl3MyD4MSSTOFgSwsH/QJWaQ5as7ZcmgBZkzjjU1UrQ74ci1gWBCSGHtuV1H2mhSnO3Wp/3fEV5a+4wz//6qy8JxjZsmxxy5+4w9CDNJY09T072iKG0EnOS0arEYgXqYnXcYHwjTtUNAcMelOd4xpkoqiTYICWFq0JSiPfPDQdnt+4/wuqcXY47QILbgAAAABJRU5ErkJggg==); +} + *, *:before, *:after { @@ -88,6 +103,9 @@ body[platform='linux'] { #app { --color1: rgba(30, 30, 30, 30%); --color2: rgba(15, 15, 15, 30%); + --bgColor: transparent; + --bgWidth: 0px; + --bgHeight: 0px; --chromeHeight: 55px; width: 100%; height: 100%; @@ -97,12 +115,66 @@ body[platform='linux'] { margin: 0 auto; position: relative; overflow: hidden; + background-size: 400% 400%; + + //&::before { + // position: absolute; + // top: -50%; + // left: -50%; + // width: var(--bgWidth); + // height: var(--bgHeight); + // background-image: var(--bgColor); + // content: ""; + // z-index: -1; + // transform: rotateZ(0deg); + // transform-origin: center; + // animation: bgRotate 10s linear infinite; + // filter: brightness(100%) saturate(200%) contrast(1.5); + //} +} + +.bgGradientMaterial-base { + position:relative; +} + +.bgGradientMaterial-base::before { + position: absolute; + top: -50%; + left: -50%; + width: 200%; + height: 250%; + background-image: var(--bgColor); + content: ""; + z-index: -1; + transform: rotateZ(0deg); + transform-origin: center; + animation: bgRotate 10s linear infinite; + filter: brightness(100%) saturate(200%) contrast(1.5); +} + +@keyframes bgRotate { + 0% { + transform: rotateZ(0deg); + } + 100% { + transform: rotateZ(360deg); + } } [hidden] { display: none !important; } +input[type="text"], input[type="number"] { + background: #1c1c1c; + border-radius: 3px; + border: 1px solid rgb(200 200 200 / 25%); + color: #eee; + padding: 6px; + font-size: 1em; + font-family: inherit; +} + .bg-artwork--placeholder { position: absolute; @@ -120,21 +192,54 @@ body[platform='linux'] { .bg-artwork { position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; + width: 200%; background: var(--artwork); - z-index: -1; - object-fit: cover; - object-position: center; - /* filter: blur(60px) saturate(180%); - opacity: 0.70; */ - filter: blur(180px) saturate(280%); - opacity: 0.60; - transition: opacity .25s var(--appleEase); + filter: brightness(200%) blur(180px) saturate(280%) contrast(2); + opacity: 1; + transition: opacity 0.25s var(--appleEase); pointer-events: none; transform: translateZ(0px); + animation: rotateBg 35s linear infinite; + backface-visibility: hidden; +} + +@keyframes rotateBg { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + + +.bg-artwork-container { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + pointer-events: none; + transform: translateZ(0px); + z-index: -1; + + .bg-artwork.a { + top:0; + left:0; + //mix-blend-mode: luminosity; + } + .bg-artwork.b { + bottom:0; + right:0; + animation-direction: reverse; + animation-delay: 10s; + } + + &.noanimation { + .bg-artwork { + animation: none; + } + } } @@ -249,6 +354,18 @@ input[type=range].web-slider::-webkit-slider-runnable-track { height: 94%; backdrop-filter: blur(40px) saturate(180%); box-shadow: var(--ciderShadow-Generic); + overflow: hidden; + + .bgArtworkMaterial { + display: none; + position: absolute; + width: 100%; + height: 100%; + + .bg-artwork-container .bg-artwork { + filter: brightness(80%) blur(180px) saturate(180%) contrast(1); + } + } } .search-input-container { @@ -340,7 +457,7 @@ input[type=range].web-slider::-webkit-slider-runnable-track { } } -.app-sidebar-button>.sidebar-user-icon { +.app-sidebar-button > .sidebar-user-icon { width: 32px; height: 32px; border-radius: 100%; @@ -351,18 +468,18 @@ input[type=range].web-slider::-webkit-slider-runnable-track { background-size: contain; } -.app-sidebar-button>.sidebar-user-text { +.app-sidebar-button > .sidebar-user-text { width: 100%; display: flex; font-size: 14px; flex-direction: column; } -.app-sidebar-button>.sidebar-user-text .fullname { +.app-sidebar-button > .sidebar-user-text .fullname { text-align: left; } -.app-sidebar-button>.sidebar-user-text .handle-text { +.app-sidebar-button > .sidebar-user-text .handle-text { font-size: 12px; opacity: 0.7; text-align: left; @@ -461,22 +578,26 @@ input[type=range].web-slider::-webkit-slider-runnable-track { .context-menu-item { background: transparent; - display: block; + display: flex; width: 100%; text-align: left; color: #eee; font-family: inherit; - font-size: 15px; - padding: 8px 12px; + font-size: 14px; + padding: 6px 12px; border: 0px; appearance: none; border-radius: 6px; margin: 2px 0px; &:hover { - background: var(--keyColor); + background: var(--selected); cursor: pointer; } + + &:active { + background: var(--selected-click); + } } .context-menu-body { @@ -525,6 +646,23 @@ input[type=range].web-slider::-webkit-slider-runnable-track { } } +.hidden-opacity { + opacity: 0; + height: 0px; + width: 0px; + margin: 0px; +} + +.spinner { + background-image: url("assets/spinner.gif"); + background-position: center; + background-repeat: no-repeat; + background-size: contain; + width: 32px; + height: 32px; + display: inline-block; +} + .app-sidebar-content::-webkit-scrollbar { display: none; } @@ -544,9 +682,15 @@ input[type=range].web-slider::-webkit-slider-runnable-track { border: 1px solid transparent; border-radius: 6px; background: transparent; - color: white; + color: #eee; transition: transform .1s; text-align: left; + + &.app-sidebar-item-playlist { + -webkit-user-drag: element; + overflow: hidden; + text-overflow: ellipsis; + } } .app-sidebar-item:hover { @@ -643,32 +787,32 @@ input[type=range].web-slider::-webkit-slider-runnable-track { } .app-chrome-item.volume-icon { - filter: contrast(0); + opacity: 0.7; background-image: url(http://localhost:9000/assets/volume-up.svg); height: 15px; width: 30px; background-repeat: no-repeat; } -.app-chrome .app-chrome-item.volume>input[type=range]::-webkit-slider-thumb { +.app-chrome .app-chrome-item.volume > input[type=range]::-webkit-slider-thumb { transition: all var(--appleTransition); } -.app-chrome .app-chrome-item.volume>input[type=range]::-webkit-slider-thumb:hover { +.app-chrome .app-chrome-item.volume > input[type=range]::-webkit-slider-thumb:hover { background-image: radial-gradient(var(--keyColor) 2px, transparent 3px, transparent 10px); transform: scale(1.2); } -.app-chrome .app-chrome-item.volume>input[type=range]::-webkit-slider-thumb:active { +.app-chrome .app-chrome-item.volume > input[type=range]::-webkit-slider-thumb:active { background-image: radial-gradient(var(--keyColor) 3px, transparent 4px, transparent 10px); transform: scale(1); } -.app-chrome .app-chrome-item.volume>input[type=range] { +.app-chrome .app-chrome-item.volume > input[type=range] { width: 100%; } -.app-chrome .app-chrome-item.volume>input[type=range] { +.app-chrome .app-chrome-item.volume > input[type=range] { -webkit-appearance: none; height: 4px; background: rgba(255, 255, 255, 0.4); @@ -677,7 +821,7 @@ input[type=range].web-slider::-webkit-slider-runnable-track { background-repeat: no-repeat; } -.app-chrome .app-chrome-item.volume>input[type=range]::-webkit-slider-thumb { +.app-chrome .app-chrome-item.volume > input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; height: 14px; width: 14px; @@ -687,7 +831,7 @@ input[type=range].web-slider::-webkit-slider-runnable-track { box-shadow: inset 0px 0px 0px 1px rgba(255, 255, 255, 0.4); } -.app-chrome .app-chrome-item.volume>input[type=range]::-webkit-slider-runnable-track { +.app-chrome .app-chrome-item.volume > input[type=range]::-webkit-slider-runnable-track { -webkit-appearance: none; box-shadow: none; border: none; @@ -703,10 +847,10 @@ input[type=range].web-slider::-webkit-slider-runnable-track { height: 100%; } -.app-chrome .app-chrome-item>.app-title { +.app-chrome .app-chrome-item > .app-title { width: 100px; font-size: 13px; - background: url("./logotmp.png"); + background: url("./logotmp.svg"); background-size: 90px; background-repeat: no-repeat; background-position: center; @@ -717,23 +861,23 @@ input[type=range].web-slider::-webkit-slider-runnable-track { -webkit-app-region: drag; } -.app-chrome .app-chrome-item>.window-controls { +.app-chrome .app-chrome-item > .window-controls { width: 138px; font-size: 13px; height: 100%; display: flex; } -.app-chrome .app-chrome-item>.window-controls>div { +.app-chrome .app-chrome-item > .window-controls > div { height: 100%; width: 32px; } -.app-chrome .app-chrome-item>.window-controls>div:hover { +.app-chrome .app-chrome-item > .window-controls > div:hover { background: rgb(200 200 200 / 10%); } -.app-chrome .app-chrome-item>.window-controls>div.close { +.app-chrome .app-chrome-item > .window-controls > div.close { width: 100%; height: 100%; background-image: var(--gfx-closeBtn); @@ -746,7 +890,7 @@ input[type=range].web-slider::-webkit-slider-runnable-track { } } -.app-chrome .app-chrome-item>.window-controls>div.minmax { +.app-chrome .app-chrome-item > .window-controls > div.minmax { background-image: var(--gfx-maxBtn); background-position: center; background-repeat: no-repeat; @@ -755,11 +899,11 @@ input[type=range].web-slider::-webkit-slider-runnable-track { height: 100%; } -.app-chrome .app-chrome-item>.window-controls>div.minmax.restore { +.app-chrome .app-chrome-item > .window-controls > div.minmax.restore { background-image: var(--gfx-restoreBtn); } -.app-chrome .app-chrome-item>.window-controls>div.minimize { +.app-chrome .app-chrome-item > .window-controls > div.minimize { background-image: var(--gfx-minBtn); background-position: center; background-repeat: no-repeat; @@ -777,23 +921,34 @@ input[type=range].web-slider::-webkit-slider-runnable-track { border-right: 1px solid rgb(200 200 200 / 8%); } -.app-chrome .app-chrome-item>.app-playback-controls { +.app-chrome .app-chrome-item > .app-playback-controls { display: flex; justify-content: center; align-content: center; width: 100%; } -.app-chrome .app-chrome-item>.app-playback-controls .song-name { +.app-chrome .app-chrome-item > .app-playback-controls .song-name { font-weight: 600; text-align: center; font-size: 13px; height: 1.3em; line-height: 1.3em; overflow: hidden; + max-width: 360px; + + .song-name-normal { + height: inherit; + } + + &.song-artist-marquee { + > marquee { + //margin-bottom: -3px; + } + } } -.app-chrome .app-chrome-item>.app-playback-controls .song-duration p { +.app-chrome .app-chrome-item > .app-playback-controls .song-duration p { font-weight: 400; font-size: 10px; height: 1.2em; @@ -802,7 +957,7 @@ input[type=range].web-slider::-webkit-slider-runnable-track { margin: 0 0 0.5em; } -.app-chrome .app-chrome-item>.app-playback-controls .song-artist { +.app-chrome .app-chrome-item > .app-playback-controls .song-artist { font-weight: 400; font-size: 12px; text-align: center; @@ -810,10 +965,21 @@ input[type=range].web-slider::-webkit-slider-runnable-track { line-height: 1.2em;*/ overflow: hidden; z-index: 1; + max-width: 360px; /* animation: marquee 10s linear infinite; */ + + .song-artist-normal { + height: inherit; + } + + &.song-artist-marquee { + > marquee { + margin-bottom: -3px; + } + } } -.app-chrome .app-chrome-item>.app-playback-controls .song-progress { +.app-chrome .app-chrome-item > .app-playback-controls .song-progress { @bgColor: transparent; //height: 16px; position: absolute; @@ -822,7 +988,7 @@ input[type=range].web-slider::-webkit-slider-runnable-track { background: @bgColor; &:hover { - >input[type=range] { + > input[type=range] { &::-webkit-slider-thumb { opacity: 1; transform: scale(1); @@ -831,7 +997,7 @@ input[type=range].web-slider::-webkit-slider-runnable-track { } } - >input[type=range] { + > input[type=range] { appearance: none; width: 100%; height: 4px; @@ -871,7 +1037,7 @@ input[type=range].web-slider::-webkit-slider-runnable-track { } } -.app-chrome .app-chrome-item>.app-playback-controls .artwork { +.app-chrome .app-chrome-item > .app-playback-controls .artwork { width: 42px; height: 42px; background-image: var(--artwork); @@ -885,7 +1051,7 @@ input[type=range].web-slider::-webkit-slider-runnable-track { image-rendering: -webkit-optimize-contrast; } -.app-chrome .app-chrome-item>.app-playback-controls .actions { +.app-chrome .app-chrome-item > .app-playback-controls .actions { width: 42px; height: 42px; border-radius: 2px; @@ -897,7 +1063,7 @@ input[type=range].web-slider::-webkit-slider-runnable-track { filter: contrast(0.8); } -.app-chrome .app-chrome-item>.app-playback-controls .playback-info { +.app-chrome .app-chrome-item > .app-playback-controls .playback-info { width: 100%; display: flex; justify-content: center; @@ -906,7 +1072,7 @@ input[type=range].web-slider::-webkit-slider-runnable-track { position: relative; } -.app-chrome .app-chrome-item>.app-playback-controls .playback-info>div { +.app-chrome .app-chrome-item > .app-playback-controls .playback-info > div { width: 100%; } @@ -1392,7 +1558,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { overflow-x: hidden; display: flex; flex-flow: column; - font-family: 'Inter', 'Noto Sans JP', sans-serif; + font-family: 'Inter', 'Noto Sans JP','Source Han Sans SC', 'Source Han Sans HK','Noto Sans SC','Noto Sans TC', 'Noto Sans HK', 'Noto Sans KR', sans-serif; } .lyric-body .no-lyrics { @@ -1402,7 +1568,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { font-weight: bold; font-size: 26px; } - + .lyric-line { --bgSpeed: 1s; appearance: none; @@ -1476,7 +1642,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { } -.lyric-line.active .lyricWaiting>div { +.lyric-line.active .lyricWaiting > div { width: 10px; height: 10px; background: white; @@ -1486,7 +1652,42 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { .lyrics-translation { font-size: 1.6rem; - font-weight: 400; + font-weight: 450; + font-family: 'Inter', 'Noto Sans JP','Noto Sans SC','Noto Sans TC', 'Noto Sans HK', 'Noto Sans KR', sans-serif; + filter: contrast(0.5); +} + +.lyric-footer { + bottom: 0; + height: 50px; + width: 100%; + position: absolute; + z-index: 1000; + opacity: 1; + background: rgba(30, 30, 30, 0.8); + justify-content: center; + align-items: center; + display: none; + transition: opacity 0.1s var(--appleEase); +} + +.lyric-body:hover + .lyric-footer, .lyric-footer:hover { + display: flex; +} + +.modular-fs .app-drawer .lyric-footer { + background: unset; + display: flex; + opacity: 0.3; +} + +.modular-fs .app-drawer .lyric-footer:hover { + opacity: 1; +} + +.modular-fs .app-drawer .lyric-body .no-lyrics { + height: 100%; + display: flex; } @keyframes lyricWaitingLine { @@ -1540,27 +1741,146 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { } .home-page { - background: linear-gradient(0deg, black, #4c2c31); top: 0; padding-top: var(--navbarHeight); + .artist-feed-card { + position: absolute; + bottom: 0; + left: 10%; + z-index: 1; + background: black; + width: 80%; + height: 96%; + overflow: scroll; + border-radius: 10px; + } + + .col.madeforyou-col { + width: 420px; + min-width: 0px; + max-width: 420px; + } + + .well.artistfeed-well { + margin-top: 0px; + height: 392px; + align-content: flex-start; + } + + .hint-text { + font-size: 0.9rem; + color: rgb(200 200 200 / 70%); + } + .user-icon { border-radius: 100%; width: 128px; height: 128px; overflow: hidden; box-shadow: var(--mediaItemShadow-Shadow); + margin: 16px; } .well.profile-well { flex-direction: column; justify-content: center; align-items: center; + + .name { + margin: 4px; + font-weight: 500; + } + + .handle { + margin: 4px; + opacity: 0.7; + font-weight: 500; + } } } /* Cider */ +.md-close-btn { + -webkit-mask-image: url("ameres://icons/webui/close.svg"); + -webkit-mask-repeat: no-repeat; + -webkit-mask-position: center; + background-color: white; + opacity: 0.75; + -webkit-mask-size: contain; + height: 18px; + width: 18px; +} + +.md-btn { + background: rgba(100, 100, 100, 0.5); + padding: 4px 12px; + border-radius: 4px; + font-size: 13px; + border: 1px solid rgb(100 100 100 / 35%); + color: #eee; + box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.3), 0px 1px 1px rgba(0, 0, 0, 0.4); + transition: transform 0.2s var(--appleEase), box-shadow 0.2s var(--appleEase); + + &.md-btn-block { + display: block; + } + + &.md-btn-primary { + background: var(--keyColor); + color: white; + } + + &:hover { + filter: brightness(125%); + } + + &:active { + filter: brightness(75%); + transform: translateY(2px); + } +} + +.md-select { + padding: 5px 10px; + font-size: 1em; + font-family: inherit; + border-radius: 4px; + border: 1px solid rgb(100 100 100 / 35%); + box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.3), 0px 1px 1px rgba(0, 0, 0, 0.4); + background: #363636; + color: #eee; +} + +.md-select:focus { + outline: none; +} + +.md-select > option { + font-size: 1em; + font-family: inherit; + padding: 8px 16px; +} + +.sidebar-playlist { + .folder-button-active { + background: rgb(255 255 255 / 12%); + } + .folder-body { + background: #ffffff0a; + border-radius: 10px; + padding: 1px 6px; + + .spinner { + display: block; + width: 100%; + height: 32px; + background-size: 16px; + } + } +} + .modal-fullscreen { display: flex; justify-content: center; @@ -1610,7 +1930,113 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { overflow-y: overlay; } - .modal-footer {} + .modal-footer { + } + } +} + +.spatialproperties-panel { + .modal-window { + height: 700px; + max-height: 700px; + width: 800px; + max-width: 800px; + overflow: hidden; + + .info-header { + padding-left: 12px; + } + + .visual-container { + display: flex; + justify-content: center; + align-items: center; + overflow: hidden; + } + + .visual { + position: relative; + height: 250px; + width: 300px; + display: inline-flex; + align-items: flex-end; + justify-content: center; + filter: drop-shadow(2px 12px 6px rgb(0 0 0 / 25%)); + margin: 0 auto; + + .face { + position: absolute; + width: calc(12px * 6); + height: calc(12px * 6); + border-radius: 6px; + transform: rotateX(60deg) rotateZ(-45deg); + transition: transform 0.2s linear, width 0.2s linear, height 0.2s linear; + } + + .listener { + position: absolute; + width: 32px; + height: 32px; + border-radius: 6px; + transform: rotateX(60deg) rotateZ(-45deg); + transition: transform 0.2s linear, width 0.2s linear, height 0.2s linear; + background: white; + color: black; + z-index: 2; + } + + .audiosource { + position: absolute; + width: 32px; + height: 32px; + border-radius: 6px; + transform: rotateX(60deg) rotateZ(-45deg); + transition: transform 0.2s linear, width 0.2s linear, height 0.2s linear; + background: yellow; + z-index: 2; + } + + .face:nth-of-type(1) { + background: linear-gradient(45deg, #28223a, #1f2038); + z-index: 1; + } + + .face:nth-of-type(2) { + background: linear-gradient(45deg, #7d53ad, #5763ff); + transform: rotateX(60deg) rotateZ(-45deg) translateZ(30px); + opacity: 0.7; + z-index: 3; + } + } + + .modal-header { + padding: 16px; + position: relative; + overflow: hidden; + + .modal-title { + text-align: center; + } + + .close-btn { + width: 50px; + height: 100%; + background-image: var(--gfx-closeBtn); + background-position: center; + background-repeat: no-repeat; + -webkit-app-region: no-drag; + appearance: none; + border: 0; + background-color: transparent; + position: absolute; + top: 0; + right: 0; + + &:hover { + background-color: rgb(196, 43, 28) + } + } + } } } @@ -1681,7 +2107,8 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { margin-right: 6px; } - .name {} + .name { + } &:hover { background: var(--selected); @@ -1738,7 +2165,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { transition: transform 0s var(--appleEase); } - >svg { + > svg { width: 8px; pointer-events: none; } @@ -1746,7 +2173,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { &:hover { background: var(--selected); - >svg { + > svg { color: rgba(200, 200, 200, 1.0); } } @@ -1770,7 +2197,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { cursor: pointer; } -.reload-btn>svg { +.reload-btn > svg { height: 50%; color: #eee; } @@ -1796,7 +2223,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { flex-flow: wrap; justify-content: center; - >.cd-mediaitem-square { + > .cd-mediaitem-square { width: 220px; height: 260px; display: inline-flex; @@ -1927,6 +2354,37 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { } } + .friends-info { + display: flex; + flex-flow: column; + + .badge-container { + display: flex; + flex-flow: wrap; + + .socialBadge { + width: 40px; + height: 40px; + border-radius: 100%; + overflow: hidden; + box-shadow: var(--mediaItemShadow-ShadowSubtle); + transition: transform .2s var(--appleEase); + margin: 6px; + + &:hover { + transform: scale(1.2); + } + } + } + + .friends-name { + text-align: center; + font-size: 0.9em; + margin: 8px; + } + } + + .playlist-time { font-size: 0.9em; margin: 6px; @@ -1950,7 +2408,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { appearance: none; box-shadow: var(--ciderShadow-Generic); - >svg { + > svg { height: 50%; color: #eee; pointer-events: none; @@ -2065,7 +2523,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { background: var(--selected-click); } - >svg { + > svg { width: 70%; } } @@ -2205,13 +2663,16 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { &.no-shadow { box-shadow: none; + &::after { display: none; } } + &.subtle-shadow { box-shadow: var(--mediaItemShadow-ShadowSubtle); } + &.shadow { box-shadow: var(--mediaItemShadow-Shadow); } @@ -2311,6 +2772,13 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { overflow-x: overlay; height: 210px; } + + &.hmedia-scroller-card { + height: 370px; + .mediaitem-card { + margin: 12px; + } + } } /* mediaitem-list-item */ @@ -2323,7 +2791,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { font-size: 14px; justify-content: center-between; align-items: center; - border-bottom: 1px solid rgb(200 200 200 / 10%); + border-radius: var(--mediaItemRadius); .artwork { height: 42px; @@ -2429,7 +2897,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { &:hover { background: rgb(200 200 200 / 10%); - + box-shadow: var(--mediaItemShadow); .overlay-play { opacity: 1; } @@ -2437,11 +2905,13 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { &.mediaitem-selected { background: var(--selected); + box-shadow: var(--mediaItemShadow); } &:active { background: var(--selected-click); + box-shadow: var(--mediaItemShadow); color: #eee; } } @@ -2540,7 +3010,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { font-size: 12px; } - >.cd-mediaitem-square-large-overlay { + > .cd-mediaitem-square-large-overlay { z-index: 3; &:hover { @@ -2548,11 +3018,11 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { } } - +.cd-mediaitem-square-large-overlay { + + .cd-mediaitem-square-large-overlay { pointer-events: none; } - &:hover+.cd-mediaitem-square-large-overlay { + &:hover + .cd-mediaitem-square-large-overlay { opacity: 1; } @@ -2563,7 +3033,6 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { } - /* mediaitem-square-large */ .cd-mediaitem-square-large { width: 190px; @@ -2578,7 +3047,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { margin-left: 10px; cursor: pointer; - >* { + > * { z-index: inherit; } } @@ -2608,25 +3077,25 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { } -.cd-mediaitem-square-large-overlay>* { +.cd-mediaitem-square-large-overlay > * { pointer-events: auto; } -.cd-mediaitem-square-large>.cd-mediaitem-square-large-overlay { +.cd-mediaitem-square-large > .cd-mediaitem-square-large-overlay { z-index: 3; } -.cd-mediaitem-square-large>.cd-mediaitem-square-large-overlay:hover { +.cd-mediaitem-square-large > .cd-mediaitem-square-large-overlay:hover { opacity: 1; } -.cd-mediaitem-square-large+.cd-mediaitem-square-large-overlay { +.cd-mediaitem-square-large + .cd-mediaitem-square-large-overlay { pointer-events: none; } -.cd-mediaitem-square-large:hover+.cd-mediaitem-square-large-overlay { +.cd-mediaitem-square-large:hover + .cd-mediaitem-square-large-overlay { opacity: 1; } @@ -2663,7 +3132,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { margin-left: 10px; cursor: pointer; - >* { + > * { z-index: inherit; } } @@ -2693,25 +3162,25 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { } -.cd-mediaitem-mvview-overlay>* { +.cd-mediaitem-mvview-overlay > * { pointer-events: auto; } -.cd-mediaitem-mvview>.cd-mediaitem-mvview-overlay { +.cd-mediaitem-mvview > .cd-mediaitem-mvview-overlay { z-index: 3; } -.cd-mediaitem-mvview>.cd-mediaitem-mvview-overlay:hover { +.cd-mediaitem-mvview > .cd-mediaitem-mvview-overlay:hover { opacity: 1; } -.cd-mediaitem-mvview+.cd-mediaitem-mvview-overlay { +.cd-mediaitem-mvview + .cd-mediaitem-mvview-overlay { pointer-events: none; } -.cd-mediaitem-mvview:hover+.cd-mediaitem-mvview-overlay { +.cd-mediaitem-mvview:hover + .cd-mediaitem-mvview-overlay { opacity: 1; } @@ -2764,8 +3233,25 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { } } - >.play-btn, - >.menu-btn { + .badge-container { + transition: opacity 0.1s var(--appleEase); + opacity: 1; + + .socialBadge { + width: 32px; + height: 32px; + position: absolute; + right: 14px; + bottom: 14px; + border-radius: 100%; + overflow: hidden; + z-index: 2; + pointer-events: none; + } + } + + > .play-btn, + > .menu-btn { opacity: 0; appearance: none; padding: 0px; @@ -2775,18 +3261,22 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { border-radius: 50%; background: rgba(50, 50, 50, 0.7); cursor: pointer; - backdrop-filter: blur(32px) saturate(180%); transition: opacity 0.1s var(--appleEase); + :hover{ + border-radius: 50%; + background: rgba(250, 0, 0, 0.7); + } } - >.play-btn { + > .play-btn { position: absolute; bottom: 14px; left: 14px; z-index: 2; + } - >.menu-btn { + > .menu-btn { position: absolute; bottom: 14px; right: 14px; @@ -2794,18 +3284,32 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { } &:hover { + > .badge-container { + opacity: 0; + } - >.play-btn, - >.menu-btn { + > .play-btn, + > .menu-btn { opacity: 1; } } } + .info-rect { + width: 90%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + } + .title { - width: 90%; + width: 100%; text-align: center; + display: flex; + align-content: center; + justify-content: center; } .subtitle { @@ -2843,10 +3347,91 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { width: 128px; } } + + &.mediaitem-card { + background: #ccc; + background: var(--spcolor); + height: 298px; + width: 230px; + max-width: 250px; + max-height: 500px; + overflow: hidden; + position: relative; + border-radius: calc(var(--mediaItemRadius) * 2); + box-shadow: var(--mediaItemShadow-ShadowSubtle); + + .artwork { + width: 230px; + height: 230px; + overflow: hidden; + border-radius: 0px; + margin: 0; + .mediaitem-artwork { + border-radius: 0px; + + &::after { + box-shadow: unset; + } + } + } + + .info-rect-card { + padding: 10px 10px 14px; + position: relative; + width: 100%; + + &::before { + background: var(--bgartwork); + content: ""; + top:0; + left:0; + bottom:0; + right:0; + position:absolute; + background-size: cover; + background-position: bottom; + z-index: 0; + opacity:1; + filter: brightness(0.5) blur(50px) saturate(180%); + } + } + + .title { + height: 100%; + display: flex; + justify-content: center; + align-items: center; + font-size: 0.9em; + font-weight: 500; + z-index: 1; + } + + .subtitle { + height: 100%; + justify-content: center; + align-items: center; + font-size: 0.75em; + width: 100%; + display: flex; + z-index: 1; + } + + &::after { + box-shadow: var(--mediaItemShadow); + content: ""; + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + pointer-events: none; + border-radius: inherit; + } + } } /* mediaitem-square */ -.albums-square-containeru>*>.cd-mediaitem-square { +.albums-square-containeru > * > .cd-mediaitem-square { --frame: max(220px, 15vw); width: var(--frame); height: calc(var(--frame) * 13 / 11); @@ -2877,8 +3462,8 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { } } - >.play-btn, - >.menu-btn { + > .play-btn, + > .menu-btn { opacity: 0; appearance: none; padding: 0px; @@ -2892,14 +3477,14 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { transition: opacity 0.1s var(--appleEase); } - >.play-btn { + > .play-btn { position: absolute; bottom: calc(var(--frame) / 220 * 14); left: calc(var(--frame) / 220 * 14); z-index: 2; } - >.menu-btn { + > .menu-btn { position: absolute; bottom: calc(var(--frame) / 220 * 14); right: calc(var(--frame) / 220 * 14); @@ -2908,8 +3493,8 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { &:hover { - >.play-btn, - >.menu-btn { + > .play-btn, + > .menu-btn { opacity: 1; } } @@ -2990,20 +3575,271 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { flex-grow: 1; } + .playback-button--small.active { + background-color: rgba(200, 200, 200, 0.7); + } + + .right-col{ + height: 50vh; + } + + .background{ + position: absolute; + background-size: cover; + width: 100%; + height: 100%; + + .bgArtworkMaterial { + position: absolute; + width: 100%; + height: 100%; + + .bg-artwork-container{ + z-index: unset; + } + + .bg-artwork-container .bg-artwork { + filter: brightness(80%) saturate(69%) blur(180px) contrast(0.8) opacity(0.8); + } + + .no-animation{ + animation : unset; + } + } + } + + + + .lyrics-col{ + + width: 60vh; + height: 50vh; + + ::-webkit-scrollbar-thumb { + box-shadow: unset; + } + + &:hover ::-webkit-scrollbar-thumb { + box-shadow: inset 0px 0px 10px 10px rgb(200 200 200 / 50%); + } + + .no-lyrics{ + width: 100%; + height: 100%; + display: flex; + justify-content: center; + } + + .lyric-line{ + font-size: 35px; + } + + } + + .queue-col{ + + width: 60vh; + height: 50vh; + + ::-webkit-scrollbar-thumb { + box-shadow: unset; + } + + &:hover ::-webkit-scrollbar-thumb { + box-shadow: inset 0px 0px 10px 10px rgb(200 200 200 / 50%); + } + } + + .tab-toggles{ + display: flex; + position: absolute; + bottom: 0; + right: 0; + width: 15vh; + height: 5vh; + justify-content: space-evenly; + + .queue { + background-image: url("./assets/list.svg") ; + padding: 0.5vh; + width: 2.5vh; + height: 2.5vh; + background-origin: content-box; + background-repeat: no-repeat; + } + + .lyrics { + background-image: url("./assets/quote-right.svg") ; + padding: 0.5vh; + width: 2.5vh; + height: 2.5vh; + background-origin: content-box; + background-repeat: no-repeat; + } + + .active { + background-color: rgba(200, 200, 200, 0.7); + border-radius: 3px; + } + } + .artwork-col { justify-content: center; align-items: center; display: flex; + flex-direction: column; .artwork { width: 50vh; height: 50vh; } - } + + .controls-parents{ + width: 50vh; + } + + .app-playback-controls { + .song-artist , .song-name { + font-weight: 600; + text-align: center; + font-size: 0.9em; + height: 1.2em; + line-height: 0.9em; + overflow: hidden; + text-overflow: ellipsis; + max-width: 360px; + + .song-name-normal { + height: inherit; + } + + &.song-artist-marquee { + > marquee { + //margin-bottom: -3px; + } + } + } + .song-artist { + font-size: 0.875em; + } + .song-name { + margin-top: 0.15vh; + display: contents; + } + } + + .app-playback-controls .playback-info { + margin-top: 0.5vh; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + position: relative; + + input[type="range"] { + width: 100%; + } + >div { + width: 100%; + text-align: center; + } + + + } + + .app-playback-controls .song-progress { + @bgColor: transparent; + //height: 16px; + position: absolute; + bottom: -1.5vh; + left: 0px; + background: @bgColor; + + .song-duration p { + font-weight: 400; + font-size: 10px; + height: 1.2em; + line-height: 1.3em; + overflow: hidden; + margin: 0 0 0.5em; + } + + &:hover { + > input[type=range] { + &::-webkit-slider-thumb { + opacity: 1; + transform: scale(1); + z-index: 1; + } + } + } + + > input[type=range] { + appearance: none; + width: 100%; + height: 4px; + background-color: rgb(200 200 200 / 10%); + border-radius: 2px; + + &::-webkit-slider-thumb { + opacity: 0; + transform: scale(0.5); + -webkit-appearance: none; + appearance: none; + width: 12px; + height: 12px; + border-radius: 100%; + background: var(--keyColor); + cursor: default; + transition: opacity .10s var(--appleEase), transform .10s var(--appleEase); + } + + &::-moz-range-thumb { + width: 8px; + height: 8px; + border-radius: 100%; + background: var(--keyColor); + cursor: default; + } + } + } + + .control-buttons { + margin-top: 2vh; + display: inline-flex; + width: 100%; + justify-content: center; + } + + } } /* Cider */ +// sidebar icon +.sidebar-icon { + width: 18px; + height: 18px; + margin-right: 8px; + + >svg { + width: 100%; + height: 100%; + color: #aaa; + } +} + +@keyframes rotate { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + // Modular .modular-fs { .app-drawer { @@ -3015,14 +3851,39 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { box-shadow: unset; background: black; + .bgArtworkMaterial { + display: block; + &::before { + top: -50%; + left: -20%; + width: 200VH; + height: 200VH; + } + } + .lyric-body { justify-content: center; align-items: center; + padding: 0px; + margin: 0px; + overflow: hidden; .lyric-line { pointer-events: none; font-weight: 500; - font-size: 1.6em; + font-size: 2em; + transform-origin: center; + animation: fsLyricIn var(--appleEase) .2s; + opacity: 0.9; + text-shadow: + -1px -1px 0 #000, + 0 -1px 0 #000, + 1px -1px 0 #000, + 1px 0 0 #000, + 1px 1px 0 #000, + 0 1px 0 #000, + -1px 1px 0 #000, + -1px 0 0 #000; &:not(.active) { display: none; @@ -3039,6 +3900,17 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { } } +@keyframes fsLyricIn { + 0% { + opacity: 0; + transform: scale(0.98) + } + 100% { + opacity: 1; + transform: scale(1); + } +} + // Modular /* Transitions */ @@ -3110,24 +3982,25 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { /* Transitions End */ -@media (prefers-color-scheme: light) { - :root { - /* */ - --gfx-closeBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAIn2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgZGM6Zm9ybWF0PSJpbWFnZS9wbmciCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTAiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMTAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEyOjU1OjM3WiIKICAgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMTAtMDVUMTQ6MjY6MjgtMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTEwLTA1VDE0OjI2OjI4LTA3OjAwIgogICB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZTk5OWM2NWYtNDhhOS0wNjQyLWI2MTktZmJlYTExMmUxOGZiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MzMyOWNhLWNkNjctMzY0Zi04MzU1LTY5N2ZmYzI0ZDdlZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjgyZjQwYmU3LTE0YzItZjc0Ni1hZmE1LWQxYmIxNzAyMjM4OCIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjEwIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTAiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSI+CiAgIDxwaG90b3Nob3A6VGV4dExheWVycz4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qSiIgogICAgICBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKIiLz4KICAgIDwvcmRmOlNlcT4KICAgPC9waG90b3Nob3A6VGV4dExheWVycz4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0iY3JlYXRlZCIKICAgICAgeG1wTU06aW5zdGFuY2VJRD0ieG1wLmlpZDo4MmY0MGJlNy0xNGMyLWY3NDYtYWZhNS1kMWJiMTcwMjIzODgiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIKICAgICAgeG1wTU06d2hlbj0iMjAyMC0wMi0xN1QxMjo1NTozN1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0ic2F2ZWQiCiAgICAgIHhtcE1NOmNoYW5nZWQ9Ii8iCiAgICAgIHhtcE1NOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkzMzI5Y2EtY2Q2Ny0zNjRmLTgzNTUtNjk3ZmZjMjRkN2VkIgogICAgICB4bXBNTTpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgICAgIHhtcE1NOndoZW49IjIwMjAtMDItMTdUMTI6NTU6MzdaIi8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMTAtMDVUMTQ6MjY6MjgtMDc6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PtPY89oAAAGCaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRv0tCURTHP2lhmGFRQUODhDVZlELU0qD0C6pBDbJa9OWPQO3xnhHRGrQKBVFLv4b6C2oNmoOgKIJoC5qLWkpe56mgRJ7Luedzv/eew73ngiWcVjJ6/QBksjktOOF3zUcWXLZX7DTQQSu+qKKrM6HxMDXt64E6M971mbVqn/vXmpbjugJ1jcKjiqrlhCeFp9dzqsm7wu1KKrosfC7s0eSCwvemHivxm8nJEv+YrIWDAbC0CLuSVRyrYiWlZYTl5bgz6TWlfB/zJY54di4ksVu8C50gE/hxMcUYAYYYZETmIfrw0i8rauQPFPNnWZVcRWaVDTRWSJIih0fUNakel5gQPS4jzYbZ/7991RM+b6m6ww8NL4bx0QO2HSjkDeP72DAKJ2B9hqtsJX/1CIY/Rc9XNPchOLfg4rqixfbgchs6n9SoFi1KVnFLIgHvZ9AcgbZbsC+Welbe5/QRwpvyVTewfwC9ct659At2bGftHD0UJwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAEpJREFUGJWNkMENwDAIA1Gh3F7sP0Ty7xD5JgpU+OuTLVvMmQohhRTCnCEK8TpfBl9eBpcBu/HXcsAZ9FQjSrWqW2Pa95gzGofPBQZRG2fS0899AAAAAElFTkSuQmCC'); - --gfx-maxBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAIn2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgZGM6Zm9ybWF0PSJpbWFnZS9wbmciCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTAiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMTAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEyOjU1OjM3WiIKICAgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMTAtMDVUMTQ6MjU6NTItMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTEwLTA1VDE0OjI1OjUyLTA3OjAwIgogICB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZTk5OWM2NWYtNDhhOS0wNjQyLWI2MTktZmJlYTExMmUxOGZiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MzMyOWNhLWNkNjctMzY0Zi04MzU1LTY5N2ZmYzI0ZDdlZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjgyZjQwYmU3LTE0YzItZjc0Ni1hZmE1LWQxYmIxNzAyMjM4OCIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjEwIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTAiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSI+CiAgIDxwaG90b3Nob3A6VGV4dExheWVycz4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qSiIgogICAgICBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKIiLz4KICAgIDwvcmRmOlNlcT4KICAgPC9waG90b3Nob3A6VGV4dExheWVycz4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0iY3JlYXRlZCIKICAgICAgeG1wTU06aW5zdGFuY2VJRD0ieG1wLmlpZDo4MmY0MGJlNy0xNGMyLWY3NDYtYWZhNS1kMWJiMTcwMjIzODgiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIKICAgICAgeG1wTU06d2hlbj0iMjAyMC0wMi0xN1QxMjo1NTozN1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0ic2F2ZWQiCiAgICAgIHhtcE1NOmNoYW5nZWQ9Ii8iCiAgICAgIHhtcE1NOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkzMzI5Y2EtY2Q2Ny0zNjRmLTgzNTUtNjk3ZmZjMjRkN2VkIgogICAgICB4bXBNTTpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgICAgIHhtcE1NOndoZW49IjIwMjAtMDItMTdUMTI6NTU6MzdaIi8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMTAtMDVUMTQ6MjU6NTItMDc6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PntJ23wAAAGCaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRv0tCURTHP2lhmGFRQUODhDVZlELU0qD0C6pBDbJa9OWPQO3xnhHRGrQKBVFLv4b6C2oNmoOgKIJoC5qLWkpe56mgRJ7Luedzv/eew73ngiWcVjJ6/QBksjktOOF3zUcWXLZX7DTQQSu+qKKrM6HxMDXt64E6M971mbVqn/vXmpbjugJ1jcKjiqrlhCeFp9dzqsm7wu1KKrosfC7s0eSCwvemHivxm8nJEv+YrIWDAbC0CLuSVRyrYiWlZYTl5bgz6TWlfB/zJY54di4ksVu8C50gE/hxMcUYAYYYZETmIfrw0i8rauQPFPNnWZVcRWaVDTRWSJIih0fUNakel5gQPS4jzYbZ/7991RM+b6m6ww8NL4bx0QO2HSjkDeP72DAKJ2B9hqtsJX/1CIY/Rc9XNPchOLfg4rqixfbgchs6n9SoFi1KVnFLIgHvZ9AcgbZbsC+Welbe5/QRwpvyVTewfwC9ct659At2bGftHD0UJwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAEhJREFUGJVjYGBgmMzAwPCXgYHhPw78l4GBYTIjlKHHwMDwlAE7EGFgYLjJANUlgEMRDPxnIqAADoaKwn8MkCDABaShaogLcACWZRl4ajKVtAAAAABJRU5ErkJggg=='); - --gfx-restoreBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAIn2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgZGM6Zm9ybWF0PSJpbWFnZS9wbmciCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTAiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMTAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEyOjU1OjM3WiIKICAgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMTAtMDVUMTQ6MjY6NTMtMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTEwLTA1VDE0OjI2OjUzLTA3OjAwIgogICB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZTk5OWM2NWYtNDhhOS0wNjQyLWI2MTktZmJlYTExMmUxOGZiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MzMyOWNhLWNkNjctMzY0Zi04MzU1LTY5N2ZmYzI0ZDdlZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjgyZjQwYmU3LTE0YzItZjc0Ni1hZmE1LWQxYmIxNzAyMjM4OCIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjEwIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTAiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSI+CiAgIDxwaG90b3Nob3A6VGV4dExheWVycz4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qSiIgogICAgICBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKIiLz4KICAgIDwvcmRmOlNlcT4KICAgPC9waG90b3Nob3A6VGV4dExheWVycz4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0iY3JlYXRlZCIKICAgICAgeG1wTU06aW5zdGFuY2VJRD0ieG1wLmlpZDo4MmY0MGJlNy0xNGMyLWY3NDYtYWZhNS1kMWJiMTcwMjIzODgiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIKICAgICAgeG1wTU06d2hlbj0iMjAyMC0wMi0xN1QxMjo1NTozN1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0ic2F2ZWQiCiAgICAgIHhtcE1NOmNoYW5nZWQ9Ii8iCiAgICAgIHhtcE1NOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkzMzI5Y2EtY2Q2Ny0zNjRmLTgzNTUtNjk3ZmZjMjRkN2VkIgogICAgICB4bXBNTTpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgICAgIHhtcE1NOndoZW49IjIwMjAtMDItMTdUMTI6NTU6MzdaIi8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMTAtMDVUMTQ6MjY6NTMtMDc6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PluKsJ0AAAGCaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRv0tCURTHP2lhmGFRQUODhDVZlELU0qD0C6pBDbJa9OWPQO3xnhHRGrQKBVFLv4b6C2oNmoOgKIJoC5qLWkpe56mgRJ7Luedzv/eew73ngiWcVjJ6/QBksjktOOF3zUcWXLZX7DTQQSu+qKKrM6HxMDXt64E6M971mbVqn/vXmpbjugJ1jcKjiqrlhCeFp9dzqsm7wu1KKrosfC7s0eSCwvemHivxm8nJEv+YrIWDAbC0CLuSVRyrYiWlZYTl5bgz6TWlfB/zJY54di4ksVu8C50gE/hxMcUYAYYYZETmIfrw0i8rauQPFPNnWZVcRWaVDTRWSJIih0fUNakel5gQPS4jzYbZ/7991RM+b6m6ww8NL4bx0QO2HSjkDeP72DAKJ2B9hqtsJX/1CIY/Rc9XNPchOLfg4rqixfbgchs6n9SoFi1KVnFLIgHvZ9AcgbZbsC+Welbe5/QRwpvyVTewfwC9ct659At2bGftHD0UJwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAGlJREFUGJWt0LEOgkAQhOFPShspSWyvMPFxKaDh0XgOq8tZuCqBIzRMMsXmn51slr9GlJVfmHC9LII3LGfoomCGHrnSloM9olnGE+3KKVgbi0oMNX1ZaXYCG50aLBj4HJwqgXuwn47eA95vgSGy6zr7OwAAAABJRU5ErkJggg=='); - --gfx-minBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxMAAAsTAQCanBgAAAaxaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pg0KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPg0KICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPg0KICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjAtMDItMTdUMTM6MDA6MzJaIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIwLTAyLTE3VDEzOjAwOjMyWiIgeG1wOk1vZGlmeURhdGU9IjIwMjAtMDItMTdUMTM6MDA6MzJaIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjg1ZDBlZGIwLWZkMDAtYjY0Zi05ZWZiLWEyYjQ1ODcwNWE4YSIgeG1wTU06RG9jdW1lbnRJRD0iYWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOmEzMDAxZTFhLTI5MTktZTQ0OS1iOTRjLWMyMTIyNDhhOWY4YSIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjc4N2Y3OTljLTRiMTEtZTU0YS1iMjBkLTY4NjE3ZWQ5YzVlMiIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciPg0KICAgICAgPHhtcE1NOkhpc3Rvcnk+DQogICAgICAgIDxyZGY6U2VxPg0KICAgICAgICAgIDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjc4N2Y3OTljLTRiMTEtZTU0YS1iMjBkLTY4NjE3ZWQ5YzVlMiIgc3RFdnQ6d2hlbj0iMjAyMC0wMi0xN1QxMzowMDozMloiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIgLz4NCiAgICAgICAgICA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6ODVkMGVkYjAtZmQwMC1iNjRmLTllZmItYTJiNDU4NzA1YThhIiBzdEV2dDp3aGVuPSIyMDIwLTAyLTE3VDEzOjAwOjMyWiIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIiAvPg0KICAgICAgICA8L3JkZjpTZXE+DQogICAgICA8L3htcE1NOkhpc3Rvcnk+DQogICAgICA8cGhvdG9zaG9wOlRleHRMYXllcnM+DQogICAgICAgIDxyZGY6QmFnPg0KICAgICAgICAgIDxyZGY6bGkgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qShIiBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKEiIC8+DQogICAgICAgIDwvcmRmOkJhZz4NCiAgICAgIDwvcGhvdG9zaG9wOlRleHRMYXllcnM+DQogICAgPC9yZGY6RGVzY3JpcHRpb24+DQogIDwvcmRmOlJERj4NCjwveDp4bXBtZXRhPg0KPD94cGFja2V0IGVuZD0iciI/PmeGdrgAAAAVSURBVChTYxhOgBGI/0OYQx0wMAAAyp4BAZ26NiYAAAAASUVORK5CYII='); - } +// @media (prefers-color-scheme: light) { +// :root { +// /* */ +// --gfx-closeBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAIn2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgZGM6Zm9ybWF0PSJpbWFnZS9wbmciCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTAiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMTAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEyOjU1OjM3WiIKICAgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMTAtMDVUMTQ6MjY6MjgtMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTEwLTA1VDE0OjI2OjI4LTA3OjAwIgogICB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZTk5OWM2NWYtNDhhOS0wNjQyLWI2MTktZmJlYTExMmUxOGZiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MzMyOWNhLWNkNjctMzY0Zi04MzU1LTY5N2ZmYzI0ZDdlZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjgyZjQwYmU3LTE0YzItZjc0Ni1hZmE1LWQxYmIxNzAyMjM4OCIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjEwIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTAiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSI+CiAgIDxwaG90b3Nob3A6VGV4dExheWVycz4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qSiIgogICAgICBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKIiLz4KICAgIDwvcmRmOlNlcT4KICAgPC9waG90b3Nob3A6VGV4dExheWVycz4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0iY3JlYXRlZCIKICAgICAgeG1wTU06aW5zdGFuY2VJRD0ieG1wLmlpZDo4MmY0MGJlNy0xNGMyLWY3NDYtYWZhNS1kMWJiMTcwMjIzODgiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIKICAgICAgeG1wTU06d2hlbj0iMjAyMC0wMi0xN1QxMjo1NTozN1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0ic2F2ZWQiCiAgICAgIHhtcE1NOmNoYW5nZWQ9Ii8iCiAgICAgIHhtcE1NOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkzMzI5Y2EtY2Q2Ny0zNjRmLTgzNTUtNjk3ZmZjMjRkN2VkIgogICAgICB4bXBNTTpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgICAgIHhtcE1NOndoZW49IjIwMjAtMDItMTdUMTI6NTU6MzdaIi8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMTAtMDVUMTQ6MjY6MjgtMDc6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PtPY89oAAAGCaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRv0tCURTHP2lhmGFRQUODhDVZlELU0qD0C6pBDbJa9OWPQO3xnhHRGrQKBVFLv4b6C2oNmoOgKIJoC5qLWkpe56mgRJ7Luedzv/eew73ngiWcVjJ6/QBksjktOOF3zUcWXLZX7DTQQSu+qKKrM6HxMDXt64E6M971mbVqn/vXmpbjugJ1jcKjiqrlhCeFp9dzqsm7wu1KKrosfC7s0eSCwvemHivxm8nJEv+YrIWDAbC0CLuSVRyrYiWlZYTl5bgz6TWlfB/zJY54di4ksVu8C50gE/hxMcUYAYYYZETmIfrw0i8rauQPFPNnWZVcRWaVDTRWSJIih0fUNakel5gQPS4jzYbZ/7991RM+b6m6ww8NL4bx0QO2HSjkDeP72DAKJ2B9hqtsJX/1CIY/Rc9XNPchOLfg4rqixfbgchs6n9SoFi1KVnFLIgHvZ9AcgbZbsC+Welbe5/QRwpvyVTewfwC9ct659At2bGftHD0UJwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAEpJREFUGJWNkMENwDAIA1Gh3F7sP0Ty7xD5JgpU+OuTLVvMmQohhRTCnCEK8TpfBl9eBpcBu/HXcsAZ9FQjSrWqW2Pa95gzGofPBQZRG2fS0899AAAAAElFTkSuQmCC'); +// --gfx-maxBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAIn2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgZGM6Zm9ybWF0PSJpbWFnZS9wbmciCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTAiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMTAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEyOjU1OjM3WiIKICAgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMTAtMDVUMTQ6MjU6NTItMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTEwLTA1VDE0OjI1OjUyLTA3OjAwIgogICB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZTk5OWM2NWYtNDhhOS0wNjQyLWI2MTktZmJlYTExMmUxOGZiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MzMyOWNhLWNkNjctMzY0Zi04MzU1LTY5N2ZmYzI0ZDdlZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjgyZjQwYmU3LTE0YzItZjc0Ni1hZmE1LWQxYmIxNzAyMjM4OCIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjEwIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTAiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSI+CiAgIDxwaG90b3Nob3A6VGV4dExheWVycz4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qSiIgogICAgICBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKIiLz4KICAgIDwvcmRmOlNlcT4KICAgPC9waG90b3Nob3A6VGV4dExheWVycz4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0iY3JlYXRlZCIKICAgICAgeG1wTU06aW5zdGFuY2VJRD0ieG1wLmlpZDo4MmY0MGJlNy0xNGMyLWY3NDYtYWZhNS1kMWJiMTcwMjIzODgiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIKICAgICAgeG1wTU06d2hlbj0iMjAyMC0wMi0xN1QxMjo1NTozN1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0ic2F2ZWQiCiAgICAgIHhtcE1NOmNoYW5nZWQ9Ii8iCiAgICAgIHhtcE1NOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkzMzI5Y2EtY2Q2Ny0zNjRmLTgzNTUtNjk3ZmZjMjRkN2VkIgogICAgICB4bXBNTTpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgICAgIHhtcE1NOndoZW49IjIwMjAtMDItMTdUMTI6NTU6MzdaIi8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMTAtMDVUMTQ6MjU6NTItMDc6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PntJ23wAAAGCaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRv0tCURTHP2lhmGFRQUODhDVZlELU0qD0C6pBDbJa9OWPQO3xnhHRGrQKBVFLv4b6C2oNmoOgKIJoC5qLWkpe56mgRJ7Luedzv/eew73ngiWcVjJ6/QBksjktOOF3zUcWXLZX7DTQQSu+qKKrM6HxMDXt64E6M971mbVqn/vXmpbjugJ1jcKjiqrlhCeFp9dzqsm7wu1KKrosfC7s0eSCwvemHivxm8nJEv+YrIWDAbC0CLuSVRyrYiWlZYTl5bgz6TWlfB/zJY54di4ksVu8C50gE/hxMcUYAYYYZETmIfrw0i8rauQPFPNnWZVcRWaVDTRWSJIih0fUNakel5gQPS4jzYbZ/7991RM+b6m6ww8NL4bx0QO2HSjkDeP72DAKJ2B9hqtsJX/1CIY/Rc9XNPchOLfg4rqixfbgchs6n9SoFi1KVnFLIgHvZ9AcgbZbsC+Welbe5/QRwpvyVTewfwC9ct659At2bGftHD0UJwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAEhJREFUGJVjYGBgmMzAwPCXgYHhPw78l4GBYTIjlKHHwMDwlAE7EGFgYLjJANUlgEMRDPxnIqAADoaKwn8MkCDABaShaogLcACWZRl4ajKVtAAAAABJRU5ErkJggg=='); +// --gfx-restoreBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAIn2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgZGM6Zm9ybWF0PSJpbWFnZS9wbmciCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTAiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMTAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEyOjU1OjM3WiIKICAgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMTAtMDVUMTQ6MjY6NTMtMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTEwLTA1VDE0OjI2OjUzLTA3OjAwIgogICB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZTk5OWM2NWYtNDhhOS0wNjQyLWI2MTktZmJlYTExMmUxOGZiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MzMyOWNhLWNkNjctMzY0Zi04MzU1LTY5N2ZmYzI0ZDdlZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjgyZjQwYmU3LTE0YzItZjc0Ni1hZmE1LWQxYmIxNzAyMjM4OCIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjEwIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTAiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSI+CiAgIDxwaG90b3Nob3A6VGV4dExheWVycz4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qSiIgogICAgICBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKIiLz4KICAgIDwvcmRmOlNlcT4KICAgPC9waG90b3Nob3A6VGV4dExheWVycz4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0iY3JlYXRlZCIKICAgICAgeG1wTU06aW5zdGFuY2VJRD0ieG1wLmlpZDo4MmY0MGJlNy0xNGMyLWY3NDYtYWZhNS1kMWJiMTcwMjIzODgiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIKICAgICAgeG1wTU06d2hlbj0iMjAyMC0wMi0xN1QxMjo1NTozN1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0ic2F2ZWQiCiAgICAgIHhtcE1NOmNoYW5nZWQ9Ii8iCiAgICAgIHhtcE1NOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkzMzI5Y2EtY2Q2Ny0zNjRmLTgzNTUtNjk3ZmZjMjRkN2VkIgogICAgICB4bXBNTTpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgICAgIHhtcE1NOndoZW49IjIwMjAtMDItMTdUMTI6NTU6MzdaIi8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMTAtMDVUMTQ6MjY6NTMtMDc6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PluKsJ0AAAGCaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRv0tCURTHP2lhmGFRQUODhDVZlELU0qD0C6pBDbJa9OWPQO3xnhHRGrQKBVFLv4b6C2oNmoOgKIJoC5qLWkpe56mgRJ7Luedzv/eew73ngiWcVjJ6/QBksjktOOF3zUcWXLZX7DTQQSu+qKKrM6HxMDXt64E6M971mbVqn/vXmpbjugJ1jcKjiqrlhCeFp9dzqsm7wu1KKrosfC7s0eSCwvemHivxm8nJEv+YrIWDAbC0CLuSVRyrYiWlZYTl5bgz6TWlfB/zJY54di4ksVu8C50gE/hxMcUYAYYYZETmIfrw0i8rauQPFPNnWZVcRWaVDTRWSJIih0fUNakel5gQPS4jzYbZ/7991RM+b6m6ww8NL4bx0QO2HSjkDeP72DAKJ2B9hqtsJX/1CIY/Rc9XNPchOLfg4rqixfbgchs6n9SoFi1KVnFLIgHvZ9AcgbZbsC+Welbe5/QRwpvyVTewfwC9ct659At2bGftHD0UJwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAGlJREFUGJWt0LEOgkAQhOFPShspSWyvMPFxKaDh0XgOq8tZuCqBIzRMMsXmn51slr9GlJVfmHC9LII3LGfoomCGHrnSloM9olnGE+3KKVgbi0oMNX1ZaXYCG50aLBj4HJwqgXuwn47eA95vgSGy6zr7OwAAAABJRU5ErkJggg=='); +// --gfx-minBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxMAAAsTAQCanBgAAAaxaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pg0KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPg0KICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPg0KICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjAtMDItMTdUMTM6MDA6MzJaIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIwLTAyLTE3VDEzOjAwOjMyWiIgeG1wOk1vZGlmeURhdGU9IjIwMjAtMDItMTdUMTM6MDA6MzJaIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjg1ZDBlZGIwLWZkMDAtYjY0Zi05ZWZiLWEyYjQ1ODcwNWE4YSIgeG1wTU06RG9jdW1lbnRJRD0iYWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOmEzMDAxZTFhLTI5MTktZTQ0OS1iOTRjLWMyMTIyNDhhOWY4YSIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjc4N2Y3OTljLTRiMTEtZTU0YS1iMjBkLTY4NjE3ZWQ5YzVlMiIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciPg0KICAgICAgPHhtcE1NOkhpc3Rvcnk+DQogICAgICAgIDxyZGY6U2VxPg0KICAgICAgICAgIDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjc4N2Y3OTljLTRiMTEtZTU0YS1iMjBkLTY4NjE3ZWQ5YzVlMiIgc3RFdnQ6d2hlbj0iMjAyMC0wMi0xN1QxMzowMDozMloiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIgLz4NCiAgICAgICAgICA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6ODVkMGVkYjAtZmQwMC1iNjRmLTllZmItYTJiNDU4NzA1YThhIiBzdEV2dDp3aGVuPSIyMDIwLTAyLTE3VDEzOjAwOjMyWiIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIiAvPg0KICAgICAgICA8L3JkZjpTZXE+DQogICAgICA8L3htcE1NOkhpc3Rvcnk+DQogICAgICA8cGhvdG9zaG9wOlRleHRMYXllcnM+DQogICAgICAgIDxyZGY6QmFnPg0KICAgICAgICAgIDxyZGY6bGkgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qShIiBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKEiIC8+DQogICAgICAgIDwvcmRmOkJhZz4NCiAgICAgIDwvcGhvdG9zaG9wOlRleHRMYXllcnM+DQogICAgPC9yZGY6RGVzY3JpcHRpb24+DQogIDwvcmRmOlJERj4NCjwveDp4bXBtZXRhPg0KPD94cGFja2V0IGVuZD0iciI/PmeGdrgAAAAVSURBVChTYxhOgBGI/0OYQx0wMAAAyp4BAZ26NiYAAAAASUVORK5CYII='); +// } +// } + +@media (prefers-color-scheme: dark) { } -@media (prefers-color-scheme: dark) { - :root { - --gfx-closeBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAIn2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgZGM6Zm9ybWF0PSJpbWFnZS9wbmciCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTAiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMTAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEyOjU1OjM3WiIKICAgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMTAtMDVUMTQ6Mjc6MzYtMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTEwLTA1VDE0OjI3OjM2LTA3OjAwIgogICB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZTk5OWM2NWYtNDhhOS0wNjQyLWI2MTktZmJlYTExMmUxOGZiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MzMyOWNhLWNkNjctMzY0Zi04MzU1LTY5N2ZmYzI0ZDdlZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjgyZjQwYmU3LTE0YzItZjc0Ni1hZmE1LWQxYmIxNzAyMjM4OCIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjEwIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTAiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSI+CiAgIDxwaG90b3Nob3A6VGV4dExheWVycz4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qSiIgogICAgICBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKIiLz4KICAgIDwvcmRmOlNlcT4KICAgPC9waG90b3Nob3A6VGV4dExheWVycz4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0iY3JlYXRlZCIKICAgICAgeG1wTU06aW5zdGFuY2VJRD0ieG1wLmlpZDo4MmY0MGJlNy0xNGMyLWY3NDYtYWZhNS1kMWJiMTcwMjIzODgiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIKICAgICAgeG1wTU06d2hlbj0iMjAyMC0wMi0xN1QxMjo1NTozN1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0ic2F2ZWQiCiAgICAgIHhtcE1NOmNoYW5nZWQ9Ii8iCiAgICAgIHhtcE1NOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkzMzI5Y2EtY2Q2Ny0zNjRmLTgzNTUtNjk3ZmZjMjRkN2VkIgogICAgICB4bXBNTTpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgICAgIHhtcE1NOndoZW49IjIwMjAtMDItMTdUMTI6NTU6MzdaIi8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMTAtMDVUMTQ6Mjc6MzYtMDc6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PmN2D9EAAAGCaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRv0tCURTHP2lhmGFRQUODhDVZlELU0qD0C6pBDbJa9OWPQO3xnhHRGrQKBVFLv4b6C2oNmoOgKIJoC5qLWkpe56mgRJ7Luedzv/eew73ngiWcVjJ6/QBksjktOOF3zUcWXLZX7DTQQSu+qKKrM6HxMDXt64E6M971mbVqn/vXmpbjugJ1jcKjiqrlhCeFp9dzqsm7wu1KKrosfC7s0eSCwvemHivxm8nJEv+YrIWDAbC0CLuSVRyrYiWlZYTl5bgz6TWlfB/zJY54di4ksVu8C50gE/hxMcUYAYYYZETmIfrw0i8rauQPFPNnWZVcRWaVDTRWSJIih0fUNakel5gQPS4jzYbZ/7991RM+b6m6ww8NL4bx0QO2HSjkDeP72DAKJ2B9hqtsJX/1CIY/Rc9XNPchOLfg4rqixfbgchs6n9SoFi1KVnFLIgHvZ9AcgbZbsC+Welbe5/QRwpvyVTewfwC9ct659At2bGftHD0UJwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAEtJREFUGJWNkMENwDAIA1FGY/8hkn8HOAqPfBsFKvz1yZYtbqwAlUIB6saUAH2NJ4MvL4PLgK/x13LAGTSqEaVa1a0x7XvcmI3D1wbntaRbB2haYwAAAABJRU5ErkJggg=='); - --gfx-maxBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAIn2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgZGM6Zm9ybWF0PSJpbWFnZS9wbmciCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTAiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMTAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEyOjU1OjM3WiIKICAgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMTAtMDVUMTQ6Mjc6NTgtMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTEwLTA1VDE0OjI3OjU4LTA3OjAwIgogICB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZTk5OWM2NWYtNDhhOS0wNjQyLWI2MTktZmJlYTExMmUxOGZiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MzMyOWNhLWNkNjctMzY0Zi04MzU1LTY5N2ZmYzI0ZDdlZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjgyZjQwYmU3LTE0YzItZjc0Ni1hZmE1LWQxYmIxNzAyMjM4OCIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjEwIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTAiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSI+CiAgIDxwaG90b3Nob3A6VGV4dExheWVycz4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qSiIgogICAgICBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKIiLz4KICAgIDwvcmRmOlNlcT4KICAgPC9waG90b3Nob3A6VGV4dExheWVycz4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0iY3JlYXRlZCIKICAgICAgeG1wTU06aW5zdGFuY2VJRD0ieG1wLmlpZDo4MmY0MGJlNy0xNGMyLWY3NDYtYWZhNS1kMWJiMTcwMjIzODgiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIKICAgICAgeG1wTU06d2hlbj0iMjAyMC0wMi0xN1QxMjo1NTozN1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0ic2F2ZWQiCiAgICAgIHhtcE1NOmNoYW5nZWQ9Ii8iCiAgICAgIHhtcE1NOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkzMzI5Y2EtY2Q2Ny0zNjRmLTgzNTUtNjk3ZmZjMjRkN2VkIgogICAgICB4bXBNTTpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgICAgIHhtcE1NOndoZW49IjIwMjAtMDItMTdUMTI6NTU6MzdaIi8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMTAtMDVUMTQ6Mjc6NTgtMDc6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PlwQMBUAAAGCaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRv0tCURTHP2lhmGFRQUODhDVZlELU0qD0C6pBDbJa9OWPQO3xnhHRGrQKBVFLv4b6C2oNmoOgKIJoC5qLWkpe56mgRJ7Luedzv/eew73ngiWcVjJ6/QBksjktOOF3zUcWXLZX7DTQQSu+qKKrM6HxMDXt64E6M971mbVqn/vXmpbjugJ1jcKjiqrlhCeFp9dzqsm7wu1KKrosfC7s0eSCwvemHivxm8nJEv+YrIWDAbC0CLuSVRyrYiWlZYTl5bgz6TWlfB/zJY54di4ksVu8C50gE/hxMcUYAYYYZETmIfrw0i8rauQPFPNnWZVcRWaVDTRWSJIih0fUNakel5gQPS4jzYbZ/7991RM+b6m6ww8NL4bx0QO2HSjkDeP72DAKJ2B9hqtsJX/1CIY/Rc9XNPchOLfg4rqixfbgchs6n9SoFi1KVnFLIgHvZ9AcgbZbsC+Welbe5/QRwpvyVTewfwC9ct659At2bGftHD0UJwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAFBJREFUGJXV0LERgCAUBNHVsQADM3uwWWbojQIs47MEGhgAuS/eSw41qeFYqGlRA7iAm74DKLyrfRABoLrOgq+/hJXngi71BOoGZKBMHqhAbtMvQzel9pREAAAAAElFTkSuQmCC'); - --gfx-restoreBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAIn2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgZGM6Zm9ybWF0PSJpbWFnZS9wbmciCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTAiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMTAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEyOjU1OjM3WiIKICAgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMTAtMDVUMTQ6Mjc6MjQtMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTEwLTA1VDE0OjI3OjI0LTA3OjAwIgogICB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZTk5OWM2NWYtNDhhOS0wNjQyLWI2MTktZmJlYTExMmUxOGZiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MzMyOWNhLWNkNjctMzY0Zi04MzU1LTY5N2ZmYzI0ZDdlZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjgyZjQwYmU3LTE0YzItZjc0Ni1hZmE1LWQxYmIxNzAyMjM4OCIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjEwIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTAiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSI+CiAgIDxwaG90b3Nob3A6VGV4dExheWVycz4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qSiIgogICAgICBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKIiLz4KICAgIDwvcmRmOlNlcT4KICAgPC9waG90b3Nob3A6VGV4dExheWVycz4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0iY3JlYXRlZCIKICAgICAgeG1wTU06aW5zdGFuY2VJRD0ieG1wLmlpZDo4MmY0MGJlNy0xNGMyLWY3NDYtYWZhNS1kMWJiMTcwMjIzODgiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIKICAgICAgeG1wTU06d2hlbj0iMjAyMC0wMi0xN1QxMjo1NTozN1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0ic2F2ZWQiCiAgICAgIHhtcE1NOmNoYW5nZWQ9Ii8iCiAgICAgIHhtcE1NOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkzMzI5Y2EtY2Q2Ny0zNjRmLTgzNTUtNjk3ZmZjMjRkN2VkIgogICAgICB4bXBNTTpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgICAgIHhtcE1NOndoZW49IjIwMjAtMDItMTdUMTI6NTU6MzdaIi8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMTAtMDVUMTQ6Mjc6MjQtMDc6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PqiFCFwAAAGCaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRv0tCURTHP2lhmGFRQUODhDVZlELU0qD0C6pBDbJa9OWPQO3xnhHRGrQKBVFLv4b6C2oNmoOgKIJoC5qLWkpe56mgRJ7Luedzv/eew73ngiWcVjJ6/QBksjktOOF3zUcWXLZX7DTQQSu+qKKrM6HxMDXt64E6M971mbVqn/vXmpbjugJ1jcKjiqrlhCeFp9dzqsm7wu1KKrosfC7s0eSCwvemHivxm8nJEv+YrIWDAbC0CLuSVRyrYiWlZYTl5bgz6TWlfB/zJY54di4ksVu8C50gE/hxMcUYAYYYZETmIfrw0i8rauQPFPNnWZVcRWaVDTRWSJIih0fUNakel5gQPS4jzYbZ/7991RM+b6m6ww8NL4bx0QO2HSjkDeP72DAKJ2B9hqtsJX/1CIY/Rc9XNPchOLfg4rqixfbgchs6n9SoFi1KVnFLIgHvZ9AcgbZbsC+Welbe5/QRwpvyVTewfwC9ct659At2bGftHD0UJwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAHNJREFUGJWtkKEOwlAMRc+QM5AwQYJFoPjZCWb2YRPIaeRTLwfTLQs0UxzX3tumtxCog78UdVTbZmM8AmsdXIABeKH2ak221dDuamnUCjyA+WtbB0zAGXgT0ycSFk31kBky/moUeBLpbsl91wi6Nnbfs/g+7XOQq6ifjfkAAAAASUVORK5CYII='); - --gfx-minBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAGOmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEzOjAwOjMyWiIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMC0wMi0xN1QxMzowMDozMloiIHhtcDpNb2RpZnlEYXRlPSIyMDIwLTAyLTE3VDEzOjAwOjMyWiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4NWQwZWRiMC1mZDAwLWI2NGYtOWVmYi1hMmI0NTg3MDVhOGEiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDphMzAwMWUxYS0yOTE5LWU0NDktYjk0Yy1jMjEyMjQ4YTlmOGEiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3ODdmNzk5Yy00YjExLWU1NGEtYjIwZC02ODYxN2VkOWM1ZTIiIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo3ODdmNzk5Yy00YjExLWU1NGEtYjIwZC02ODYxN2VkOWM1ZTIiIHN0RXZ0OndoZW49IjIwMjAtMDItMTdUMTM6MDA6MzJaIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjg1ZDBlZGIwLWZkMDAtYjY0Zi05ZWZiLWEyYjQ1ODcwNWE4YSIgc3RFdnQ6d2hlbj0iMjAyMC0wMi0xN1QxMzowMDozMloiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPHBob3Rvc2hvcDpUZXh0TGF5ZXJzPiA8cmRmOkJhZz4gPHJkZjpsaSBwaG90b3Nob3A6TGF5ZXJOYW1lPSLupKEiIHBob3Rvc2hvcDpMYXllclRleHQ9Iu6koSIvPiA8L3JkZjpCYWc+IDwvcGhvdG9zaG9wOlRleHRMYXllcnM+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+FwvRXAAAABdJREFUGNNj/P//PwMxgHGIKPw/XDwDAOr1HuzlELLnAAAAAElFTkSuQmCC'); - } +:root { + --gfx-closeBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAIn2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgZGM6Zm9ybWF0PSJpbWFnZS9wbmciCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTAiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMTAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEyOjU1OjM3WiIKICAgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMTAtMDVUMTQ6Mjc6MzYtMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTEwLTA1VDE0OjI3OjM2LTA3OjAwIgogICB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZTk5OWM2NWYtNDhhOS0wNjQyLWI2MTktZmJlYTExMmUxOGZiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MzMyOWNhLWNkNjctMzY0Zi04MzU1LTY5N2ZmYzI0ZDdlZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjgyZjQwYmU3LTE0YzItZjc0Ni1hZmE1LWQxYmIxNzAyMjM4OCIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjEwIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTAiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSI+CiAgIDxwaG90b3Nob3A6VGV4dExheWVycz4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qSiIgogICAgICBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKIiLz4KICAgIDwvcmRmOlNlcT4KICAgPC9waG90b3Nob3A6VGV4dExheWVycz4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0iY3JlYXRlZCIKICAgICAgeG1wTU06aW5zdGFuY2VJRD0ieG1wLmlpZDo4MmY0MGJlNy0xNGMyLWY3NDYtYWZhNS1kMWJiMTcwMjIzODgiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIKICAgICAgeG1wTU06d2hlbj0iMjAyMC0wMi0xN1QxMjo1NTozN1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0ic2F2ZWQiCiAgICAgIHhtcE1NOmNoYW5nZWQ9Ii8iCiAgICAgIHhtcE1NOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkzMzI5Y2EtY2Q2Ny0zNjRmLTgzNTUtNjk3ZmZjMjRkN2VkIgogICAgICB4bXBNTTpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgICAgIHhtcE1NOndoZW49IjIwMjAtMDItMTdUMTI6NTU6MzdaIi8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMTAtMDVUMTQ6Mjc6MzYtMDc6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PmN2D9EAAAGCaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRv0tCURTHP2lhmGFRQUODhDVZlELU0qD0C6pBDbJa9OWPQO3xnhHRGrQKBVFLv4b6C2oNmoOgKIJoC5qLWkpe56mgRJ7Luedzv/eew73ngiWcVjJ6/QBksjktOOF3zUcWXLZX7DTQQSu+qKKrM6HxMDXt64E6M971mbVqn/vXmpbjugJ1jcKjiqrlhCeFp9dzqsm7wu1KKrosfC7s0eSCwvemHivxm8nJEv+YrIWDAbC0CLuSVRyrYiWlZYTl5bgz6TWlfB/zJY54di4ksVu8C50gE/hxMcUYAYYYZETmIfrw0i8rauQPFPNnWZVcRWaVDTRWSJIih0fUNakel5gQPS4jzYbZ/7991RM+b6m6ww8NL4bx0QO2HSjkDeP72DAKJ2B9hqtsJX/1CIY/Rc9XNPchOLfg4rqixfbgchs6n9SoFi1KVnFLIgHvZ9AcgbZbsC+Welbe5/QRwpvyVTewfwC9ct659At2bGftHD0UJwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAEtJREFUGJWNkMENwDAIA1FGY/8hkn8HOAqPfBsFKvz1yZYtbqwAlUIB6saUAH2NJ4MvL4PLgK/x13LAGTSqEaVa1a0x7XvcmI3D1wbntaRbB2haYwAAAABJRU5ErkJggg=='); + --gfx-maxBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAIn2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgZGM6Zm9ybWF0PSJpbWFnZS9wbmciCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTAiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMTAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEyOjU1OjM3WiIKICAgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMTAtMDVUMTQ6Mjc6NTgtMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTEwLTA1VDE0OjI3OjU4LTA3OjAwIgogICB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZTk5OWM2NWYtNDhhOS0wNjQyLWI2MTktZmJlYTExMmUxOGZiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MzMyOWNhLWNkNjctMzY0Zi04MzU1LTY5N2ZmYzI0ZDdlZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjgyZjQwYmU3LTE0YzItZjc0Ni1hZmE1LWQxYmIxNzAyMjM4OCIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjEwIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTAiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSI+CiAgIDxwaG90b3Nob3A6VGV4dExheWVycz4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qSiIgogICAgICBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKIiLz4KICAgIDwvcmRmOlNlcT4KICAgPC9waG90b3Nob3A6VGV4dExheWVycz4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0iY3JlYXRlZCIKICAgICAgeG1wTU06aW5zdGFuY2VJRD0ieG1wLmlpZDo4MmY0MGJlNy0xNGMyLWY3NDYtYWZhNS1kMWJiMTcwMjIzODgiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIKICAgICAgeG1wTU06d2hlbj0iMjAyMC0wMi0xN1QxMjo1NTozN1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0ic2F2ZWQiCiAgICAgIHhtcE1NOmNoYW5nZWQ9Ii8iCiAgICAgIHhtcE1NOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkzMzI5Y2EtY2Q2Ny0zNjRmLTgzNTUtNjk3ZmZjMjRkN2VkIgogICAgICB4bXBNTTpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgICAgIHhtcE1NOndoZW49IjIwMjAtMDItMTdUMTI6NTU6MzdaIi8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMTAtMDVUMTQ6Mjc6NTgtMDc6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PlwQMBUAAAGCaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRv0tCURTHP2lhmGFRQUODhDVZlELU0qD0C6pBDbJa9OWPQO3xnhHRGrQKBVFLv4b6C2oNmoOgKIJoC5qLWkpe56mgRJ7Luedzv/eew73ngiWcVjJ6/QBksjktOOF3zUcWXLZX7DTQQSu+qKKrM6HxMDXt64E6M971mbVqn/vXmpbjugJ1jcKjiqrlhCeFp9dzqsm7wu1KKrosfC7s0eSCwvemHivxm8nJEv+YrIWDAbC0CLuSVRyrYiWlZYTl5bgz6TWlfB/zJY54di4ksVu8C50gE/hxMcUYAYYYZETmIfrw0i8rauQPFPNnWZVcRWaVDTRWSJIih0fUNakel5gQPS4jzYbZ/7991RM+b6m6ww8NL4bx0QO2HSjkDeP72DAKJ2B9hqtsJX/1CIY/Rc9XNPchOLfg4rqixfbgchs6n9SoFi1KVnFLIgHvZ9AcgbZbsC+Welbe5/QRwpvyVTewfwC9ct659At2bGftHD0UJwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAFBJREFUGJXV0LERgCAUBNHVsQADM3uwWWbojQIs47MEGhgAuS/eSw41qeFYqGlRA7iAm74DKLyrfRABoLrOgq+/hJXngi71BOoGZKBMHqhAbtMvQzel9pREAAAAAElFTkSuQmCC'); + --gfx-restoreBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAIn2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgZGM6Zm9ybWF0PSJpbWFnZS9wbmciCiAgIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiCiAgIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMTAiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iMTAiCiAgIHRpZmY6UmVzb2x1dGlvblVuaXQ9IjIiCiAgIHRpZmY6WFJlc29sdXRpb249IjcyLjAiCiAgIHRpZmY6WVJlc29sdXRpb249IjcyLjAiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEyOjU1OjM3WiIKICAgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMTAtMDVUMTQ6Mjc6MjQtMDc6MDAiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIxLTEwLTA1VDE0OjI3OjI0LTA3OjAwIgogICB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6ZTk5OWM2NWYtNDhhOS0wNjQyLWI2MTktZmJlYTExMmUxOGZiIgogICB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MzMyOWNhLWNkNjctMzY0Zi04MzU1LTY5N2ZmYzI0ZDdlZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjgyZjQwYmU3LTE0YzItZjc0Ni1hZmE1LWQxYmIxNzAyMjM4OCIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjEwIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iMTAiCiAgIGV4aWY6Q29sb3JTcGFjZT0iMSI+CiAgIDxwaG90b3Nob3A6VGV4dExheWVycz4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgcGhvdG9zaG9wOkxheWVyTmFtZT0i7qSiIgogICAgICBwaG90b3Nob3A6TGF5ZXJUZXh0PSLupKIiLz4KICAgIDwvcmRmOlNlcT4KICAgPC9waG90b3Nob3A6VGV4dExheWVycz4KICAgPHhtcE1NOkhpc3Rvcnk+CiAgICA8cmRmOlNlcT4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0iY3JlYXRlZCIKICAgICAgeG1wTU06aW5zdGFuY2VJRD0ieG1wLmlpZDo4MmY0MGJlNy0xNGMyLWY3NDYtYWZhNS1kMWJiMTcwMjIzODgiCiAgICAgIHhtcE1NOnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIKICAgICAgeG1wTU06d2hlbj0iMjAyMC0wMi0xN1QxMjo1NTozN1oiLz4KICAgICA8cmRmOmxpCiAgICAgIHhtcE1NOmFjdGlvbj0ic2F2ZWQiCiAgICAgIHhtcE1NOmNoYW5nZWQ9Ii8iCiAgICAgIHhtcE1NOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkzMzI5Y2EtY2Q2Ny0zNjRmLTgzNTUtNjk3ZmZjMjRkN2VkIgogICAgICB4bXBNTTpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiCiAgICAgIHhtcE1NOndoZW49IjIwMjAtMDItMTdUMTI6NTU6MzdaIi8+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjEwLjEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjEtMTAtMDVUMTQ6Mjc6MjQtMDc6MDAiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFja2V0IGVuZD0iciI/PqiFCFwAAAGCaUNDUHNSR0IgSUVDNjE5NjYtMi4xAAAokXWRv0tCURTHP2lhmGFRQUODhDVZlELU0qD0C6pBDbJa9OWPQO3xnhHRGrQKBVFLv4b6C2oNmoOgKIJoC5qLWkpe56mgRJ7Luedzv/eew73ngiWcVjJ6/QBksjktOOF3zUcWXLZX7DTQQSu+qKKrM6HxMDXt64E6M971mbVqn/vXmpbjugJ1jcKjiqrlhCeFp9dzqsm7wu1KKrosfC7s0eSCwvemHivxm8nJEv+YrIWDAbC0CLuSVRyrYiWlZYTl5bgz6TWlfB/zJY54di4ksVu8C50gE/hxMcUYAYYYZETmIfrw0i8rauQPFPNnWZVcRWaVDTRWSJIih0fUNakel5gQPS4jzYbZ/7991RM+b6m6ww8NL4bx0QO2HSjkDeP72DAKJ2B9hqtsJX/1CIY/Rc9XNPchOLfg4rqixfbgchs6n9SoFi1KVnFLIgHvZ9AcgbZbsC+Welbe5/QRwpvyVTewfwC9ct659At2bGftHD0UJwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAHNJREFUGJWtkKEOwlAMRc+QM5AwQYJFoPjZCWb2YRPIaeRTLwfTLQs0UxzX3tumtxCog78UdVTbZmM8AmsdXIABeKH2ak221dDuamnUCjyA+WtbB0zAGXgT0ycSFk31kBky/moUeBLpbsl91wi6Nnbfs/g+7XOQq6ifjfkAAAAASUVORK5CYII='); + --gfx-minBtn: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAGOmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTAyLTE3VDEzOjAwOjMyWiIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMC0wMi0xN1QxMzowMDozMloiIHhtcDpNb2RpZnlEYXRlPSIyMDIwLTAyLTE3VDEzOjAwOjMyWiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4NWQwZWRiMC1mZDAwLWI2NGYtOWVmYi1hMmI0NTg3MDVhOGEiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDphMzAwMWUxYS0yOTE5LWU0NDktYjk0Yy1jMjEyMjQ4YTlmOGEiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3ODdmNzk5Yy00YjExLWU1NGEtYjIwZC02ODYxN2VkOWM1ZTIiIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo3ODdmNzk5Yy00YjExLWU1NGEtYjIwZC02ODYxN2VkOWM1ZTIiIHN0RXZ0OndoZW49IjIwMjAtMDItMTdUMTM6MDA6MzJaIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjg1ZDBlZGIwLWZkMDAtYjY0Zi05ZWZiLWEyYjQ1ODcwNWE4YSIgc3RFdnQ6d2hlbj0iMjAyMC0wMi0xN1QxMzowMDozMloiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPHBob3Rvc2hvcDpUZXh0TGF5ZXJzPiA8cmRmOkJhZz4gPHJkZjpsaSBwaG90b3Nob3A6TGF5ZXJOYW1lPSLupKEiIHBob3Rvc2hvcDpMYXllclRleHQ9Iu6koSIvPiA8L3JkZjpCYWc+IDwvcGhvdG9zaG9wOlRleHRMYXllcnM+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+FwvRXAAAABdJREFUGNNj/P//PwMxgHGIKPw/XDwDAOr1HuzlELLnAAAAAElFTkSuQmCC'); } @@ -3182,7 +4055,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { cursor: pointer; } -#apple-music-video-player-controls #player-pip>svg { +#apple-music-video-player-controls #player-pip > svg { width: 50%; } @@ -3201,7 +4074,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb { cursor: pointer; } -#apple-music-video-player-controls #player-fullscreen>svg { +#apple-music-video-player-controls #player-fullscreen > svg { width: 50%; } @@ -3225,6 +4098,7 @@ div#captions { background: rgba(0, 0, 0, 0.6); color: yellow; white-space: pre-line; + font-family: 'Inter', 'Noto Sans JP','Source Han Sans SC', 'Source Han Sans HK','Source Han Sans SC', 'Source Han Sans HK','Noto Sans SC','Noto Sans TC', 'Noto Sans HK', 'Noto Sans KR', sans-serif; } [v-cloak] { @@ -3331,6 +4205,13 @@ input[type=checkbox][switch]:checked:active::before { } body.no-gpu { + --ciderShadow-Generic: var(--mediaItemShadow); + --mediaItemShadow-Shadow: var(--mediaItemShadow); + --mediaItemShadow-ShadowSubtle: var(--mediaItemShadow); + + .bg-artwork-container { + display: none; + } #navigation-bar { backdrop-filter: unset; mix-blend-mode: unset; @@ -3359,4 +4240,14 @@ body.no-gpu { .wpfade-leave-to { opacity: 0; } + + .drawertransition-enter-active, + .drawertransition-leave-active { + transition: right 0s var(--appleEase); + } + + .drawertransition-enter, + .drawertransition-leave-to { + right: -300px; + } } \ No newline at end of file diff --git a/src/renderer/vibrant.min.js b/src/renderer/vibrant.min.js new file mode 100644 index 00000000..5144adb6 --- /dev/null +++ b/src/renderer/vibrant.min.js @@ -0,0 +1,12492 @@ +/******/ (function(modules) { // webpackBootstrap + /******/ // The module cache + /******/ var installedModules = {}; + /******/ + /******/ // The require function + /******/ function __webpack_require__(moduleId) { + /******/ + /******/ // Check if module is in cache + /******/ if(installedModules[moduleId]) + /******/ return installedModules[moduleId].exports; + /******/ + /******/ // Create a new module (and put it into the cache) + /******/ var module = installedModules[moduleId] = { + /******/ i: moduleId, + /******/ l: false, + /******/ exports: {} + /******/ }; + /******/ + /******/ // Execute the module function + /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + /******/ + /******/ // Flag the module as loaded + /******/ module.l = true; + /******/ + /******/ // Return the exports of the module + /******/ return module.exports; + /******/ } + /******/ + /******/ + /******/ // expose the modules object (__webpack_modules__) + /******/ __webpack_require__.m = modules; + /******/ + /******/ // expose the module cache + /******/ __webpack_require__.c = installedModules; + /******/ + /******/ // identity function for calling harmony imports with the correct context + /******/ __webpack_require__.i = function(value) { return value; }; + /******/ + /******/ // define getter function for harmony exports + /******/ __webpack_require__.d = function(exports, name, getter) { + /******/ if(!__webpack_require__.o(exports, name)) { + /******/ Object.defineProperty(exports, name, { + /******/ configurable: false, + /******/ enumerable: true, + /******/ get: getter + /******/ }); + /******/ } + /******/ }; + /******/ + /******/ // getDefaultExport function for compatibility with non-harmony modules + /******/ __webpack_require__.n = function(module) { + /******/ var getter = module && module.__esModule ? + /******/ function getDefault() { return module['default']; } : + /******/ function getModuleExports() { return module; }; + /******/ __webpack_require__.d(getter, 'a', getter); + /******/ return getter; + /******/ }; + /******/ + /******/ // Object.prototype.hasOwnProperty.call + /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; + /******/ + /******/ // __webpack_public_path__ + /******/ __webpack_require__.p = ""; + /******/ + /******/ // Load entry module and return exports + /******/ return __webpack_require__(__webpack_require__.s = 151); + /******/ }) + /************************************************************************/ + /******/ ([ + /* 0 */ + /***/ (function(module, exports, __webpack_require__) { + + var freeGlobal = __webpack_require__(33); + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + module.exports = root; + + + /***/ }), + /* 1 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseIsNative = __webpack_require__(66), + getValue = __webpack_require__(90); + + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; + } + + module.exports = getNative; + + + /***/ }), + /* 2 */ + /***/ (function(module, exports) { + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } + + module.exports = isObject; + + + /***/ }), + /* 3 */ + /***/ (function(module, exports, __webpack_require__) { + + var assignValue = __webpack_require__(28), + baseAssignValue = __webpack_require__(29); + + /** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; + } + + module.exports = copyObject; + + + /***/ }), + /* 4 */ + /***/ (function(module, exports, __webpack_require__) { + + var listCacheClear = __webpack_require__(102), + listCacheDelete = __webpack_require__(103), + listCacheGet = __webpack_require__(104), + listCacheHas = __webpack_require__(105), + listCacheSet = __webpack_require__(106); + + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + +// Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + + module.exports = ListCache; + + + /***/ }), + /* 5 */ + /***/ (function(module, exports, __webpack_require__) { + + var eq = __webpack_require__(9); + + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } + + module.exports = assocIndexOf; + + + /***/ }), + /* 6 */ + /***/ (function(module, exports, __webpack_require__) { + + var Symbol = __webpack_require__(15), + getRawTag = __webpack_require__(88), + objectToString = __webpack_require__(116); + + /** `Object#toString` result references. */ + var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; + + /** Built-in value references. */ + var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + + /** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); + } + + module.exports = baseGetTag; + + + /***/ }), + /* 7 */ + /***/ (function(module, exports, __webpack_require__) { + + var isKeyable = __webpack_require__(100); + + /** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } + + module.exports = getMapData; + + + /***/ }), + /* 8 */ + /***/ (function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(1); + + /* Built-in method references that are verified to be native. */ + var nativeCreate = getNative(Object, 'create'); + + module.exports = nativeCreate; + + + /***/ }), + /* 9 */ + /***/ (function(module, exports) { + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + module.exports = eq; + + + /***/ }), + /* 10 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + Object.defineProperty(exports, "__esModule", { value: true }); + var Bluebird = __webpack_require__(13); + exports.DELTAE94_DIFF_STATUS = { + NA: 0, + PERFECT: 1, + CLOSE: 2, + GOOD: 10, + SIMILAR: 50 + }; + exports.SIGBITS = 5; + exports.RSHIFT = 8 - exports.SIGBITS; + function defer() { + var resolve; + var reject; + var promise = new Bluebird(function (_resolve, _reject) { + resolve = _resolve; + reject = _reject; + }); + return { resolve: resolve, reject: reject, promise: promise }; + } + exports.defer = defer; + function hexToRgb(hex) { + var m = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return m === null ? null : [m[1], m[2], m[3]].map(function (s) { return parseInt(s, 16); }); + } + exports.hexToRgb = hexToRgb; + function rgbToHex(r, g, b) { + return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1, 7); + } + exports.rgbToHex = rgbToHex; + function rgbToHsl(r, g, b) { + r /= 255; + g /= 255; + b /= 255; + var max = Math.max(r, g, b); + var min = Math.min(r, g, b); + var h; + var s; + var l = (max + min) / 2; + if (max === min) { + h = s = 0; + } + else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + return [h, s, l]; + } + exports.rgbToHsl = rgbToHsl; + function hslToRgb(h, s, l) { + var r; + var g; + var b; + function hue2rgb(p, q, t) { + if (t < 0) + t += 1; + if (t > 1) + t -= 1; + if (t < 1 / 6) + return p + (q - p) * 6 * t; + if (t < 1 / 2) + return q; + if (t < 2 / 3) + return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + if (s === 0) { + r = g = b = l; + } + else { + var q = l < 0.5 ? l * (1 + s) : l + s - (l * s); + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - (1 / 3)); + } + return [ + r * 255, + g * 255, + b * 255 + ]; + } + exports.hslToRgb = hslToRgb; + function rgbToXyz(r, g, b) { + r /= 255; + g /= 255; + b /= 255; + r = r > 0.04045 ? Math.pow((r + 0.005) / 1.055, 2.4) : r / 12.92; + g = g > 0.04045 ? Math.pow((g + 0.005) / 1.055, 2.4) : g / 12.92; + b = b > 0.04045 ? Math.pow((b + 0.005) / 1.055, 2.4) : b / 12.92; + r *= 100; + g *= 100; + b *= 100; + var x = r * 0.4124 + g * 0.3576 + b * 0.1805; + var y = r * 0.2126 + g * 0.7152 + b * 0.0722; + var z = r * 0.0193 + g * 0.1192 + b * 0.9505; + return [x, y, z]; + } + exports.rgbToXyz = rgbToXyz; + function xyzToCIELab(x, y, z) { + var REF_X = 95.047; + var REF_Y = 100; + var REF_Z = 108.883; + x /= REF_X; + y /= REF_Y; + z /= REF_Z; + x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116; + y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116; + z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116; + var L = 116 * y - 16; + var a = 500 * (x - y); + var b = 200 * (y - z); + return [L, a, b]; + } + exports.xyzToCIELab = xyzToCIELab; + function rgbToCIELab(r, g, b) { + var _a = rgbToXyz(r, g, b), x = _a[0], y = _a[1], z = _a[2]; + return xyzToCIELab(x, y, z); + } + exports.rgbToCIELab = rgbToCIELab; + function deltaE94(lab1, lab2) { + var WEIGHT_L = 1; + var WEIGHT_C = 1; + var WEIGHT_H = 1; + var L1 = lab1[0], a1 = lab1[1], b1 = lab1[2]; + var L2 = lab2[0], a2 = lab2[1], b2 = lab2[2]; + var dL = L1 - L2; + var da = a1 - a2; + var db = b1 - b2; + var xC1 = Math.sqrt(a1 * a1 + b1 * b1); + var xC2 = Math.sqrt(a2 * a2 + b2 * b2); + var xDL = L2 - L1; + var xDC = xC2 - xC1; + var xDE = Math.sqrt(dL * dL + da * da + db * db); + var xDH = (Math.sqrt(xDE) > Math.sqrt(Math.abs(xDL)) + Math.sqrt(Math.abs(xDC))) + ? Math.sqrt(xDE * xDE - xDL * xDL - xDC * xDC) + : 0; + var xSC = 1 + 0.045 * xC1; + var xSH = 1 + 0.015 * xC1; + xDL /= WEIGHT_L; + xDC /= WEIGHT_C * xSC; + xDH /= WEIGHT_H * xSH; + return Math.sqrt(xDL * xDL + xDC * xDC + xDH * xDH); + } + exports.deltaE94 = deltaE94; + function rgbDiff(rgb1, rgb2) { + var lab1 = rgbToCIELab.apply(undefined, rgb1); + var lab2 = rgbToCIELab.apply(undefined, rgb2); + return deltaE94(lab1, lab2); + } + exports.rgbDiff = rgbDiff; + function hexDiff(hex1, hex2) { + var rgb1 = hexToRgb(hex1); + var rgb2 = hexToRgb(hex2); + return rgbDiff(rgb1, rgb2); + } + exports.hexDiff = hexDiff; + function getColorDiffStatus(d) { + if (d < exports.DELTAE94_DIFF_STATUS.NA) + return 'N/A'; + // Not perceptible by human eyes + if (d <= exports.DELTAE94_DIFF_STATUS.PERFECT) + return 'Perfect'; + // Perceptible through close observation + if (d <= exports.DELTAE94_DIFF_STATUS.CLOSE) + return 'Close'; + // Perceptible at a glance + if (d <= exports.DELTAE94_DIFF_STATUS.GOOD) + return 'Good'; + // Colors are more similar than opposite + if (d < exports.DELTAE94_DIFF_STATUS.SIMILAR) + return 'Similar'; + return 'Wrong'; + } + exports.getColorDiffStatus = getColorDiffStatus; + function getColorIndex(r, g, b) { + return (r << (2 * exports.SIGBITS)) + (g << exports.SIGBITS) + b; + } + exports.getColorIndex = getColorIndex; + + + /***/ }), + /* 11 */ + /***/ (function(module, exports) { + + var g; + +// This works in non-strict mode + g = (function() { + return this; + })(); + + try { + // This works if eval is allowed (see CSP) + g = g || Function("return this")() || (1,eval)("this"); + } catch(e) { + // This works if the window reference is available + if(typeof window === "object") + g = window; + } + +// g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + + module.exports = g; + + + /***/ }), + /* 12 */ + /***/ (function(module, exports) { + + module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + if(!module.children) module.children = []; + Object.defineProperty(module, "loaded", { + enumerable: true, + get: function() { + return module.l; + } + }); + Object.defineProperty(module, "id", { + enumerable: true, + get: function() { + return module.i; + } + }); + module.webpackPolyfill = 1; + } + return module; + }; + + + /***/ }), + /* 13 */ + /***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(process, global, setImmediate) {/* @preserve + * The MIT License (MIT) + * + * Copyright (c) 2013-2015 Petka Antonov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + /** + * bluebird build version 3.4.7 + * Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, using, timers, filter, any, each + */ + !function(e){if(true)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Promise=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof _dereq_=="function"&&_dereq_;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof _dereq_=="function"&&_dereq_;for(var o=0;o 0) { + var fn = queue.shift(); + if (typeof fn !== "function") { + fn._settlePromises(); + continue; + } + var receiver = queue.shift(); + var arg = queue.shift(); + fn.call(receiver, arg); + } + }; + + Async.prototype._drainQueues = function () { + this._drainQueue(this._normalQueue); + this._reset(); + this._haveDrainedQueues = true; + this._drainQueue(this._lateQueue); + }; + + Async.prototype._queueTick = function () { + if (!this._isTickUsed) { + this._isTickUsed = true; + this._schedule(this.drainQueues); + } + }; + + Async.prototype._reset = function () { + this._isTickUsed = false; + }; + + module.exports = Async; + module.exports.firstLineError = firstLineError; + + },{"./queue":26,"./schedule":29,"./util":36}],3:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, INTERNAL, tryConvertToPromise, debug) { + var calledBind = false; + var rejectThis = function(_, e) { + this._reject(e); + }; + + var targetRejected = function(e, context) { + context.promiseRejectionQueued = true; + context.bindingPromise._then(rejectThis, rejectThis, null, this, e); + }; + + var bindingResolved = function(thisArg, context) { + if (((this._bitField & 50397184) === 0)) { + this._resolveCallback(context.target); + } + }; + + var bindingRejected = function(e, context) { + if (!context.promiseRejectionQueued) this._reject(e); + }; + + Promise.prototype.bind = function (thisArg) { + if (!calledBind) { + calledBind = true; + Promise.prototype._propagateFrom = debug.propagateFromFunction(); + Promise.prototype._boundValue = debug.boundValueFunction(); + } + var maybePromise = tryConvertToPromise(thisArg); + var ret = new Promise(INTERNAL); + ret._propagateFrom(this, 1); + var target = this._target(); + ret._setBoundTo(maybePromise); + if (maybePromise instanceof Promise) { + var context = { + promiseRejectionQueued: false, + promise: ret, + target: target, + bindingPromise: maybePromise + }; + target._then(INTERNAL, targetRejected, undefined, ret, context); + maybePromise._then( + bindingResolved, bindingRejected, undefined, ret, context); + ret._setOnCancel(maybePromise); + } else { + ret._resolveCallback(target); + } + return ret; + }; + + Promise.prototype._setBoundTo = function (obj) { + if (obj !== undefined) { + this._bitField = this._bitField | 2097152; + this._boundTo = obj; + } else { + this._bitField = this._bitField & (~2097152); + } + }; + + Promise.prototype._isBound = function () { + return (this._bitField & 2097152) === 2097152; + }; + + Promise.bind = function (thisArg, value) { + return Promise.resolve(value).bind(thisArg); + }; + }; + + },{}],4:[function(_dereq_,module,exports){ + "use strict"; + var old; + if (typeof Promise !== "undefined") old = Promise; + function noConflict() { + try { if (Promise === bluebird) Promise = old; } + catch (e) {} + return bluebird; + } + var bluebird = _dereq_("./promise")(); + bluebird.noConflict = noConflict; + module.exports = bluebird; + + },{"./promise":22}],5:[function(_dereq_,module,exports){ + "use strict"; + var cr = Object.create; + if (cr) { + var callerCache = cr(null); + var getterCache = cr(null); + callerCache[" size"] = getterCache[" size"] = 0; + } + + module.exports = function(Promise) { + var util = _dereq_("./util"); + var canEvaluate = util.canEvaluate; + var isIdentifier = util.isIdentifier; + + var getMethodCaller; + var getGetter; + if (false) { + var makeMethodCaller = function (methodName) { + return new Function("ensureMethod", " \n\ + return function(obj) { \n\ + 'use strict' \n\ + var len = this.length; \n\ + ensureMethod(obj, 'methodName'); \n\ + switch(len) { \n\ + case 1: return obj.methodName(this[0]); \n\ + case 2: return obj.methodName(this[0], this[1]); \n\ + case 3: return obj.methodName(this[0], this[1], this[2]); \n\ + case 0: return obj.methodName(); \n\ + default: \n\ + return obj.methodName.apply(obj, this); \n\ + } \n\ + }; \n\ + ".replace(/methodName/g, methodName))(ensureMethod); + }; + + var makeGetter = function (propertyName) { + return new Function("obj", " \n\ + 'use strict'; \n\ + return obj.propertyName; \n\ + ".replace("propertyName", propertyName)); + }; + + var getCompiled = function(name, compiler, cache) { + var ret = cache[name]; + if (typeof ret !== "function") { + if (!isIdentifier(name)) { + return null; + } + ret = compiler(name); + cache[name] = ret; + cache[" size"]++; + if (cache[" size"] > 512) { + var keys = Object.keys(cache); + for (var i = 0; i < 256; ++i) delete cache[keys[i]]; + cache[" size"] = keys.length - 256; + } + } + return ret; + }; + + getMethodCaller = function(name) { + return getCompiled(name, makeMethodCaller, callerCache); + }; + + getGetter = function(name) { + return getCompiled(name, makeGetter, getterCache); + }; + } + + function ensureMethod(obj, methodName) { + var fn; + if (obj != null) fn = obj[methodName]; + if (typeof fn !== "function") { + var message = "Object " + util.classString(obj) + " has no method '" + + util.toString(methodName) + "'"; + throw new Promise.TypeError(message); + } + return fn; + } + + function caller(obj) { + var methodName = this.pop(); + var fn = ensureMethod(obj, methodName); + return fn.apply(obj, this); + } + Promise.prototype.call = function (methodName) { + var args = [].slice.call(arguments, 1);; + if (false) { + if (canEvaluate) { + var maybeCaller = getMethodCaller(methodName); + if (maybeCaller !== null) { + return this._then( + maybeCaller, undefined, undefined, args, undefined); + } + } + } + args.push(methodName); + return this._then(caller, undefined, undefined, args, undefined); + }; + + function namedGetter(obj) { + return obj[this]; + } + function indexedGetter(obj) { + var index = +this; + if (index < 0) index = Math.max(0, index + obj.length); + return obj[index]; + } + Promise.prototype.get = function (propertyName) { + var isIndex = (typeof propertyName === "number"); + var getter; + if (!isIndex) { + if (canEvaluate) { + var maybeGetter = getGetter(propertyName); + getter = maybeGetter !== null ? maybeGetter : namedGetter; + } else { + getter = namedGetter; + } + } else { + getter = indexedGetter; + } + return this._then(getter, undefined, undefined, propertyName, undefined); + }; + }; + + },{"./util":36}],6:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, PromiseArray, apiRejection, debug) { + var util = _dereq_("./util"); + var tryCatch = util.tryCatch; + var errorObj = util.errorObj; + var async = Promise._async; + + Promise.prototype["break"] = Promise.prototype.cancel = function() { + if (!debug.cancellation()) return this._warn("cancellation is disabled"); + + var promise = this; + var child = promise; + while (promise._isCancellable()) { + if (!promise._cancelBy(child)) { + if (child._isFollowing()) { + child._followee().cancel(); + } else { + child._cancelBranched(); + } + break; + } + + var parent = promise._cancellationParent; + if (parent == null || !parent._isCancellable()) { + if (promise._isFollowing()) { + promise._followee().cancel(); + } else { + promise._cancelBranched(); + } + break; + } else { + if (promise._isFollowing()) promise._followee().cancel(); + promise._setWillBeCancelled(); + child = promise; + promise = parent; + } + } + }; + + Promise.prototype._branchHasCancelled = function() { + this._branchesRemainingToCancel--; + }; + + Promise.prototype._enoughBranchesHaveCancelled = function() { + return this._branchesRemainingToCancel === undefined || + this._branchesRemainingToCancel <= 0; + }; + + Promise.prototype._cancelBy = function(canceller) { + if (canceller === this) { + this._branchesRemainingToCancel = 0; + this._invokeOnCancel(); + return true; + } else { + this._branchHasCancelled(); + if (this._enoughBranchesHaveCancelled()) { + this._invokeOnCancel(); + return true; + } + } + return false; + }; + + Promise.prototype._cancelBranched = function() { + if (this._enoughBranchesHaveCancelled()) { + this._cancel(); + } + }; + + Promise.prototype._cancel = function() { + if (!this._isCancellable()) return; + this._setCancelled(); + async.invoke(this._cancelPromises, this, undefined); + }; + + Promise.prototype._cancelPromises = function() { + if (this._length() > 0) this._settlePromises(); + }; + + Promise.prototype._unsetOnCancel = function() { + this._onCancelField = undefined; + }; + + Promise.prototype._isCancellable = function() { + return this.isPending() && !this._isCancelled(); + }; + + Promise.prototype.isCancellable = function() { + return this.isPending() && !this.isCancelled(); + }; + + Promise.prototype._doInvokeOnCancel = function(onCancelCallback, internalOnly) { + if (util.isArray(onCancelCallback)) { + for (var i = 0; i < onCancelCallback.length; ++i) { + this._doInvokeOnCancel(onCancelCallback[i], internalOnly); + } + } else if (onCancelCallback !== undefined) { + if (typeof onCancelCallback === "function") { + if (!internalOnly) { + var e = tryCatch(onCancelCallback).call(this._boundValue()); + if (e === errorObj) { + this._attachExtraTrace(e.e); + async.throwLater(e.e); + } + } + } else { + onCancelCallback._resultCancelled(this); + } + } + }; + + Promise.prototype._invokeOnCancel = function() { + var onCancelCallback = this._onCancel(); + this._unsetOnCancel(); + async.invoke(this._doInvokeOnCancel, this, onCancelCallback); + }; + + Promise.prototype._invokeInternalOnCancel = function() { + if (this._isCancellable()) { + this._doInvokeOnCancel(this._onCancel(), true); + this._unsetOnCancel(); + } + }; + + Promise.prototype._resultCancelled = function() { + this.cancel(); + }; + + }; + + },{"./util":36}],7:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(NEXT_FILTER) { + var util = _dereq_("./util"); + var getKeys = _dereq_("./es5").keys; + var tryCatch = util.tryCatch; + var errorObj = util.errorObj; + + function catchFilter(instances, cb, promise) { + return function(e) { + var boundTo = promise._boundValue(); + predicateLoop: for (var i = 0; i < instances.length; ++i) { + var item = instances[i]; + + if (item === Error || + (item != null && item.prototype instanceof Error)) { + if (e instanceof item) { + return tryCatch(cb).call(boundTo, e); + } + } else if (typeof item === "function") { + var matchesPredicate = tryCatch(item).call(boundTo, e); + if (matchesPredicate === errorObj) { + return matchesPredicate; + } else if (matchesPredicate) { + return tryCatch(cb).call(boundTo, e); + } + } else if (util.isObject(e)) { + var keys = getKeys(item); + for (var j = 0; j < keys.length; ++j) { + var key = keys[j]; + if (item[key] != e[key]) { + continue predicateLoop; + } + } + return tryCatch(cb).call(boundTo, e); + } + } + return NEXT_FILTER; + }; + } + + return catchFilter; + }; + + },{"./es5":13,"./util":36}],8:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise) { + var longStackTraces = false; + var contextStack = []; + + Promise.prototype._promiseCreated = function() {}; + Promise.prototype._pushContext = function() {}; + Promise.prototype._popContext = function() {return null;}; + Promise._peekContext = Promise.prototype._peekContext = function() {}; + + function Context() { + this._trace = new Context.CapturedTrace(peekContext()); + } + Context.prototype._pushContext = function () { + if (this._trace !== undefined) { + this._trace._promiseCreated = null; + contextStack.push(this._trace); + } + }; + + Context.prototype._popContext = function () { + if (this._trace !== undefined) { + var trace = contextStack.pop(); + var ret = trace._promiseCreated; + trace._promiseCreated = null; + return ret; + } + return null; + }; + + function createContext() { + if (longStackTraces) return new Context(); + } + + function peekContext() { + var lastIndex = contextStack.length - 1; + if (lastIndex >= 0) { + return contextStack[lastIndex]; + } + return undefined; + } + Context.CapturedTrace = null; + Context.create = createContext; + Context.deactivateLongStackTraces = function() {}; + Context.activateLongStackTraces = function() { + var Promise_pushContext = Promise.prototype._pushContext; + var Promise_popContext = Promise.prototype._popContext; + var Promise_PeekContext = Promise._peekContext; + var Promise_peekContext = Promise.prototype._peekContext; + var Promise_promiseCreated = Promise.prototype._promiseCreated; + Context.deactivateLongStackTraces = function() { + Promise.prototype._pushContext = Promise_pushContext; + Promise.prototype._popContext = Promise_popContext; + Promise._peekContext = Promise_PeekContext; + Promise.prototype._peekContext = Promise_peekContext; + Promise.prototype._promiseCreated = Promise_promiseCreated; + longStackTraces = false; + }; + longStackTraces = true; + Promise.prototype._pushContext = Context.prototype._pushContext; + Promise.prototype._popContext = Context.prototype._popContext; + Promise._peekContext = Promise.prototype._peekContext = peekContext; + Promise.prototype._promiseCreated = function() { + var ctx = this._peekContext(); + if (ctx && ctx._promiseCreated == null) ctx._promiseCreated = this; + }; + }; + return Context; + }; + + },{}],9:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, Context) { + var getDomain = Promise._getDomain; + var async = Promise._async; + var Warning = _dereq_("./errors").Warning; + var util = _dereq_("./util"); + var canAttachTrace = util.canAttachTrace; + var unhandledRejectionHandled; + var possiblyUnhandledRejection; + var bluebirdFramePattern = + /[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/; + var nodeFramePattern = /\((?:timers\.js):\d+:\d+\)/; + var parseLinePattern = /[\/<\(](.+?):(\d+):(\d+)\)?\s*$/; + var stackFramePattern = null; + var formatStack = null; + var indentStackFrames = false; + var printWarning; + var debugging = !!(util.env("BLUEBIRD_DEBUG") != 0 && + (true || + util.env("BLUEBIRD_DEBUG") || + util.env("NODE_ENV") === "development")); + + var warnings = !!(util.env("BLUEBIRD_WARNINGS") != 0 && + (debugging || util.env("BLUEBIRD_WARNINGS"))); + + var longStackTraces = !!(util.env("BLUEBIRD_LONG_STACK_TRACES") != 0 && + (debugging || util.env("BLUEBIRD_LONG_STACK_TRACES"))); + + var wForgottenReturn = util.env("BLUEBIRD_W_FORGOTTEN_RETURN") != 0 && + (warnings || !!util.env("BLUEBIRD_W_FORGOTTEN_RETURN")); + + Promise.prototype.suppressUnhandledRejections = function() { + var target = this._target(); + target._bitField = ((target._bitField & (~1048576)) | + 524288); + }; + + Promise.prototype._ensurePossibleRejectionHandled = function () { + if ((this._bitField & 524288) !== 0) return; + this._setRejectionIsUnhandled(); + async.invokeLater(this._notifyUnhandledRejection, this, undefined); + }; + + Promise.prototype._notifyUnhandledRejectionIsHandled = function () { + fireRejectionEvent("rejectionHandled", + unhandledRejectionHandled, undefined, this); + }; + + Promise.prototype._setReturnedNonUndefined = function() { + this._bitField = this._bitField | 268435456; + }; + + Promise.prototype._returnedNonUndefined = function() { + return (this._bitField & 268435456) !== 0; + }; + + Promise.prototype._notifyUnhandledRejection = function () { + if (this._isRejectionUnhandled()) { + var reason = this._settledValue(); + this._setUnhandledRejectionIsNotified(); + fireRejectionEvent("unhandledRejection", + possiblyUnhandledRejection, reason, this); + } + }; + + Promise.prototype._setUnhandledRejectionIsNotified = function () { + this._bitField = this._bitField | 262144; + }; + + Promise.prototype._unsetUnhandledRejectionIsNotified = function () { + this._bitField = this._bitField & (~262144); + }; + + Promise.prototype._isUnhandledRejectionNotified = function () { + return (this._bitField & 262144) > 0; + }; + + Promise.prototype._setRejectionIsUnhandled = function () { + this._bitField = this._bitField | 1048576; + }; + + Promise.prototype._unsetRejectionIsUnhandled = function () { + this._bitField = this._bitField & (~1048576); + if (this._isUnhandledRejectionNotified()) { + this._unsetUnhandledRejectionIsNotified(); + this._notifyUnhandledRejectionIsHandled(); + } + }; + + Promise.prototype._isRejectionUnhandled = function () { + return (this._bitField & 1048576) > 0; + }; + + Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) { + return warn(message, shouldUseOwnTrace, promise || this); + }; + + Promise.onPossiblyUnhandledRejection = function (fn) { + var domain = getDomain(); + possiblyUnhandledRejection = + typeof fn === "function" ? (domain === null ? + fn : util.domainBind(domain, fn)) + : undefined; + }; + + Promise.onUnhandledRejectionHandled = function (fn) { + var domain = getDomain(); + unhandledRejectionHandled = + typeof fn === "function" ? (domain === null ? + fn : util.domainBind(domain, fn)) + : undefined; + }; + + var disableLongStackTraces = function() {}; + Promise.longStackTraces = function () { + if (async.haveItemsQueued() && !config.longStackTraces) { + throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + if (!config.longStackTraces && longStackTracesIsSupported()) { + var Promise_captureStackTrace = Promise.prototype._captureStackTrace; + var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace; + config.longStackTraces = true; + disableLongStackTraces = function() { + if (async.haveItemsQueued() && !config.longStackTraces) { + throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + Promise.prototype._captureStackTrace = Promise_captureStackTrace; + Promise.prototype._attachExtraTrace = Promise_attachExtraTrace; + Context.deactivateLongStackTraces(); + async.enableTrampoline(); + config.longStackTraces = false; + }; + Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace; + Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace; + Context.activateLongStackTraces(); + async.disableTrampolineIfNecessary(); + } + }; + + Promise.hasLongStackTraces = function () { + return config.longStackTraces && longStackTracesIsSupported(); + }; + + var fireDomEvent = (function() { + try { + if (typeof CustomEvent === "function") { + var event = new CustomEvent("CustomEvent"); + util.global.dispatchEvent(event); + return function(name, event) { + var domEvent = new CustomEvent(name.toLowerCase(), { + detail: event, + cancelable: true + }); + return !util.global.dispatchEvent(domEvent); + }; + } else if (typeof Event === "function") { + var event = new Event("CustomEvent"); + util.global.dispatchEvent(event); + return function(name, event) { + var domEvent = new Event(name.toLowerCase(), { + cancelable: true + }); + domEvent.detail = event; + return !util.global.dispatchEvent(domEvent); + }; + } else { + var event = document.createEvent("CustomEvent"); + event.initCustomEvent("testingtheevent", false, true, {}); + util.global.dispatchEvent(event); + return function(name, event) { + var domEvent = document.createEvent("CustomEvent"); + domEvent.initCustomEvent(name.toLowerCase(), false, true, + event); + return !util.global.dispatchEvent(domEvent); + }; + } + } catch (e) {} + return function() { + return false; + }; + })(); + + var fireGlobalEvent = (function() { + if (util.isNode) { + return function() { + return process.emit.apply(process, arguments); + }; + } else { + if (!util.global) { + return function() { + return false; + }; + } + return function(name) { + var methodName = "on" + name.toLowerCase(); + var method = util.global[methodName]; + if (!method) return false; + method.apply(util.global, [].slice.call(arguments, 1)); + return true; + }; + } + })(); + + function generatePromiseLifecycleEventObject(name, promise) { + return {promise: promise}; + } + + var eventToObjectGenerator = { + promiseCreated: generatePromiseLifecycleEventObject, + promiseFulfilled: generatePromiseLifecycleEventObject, + promiseRejected: generatePromiseLifecycleEventObject, + promiseResolved: generatePromiseLifecycleEventObject, + promiseCancelled: generatePromiseLifecycleEventObject, + promiseChained: function(name, promise, child) { + return {promise: promise, child: child}; + }, + warning: function(name, warning) { + return {warning: warning}; + }, + unhandledRejection: function (name, reason, promise) { + return {reason: reason, promise: promise}; + }, + rejectionHandled: generatePromiseLifecycleEventObject + }; + + var activeFireEvent = function (name) { + var globalEventFired = false; + try { + globalEventFired = fireGlobalEvent.apply(null, arguments); + } catch (e) { + async.throwLater(e); + globalEventFired = true; + } + + var domEventFired = false; + try { + domEventFired = fireDomEvent(name, + eventToObjectGenerator[name].apply(null, arguments)); + } catch (e) { + async.throwLater(e); + domEventFired = true; + } + + return domEventFired || globalEventFired; + }; + + Promise.config = function(opts) { + opts = Object(opts); + if ("longStackTraces" in opts) { + if (opts.longStackTraces) { + Promise.longStackTraces(); + } else if (!opts.longStackTraces && Promise.hasLongStackTraces()) { + disableLongStackTraces(); + } + } + if ("warnings" in opts) { + var warningsOption = opts.warnings; + config.warnings = !!warningsOption; + wForgottenReturn = config.warnings; + + if (util.isObject(warningsOption)) { + if ("wForgottenReturn" in warningsOption) { + wForgottenReturn = !!warningsOption.wForgottenReturn; + } + } + } + if ("cancellation" in opts && opts.cancellation && !config.cancellation) { + if (async.haveItemsQueued()) { + throw new Error( + "cannot enable cancellation after promises are in use"); + } + Promise.prototype._clearCancellationData = + cancellationClearCancellationData; + Promise.prototype._propagateFrom = cancellationPropagateFrom; + Promise.prototype._onCancel = cancellationOnCancel; + Promise.prototype._setOnCancel = cancellationSetOnCancel; + Promise.prototype._attachCancellationCallback = + cancellationAttachCancellationCallback; + Promise.prototype._execute = cancellationExecute; + propagateFromFunction = cancellationPropagateFrom; + config.cancellation = true; + } + if ("monitoring" in opts) { + if (opts.monitoring && !config.monitoring) { + config.monitoring = true; + Promise.prototype._fireEvent = activeFireEvent; + } else if (!opts.monitoring && config.monitoring) { + config.monitoring = false; + Promise.prototype._fireEvent = defaultFireEvent; + } + } + return Promise; + }; + + function defaultFireEvent() { return false; } + + Promise.prototype._fireEvent = defaultFireEvent; + Promise.prototype._execute = function(executor, resolve, reject) { + try { + executor(resolve, reject); + } catch (e) { + return e; + } + }; + Promise.prototype._onCancel = function () {}; + Promise.prototype._setOnCancel = function (handler) { ; }; + Promise.prototype._attachCancellationCallback = function(onCancel) { + ; + }; + Promise.prototype._captureStackTrace = function () {}; + Promise.prototype._attachExtraTrace = function () {}; + Promise.prototype._clearCancellationData = function() {}; + Promise.prototype._propagateFrom = function (parent, flags) { + ; + ; + }; + + function cancellationExecute(executor, resolve, reject) { + var promise = this; + try { + executor(resolve, reject, function(onCancel) { + if (typeof onCancel !== "function") { + throw new TypeError("onCancel must be a function, got: " + + util.toString(onCancel)); + } + promise._attachCancellationCallback(onCancel); + }); + } catch (e) { + return e; + } + } + + function cancellationAttachCancellationCallback(onCancel) { + if (!this._isCancellable()) return this; + + var previousOnCancel = this._onCancel(); + if (previousOnCancel !== undefined) { + if (util.isArray(previousOnCancel)) { + previousOnCancel.push(onCancel); + } else { + this._setOnCancel([previousOnCancel, onCancel]); + } + } else { + this._setOnCancel(onCancel); + } + } + + function cancellationOnCancel() { + return this._onCancelField; + } + + function cancellationSetOnCancel(onCancel) { + this._onCancelField = onCancel; + } + + function cancellationClearCancellationData() { + this._cancellationParent = undefined; + this._onCancelField = undefined; + } + + function cancellationPropagateFrom(parent, flags) { + if ((flags & 1) !== 0) { + this._cancellationParent = parent; + var branchesRemainingToCancel = parent._branchesRemainingToCancel; + if (branchesRemainingToCancel === undefined) { + branchesRemainingToCancel = 0; + } + parent._branchesRemainingToCancel = branchesRemainingToCancel + 1; + } + if ((flags & 2) !== 0 && parent._isBound()) { + this._setBoundTo(parent._boundTo); + } + } + + function bindingPropagateFrom(parent, flags) { + if ((flags & 2) !== 0 && parent._isBound()) { + this._setBoundTo(parent._boundTo); + } + } + var propagateFromFunction = bindingPropagateFrom; + + function boundValueFunction() { + var ret = this._boundTo; + if (ret !== undefined) { + if (ret instanceof Promise) { + if (ret.isFulfilled()) { + return ret.value(); + } else { + return undefined; + } + } + } + return ret; + } + + function longStackTracesCaptureStackTrace() { + this._trace = new CapturedTrace(this._peekContext()); + } + + function longStackTracesAttachExtraTrace(error, ignoreSelf) { + if (canAttachTrace(error)) { + var trace = this._trace; + if (trace !== undefined) { + if (ignoreSelf) trace = trace._parent; + } + if (trace !== undefined) { + trace.attachExtraTrace(error); + } else if (!error.__stackCleaned__) { + var parsed = parseStackAndMessage(error); + util.notEnumerableProp(error, "stack", + parsed.message + "\n" + parsed.stack.join("\n")); + util.notEnumerableProp(error, "__stackCleaned__", true); + } + } + } + + function checkForgottenReturns(returnValue, promiseCreated, name, promise, + parent) { + if (returnValue === undefined && promiseCreated !== null && + wForgottenReturn) { + if (parent !== undefined && parent._returnedNonUndefined()) return; + if ((promise._bitField & 65535) === 0) return; + + if (name) name = name + " "; + var handlerLine = ""; + var creatorLine = ""; + if (promiseCreated._trace) { + var traceLines = promiseCreated._trace.stack.split("\n"); + var stack = cleanStack(traceLines); + for (var i = stack.length - 1; i >= 0; --i) { + var line = stack[i]; + if (!nodeFramePattern.test(line)) { + var lineMatches = line.match(parseLinePattern); + if (lineMatches) { + handlerLine = "at " + lineMatches[1] + + ":" + lineMatches[2] + ":" + lineMatches[3] + " "; + } + break; + } + } + + if (stack.length > 0) { + var firstUserLine = stack[0]; + for (var i = 0; i < traceLines.length; ++i) { + + if (traceLines[i] === firstUserLine) { + if (i > 0) { + creatorLine = "\n" + traceLines[i - 1]; + } + break; + } + } + + } + } + var msg = "a promise was created in a " + name + + "handler " + handlerLine + "but was not returned from it, " + + "see http://goo.gl/rRqMUw" + + creatorLine; + promise._warn(msg, true, promiseCreated); + } + } + + function deprecated(name, replacement) { + var message = name + + " is deprecated and will be removed in a future version."; + if (replacement) message += " Use " + replacement + " instead."; + return warn(message); + } + + function warn(message, shouldUseOwnTrace, promise) { + if (!config.warnings) return; + var warning = new Warning(message); + var ctx; + if (shouldUseOwnTrace) { + promise._attachExtraTrace(warning); + } else if (config.longStackTraces && (ctx = Promise._peekContext())) { + ctx.attachExtraTrace(warning); + } else { + var parsed = parseStackAndMessage(warning); + warning.stack = parsed.message + "\n" + parsed.stack.join("\n"); + } + + if (!activeFireEvent("warning", warning)) { + formatAndLogError(warning, "", true); + } + } + + function reconstructStack(message, stacks) { + for (var i = 0; i < stacks.length - 1; ++i) { + stacks[i].push("From previous event:"); + stacks[i] = stacks[i].join("\n"); + } + if (i < stacks.length) { + stacks[i] = stacks[i].join("\n"); + } + return message + "\n" + stacks.join("\n"); + } + + function removeDuplicateOrEmptyJumps(stacks) { + for (var i = 0; i < stacks.length; ++i) { + if (stacks[i].length === 0 || + ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) { + stacks.splice(i, 1); + i--; + } + } + } + + function removeCommonRoots(stacks) { + var current = stacks[0]; + for (var i = 1; i < stacks.length; ++i) { + var prev = stacks[i]; + var currentLastIndex = current.length - 1; + var currentLastLine = current[currentLastIndex]; + var commonRootMeetPoint = -1; + + for (var j = prev.length - 1; j >= 0; --j) { + if (prev[j] === currentLastLine) { + commonRootMeetPoint = j; + break; + } + } + + for (var j = commonRootMeetPoint; j >= 0; --j) { + var line = prev[j]; + if (current[currentLastIndex] === line) { + current.pop(); + currentLastIndex--; + } else { + break; + } + } + current = prev; + } + } + + function cleanStack(stack) { + var ret = []; + for (var i = 0; i < stack.length; ++i) { + var line = stack[i]; + var isTraceLine = " (No stack trace)" === line || + stackFramePattern.test(line); + var isInternalFrame = isTraceLine && shouldIgnore(line); + if (isTraceLine && !isInternalFrame) { + if (indentStackFrames && line.charAt(0) !== " ") { + line = " " + line; + } + ret.push(line); + } + } + return ret; + } + + function stackFramesAsArray(error) { + var stack = error.stack.replace(/\s+$/g, "").split("\n"); + for (var i = 0; i < stack.length; ++i) { + var line = stack[i]; + if (" (No stack trace)" === line || stackFramePattern.test(line)) { + break; + } + } + if (i > 0 && error.name != "SyntaxError") { + stack = stack.slice(i); + } + return stack; + } + + function parseStackAndMessage(error) { + var stack = error.stack; + var message = error.toString(); + stack = typeof stack === "string" && stack.length > 0 + ? stackFramesAsArray(error) : [" (No stack trace)"]; + return { + message: message, + stack: error.name == "SyntaxError" ? stack : cleanStack(stack) + }; + } + + function formatAndLogError(error, title, isSoft) { + if (typeof console !== "undefined") { + var message; + if (util.isObject(error)) { + var stack = error.stack; + message = title + formatStack(stack, error); + } else { + message = title + String(error); + } + if (typeof printWarning === "function") { + printWarning(message, isSoft); + } else if (typeof console.log === "function" || + typeof console.log === "object") { + console.log(message); + } + } + } + + function fireRejectionEvent(name, localHandler, reason, promise) { + var localEventFired = false; + try { + if (typeof localHandler === "function") { + localEventFired = true; + if (name === "rejectionHandled") { + localHandler(promise); + } else { + localHandler(reason, promise); + } + } + } catch (e) { + async.throwLater(e); + } + + if (name === "unhandledRejection") { + if (!activeFireEvent(name, reason, promise) && !localEventFired) { + formatAndLogError(reason, "Unhandled rejection "); + } + } else { + activeFireEvent(name, promise); + } + } + + function formatNonError(obj) { + var str; + if (typeof obj === "function") { + str = "[function " + + (obj.name || "anonymous") + + "]"; + } else { + str = obj && typeof obj.toString === "function" + ? obj.toString() : util.toString(obj); + var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/; + if (ruselessToString.test(str)) { + try { + var newStr = JSON.stringify(obj); + str = newStr; + } + catch(e) { + + } + } + if (str.length === 0) { + str = "(empty array)"; + } + } + return ("(<" + snip(str) + ">, no stack trace)"); + } + + function snip(str) { + var maxChars = 41; + if (str.length < maxChars) { + return str; + } + return str.substr(0, maxChars - 3) + "..."; + } + + function longStackTracesIsSupported() { + return typeof captureStackTrace === "function"; + } + + var shouldIgnore = function() { return false; }; + var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/; + function parseLineInfo(line) { + var matches = line.match(parseLineInfoRegex); + if (matches) { + return { + fileName: matches[1], + line: parseInt(matches[2], 10) + }; + } + } + + function setBounds(firstLineError, lastLineError) { + if (!longStackTracesIsSupported()) return; + var firstStackLines = firstLineError.stack.split("\n"); + var lastStackLines = lastLineError.stack.split("\n"); + var firstIndex = -1; + var lastIndex = -1; + var firstFileName; + var lastFileName; + for (var i = 0; i < firstStackLines.length; ++i) { + var result = parseLineInfo(firstStackLines[i]); + if (result) { + firstFileName = result.fileName; + firstIndex = result.line; + break; + } + } + for (var i = 0; i < lastStackLines.length; ++i) { + var result = parseLineInfo(lastStackLines[i]); + if (result) { + lastFileName = result.fileName; + lastIndex = result.line; + break; + } + } + if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName || + firstFileName !== lastFileName || firstIndex >= lastIndex) { + return; + } + + shouldIgnore = function(line) { + if (bluebirdFramePattern.test(line)) return true; + var info = parseLineInfo(line); + if (info) { + if (info.fileName === firstFileName && + (firstIndex <= info.line && info.line <= lastIndex)) { + return true; + } + } + return false; + }; + } + + function CapturedTrace(parent) { + this._parent = parent; + this._promisesCreated = 0; + var length = this._length = 1 + (parent === undefined ? 0 : parent._length); + captureStackTrace(this, CapturedTrace); + if (length > 32) this.uncycle(); + } + util.inherits(CapturedTrace, Error); + Context.CapturedTrace = CapturedTrace; + + CapturedTrace.prototype.uncycle = function() { + var length = this._length; + if (length < 2) return; + var nodes = []; + var stackToIndex = {}; + + for (var i = 0, node = this; node !== undefined; ++i) { + nodes.push(node); + node = node._parent; + } + length = this._length = i; + for (var i = length - 1; i >= 0; --i) { + var stack = nodes[i].stack; + if (stackToIndex[stack] === undefined) { + stackToIndex[stack] = i; + } + } + for (var i = 0; i < length; ++i) { + var currentStack = nodes[i].stack; + var index = stackToIndex[currentStack]; + if (index !== undefined && index !== i) { + if (index > 0) { + nodes[index - 1]._parent = undefined; + nodes[index - 1]._length = 1; + } + nodes[i]._parent = undefined; + nodes[i]._length = 1; + var cycleEdgeNode = i > 0 ? nodes[i - 1] : this; + + if (index < length - 1) { + cycleEdgeNode._parent = nodes[index + 1]; + cycleEdgeNode._parent.uncycle(); + cycleEdgeNode._length = + cycleEdgeNode._parent._length + 1; + } else { + cycleEdgeNode._parent = undefined; + cycleEdgeNode._length = 1; + } + var currentChildLength = cycleEdgeNode._length + 1; + for (var j = i - 2; j >= 0; --j) { + nodes[j]._length = currentChildLength; + currentChildLength++; + } + return; + } + } + }; + + CapturedTrace.prototype.attachExtraTrace = function(error) { + if (error.__stackCleaned__) return; + this.uncycle(); + var parsed = parseStackAndMessage(error); + var message = parsed.message; + var stacks = [parsed.stack]; + + var trace = this; + while (trace !== undefined) { + stacks.push(cleanStack(trace.stack.split("\n"))); + trace = trace._parent; + } + removeCommonRoots(stacks); + removeDuplicateOrEmptyJumps(stacks); + util.notEnumerableProp(error, "stack", reconstructStack(message, stacks)); + util.notEnumerableProp(error, "__stackCleaned__", true); + }; + + var captureStackTrace = (function stackDetection() { + var v8stackFramePattern = /^\s*at\s*/; + var v8stackFormatter = function(stack, error) { + if (typeof stack === "string") return stack; + + if (error.name !== undefined && + error.message !== undefined) { + return error.toString(); + } + return formatNonError(error); + }; + + if (typeof Error.stackTraceLimit === "number" && + typeof Error.captureStackTrace === "function") { + Error.stackTraceLimit += 6; + stackFramePattern = v8stackFramePattern; + formatStack = v8stackFormatter; + var captureStackTrace = Error.captureStackTrace; + + shouldIgnore = function(line) { + return bluebirdFramePattern.test(line); + }; + return function(receiver, ignoreUntil) { + Error.stackTraceLimit += 6; + captureStackTrace(receiver, ignoreUntil); + Error.stackTraceLimit -= 6; + }; + } + var err = new Error(); + + if (typeof err.stack === "string" && + err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) { + stackFramePattern = /@/; + formatStack = v8stackFormatter; + indentStackFrames = true; + return function captureStackTrace(o) { + o.stack = new Error().stack; + }; + } + + var hasStackAfterThrow; + try { throw new Error(); } + catch(e) { + hasStackAfterThrow = ("stack" in e); + } + if (!("stack" in err) && hasStackAfterThrow && + typeof Error.stackTraceLimit === "number") { + stackFramePattern = v8stackFramePattern; + formatStack = v8stackFormatter; + return function captureStackTrace(o) { + Error.stackTraceLimit += 6; + try { throw new Error(); } + catch(e) { o.stack = e.stack; } + Error.stackTraceLimit -= 6; + }; + } + + formatStack = function(stack, error) { + if (typeof stack === "string") return stack; + + if ((typeof error === "object" || + typeof error === "function") && + error.name !== undefined && + error.message !== undefined) { + return error.toString(); + } + return formatNonError(error); + }; + + return null; + + })([]); + + if (typeof console !== "undefined" && typeof console.warn !== "undefined") { + printWarning = function (message) { + console.warn(message); + }; + if (util.isNode && process.stderr.isTTY) { + printWarning = function(message, isSoft) { + var color = isSoft ? "\u001b[33m" : "\u001b[31m"; + console.warn(color + message + "\u001b[0m\n"); + }; + } else if (!util.isNode && typeof (new Error().stack) === "string") { + printWarning = function(message, isSoft) { + console.warn("%c" + message, + isSoft ? "color: darkorange" : "color: red"); + }; + } + } + + var config = { + warnings: warnings, + longStackTraces: false, + cancellation: false, + monitoring: false + }; + + if (longStackTraces) Promise.longStackTraces(); + + return { + longStackTraces: function() { + return config.longStackTraces; + }, + warnings: function() { + return config.warnings; + }, + cancellation: function() { + return config.cancellation; + }, + monitoring: function() { + return config.monitoring; + }, + propagateFromFunction: function() { + return propagateFromFunction; + }, + boundValueFunction: function() { + return boundValueFunction; + }, + checkForgottenReturns: checkForgottenReturns, + setBounds: setBounds, + warn: warn, + deprecated: deprecated, + CapturedTrace: CapturedTrace, + fireDomEvent: fireDomEvent, + fireGlobalEvent: fireGlobalEvent + }; + }; + + },{"./errors":12,"./util":36}],10:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise) { + function returner() { + return this.value; + } + function thrower() { + throw this.reason; + } + + Promise.prototype["return"] = + Promise.prototype.thenReturn = function (value) { + if (value instanceof Promise) value.suppressUnhandledRejections(); + return this._then( + returner, undefined, undefined, {value: value}, undefined); + }; + + Promise.prototype["throw"] = + Promise.prototype.thenThrow = function (reason) { + return this._then( + thrower, undefined, undefined, {reason: reason}, undefined); + }; + + Promise.prototype.catchThrow = function (reason) { + if (arguments.length <= 1) { + return this._then( + undefined, thrower, undefined, {reason: reason}, undefined); + } else { + var _reason = arguments[1]; + var handler = function() {throw _reason;}; + return this.caught(reason, handler); + } + }; + + Promise.prototype.catchReturn = function (value) { + if (arguments.length <= 1) { + if (value instanceof Promise) value.suppressUnhandledRejections(); + return this._then( + undefined, returner, undefined, {value: value}, undefined); + } else { + var _value = arguments[1]; + if (_value instanceof Promise) _value.suppressUnhandledRejections(); + var handler = function() {return _value;}; + return this.caught(value, handler); + } + }; + }; + + },{}],11:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, INTERNAL) { + var PromiseReduce = Promise.reduce; + var PromiseAll = Promise.all; + + function promiseAllThis() { + return PromiseAll(this); + } + + function PromiseMapSeries(promises, fn) { + return PromiseReduce(promises, fn, INTERNAL, INTERNAL); + } + + Promise.prototype.each = function (fn) { + return PromiseReduce(this, fn, INTERNAL, 0) + ._then(promiseAllThis, undefined, undefined, this, undefined); + }; + + Promise.prototype.mapSeries = function (fn) { + return PromiseReduce(this, fn, INTERNAL, INTERNAL); + }; + + Promise.each = function (promises, fn) { + return PromiseReduce(promises, fn, INTERNAL, 0) + ._then(promiseAllThis, undefined, undefined, promises, undefined); + }; + + Promise.mapSeries = PromiseMapSeries; + }; + + + },{}],12:[function(_dereq_,module,exports){ + "use strict"; + var es5 = _dereq_("./es5"); + var Objectfreeze = es5.freeze; + var util = _dereq_("./util"); + var inherits = util.inherits; + var notEnumerableProp = util.notEnumerableProp; + + function subError(nameProperty, defaultMessage) { + function SubError(message) { + if (!(this instanceof SubError)) return new SubError(message); + notEnumerableProp(this, "message", + typeof message === "string" ? message : defaultMessage); + notEnumerableProp(this, "name", nameProperty); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } else { + Error.call(this); + } + } + inherits(SubError, Error); + return SubError; + } + + var _TypeError, _RangeError; + var Warning = subError("Warning", "warning"); + var CancellationError = subError("CancellationError", "cancellation error"); + var TimeoutError = subError("TimeoutError", "timeout error"); + var AggregateError = subError("AggregateError", "aggregate error"); + try { + _TypeError = TypeError; + _RangeError = RangeError; + } catch(e) { + _TypeError = subError("TypeError", "type error"); + _RangeError = subError("RangeError", "range error"); + } + + var methods = ("join pop push shift unshift slice filter forEach some " + + "every map indexOf lastIndexOf reduce reduceRight sort reverse").split(" "); + + for (var i = 0; i < methods.length; ++i) { + if (typeof Array.prototype[methods[i]] === "function") { + AggregateError.prototype[methods[i]] = Array.prototype[methods[i]]; + } + } + + es5.defineProperty(AggregateError.prototype, "length", { + value: 0, + configurable: false, + writable: true, + enumerable: true + }); + AggregateError.prototype["isOperational"] = true; + var level = 0; + AggregateError.prototype.toString = function() { + var indent = Array(level * 4 + 1).join(" "); + var ret = "\n" + indent + "AggregateError of:" + "\n"; + level++; + indent = Array(level * 4 + 1).join(" "); + for (var i = 0; i < this.length; ++i) { + var str = this[i] === this ? "[Circular AggregateError]" : this[i] + ""; + var lines = str.split("\n"); + for (var j = 0; j < lines.length; ++j) { + lines[j] = indent + lines[j]; + } + str = lines.join("\n"); + ret += str + "\n"; + } + level--; + return ret; + }; + + function OperationalError(message) { + if (!(this instanceof OperationalError)) + return new OperationalError(message); + notEnumerableProp(this, "name", "OperationalError"); + notEnumerableProp(this, "message", message); + this.cause = message; + this["isOperational"] = true; + + if (message instanceof Error) { + notEnumerableProp(this, "message", message.message); + notEnumerableProp(this, "stack", message.stack); + } else if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + + } + inherits(OperationalError, Error); + + var errorTypes = Error["__BluebirdErrorTypes__"]; + if (!errorTypes) { + errorTypes = Objectfreeze({ + CancellationError: CancellationError, + TimeoutError: TimeoutError, + OperationalError: OperationalError, + RejectionError: OperationalError, + AggregateError: AggregateError + }); + es5.defineProperty(Error, "__BluebirdErrorTypes__", { + value: errorTypes, + writable: false, + enumerable: false, + configurable: false + }); + } + + module.exports = { + Error: Error, + TypeError: _TypeError, + RangeError: _RangeError, + CancellationError: errorTypes.CancellationError, + OperationalError: errorTypes.OperationalError, + TimeoutError: errorTypes.TimeoutError, + AggregateError: errorTypes.AggregateError, + Warning: Warning + }; + + },{"./es5":13,"./util":36}],13:[function(_dereq_,module,exports){ + var isES5 = (function(){ + "use strict"; + return this === undefined; + })(); + + if (isES5) { + module.exports = { + freeze: Object.freeze, + defineProperty: Object.defineProperty, + getDescriptor: Object.getOwnPropertyDescriptor, + keys: Object.keys, + names: Object.getOwnPropertyNames, + getPrototypeOf: Object.getPrototypeOf, + isArray: Array.isArray, + isES5: isES5, + propertyIsWritable: function(obj, prop) { + var descriptor = Object.getOwnPropertyDescriptor(obj, prop); + return !!(!descriptor || descriptor.writable || descriptor.set); + } + }; + } else { + var has = {}.hasOwnProperty; + var str = {}.toString; + var proto = {}.constructor.prototype; + + var ObjectKeys = function (o) { + var ret = []; + for (var key in o) { + if (has.call(o, key)) { + ret.push(key); + } + } + return ret; + }; + + var ObjectGetDescriptor = function(o, key) { + return {value: o[key]}; + }; + + var ObjectDefineProperty = function (o, key, desc) { + o[key] = desc.value; + return o; + }; + + var ObjectFreeze = function (obj) { + return obj; + }; + + var ObjectGetPrototypeOf = function (obj) { + try { + return Object(obj).constructor.prototype; + } + catch (e) { + return proto; + } + }; + + var ArrayIsArray = function (obj) { + try { + return str.call(obj) === "[object Array]"; + } + catch(e) { + return false; + } + }; + + module.exports = { + isArray: ArrayIsArray, + keys: ObjectKeys, + names: ObjectKeys, + defineProperty: ObjectDefineProperty, + getDescriptor: ObjectGetDescriptor, + freeze: ObjectFreeze, + getPrototypeOf: ObjectGetPrototypeOf, + isES5: isES5, + propertyIsWritable: function() { + return true; + } + }; + } + + },{}],14:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, INTERNAL) { + var PromiseMap = Promise.map; + + Promise.prototype.filter = function (fn, options) { + return PromiseMap(this, fn, options, INTERNAL); + }; + + Promise.filter = function (promises, fn, options) { + return PromiseMap(promises, fn, options, INTERNAL); + }; + }; + + },{}],15:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, tryConvertToPromise) { + var util = _dereq_("./util"); + var CancellationError = Promise.CancellationError; + var errorObj = util.errorObj; + + function PassThroughHandlerContext(promise, type, handler) { + this.promise = promise; + this.type = type; + this.handler = handler; + this.called = false; + this.cancelPromise = null; + } + + PassThroughHandlerContext.prototype.isFinallyHandler = function() { + return this.type === 0; + }; + + function FinallyHandlerCancelReaction(finallyHandler) { + this.finallyHandler = finallyHandler; + } + + FinallyHandlerCancelReaction.prototype._resultCancelled = function() { + checkCancel(this.finallyHandler); + }; + + function checkCancel(ctx, reason) { + if (ctx.cancelPromise != null) { + if (arguments.length > 1) { + ctx.cancelPromise._reject(reason); + } else { + ctx.cancelPromise._cancel(); + } + ctx.cancelPromise = null; + return true; + } + return false; + } + + function succeed() { + return finallyHandler.call(this, this.promise._target()._settledValue()); + } + function fail(reason) { + if (checkCancel(this, reason)) return; + errorObj.e = reason; + return errorObj; + } + function finallyHandler(reasonOrValue) { + var promise = this.promise; + var handler = this.handler; + + if (!this.called) { + this.called = true; + var ret = this.isFinallyHandler() + ? handler.call(promise._boundValue()) + : handler.call(promise._boundValue(), reasonOrValue); + if (ret !== undefined) { + promise._setReturnedNonUndefined(); + var maybePromise = tryConvertToPromise(ret, promise); + if (maybePromise instanceof Promise) { + if (this.cancelPromise != null) { + if (maybePromise._isCancelled()) { + var reason = + new CancellationError("late cancellation observer"); + promise._attachExtraTrace(reason); + errorObj.e = reason; + return errorObj; + } else if (maybePromise.isPending()) { + maybePromise._attachCancellationCallback( + new FinallyHandlerCancelReaction(this)); + } + } + return maybePromise._then( + succeed, fail, undefined, this, undefined); + } + } + } + + if (promise.isRejected()) { + checkCancel(this); + errorObj.e = reasonOrValue; + return errorObj; + } else { + checkCancel(this); + return reasonOrValue; + } + } + + Promise.prototype._passThrough = function(handler, type, success, fail) { + if (typeof handler !== "function") return this.then(); + return this._then(success, + fail, + undefined, + new PassThroughHandlerContext(this, type, handler), + undefined); + }; + + Promise.prototype.lastly = + Promise.prototype["finally"] = function (handler) { + return this._passThrough(handler, + 0, + finallyHandler, + finallyHandler); + }; + + Promise.prototype.tap = function (handler) { + return this._passThrough(handler, 1, finallyHandler); + }; + + return PassThroughHandlerContext; + }; + + },{"./util":36}],16:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, + apiRejection, + INTERNAL, + tryConvertToPromise, + Proxyable, + debug) { + var errors = _dereq_("./errors"); + var TypeError = errors.TypeError; + var util = _dereq_("./util"); + var errorObj = util.errorObj; + var tryCatch = util.tryCatch; + var yieldHandlers = []; + + function promiseFromYieldHandler(value, yieldHandlers, traceParent) { + for (var i = 0; i < yieldHandlers.length; ++i) { + traceParent._pushContext(); + var result = tryCatch(yieldHandlers[i])(value); + traceParent._popContext(); + if (result === errorObj) { + traceParent._pushContext(); + var ret = Promise.reject(errorObj.e); + traceParent._popContext(); + return ret; + } + var maybePromise = tryConvertToPromise(result, traceParent); + if (maybePromise instanceof Promise) return maybePromise; + } + return null; + } + + function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) { + if (debug.cancellation()) { + var internal = new Promise(INTERNAL); + var _finallyPromise = this._finallyPromise = new Promise(INTERNAL); + this._promise = internal.lastly(function() { + return _finallyPromise; + }); + internal._captureStackTrace(); + internal._setOnCancel(this); + } else { + var promise = this._promise = new Promise(INTERNAL); + promise._captureStackTrace(); + } + this._stack = stack; + this._generatorFunction = generatorFunction; + this._receiver = receiver; + this._generator = undefined; + this._yieldHandlers = typeof yieldHandler === "function" + ? [yieldHandler].concat(yieldHandlers) + : yieldHandlers; + this._yieldedPromise = null; + this._cancellationPhase = false; + } + util.inherits(PromiseSpawn, Proxyable); + + PromiseSpawn.prototype._isResolved = function() { + return this._promise === null; + }; + + PromiseSpawn.prototype._cleanup = function() { + this._promise = this._generator = null; + if (debug.cancellation() && this._finallyPromise !== null) { + this._finallyPromise._fulfill(); + this._finallyPromise = null; + } + }; + + PromiseSpawn.prototype._promiseCancelled = function() { + if (this._isResolved()) return; + var implementsReturn = typeof this._generator["return"] !== "undefined"; + + var result; + if (!implementsReturn) { + var reason = new Promise.CancellationError( + "generator .return() sentinel"); + Promise.coroutine.returnSentinel = reason; + this._promise._attachExtraTrace(reason); + this._promise._pushContext(); + result = tryCatch(this._generator["throw"]).call(this._generator, + reason); + this._promise._popContext(); + } else { + this._promise._pushContext(); + result = tryCatch(this._generator["return"]).call(this._generator, + undefined); + this._promise._popContext(); + } + this._cancellationPhase = true; + this._yieldedPromise = null; + this._continue(result); + }; + + PromiseSpawn.prototype._promiseFulfilled = function(value) { + this._yieldedPromise = null; + this._promise._pushContext(); + var result = tryCatch(this._generator.next).call(this._generator, value); + this._promise._popContext(); + this._continue(result); + }; + + PromiseSpawn.prototype._promiseRejected = function(reason) { + this._yieldedPromise = null; + this._promise._attachExtraTrace(reason); + this._promise._pushContext(); + var result = tryCatch(this._generator["throw"]) + .call(this._generator, reason); + this._promise._popContext(); + this._continue(result); + }; + + PromiseSpawn.prototype._resultCancelled = function() { + if (this._yieldedPromise instanceof Promise) { + var promise = this._yieldedPromise; + this._yieldedPromise = null; + promise.cancel(); + } + }; + + PromiseSpawn.prototype.promise = function () { + return this._promise; + }; + + PromiseSpawn.prototype._run = function () { + this._generator = this._generatorFunction.call(this._receiver); + this._receiver = + this._generatorFunction = undefined; + this._promiseFulfilled(undefined); + }; + + PromiseSpawn.prototype._continue = function (result) { + var promise = this._promise; + if (result === errorObj) { + this._cleanup(); + if (this._cancellationPhase) { + return promise.cancel(); + } else { + return promise._rejectCallback(result.e, false); + } + } + + var value = result.value; + if (result.done === true) { + this._cleanup(); + if (this._cancellationPhase) { + return promise.cancel(); + } else { + return promise._resolveCallback(value); + } + } else { + var maybePromise = tryConvertToPromise(value, this._promise); + if (!(maybePromise instanceof Promise)) { + maybePromise = + promiseFromYieldHandler(maybePromise, + this._yieldHandlers, + this._promise); + if (maybePromise === null) { + this._promiseRejected( + new TypeError( + "A value %s was yielded that could not be treated as a promise\u000a\u000a See http://goo.gl/MqrFmX\u000a\u000a".replace("%s", value) + + "From coroutine:\u000a" + + this._stack.split("\n").slice(1, -7).join("\n") + ) + ); + return; + } + } + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + this._yieldedPromise = maybePromise; + maybePromise._proxy(this, null); + } else if (((bitField & 33554432) !== 0)) { + Promise._async.invoke( + this._promiseFulfilled, this, maybePromise._value() + ); + } else if (((bitField & 16777216) !== 0)) { + Promise._async.invoke( + this._promiseRejected, this, maybePromise._reason() + ); + } else { + this._promiseCancelled(); + } + } + }; + + Promise.coroutine = function (generatorFunction, options) { + if (typeof generatorFunction !== "function") { + throw new TypeError("generatorFunction must be a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + var yieldHandler = Object(options).yieldHandler; + var PromiseSpawn$ = PromiseSpawn; + var stack = new Error().stack; + return function () { + var generator = generatorFunction.apply(this, arguments); + var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler, + stack); + var ret = spawn.promise(); + spawn._generator = generator; + spawn._promiseFulfilled(undefined); + return ret; + }; + }; + + Promise.coroutine.addYieldHandler = function(fn) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + yieldHandlers.push(fn); + }; + + Promise.spawn = function (generatorFunction) { + debug.deprecated("Promise.spawn()", "Promise.coroutine()"); + if (typeof generatorFunction !== "function") { + return apiRejection("generatorFunction must be a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + var spawn = new PromiseSpawn(generatorFunction, this); + var ret = spawn.promise(); + spawn._run(Promise.spawn); + return ret; + }; + }; + + },{"./errors":12,"./util":36}],17:[function(_dereq_,module,exports){ + "use strict"; + module.exports = + function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, + getDomain) { + var util = _dereq_("./util"); + var canEvaluate = util.canEvaluate; + var tryCatch = util.tryCatch; + var errorObj = util.errorObj; + var reject; + + if (false) { + if (canEvaluate) { + var thenCallback = function(i) { + return new Function("value", "holder", " \n\ + 'use strict'; \n\ + holder.pIndex = value; \n\ + holder.checkFulfillment(this); \n\ + ".replace(/Index/g, i)); + }; + + var promiseSetter = function(i) { + return new Function("promise", "holder", " \n\ + 'use strict'; \n\ + holder.pIndex = promise; \n\ + ".replace(/Index/g, i)); + }; + + var generateHolderClass = function(total) { + var props = new Array(total); + for (var i = 0; i < props.length; ++i) { + props[i] = "this.p" + (i+1); + } + var assignment = props.join(" = ") + " = null;"; + var cancellationCode= "var promise;\n" + props.map(function(prop) { + return " \n\ + promise = " + prop + "; \n\ + if (promise instanceof Promise) { \n\ + promise.cancel(); \n\ + } \n\ + "; + }).join("\n"); + var passedArguments = props.join(", "); + var name = "Holder$" + total; + + + var code = "return function(tryCatch, errorObj, Promise, async) { \n\ + 'use strict'; \n\ + function [TheName](fn) { \n\ + [TheProperties] \n\ + this.fn = fn; \n\ + this.asyncNeeded = true; \n\ + this.now = 0; \n\ + } \n\ + \n\ + [TheName].prototype._callFunction = function(promise) { \n\ + promise._pushContext(); \n\ + var ret = tryCatch(this.fn)([ThePassedArguments]); \n\ + promise._popContext(); \n\ + if (ret === errorObj) { \n\ + promise._rejectCallback(ret.e, false); \n\ + } else { \n\ + promise._resolveCallback(ret); \n\ + } \n\ + }; \n\ + \n\ + [TheName].prototype.checkFulfillment = function(promise) { \n\ + var now = ++this.now; \n\ + if (now === [TheTotal]) { \n\ + if (this.asyncNeeded) { \n\ + async.invoke(this._callFunction, this, promise); \n\ + } else { \n\ + this._callFunction(promise); \n\ + } \n\ + \n\ + } \n\ + }; \n\ + \n\ + [TheName].prototype._resultCancelled = function() { \n\ + [CancellationCode] \n\ + }; \n\ + \n\ + return [TheName]; \n\ + }(tryCatch, errorObj, Promise, async); \n\ + "; + + code = code.replace(/\[TheName\]/g, name) + .replace(/\[TheTotal\]/g, total) + .replace(/\[ThePassedArguments\]/g, passedArguments) + .replace(/\[TheProperties\]/g, assignment) + .replace(/\[CancellationCode\]/g, cancellationCode); + + return new Function("tryCatch", "errorObj", "Promise", "async", code) + (tryCatch, errorObj, Promise, async); + }; + + var holderClasses = []; + var thenCallbacks = []; + var promiseSetters = []; + + for (var i = 0; i < 8; ++i) { + holderClasses.push(generateHolderClass(i + 1)); + thenCallbacks.push(thenCallback(i + 1)); + promiseSetters.push(promiseSetter(i + 1)); + } + + reject = function (reason) { + this._reject(reason); + }; + }} + + Promise.join = function () { + var last = arguments.length - 1; + var fn; + if (last > 0 && typeof arguments[last] === "function") { + fn = arguments[last]; + if (false) { + if (last <= 8 && canEvaluate) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + var HolderClass = holderClasses[last - 1]; + var holder = new HolderClass(fn); + var callbacks = thenCallbacks; + + for (var i = 0; i < last; ++i) { + var maybePromise = tryConvertToPromise(arguments[i], ret); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + maybePromise._then(callbacks[i], reject, + undefined, ret, holder); + promiseSetters[i](maybePromise, holder); + holder.asyncNeeded = false; + } else if (((bitField & 33554432) !== 0)) { + callbacks[i].call(ret, + maybePromise._value(), holder); + } else if (((bitField & 16777216) !== 0)) { + ret._reject(maybePromise._reason()); + } else { + ret._cancel(); + } + } else { + callbacks[i].call(ret, maybePromise, holder); + } + } + + if (!ret._isFateSealed()) { + if (holder.asyncNeeded) { + var domain = getDomain(); + if (domain !== null) { + holder.fn = util.domainBind(domain, holder.fn); + } + } + ret._setAsyncGuaranteed(); + ret._setOnCancel(holder); + } + return ret; + } + } + } + var args = [].slice.call(arguments);; + if (fn) args.pop(); + var ret = new PromiseArray(args).promise(); + return fn !== undefined ? ret.spread(fn) : ret; + }; + + }; + + },{"./util":36}],18:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, + PromiseArray, + apiRejection, + tryConvertToPromise, + INTERNAL, + debug) { + var getDomain = Promise._getDomain; + var util = _dereq_("./util"); + var tryCatch = util.tryCatch; + var errorObj = util.errorObj; + var async = Promise._async; + + function MappingPromiseArray(promises, fn, limit, _filter) { + this.constructor$(promises); + this._promise._captureStackTrace(); + var domain = getDomain(); + this._callback = domain === null ? fn : util.domainBind(domain, fn); + this._preservedValues = _filter === INTERNAL + ? new Array(this.length()) + : null; + this._limit = limit; + this._inFlight = 0; + this._queue = []; + async.invoke(this._asyncInit, this, undefined); + } + util.inherits(MappingPromiseArray, PromiseArray); + + MappingPromiseArray.prototype._asyncInit = function() { + this._init$(undefined, -2); + }; + + MappingPromiseArray.prototype._init = function () {}; + + MappingPromiseArray.prototype._promiseFulfilled = function (value, index) { + var values = this._values; + var length = this.length(); + var preservedValues = this._preservedValues; + var limit = this._limit; + + if (index < 0) { + index = (index * -1) - 1; + values[index] = value; + if (limit >= 1) { + this._inFlight--; + this._drainQueue(); + if (this._isResolved()) return true; + } + } else { + if (limit >= 1 && this._inFlight >= limit) { + values[index] = value; + this._queue.push(index); + return false; + } + if (preservedValues !== null) preservedValues[index] = value; + + var promise = this._promise; + var callback = this._callback; + var receiver = promise._boundValue(); + promise._pushContext(); + var ret = tryCatch(callback).call(receiver, value, index, length); + var promiseCreated = promise._popContext(); + debug.checkForgottenReturns( + ret, + promiseCreated, + preservedValues !== null ? "Promise.filter" : "Promise.map", + promise + ); + if (ret === errorObj) { + this._reject(ret.e); + return true; + } + + var maybePromise = tryConvertToPromise(ret, this._promise); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + if (limit >= 1) this._inFlight++; + values[index] = maybePromise; + maybePromise._proxy(this, (index + 1) * -1); + return false; + } else if (((bitField & 33554432) !== 0)) { + ret = maybePromise._value(); + } else if (((bitField & 16777216) !== 0)) { + this._reject(maybePromise._reason()); + return true; + } else { + this._cancel(); + return true; + } + } + values[index] = ret; + } + var totalResolved = ++this._totalResolved; + if (totalResolved >= length) { + if (preservedValues !== null) { + this._filter(values, preservedValues); + } else { + this._resolve(values); + } + return true; + } + return false; + }; + + MappingPromiseArray.prototype._drainQueue = function () { + var queue = this._queue; + var limit = this._limit; + var values = this._values; + while (queue.length > 0 && this._inFlight < limit) { + if (this._isResolved()) return; + var index = queue.pop(); + this._promiseFulfilled(values[index], index); + } + }; + + MappingPromiseArray.prototype._filter = function (booleans, values) { + var len = values.length; + var ret = new Array(len); + var j = 0; + for (var i = 0; i < len; ++i) { + if (booleans[i]) ret[j++] = values[i]; + } + ret.length = j; + this._resolve(ret); + }; + + MappingPromiseArray.prototype.preservedValues = function () { + return this._preservedValues; + }; + + function map(promises, fn, options, _filter) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + + var limit = 0; + if (options !== undefined) { + if (typeof options === "object" && options !== null) { + if (typeof options.concurrency !== "number") { + return Promise.reject( + new TypeError("'concurrency' must be a number but it is " + + util.classString(options.concurrency))); + } + limit = options.concurrency; + } else { + return Promise.reject(new TypeError( + "options argument must be an object but it is " + + util.classString(options))); + } + } + limit = typeof limit === "number" && + isFinite(limit) && limit >= 1 ? limit : 0; + return new MappingPromiseArray(promises, fn, limit, _filter).promise(); + } + + Promise.prototype.map = function (fn, options) { + return map(this, fn, options, null); + }; + + Promise.map = function (promises, fn, options, _filter) { + return map(promises, fn, options, _filter); + }; + + + }; + + },{"./util":36}],19:[function(_dereq_,module,exports){ + "use strict"; + module.exports = + function(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug) { + var util = _dereq_("./util"); + var tryCatch = util.tryCatch; + + Promise.method = function (fn) { + if (typeof fn !== "function") { + throw new Promise.TypeError("expecting a function but got " + util.classString(fn)); + } + return function () { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._pushContext(); + var value = tryCatch(fn).apply(this, arguments); + var promiseCreated = ret._popContext(); + debug.checkForgottenReturns( + value, promiseCreated, "Promise.method", ret); + ret._resolveFromSyncValue(value); + return ret; + }; + }; + + Promise.attempt = Promise["try"] = function (fn) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._pushContext(); + var value; + if (arguments.length > 1) { + debug.deprecated("calling Promise.try with more than 1 argument"); + var arg = arguments[1]; + var ctx = arguments[2]; + value = util.isArray(arg) ? tryCatch(fn).apply(ctx, arg) + : tryCatch(fn).call(ctx, arg); + } else { + value = tryCatch(fn)(); + } + var promiseCreated = ret._popContext(); + debug.checkForgottenReturns( + value, promiseCreated, "Promise.try", ret); + ret._resolveFromSyncValue(value); + return ret; + }; + + Promise.prototype._resolveFromSyncValue = function (value) { + if (value === util.errorObj) { + this._rejectCallback(value.e, false); + } else { + this._resolveCallback(value, true); + } + }; + }; + + },{"./util":36}],20:[function(_dereq_,module,exports){ + "use strict"; + var util = _dereq_("./util"); + var maybeWrapAsError = util.maybeWrapAsError; + var errors = _dereq_("./errors"); + var OperationalError = errors.OperationalError; + var es5 = _dereq_("./es5"); + + function isUntypedError(obj) { + return obj instanceof Error && + es5.getPrototypeOf(obj) === Error.prototype; + } + + var rErrorKey = /^(?:name|message|stack|cause)$/; + function wrapAsOperationalError(obj) { + var ret; + if (isUntypedError(obj)) { + ret = new OperationalError(obj); + ret.name = obj.name; + ret.message = obj.message; + ret.stack = obj.stack; + var keys = es5.keys(obj); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (!rErrorKey.test(key)) { + ret[key] = obj[key]; + } + } + return ret; + } + util.markAsOriginatingFromRejection(obj); + return obj; + } + + function nodebackForPromise(promise, multiArgs) { + return function(err, value) { + if (promise === null) return; + if (err) { + var wrapped = wrapAsOperationalError(maybeWrapAsError(err)); + promise._attachExtraTrace(wrapped); + promise._reject(wrapped); + } else if (!multiArgs) { + promise._fulfill(value); + } else { + var args = [].slice.call(arguments, 1);; + promise._fulfill(args); + } + promise = null; + }; + } + + module.exports = nodebackForPromise; + + },{"./errors":12,"./es5":13,"./util":36}],21:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise) { + var util = _dereq_("./util"); + var async = Promise._async; + var tryCatch = util.tryCatch; + var errorObj = util.errorObj; + + function spreadAdapter(val, nodeback) { + var promise = this; + if (!util.isArray(val)) return successAdapter.call(promise, val, nodeback); + var ret = + tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val)); + if (ret === errorObj) { + async.throwLater(ret.e); + } + } + + function successAdapter(val, nodeback) { + var promise = this; + var receiver = promise._boundValue(); + var ret = val === undefined + ? tryCatch(nodeback).call(receiver, null) + : tryCatch(nodeback).call(receiver, null, val); + if (ret === errorObj) { + async.throwLater(ret.e); + } + } + function errorAdapter(reason, nodeback) { + var promise = this; + if (!reason) { + var newReason = new Error(reason + ""); + newReason.cause = reason; + reason = newReason; + } + var ret = tryCatch(nodeback).call(promise._boundValue(), reason); + if (ret === errorObj) { + async.throwLater(ret.e); + } + } + + Promise.prototype.asCallback = Promise.prototype.nodeify = function (nodeback, + options) { + if (typeof nodeback == "function") { + var adapter = successAdapter; + if (options !== undefined && Object(options).spread) { + adapter = spreadAdapter; + } + this._then( + adapter, + errorAdapter, + undefined, + this, + nodeback + ); + } + return this; + }; + }; + + },{"./util":36}],22:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function() { + var makeSelfResolutionError = function () { + return new TypeError("circular promise resolution chain\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + }; + var reflectHandler = function() { + return new Promise.PromiseInspection(this._target()); + }; + var apiRejection = function(msg) { + return Promise.reject(new TypeError(msg)); + }; + function Proxyable() {} + var UNDEFINED_BINDING = {}; + var util = _dereq_("./util"); + + var getDomain; + if (util.isNode) { + getDomain = function() { + var ret = process.domain; + if (ret === undefined) ret = null; + return ret; + }; + } else { + getDomain = function() { + return null; + }; + } + util.notEnumerableProp(Promise, "_getDomain", getDomain); + + var es5 = _dereq_("./es5"); + var Async = _dereq_("./async"); + var async = new Async(); + es5.defineProperty(Promise, "_async", {value: async}); + var errors = _dereq_("./errors"); + var TypeError = Promise.TypeError = errors.TypeError; + Promise.RangeError = errors.RangeError; + var CancellationError = Promise.CancellationError = errors.CancellationError; + Promise.TimeoutError = errors.TimeoutError; + Promise.OperationalError = errors.OperationalError; + Promise.RejectionError = errors.OperationalError; + Promise.AggregateError = errors.AggregateError; + var INTERNAL = function(){}; + var APPLY = {}; + var NEXT_FILTER = {}; + var tryConvertToPromise = _dereq_("./thenables")(Promise, INTERNAL); + var PromiseArray = + _dereq_("./promise_array")(Promise, INTERNAL, + tryConvertToPromise, apiRejection, Proxyable); + var Context = _dereq_("./context")(Promise); + /*jshint unused:false*/ + var createContext = Context.create; + var debug = _dereq_("./debuggability")(Promise, Context); + var CapturedTrace = debug.CapturedTrace; + var PassThroughHandlerContext = + _dereq_("./finally")(Promise, tryConvertToPromise); + var catchFilter = _dereq_("./catch_filter")(NEXT_FILTER); + var nodebackForPromise = _dereq_("./nodeback"); + var errorObj = util.errorObj; + var tryCatch = util.tryCatch; + function check(self, executor) { + if (typeof executor !== "function") { + throw new TypeError("expecting a function but got " + util.classString(executor)); + } + if (self.constructor !== Promise) { + throw new TypeError("the promise constructor cannot be invoked directly\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + } + + function Promise(executor) { + this._bitField = 0; + this._fulfillmentHandler0 = undefined; + this._rejectionHandler0 = undefined; + this._promise0 = undefined; + this._receiver0 = undefined; + if (executor !== INTERNAL) { + check(this, executor); + this._resolveFromExecutor(executor); + } + this._promiseCreated(); + this._fireEvent("promiseCreated", this); + } + + Promise.prototype.toString = function () { + return "[object Promise]"; + }; + + Promise.prototype.caught = Promise.prototype["catch"] = function (fn) { + var len = arguments.length; + if (len > 1) { + var catchInstances = new Array(len - 1), + j = 0, i; + for (i = 0; i < len - 1; ++i) { + var item = arguments[i]; + if (util.isObject(item)) { + catchInstances[j++] = item; + } else { + return apiRejection("expecting an object but got " + + "A catch statement predicate " + util.classString(item)); + } + } + catchInstances.length = j; + fn = arguments[i]; + return this.then(undefined, catchFilter(catchInstances, fn, this)); + } + return this.then(undefined, fn); + }; + + Promise.prototype.reflect = function () { + return this._then(reflectHandler, + reflectHandler, undefined, this, undefined); + }; + + Promise.prototype.then = function (didFulfill, didReject) { + if (debug.warnings() && arguments.length > 0 && + typeof didFulfill !== "function" && + typeof didReject !== "function") { + var msg = ".then() only accepts functions but was passed: " + + util.classString(didFulfill); + if (arguments.length > 1) { + msg += ", " + util.classString(didReject); + } + this._warn(msg); + } + return this._then(didFulfill, didReject, undefined, undefined, undefined); + }; + + Promise.prototype.done = function (didFulfill, didReject) { + var promise = + this._then(didFulfill, didReject, undefined, undefined, undefined); + promise._setIsFinal(); + }; + + Promise.prototype.spread = function (fn) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + return this.all()._then(fn, undefined, undefined, APPLY, undefined); + }; + + Promise.prototype.toJSON = function () { + var ret = { + isFulfilled: false, + isRejected: false, + fulfillmentValue: undefined, + rejectionReason: undefined + }; + if (this.isFulfilled()) { + ret.fulfillmentValue = this.value(); + ret.isFulfilled = true; + } else if (this.isRejected()) { + ret.rejectionReason = this.reason(); + ret.isRejected = true; + } + return ret; + }; + + Promise.prototype.all = function () { + if (arguments.length > 0) { + this._warn(".all() was passed arguments but it does not take any"); + } + return new PromiseArray(this).promise(); + }; + + Promise.prototype.error = function (fn) { + return this.caught(util.originatesFromRejection, fn); + }; + + Promise.getNewLibraryCopy = module.exports; + + Promise.is = function (val) { + return val instanceof Promise; + }; + + Promise.fromNode = Promise.fromCallback = function(fn) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + var multiArgs = arguments.length > 1 ? !!Object(arguments[1]).multiArgs + : false; + var result = tryCatch(fn)(nodebackForPromise(ret, multiArgs)); + if (result === errorObj) { + ret._rejectCallback(result.e, true); + } + if (!ret._isFateSealed()) ret._setAsyncGuaranteed(); + return ret; + }; + + Promise.all = function (promises) { + return new PromiseArray(promises).promise(); + }; + + Promise.cast = function (obj) { + var ret = tryConvertToPromise(obj); + if (!(ret instanceof Promise)) { + ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._setFulfilled(); + ret._rejectionHandler0 = obj; + } + return ret; + }; + + Promise.resolve = Promise.fulfilled = Promise.cast; + + Promise.reject = Promise.rejected = function (reason) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._rejectCallback(reason, true); + return ret; + }; + + Promise.setScheduler = function(fn) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + return async.setScheduler(fn); + }; + + Promise.prototype._then = function ( + didFulfill, + didReject, + _, receiver, + internalData + ) { + var haveInternalData = internalData !== undefined; + var promise = haveInternalData ? internalData : new Promise(INTERNAL); + var target = this._target(); + var bitField = target._bitField; + + if (!haveInternalData) { + promise._propagateFrom(this, 3); + promise._captureStackTrace(); + if (receiver === undefined && + ((this._bitField & 2097152) !== 0)) { + if (!((bitField & 50397184) === 0)) { + receiver = this._boundValue(); + } else { + receiver = target === this ? undefined : this._boundTo; + } + } + this._fireEvent("promiseChained", this, promise); + } + + var domain = getDomain(); + if (!((bitField & 50397184) === 0)) { + var handler, value, settler = target._settlePromiseCtx; + if (((bitField & 33554432) !== 0)) { + value = target._rejectionHandler0; + handler = didFulfill; + } else if (((bitField & 16777216) !== 0)) { + value = target._fulfillmentHandler0; + handler = didReject; + target._unsetRejectionIsUnhandled(); + } else { + settler = target._settlePromiseLateCancellationObserver; + value = new CancellationError("late cancellation observer"); + target._attachExtraTrace(value); + handler = didReject; + } + + async.invoke(settler, target, { + handler: domain === null ? handler + : (typeof handler === "function" && + util.domainBind(domain, handler)), + promise: promise, + receiver: receiver, + value: value + }); + } else { + target._addCallbacks(didFulfill, didReject, promise, receiver, domain); + } + + return promise; + }; + + Promise.prototype._length = function () { + return this._bitField & 65535; + }; + + Promise.prototype._isFateSealed = function () { + return (this._bitField & 117506048) !== 0; + }; + + Promise.prototype._isFollowing = function () { + return (this._bitField & 67108864) === 67108864; + }; + + Promise.prototype._setLength = function (len) { + this._bitField = (this._bitField & -65536) | + (len & 65535); + }; + + Promise.prototype._setFulfilled = function () { + this._bitField = this._bitField | 33554432; + this._fireEvent("promiseFulfilled", this); + }; + + Promise.prototype._setRejected = function () { + this._bitField = this._bitField | 16777216; + this._fireEvent("promiseRejected", this); + }; + + Promise.prototype._setFollowing = function () { + this._bitField = this._bitField | 67108864; + this._fireEvent("promiseResolved", this); + }; + + Promise.prototype._setIsFinal = function () { + this._bitField = this._bitField | 4194304; + }; + + Promise.prototype._isFinal = function () { + return (this._bitField & 4194304) > 0; + }; + + Promise.prototype._unsetCancelled = function() { + this._bitField = this._bitField & (~65536); + }; + + Promise.prototype._setCancelled = function() { + this._bitField = this._bitField | 65536; + this._fireEvent("promiseCancelled", this); + }; + + Promise.prototype._setWillBeCancelled = function() { + this._bitField = this._bitField | 8388608; + }; + + Promise.prototype._setAsyncGuaranteed = function() { + if (async.hasCustomScheduler()) return; + this._bitField = this._bitField | 134217728; + }; + + Promise.prototype._receiverAt = function (index) { + var ret = index === 0 ? this._receiver0 : this[ + index * 4 - 4 + 3]; + if (ret === UNDEFINED_BINDING) { + return undefined; + } else if (ret === undefined && this._isBound()) { + return this._boundValue(); + } + return ret; + }; + + Promise.prototype._promiseAt = function (index) { + return this[ + index * 4 - 4 + 2]; + }; + + Promise.prototype._fulfillmentHandlerAt = function (index) { + return this[ + index * 4 - 4 + 0]; + }; + + Promise.prototype._rejectionHandlerAt = function (index) { + return this[ + index * 4 - 4 + 1]; + }; + + Promise.prototype._boundValue = function() {}; + + Promise.prototype._migrateCallback0 = function (follower) { + var bitField = follower._bitField; + var fulfill = follower._fulfillmentHandler0; + var reject = follower._rejectionHandler0; + var promise = follower._promise0; + var receiver = follower._receiverAt(0); + if (receiver === undefined) receiver = UNDEFINED_BINDING; + this._addCallbacks(fulfill, reject, promise, receiver, null); + }; + + Promise.prototype._migrateCallbackAt = function (follower, index) { + var fulfill = follower._fulfillmentHandlerAt(index); + var reject = follower._rejectionHandlerAt(index); + var promise = follower._promiseAt(index); + var receiver = follower._receiverAt(index); + if (receiver === undefined) receiver = UNDEFINED_BINDING; + this._addCallbacks(fulfill, reject, promise, receiver, null); + }; + + Promise.prototype._addCallbacks = function ( + fulfill, + reject, + promise, + receiver, + domain + ) { + var index = this._length(); + + if (index >= 65535 - 4) { + index = 0; + this._setLength(0); + } + + if (index === 0) { + this._promise0 = promise; + this._receiver0 = receiver; + if (typeof fulfill === "function") { + this._fulfillmentHandler0 = + domain === null ? fulfill : util.domainBind(domain, fulfill); + } + if (typeof reject === "function") { + this._rejectionHandler0 = + domain === null ? reject : util.domainBind(domain, reject); + } + } else { + var base = index * 4 - 4; + this[base + 2] = promise; + this[base + 3] = receiver; + if (typeof fulfill === "function") { + this[base + 0] = + domain === null ? fulfill : util.domainBind(domain, fulfill); + } + if (typeof reject === "function") { + this[base + 1] = + domain === null ? reject : util.domainBind(domain, reject); + } + } + this._setLength(index + 1); + return index; + }; + + Promise.prototype._proxy = function (proxyable, arg) { + this._addCallbacks(undefined, undefined, arg, proxyable, null); + }; + + Promise.prototype._resolveCallback = function(value, shouldBind) { + if (((this._bitField & 117506048) !== 0)) return; + if (value === this) + return this._rejectCallback(makeSelfResolutionError(), false); + var maybePromise = tryConvertToPromise(value, this); + if (!(maybePromise instanceof Promise)) return this._fulfill(value); + + if (shouldBind) this._propagateFrom(maybePromise, 2); + + var promise = maybePromise._target(); + + if (promise === this) { + this._reject(makeSelfResolutionError()); + return; + } + + var bitField = promise._bitField; + if (((bitField & 50397184) === 0)) { + var len = this._length(); + if (len > 0) promise._migrateCallback0(this); + for (var i = 1; i < len; ++i) { + promise._migrateCallbackAt(this, i); + } + this._setFollowing(); + this._setLength(0); + this._setFollowee(promise); + } else if (((bitField & 33554432) !== 0)) { + this._fulfill(promise._value()); + } else if (((bitField & 16777216) !== 0)) { + this._reject(promise._reason()); + } else { + var reason = new CancellationError("late cancellation observer"); + promise._attachExtraTrace(reason); + this._reject(reason); + } + }; + + Promise.prototype._rejectCallback = + function(reason, synchronous, ignoreNonErrorWarnings) { + var trace = util.ensureErrorObject(reason); + var hasStack = trace === reason; + if (!hasStack && !ignoreNonErrorWarnings && debug.warnings()) { + var message = "a promise was rejected with a non-error: " + + util.classString(reason); + this._warn(message, true); + } + this._attachExtraTrace(trace, synchronous ? hasStack : false); + this._reject(reason); + }; + + Promise.prototype._resolveFromExecutor = function (executor) { + var promise = this; + this._captureStackTrace(); + this._pushContext(); + var synchronous = true; + var r = this._execute(executor, function(value) { + promise._resolveCallback(value); + }, function (reason) { + promise._rejectCallback(reason, synchronous); + }); + synchronous = false; + this._popContext(); + + if (r !== undefined) { + promise._rejectCallback(r, true); + } + }; + + Promise.prototype._settlePromiseFromHandler = function ( + handler, receiver, value, promise + ) { + var bitField = promise._bitField; + if (((bitField & 65536) !== 0)) return; + promise._pushContext(); + var x; + if (receiver === APPLY) { + if (!value || typeof value.length !== "number") { + x = errorObj; + x.e = new TypeError("cannot .spread() a non-array: " + + util.classString(value)); + } else { + x = tryCatch(handler).apply(this._boundValue(), value); + } + } else { + x = tryCatch(handler).call(receiver, value); + } + var promiseCreated = promise._popContext(); + bitField = promise._bitField; + if (((bitField & 65536) !== 0)) return; + + if (x === NEXT_FILTER) { + promise._reject(value); + } else if (x === errorObj) { + promise._rejectCallback(x.e, false); + } else { + debug.checkForgottenReturns(x, promiseCreated, "", promise, this); + promise._resolveCallback(x); + } + }; + + Promise.prototype._target = function() { + var ret = this; + while (ret._isFollowing()) ret = ret._followee(); + return ret; + }; + + Promise.prototype._followee = function() { + return this._rejectionHandler0; + }; + + Promise.prototype._setFollowee = function(promise) { + this._rejectionHandler0 = promise; + }; + + Promise.prototype._settlePromise = function(promise, handler, receiver, value) { + var isPromise = promise instanceof Promise; + var bitField = this._bitField; + var asyncGuaranteed = ((bitField & 134217728) !== 0); + if (((bitField & 65536) !== 0)) { + if (isPromise) promise._invokeInternalOnCancel(); + + if (receiver instanceof PassThroughHandlerContext && + receiver.isFinallyHandler()) { + receiver.cancelPromise = promise; + if (tryCatch(handler).call(receiver, value) === errorObj) { + promise._reject(errorObj.e); + } + } else if (handler === reflectHandler) { + promise._fulfill(reflectHandler.call(receiver)); + } else if (receiver instanceof Proxyable) { + receiver._promiseCancelled(promise); + } else if (isPromise || promise instanceof PromiseArray) { + promise._cancel(); + } else { + receiver.cancel(); + } + } else if (typeof handler === "function") { + if (!isPromise) { + handler.call(receiver, value, promise); + } else { + if (asyncGuaranteed) promise._setAsyncGuaranteed(); + this._settlePromiseFromHandler(handler, receiver, value, promise); + } + } else if (receiver instanceof Proxyable) { + if (!receiver._isResolved()) { + if (((bitField & 33554432) !== 0)) { + receiver._promiseFulfilled(value, promise); + } else { + receiver._promiseRejected(value, promise); + } + } + } else if (isPromise) { + if (asyncGuaranteed) promise._setAsyncGuaranteed(); + if (((bitField & 33554432) !== 0)) { + promise._fulfill(value); + } else { + promise._reject(value); + } + } + }; + + Promise.prototype._settlePromiseLateCancellationObserver = function(ctx) { + var handler = ctx.handler; + var promise = ctx.promise; + var receiver = ctx.receiver; + var value = ctx.value; + if (typeof handler === "function") { + if (!(promise instanceof Promise)) { + handler.call(receiver, value, promise); + } else { + this._settlePromiseFromHandler(handler, receiver, value, promise); + } + } else if (promise instanceof Promise) { + promise._reject(value); + } + }; + + Promise.prototype._settlePromiseCtx = function(ctx) { + this._settlePromise(ctx.promise, ctx.handler, ctx.receiver, ctx.value); + }; + + Promise.prototype._settlePromise0 = function(handler, value, bitField) { + var promise = this._promise0; + var receiver = this._receiverAt(0); + this._promise0 = undefined; + this._receiver0 = undefined; + this._settlePromise(promise, handler, receiver, value); + }; + + Promise.prototype._clearCallbackDataAtIndex = function(index) { + var base = index * 4 - 4; + this[base + 2] = + this[base + 3] = + this[base + 0] = + this[base + 1] = undefined; + }; + + Promise.prototype._fulfill = function (value) { + var bitField = this._bitField; + if (((bitField & 117506048) >>> 16)) return; + if (value === this) { + var err = makeSelfResolutionError(); + this._attachExtraTrace(err); + return this._reject(err); + } + this._setFulfilled(); + this._rejectionHandler0 = value; + + if ((bitField & 65535) > 0) { + if (((bitField & 134217728) !== 0)) { + this._settlePromises(); + } else { + async.settlePromises(this); + } + } + }; + + Promise.prototype._reject = function (reason) { + var bitField = this._bitField; + if (((bitField & 117506048) >>> 16)) return; + this._setRejected(); + this._fulfillmentHandler0 = reason; + + if (this._isFinal()) { + return async.fatalError(reason, util.isNode); + } + + if ((bitField & 65535) > 0) { + async.settlePromises(this); + } else { + this._ensurePossibleRejectionHandled(); + } + }; + + Promise.prototype._fulfillPromises = function (len, value) { + for (var i = 1; i < len; i++) { + var handler = this._fulfillmentHandlerAt(i); + var promise = this._promiseAt(i); + var receiver = this._receiverAt(i); + this._clearCallbackDataAtIndex(i); + this._settlePromise(promise, handler, receiver, value); + } + }; + + Promise.prototype._rejectPromises = function (len, reason) { + for (var i = 1; i < len; i++) { + var handler = this._rejectionHandlerAt(i); + var promise = this._promiseAt(i); + var receiver = this._receiverAt(i); + this._clearCallbackDataAtIndex(i); + this._settlePromise(promise, handler, receiver, reason); + } + }; + + Promise.prototype._settlePromises = function () { + var bitField = this._bitField; + var len = (bitField & 65535); + + if (len > 0) { + if (((bitField & 16842752) !== 0)) { + var reason = this._fulfillmentHandler0; + this._settlePromise0(this._rejectionHandler0, reason, bitField); + this._rejectPromises(len, reason); + } else { + var value = this._rejectionHandler0; + this._settlePromise0(this._fulfillmentHandler0, value, bitField); + this._fulfillPromises(len, value); + } + this._setLength(0); + } + this._clearCancellationData(); + }; + + Promise.prototype._settledValue = function() { + var bitField = this._bitField; + if (((bitField & 33554432) !== 0)) { + return this._rejectionHandler0; + } else if (((bitField & 16777216) !== 0)) { + return this._fulfillmentHandler0; + } + }; + + function deferResolve(v) {this.promise._resolveCallback(v);} + function deferReject(v) {this.promise._rejectCallback(v, false);} + + Promise.defer = Promise.pending = function() { + debug.deprecated("Promise.defer", "new Promise"); + var promise = new Promise(INTERNAL); + return { + promise: promise, + resolve: deferResolve, + reject: deferReject + }; + }; + + util.notEnumerableProp(Promise, + "_makeSelfResolutionError", + makeSelfResolutionError); + + _dereq_("./method")(Promise, INTERNAL, tryConvertToPromise, apiRejection, + debug); + _dereq_("./bind")(Promise, INTERNAL, tryConvertToPromise, debug); + _dereq_("./cancel")(Promise, PromiseArray, apiRejection, debug); + _dereq_("./direct_resolve")(Promise); + _dereq_("./synchronous_inspection")(Promise); + _dereq_("./join")( + Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, getDomain); + Promise.Promise = Promise; + Promise.version = "3.4.7"; + _dereq_('./map.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug); + _dereq_('./call_get.js')(Promise); + _dereq_('./using.js')(Promise, apiRejection, tryConvertToPromise, createContext, INTERNAL, debug); + _dereq_('./timers.js')(Promise, INTERNAL, debug); + _dereq_('./generators.js')(Promise, apiRejection, INTERNAL, tryConvertToPromise, Proxyable, debug); + _dereq_('./nodeify.js')(Promise); + _dereq_('./promisify.js')(Promise, INTERNAL); + _dereq_('./props.js')(Promise, PromiseArray, tryConvertToPromise, apiRejection); + _dereq_('./race.js')(Promise, INTERNAL, tryConvertToPromise, apiRejection); + _dereq_('./reduce.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug); + _dereq_('./settle.js')(Promise, PromiseArray, debug); + _dereq_('./some.js')(Promise, PromiseArray, apiRejection); + _dereq_('./filter.js')(Promise, INTERNAL); + _dereq_('./each.js')(Promise, INTERNAL); + _dereq_('./any.js')(Promise); + + util.toFastProperties(Promise); + util.toFastProperties(Promise.prototype); + function fillTypes(value) { + var p = new Promise(INTERNAL); + p._fulfillmentHandler0 = value; + p._rejectionHandler0 = value; + p._promise0 = value; + p._receiver0 = value; + } + // Complete slack tracking, opt out of field-type tracking and + // stabilize map + fillTypes({a: 1}); + fillTypes({b: 2}); + fillTypes({c: 3}); + fillTypes(1); + fillTypes(function(){}); + fillTypes(undefined); + fillTypes(false); + fillTypes(new Promise(INTERNAL)); + debug.setBounds(Async.firstLineError, util.lastLineError); + return Promise; + + }; + + },{"./any.js":1,"./async":2,"./bind":3,"./call_get.js":5,"./cancel":6,"./catch_filter":7,"./context":8,"./debuggability":9,"./direct_resolve":10,"./each.js":11,"./errors":12,"./es5":13,"./filter.js":14,"./finally":15,"./generators.js":16,"./join":17,"./map.js":18,"./method":19,"./nodeback":20,"./nodeify.js":21,"./promise_array":23,"./promisify.js":24,"./props.js":25,"./race.js":27,"./reduce.js":28,"./settle.js":30,"./some.js":31,"./synchronous_inspection":32,"./thenables":33,"./timers.js":34,"./using.js":35,"./util":36}],23:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, INTERNAL, tryConvertToPromise, + apiRejection, Proxyable) { + var util = _dereq_("./util"); + var isArray = util.isArray; + + function toResolutionValue(val) { + switch(val) { + case -2: return []; + case -3: return {}; + } + } + + function PromiseArray(values) { + var promise = this._promise = new Promise(INTERNAL); + if (values instanceof Promise) { + promise._propagateFrom(values, 3); + } + promise._setOnCancel(this); + this._values = values; + this._length = 0; + this._totalResolved = 0; + this._init(undefined, -2); + } + util.inherits(PromiseArray, Proxyable); + + PromiseArray.prototype.length = function () { + return this._length; + }; + + PromiseArray.prototype.promise = function () { + return this._promise; + }; + + PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) { + var values = tryConvertToPromise(this._values, this._promise); + if (values instanceof Promise) { + values = values._target(); + var bitField = values._bitField; + ; + this._values = values; + + if (((bitField & 50397184) === 0)) { + this._promise._setAsyncGuaranteed(); + return values._then( + init, + this._reject, + undefined, + this, + resolveValueIfEmpty + ); + } else if (((bitField & 33554432) !== 0)) { + values = values._value(); + } else if (((bitField & 16777216) !== 0)) { + return this._reject(values._reason()); + } else { + return this._cancel(); + } + } + values = util.asArray(values); + if (values === null) { + var err = apiRejection( + "expecting an array or an iterable object but got " + util.classString(values)).reason(); + this._promise._rejectCallback(err, false); + return; + } + + if (values.length === 0) { + if (resolveValueIfEmpty === -5) { + this._resolveEmptyArray(); + } + else { + this._resolve(toResolutionValue(resolveValueIfEmpty)); + } + return; + } + this._iterate(values); + }; + + PromiseArray.prototype._iterate = function(values) { + var len = this.getActualLength(values.length); + this._length = len; + this._values = this.shouldCopyValues() ? new Array(len) : this._values; + var result = this._promise; + var isResolved = false; + var bitField = null; + for (var i = 0; i < len; ++i) { + var maybePromise = tryConvertToPromise(values[i], result); + + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + bitField = maybePromise._bitField; + } else { + bitField = null; + } + + if (isResolved) { + if (bitField !== null) { + maybePromise.suppressUnhandledRejections(); + } + } else if (bitField !== null) { + if (((bitField & 50397184) === 0)) { + maybePromise._proxy(this, i); + this._values[i] = maybePromise; + } else if (((bitField & 33554432) !== 0)) { + isResolved = this._promiseFulfilled(maybePromise._value(), i); + } else if (((bitField & 16777216) !== 0)) { + isResolved = this._promiseRejected(maybePromise._reason(), i); + } else { + isResolved = this._promiseCancelled(i); + } + } else { + isResolved = this._promiseFulfilled(maybePromise, i); + } + } + if (!isResolved) result._setAsyncGuaranteed(); + }; + + PromiseArray.prototype._isResolved = function () { + return this._values === null; + }; + + PromiseArray.prototype._resolve = function (value) { + this._values = null; + this._promise._fulfill(value); + }; + + PromiseArray.prototype._cancel = function() { + if (this._isResolved() || !this._promise._isCancellable()) return; + this._values = null; + this._promise._cancel(); + }; + + PromiseArray.prototype._reject = function (reason) { + this._values = null; + this._promise._rejectCallback(reason, false); + }; + + PromiseArray.prototype._promiseFulfilled = function (value, index) { + this._values[index] = value; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + this._resolve(this._values); + return true; + } + return false; + }; + + PromiseArray.prototype._promiseCancelled = function() { + this._cancel(); + return true; + }; + + PromiseArray.prototype._promiseRejected = function (reason) { + this._totalResolved++; + this._reject(reason); + return true; + }; + + PromiseArray.prototype._resultCancelled = function() { + if (this._isResolved()) return; + var values = this._values; + this._cancel(); + if (values instanceof Promise) { + values.cancel(); + } else { + for (var i = 0; i < values.length; ++i) { + if (values[i] instanceof Promise) { + values[i].cancel(); + } + } + } + }; + + PromiseArray.prototype.shouldCopyValues = function () { + return true; + }; + + PromiseArray.prototype.getActualLength = function (len) { + return len; + }; + + return PromiseArray; + }; + + },{"./util":36}],24:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, INTERNAL) { + var THIS = {}; + var util = _dereq_("./util"); + var nodebackForPromise = _dereq_("./nodeback"); + var withAppended = util.withAppended; + var maybeWrapAsError = util.maybeWrapAsError; + var canEvaluate = util.canEvaluate; + var TypeError = _dereq_("./errors").TypeError; + var defaultSuffix = "Async"; + var defaultPromisified = {__isPromisified__: true}; + var noCopyProps = [ + "arity", "length", + "name", + "arguments", + "caller", + "callee", + "prototype", + "__isPromisified__" + ]; + var noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$"); + + var defaultFilter = function(name) { + return util.isIdentifier(name) && + name.charAt(0) !== "_" && + name !== "constructor"; + }; + + function propsFilter(key) { + return !noCopyPropsPattern.test(key); + } + + function isPromisified(fn) { + try { + return fn.__isPromisified__ === true; + } + catch (e) { + return false; + } + } + + function hasPromisified(obj, key, suffix) { + var val = util.getDataPropertyOrDefault(obj, key + suffix, + defaultPromisified); + return val ? isPromisified(val) : false; + } + function checkValid(ret, suffix, suffixRegexp) { + for (var i = 0; i < ret.length; i += 2) { + var key = ret[i]; + if (suffixRegexp.test(key)) { + var keyWithoutAsyncSuffix = key.replace(suffixRegexp, ""); + for (var j = 0; j < ret.length; j += 2) { + if (ret[j] === keyWithoutAsyncSuffix) { + throw new TypeError("Cannot promisify an API that has normal methods with '%s'-suffix\u000a\u000a See http://goo.gl/MqrFmX\u000a" + .replace("%s", suffix)); + } + } + } + } + } + + function promisifiableMethods(obj, suffix, suffixRegexp, filter) { + var keys = util.inheritedDataKeys(obj); + var ret = []; + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + var value = obj[key]; + var passesDefaultFilter = filter === defaultFilter + ? true : defaultFilter(key, value, obj); + if (typeof value === "function" && + !isPromisified(value) && + !hasPromisified(obj, key, suffix) && + filter(key, value, obj, passesDefaultFilter)) { + ret.push(key, value); + } + } + checkValid(ret, suffix, suffixRegexp); + return ret; + } + + var escapeIdentRegex = function(str) { + return str.replace(/([$])/, "\\$"); + }; + + var makeNodePromisifiedEval; + if (false) { + var switchCaseArgumentOrder = function(likelyArgumentCount) { + var ret = [likelyArgumentCount]; + var min = Math.max(0, likelyArgumentCount - 1 - 3); + for(var i = likelyArgumentCount - 1; i >= min; --i) { + ret.push(i); + } + for(var i = likelyArgumentCount + 1; i <= 3; ++i) { + ret.push(i); + } + return ret; + }; + + var argumentSequence = function(argumentCount) { + return util.filledRange(argumentCount, "_arg", ""); + }; + + var parameterDeclaration = function(parameterCount) { + return util.filledRange( + Math.max(parameterCount, 3), "_arg", ""); + }; + + var parameterCount = function(fn) { + if (typeof fn.length === "number") { + return Math.max(Math.min(fn.length, 1023 + 1), 0); + } + return 0; + }; + + makeNodePromisifiedEval = + function(callback, receiver, originalName, fn, _, multiArgs) { + var newParameterCount = Math.max(0, parameterCount(fn) - 1); + var argumentOrder = switchCaseArgumentOrder(newParameterCount); + var shouldProxyThis = typeof callback === "string" || receiver === THIS; + + function generateCallForArgumentCount(count) { + var args = argumentSequence(count).join(", "); + var comma = count > 0 ? ", " : ""; + var ret; + if (shouldProxyThis) { + ret = "ret = callback.call(this, {{args}}, nodeback); break;\n"; + } else { + ret = receiver === undefined + ? "ret = callback({{args}}, nodeback); break;\n" + : "ret = callback.call(receiver, {{args}}, nodeback); break;\n"; + } + return ret.replace("{{args}}", args).replace(", ", comma); + } + + function generateArgumentSwitchCase() { + var ret = ""; + for (var i = 0; i < argumentOrder.length; ++i) { + ret += "case " + argumentOrder[i] +":" + + generateCallForArgumentCount(argumentOrder[i]); + } + + ret += " \n\ + default: \n\ + var args = new Array(len + 1); \n\ + var i = 0; \n\ + for (var i = 0; i < len; ++i) { \n\ + args[i] = arguments[i]; \n\ + } \n\ + args[i] = nodeback; \n\ + [CodeForCall] \n\ + break; \n\ + ".replace("[CodeForCall]", (shouldProxyThis + ? "ret = callback.apply(this, args);\n" + : "ret = callback.apply(receiver, args);\n")); + return ret; + } + + var getFunctionCode = typeof callback === "string" + ? ("this != null ? this['"+callback+"'] : fn") + : "fn"; + var body = "'use strict'; \n\ + var ret = function (Parameters) { \n\ + 'use strict'; \n\ + var len = arguments.length; \n\ + var promise = new Promise(INTERNAL); \n\ + promise._captureStackTrace(); \n\ + var nodeback = nodebackForPromise(promise, " + multiArgs + "); \n\ + var ret; \n\ + var callback = tryCatch([GetFunctionCode]); \n\ + switch(len) { \n\ + [CodeForSwitchCase] \n\ + } \n\ + if (ret === errorObj) { \n\ + promise._rejectCallback(maybeWrapAsError(ret.e), true, true);\n\ + } \n\ + if (!promise._isFateSealed()) promise._setAsyncGuaranteed(); \n\ + return promise; \n\ + }; \n\ + notEnumerableProp(ret, '__isPromisified__', true); \n\ + return ret; \n\ + ".replace("[CodeForSwitchCase]", generateArgumentSwitchCase()) + .replace("[GetFunctionCode]", getFunctionCode); + body = body.replace("Parameters", parameterDeclaration(newParameterCount)); + return new Function("Promise", + "fn", + "receiver", + "withAppended", + "maybeWrapAsError", + "nodebackForPromise", + "tryCatch", + "errorObj", + "notEnumerableProp", + "INTERNAL", + body)( + Promise, + fn, + receiver, + withAppended, + maybeWrapAsError, + nodebackForPromise, + util.tryCatch, + util.errorObj, + util.notEnumerableProp, + INTERNAL); + }; + } + + function makeNodePromisifiedClosure(callback, receiver, _, fn, __, multiArgs) { + var defaultThis = (function() {return this;})(); + var method = callback; + if (typeof method === "string") { + callback = fn; + } + function promisified() { + var _receiver = receiver; + if (receiver === THIS) _receiver = this; + var promise = new Promise(INTERNAL); + promise._captureStackTrace(); + var cb = typeof method === "string" && this !== defaultThis + ? this[method] : callback; + var fn = nodebackForPromise(promise, multiArgs); + try { + cb.apply(_receiver, withAppended(arguments, fn)); + } catch(e) { + promise._rejectCallback(maybeWrapAsError(e), true, true); + } + if (!promise._isFateSealed()) promise._setAsyncGuaranteed(); + return promise; + } + util.notEnumerableProp(promisified, "__isPromisified__", true); + return promisified; + } + + var makeNodePromisified = canEvaluate + ? makeNodePromisifiedEval + : makeNodePromisifiedClosure; + + function promisifyAll(obj, suffix, filter, promisifier, multiArgs) { + var suffixRegexp = new RegExp(escapeIdentRegex(suffix) + "$"); + var methods = + promisifiableMethods(obj, suffix, suffixRegexp, filter); + + for (var i = 0, len = methods.length; i < len; i+= 2) { + var key = methods[i]; + var fn = methods[i+1]; + var promisifiedKey = key + suffix; + if (promisifier === makeNodePromisified) { + obj[promisifiedKey] = + makeNodePromisified(key, THIS, key, fn, suffix, multiArgs); + } else { + var promisified = promisifier(fn, function() { + return makeNodePromisified(key, THIS, key, + fn, suffix, multiArgs); + }); + util.notEnumerableProp(promisified, "__isPromisified__", true); + obj[promisifiedKey] = promisified; + } + } + util.toFastProperties(obj); + return obj; + } + + function promisify(callback, receiver, multiArgs) { + return makeNodePromisified(callback, receiver, undefined, + callback, null, multiArgs); + } + + Promise.promisify = function (fn, options) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + if (isPromisified(fn)) { + return fn; + } + options = Object(options); + var receiver = options.context === undefined ? THIS : options.context; + var multiArgs = !!options.multiArgs; + var ret = promisify(fn, receiver, multiArgs); + util.copyDescriptors(fn, ret, propsFilter); + return ret; + }; + + Promise.promisifyAll = function (target, options) { + if (typeof target !== "function" && typeof target !== "object") { + throw new TypeError("the target of promisifyAll must be an object or a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + options = Object(options); + var multiArgs = !!options.multiArgs; + var suffix = options.suffix; + if (typeof suffix !== "string") suffix = defaultSuffix; + var filter = options.filter; + if (typeof filter !== "function") filter = defaultFilter; + var promisifier = options.promisifier; + if (typeof promisifier !== "function") promisifier = makeNodePromisified; + + if (!util.isIdentifier(suffix)) { + throw new RangeError("suffix must be a valid identifier\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + + var keys = util.inheritedDataKeys(target); + for (var i = 0; i < keys.length; ++i) { + var value = target[keys[i]]; + if (keys[i] !== "constructor" && + util.isClass(value)) { + promisifyAll(value.prototype, suffix, filter, promisifier, + multiArgs); + promisifyAll(value, suffix, filter, promisifier, multiArgs); + } + } + + return promisifyAll(target, suffix, filter, promisifier, multiArgs); + }; + }; + + + },{"./errors":12,"./nodeback":20,"./util":36}],25:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function( + Promise, PromiseArray, tryConvertToPromise, apiRejection) { + var util = _dereq_("./util"); + var isObject = util.isObject; + var es5 = _dereq_("./es5"); + var Es6Map; + if (typeof Map === "function") Es6Map = Map; + + var mapToEntries = (function() { + var index = 0; + var size = 0; + + function extractEntry(value, key) { + this[index] = value; + this[index + size] = key; + index++; + } + + return function mapToEntries(map) { + size = map.size; + index = 0; + var ret = new Array(map.size * 2); + map.forEach(extractEntry, ret); + return ret; + }; + })(); + + var entriesToMap = function(entries) { + var ret = new Es6Map(); + var length = entries.length / 2 | 0; + for (var i = 0; i < length; ++i) { + var key = entries[length + i]; + var value = entries[i]; + ret.set(key, value); + } + return ret; + }; + + function PropertiesPromiseArray(obj) { + var isMap = false; + var entries; + if (Es6Map !== undefined && obj instanceof Es6Map) { + entries = mapToEntries(obj); + isMap = true; + } else { + var keys = es5.keys(obj); + var len = keys.length; + entries = new Array(len * 2); + for (var i = 0; i < len; ++i) { + var key = keys[i]; + entries[i] = obj[key]; + entries[i + len] = key; + } + } + this.constructor$(entries); + this._isMap = isMap; + this._init$(undefined, -3); + } + util.inherits(PropertiesPromiseArray, PromiseArray); + + PropertiesPromiseArray.prototype._init = function () {}; + + PropertiesPromiseArray.prototype._promiseFulfilled = function (value, index) { + this._values[index] = value; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + var val; + if (this._isMap) { + val = entriesToMap(this._values); + } else { + val = {}; + var keyOffset = this.length(); + for (var i = 0, len = this.length(); i < len; ++i) { + val[this._values[i + keyOffset]] = this._values[i]; + } + } + this._resolve(val); + return true; + } + return false; + }; + + PropertiesPromiseArray.prototype.shouldCopyValues = function () { + return false; + }; + + PropertiesPromiseArray.prototype.getActualLength = function (len) { + return len >> 1; + }; + + function props(promises) { + var ret; + var castValue = tryConvertToPromise(promises); + + if (!isObject(castValue)) { + return apiRejection("cannot await properties of a non-object\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } else if (castValue instanceof Promise) { + ret = castValue._then( + Promise.props, undefined, undefined, undefined, undefined); + } else { + ret = new PropertiesPromiseArray(castValue).promise(); + } + + if (castValue instanceof Promise) { + ret._propagateFrom(castValue, 2); + } + return ret; + } + + Promise.prototype.props = function () { + return props(this); + }; + + Promise.props = function (promises) { + return props(promises); + }; + }; + + },{"./es5":13,"./util":36}],26:[function(_dereq_,module,exports){ + "use strict"; + function arrayMove(src, srcIndex, dst, dstIndex, len) { + for (var j = 0; j < len; ++j) { + dst[j + dstIndex] = src[j + srcIndex]; + src[j + srcIndex] = void 0; + } + } + + function Queue(capacity) { + this._capacity = capacity; + this._length = 0; + this._front = 0; + } + + Queue.prototype._willBeOverCapacity = function (size) { + return this._capacity < size; + }; + + Queue.prototype._pushOne = function (arg) { + var length = this.length(); + this._checkCapacity(length + 1); + var i = (this._front + length) & (this._capacity - 1); + this[i] = arg; + this._length = length + 1; + }; + + Queue.prototype.push = function (fn, receiver, arg) { + var length = this.length() + 3; + if (this._willBeOverCapacity(length)) { + this._pushOne(fn); + this._pushOne(receiver); + this._pushOne(arg); + return; + } + var j = this._front + length - 3; + this._checkCapacity(length); + var wrapMask = this._capacity - 1; + this[(j + 0) & wrapMask] = fn; + this[(j + 1) & wrapMask] = receiver; + this[(j + 2) & wrapMask] = arg; + this._length = length; + }; + + Queue.prototype.shift = function () { + var front = this._front, + ret = this[front]; + + this[front] = undefined; + this._front = (front + 1) & (this._capacity - 1); + this._length--; + return ret; + }; + + Queue.prototype.length = function () { + return this._length; + }; + + Queue.prototype._checkCapacity = function (size) { + if (this._capacity < size) { + this._resizeTo(this._capacity << 1); + } + }; + + Queue.prototype._resizeTo = function (capacity) { + var oldCapacity = this._capacity; + this._capacity = capacity; + var front = this._front; + var length = this._length; + var moveItemsCount = (front + length) & (oldCapacity - 1); + arrayMove(this, 0, this, oldCapacity, moveItemsCount); + }; + + module.exports = Queue; + + },{}],27:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function( + Promise, INTERNAL, tryConvertToPromise, apiRejection) { + var util = _dereq_("./util"); + + var raceLater = function (promise) { + return promise.then(function(array) { + return race(array, promise); + }); + }; + + function race(promises, parent) { + var maybePromise = tryConvertToPromise(promises); + + if (maybePromise instanceof Promise) { + return raceLater(maybePromise); + } else { + promises = util.asArray(promises); + if (promises === null) + return apiRejection("expecting an array or an iterable object but got " + util.classString(promises)); + } + + var ret = new Promise(INTERNAL); + if (parent !== undefined) { + ret._propagateFrom(parent, 3); + } + var fulfill = ret._fulfill; + var reject = ret._reject; + for (var i = 0, len = promises.length; i < len; ++i) { + var val = promises[i]; + + if (val === undefined && !(i in promises)) { + continue; + } + + Promise.cast(val)._then(fulfill, reject, undefined, ret, null); + } + return ret; + } + + Promise.race = function (promises) { + return race(promises, undefined); + }; + + Promise.prototype.race = function () { + return race(this, undefined); + }; + + }; + + },{"./util":36}],28:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, + PromiseArray, + apiRejection, + tryConvertToPromise, + INTERNAL, + debug) { + var getDomain = Promise._getDomain; + var util = _dereq_("./util"); + var tryCatch = util.tryCatch; + + function ReductionPromiseArray(promises, fn, initialValue, _each) { + this.constructor$(promises); + var domain = getDomain(); + this._fn = domain === null ? fn : util.domainBind(domain, fn); + if (initialValue !== undefined) { + initialValue = Promise.resolve(initialValue); + initialValue._attachCancellationCallback(this); + } + this._initialValue = initialValue; + this._currentCancellable = null; + if(_each === INTERNAL) { + this._eachValues = Array(this._length); + } else if (_each === 0) { + this._eachValues = null; + } else { + this._eachValues = undefined; + } + this._promise._captureStackTrace(); + this._init$(undefined, -5); + } + util.inherits(ReductionPromiseArray, PromiseArray); + + ReductionPromiseArray.prototype._gotAccum = function(accum) { + if (this._eachValues !== undefined && + this._eachValues !== null && + accum !== INTERNAL) { + this._eachValues.push(accum); + } + }; + + ReductionPromiseArray.prototype._eachComplete = function(value) { + if (this._eachValues !== null) { + this._eachValues.push(value); + } + return this._eachValues; + }; + + ReductionPromiseArray.prototype._init = function() {}; + + ReductionPromiseArray.prototype._resolveEmptyArray = function() { + this._resolve(this._eachValues !== undefined ? this._eachValues + : this._initialValue); + }; + + ReductionPromiseArray.prototype.shouldCopyValues = function () { + return false; + }; + + ReductionPromiseArray.prototype._resolve = function(value) { + this._promise._resolveCallback(value); + this._values = null; + }; + + ReductionPromiseArray.prototype._resultCancelled = function(sender) { + if (sender === this._initialValue) return this._cancel(); + if (this._isResolved()) return; + this._resultCancelled$(); + if (this._currentCancellable instanceof Promise) { + this._currentCancellable.cancel(); + } + if (this._initialValue instanceof Promise) { + this._initialValue.cancel(); + } + }; + + ReductionPromiseArray.prototype._iterate = function (values) { + this._values = values; + var value; + var i; + var length = values.length; + if (this._initialValue !== undefined) { + value = this._initialValue; + i = 0; + } else { + value = Promise.resolve(values[0]); + i = 1; + } + + this._currentCancellable = value; + + if (!value.isRejected()) { + for (; i < length; ++i) { + var ctx = { + accum: null, + value: values[i], + index: i, + length: length, + array: this + }; + value = value._then(gotAccum, undefined, undefined, ctx, undefined); + } + } + + if (this._eachValues !== undefined) { + value = value + ._then(this._eachComplete, undefined, undefined, this, undefined); + } + value._then(completed, completed, undefined, value, this); + }; + + Promise.prototype.reduce = function (fn, initialValue) { + return reduce(this, fn, initialValue, null); + }; + + Promise.reduce = function (promises, fn, initialValue, _each) { + return reduce(promises, fn, initialValue, _each); + }; + + function completed(valueOrReason, array) { + if (this.isFulfilled()) { + array._resolve(valueOrReason); + } else { + array._reject(valueOrReason); + } + } + + function reduce(promises, fn, initialValue, _each) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var array = new ReductionPromiseArray(promises, fn, initialValue, _each); + return array.promise(); + } + + function gotAccum(accum) { + this.accum = accum; + this.array._gotAccum(accum); + var value = tryConvertToPromise(this.value, this.array._promise); + if (value instanceof Promise) { + this.array._currentCancellable = value; + return value._then(gotValue, undefined, undefined, this, undefined); + } else { + return gotValue.call(this, value); + } + } + + function gotValue(value) { + var array = this.array; + var promise = array._promise; + var fn = tryCatch(array._fn); + promise._pushContext(); + var ret; + if (array._eachValues !== undefined) { + ret = fn.call(promise._boundValue(), value, this.index, this.length); + } else { + ret = fn.call(promise._boundValue(), + this.accum, value, this.index, this.length); + } + if (ret instanceof Promise) { + array._currentCancellable = ret; + } + var promiseCreated = promise._popContext(); + debug.checkForgottenReturns( + ret, + promiseCreated, + array._eachValues !== undefined ? "Promise.each" : "Promise.reduce", + promise + ); + return ret; + } + }; + + },{"./util":36}],29:[function(_dereq_,module,exports){ + "use strict"; + var util = _dereq_("./util"); + var schedule; + var noAsyncScheduler = function() { + throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + }; + var NativePromise = util.getNativePromise(); + if (util.isNode && typeof MutationObserver === "undefined") { + var GlobalSetImmediate = global.setImmediate; + var ProcessNextTick = process.nextTick; + schedule = util.isRecentNode + ? function(fn) { GlobalSetImmediate.call(global, fn); } + : function(fn) { ProcessNextTick.call(process, fn); }; + } else if (typeof NativePromise === "function" && + typeof NativePromise.resolve === "function") { + var nativePromise = NativePromise.resolve(); + schedule = function(fn) { + nativePromise.then(fn); + }; + } else if ((typeof MutationObserver !== "undefined") && + !(typeof window !== "undefined" && + window.navigator && + (window.navigator.standalone || window.cordova))) { + schedule = (function() { + var div = document.createElement("div"); + var opts = {attributes: true}; + var toggleScheduled = false; + var div2 = document.createElement("div"); + var o2 = new MutationObserver(function() { + div.classList.toggle("foo"); + toggleScheduled = false; + }); + o2.observe(div2, opts); + + var scheduleToggle = function() { + if (toggleScheduled) return; + toggleScheduled = true; + div2.classList.toggle("foo"); + }; + + return function schedule(fn) { + var o = new MutationObserver(function() { + o.disconnect(); + fn(); + }); + o.observe(div, opts); + scheduleToggle(); + }; + })(); + } else if (typeof setImmediate !== "undefined") { + schedule = function (fn) { + setImmediate(fn); + }; + } else if (typeof setTimeout !== "undefined") { + schedule = function (fn) { + setTimeout(fn, 0); + }; + } else { + schedule = noAsyncScheduler; + } + module.exports = schedule; + + },{"./util":36}],30:[function(_dereq_,module,exports){ + "use strict"; + module.exports = + function(Promise, PromiseArray, debug) { + var PromiseInspection = Promise.PromiseInspection; + var util = _dereq_("./util"); + + function SettledPromiseArray(values) { + this.constructor$(values); + } + util.inherits(SettledPromiseArray, PromiseArray); + + SettledPromiseArray.prototype._promiseResolved = function (index, inspection) { + this._values[index] = inspection; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + this._resolve(this._values); + return true; + } + return false; + }; + + SettledPromiseArray.prototype._promiseFulfilled = function (value, index) { + var ret = new PromiseInspection(); + ret._bitField = 33554432; + ret._settledValueField = value; + return this._promiseResolved(index, ret); + }; + SettledPromiseArray.prototype._promiseRejected = function (reason, index) { + var ret = new PromiseInspection(); + ret._bitField = 16777216; + ret._settledValueField = reason; + return this._promiseResolved(index, ret); + }; + + Promise.settle = function (promises) { + debug.deprecated(".settle()", ".reflect()"); + return new SettledPromiseArray(promises).promise(); + }; + + Promise.prototype.settle = function () { + return Promise.settle(this); + }; + }; + + },{"./util":36}],31:[function(_dereq_,module,exports){ + "use strict"; + module.exports = + function(Promise, PromiseArray, apiRejection) { + var util = _dereq_("./util"); + var RangeError = _dereq_("./errors").RangeError; + var AggregateError = _dereq_("./errors").AggregateError; + var isArray = util.isArray; + var CANCELLATION = {}; + + + function SomePromiseArray(values) { + this.constructor$(values); + this._howMany = 0; + this._unwrap = false; + this._initialized = false; + } + util.inherits(SomePromiseArray, PromiseArray); + + SomePromiseArray.prototype._init = function () { + if (!this._initialized) { + return; + } + if (this._howMany === 0) { + this._resolve([]); + return; + } + this._init$(undefined, -5); + var isArrayResolved = isArray(this._values); + if (!this._isResolved() && + isArrayResolved && + this._howMany > this._canPossiblyFulfill()) { + this._reject(this._getRangeError(this.length())); + } + }; + + SomePromiseArray.prototype.init = function () { + this._initialized = true; + this._init(); + }; + + SomePromiseArray.prototype.setUnwrap = function () { + this._unwrap = true; + }; + + SomePromiseArray.prototype.howMany = function () { + return this._howMany; + }; + + SomePromiseArray.prototype.setHowMany = function (count) { + this._howMany = count; + }; + + SomePromiseArray.prototype._promiseFulfilled = function (value) { + this._addFulfilled(value); + if (this._fulfilled() === this.howMany()) { + this._values.length = this.howMany(); + if (this.howMany() === 1 && this._unwrap) { + this._resolve(this._values[0]); + } else { + this._resolve(this._values); + } + return true; + } + return false; + + }; + SomePromiseArray.prototype._promiseRejected = function (reason) { + this._addRejected(reason); + return this._checkOutcome(); + }; + + SomePromiseArray.prototype._promiseCancelled = function () { + if (this._values instanceof Promise || this._values == null) { + return this._cancel(); + } + this._addRejected(CANCELLATION); + return this._checkOutcome(); + }; + + SomePromiseArray.prototype._checkOutcome = function() { + if (this.howMany() > this._canPossiblyFulfill()) { + var e = new AggregateError(); + for (var i = this.length(); i < this._values.length; ++i) { + if (this._values[i] !== CANCELLATION) { + e.push(this._values[i]); + } + } + if (e.length > 0) { + this._reject(e); + } else { + this._cancel(); + } + return true; + } + return false; + }; + + SomePromiseArray.prototype._fulfilled = function () { + return this._totalResolved; + }; + + SomePromiseArray.prototype._rejected = function () { + return this._values.length - this.length(); + }; + + SomePromiseArray.prototype._addRejected = function (reason) { + this._values.push(reason); + }; + + SomePromiseArray.prototype._addFulfilled = function (value) { + this._values[this._totalResolved++] = value; + }; + + SomePromiseArray.prototype._canPossiblyFulfill = function () { + return this.length() - this._rejected(); + }; + + SomePromiseArray.prototype._getRangeError = function (count) { + var message = "Input array must contain at least " + + this._howMany + " items but contains only " + count + " items"; + return new RangeError(message); + }; + + SomePromiseArray.prototype._resolveEmptyArray = function () { + this._reject(this._getRangeError(0)); + }; + + function some(promises, howMany) { + if ((howMany | 0) !== howMany || howMany < 0) { + return apiRejection("expecting a positive integer\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + var ret = new SomePromiseArray(promises); + var promise = ret.promise(); + ret.setHowMany(howMany); + ret.init(); + return promise; + } + + Promise.some = function (promises, howMany) { + return some(promises, howMany); + }; + + Promise.prototype.some = function (howMany) { + return some(this, howMany); + }; + + Promise._SomePromiseArray = SomePromiseArray; + }; + + },{"./errors":12,"./util":36}],32:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise) { + function PromiseInspection(promise) { + if (promise !== undefined) { + promise = promise._target(); + this._bitField = promise._bitField; + this._settledValueField = promise._isFateSealed() + ? promise._settledValue() : undefined; + } + else { + this._bitField = 0; + this._settledValueField = undefined; + } + } + + PromiseInspection.prototype._settledValue = function() { + return this._settledValueField; + }; + + var value = PromiseInspection.prototype.value = function () { + if (!this.isFulfilled()) { + throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + return this._settledValue(); + }; + + var reason = PromiseInspection.prototype.error = + PromiseInspection.prototype.reason = function () { + if (!this.isRejected()) { + throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + return this._settledValue(); + }; + + var isFulfilled = PromiseInspection.prototype.isFulfilled = function() { + return (this._bitField & 33554432) !== 0; + }; + + var isRejected = PromiseInspection.prototype.isRejected = function () { + return (this._bitField & 16777216) !== 0; + }; + + var isPending = PromiseInspection.prototype.isPending = function () { + return (this._bitField & 50397184) === 0; + }; + + var isResolved = PromiseInspection.prototype.isResolved = function () { + return (this._bitField & 50331648) !== 0; + }; + + PromiseInspection.prototype.isCancelled = function() { + return (this._bitField & 8454144) !== 0; + }; + + Promise.prototype.__isCancelled = function() { + return (this._bitField & 65536) === 65536; + }; + + Promise.prototype._isCancelled = function() { + return this._target().__isCancelled(); + }; + + Promise.prototype.isCancelled = function() { + return (this._target()._bitField & 8454144) !== 0; + }; + + Promise.prototype.isPending = function() { + return isPending.call(this._target()); + }; + + Promise.prototype.isRejected = function() { + return isRejected.call(this._target()); + }; + + Promise.prototype.isFulfilled = function() { + return isFulfilled.call(this._target()); + }; + + Promise.prototype.isResolved = function() { + return isResolved.call(this._target()); + }; + + Promise.prototype.value = function() { + return value.call(this._target()); + }; + + Promise.prototype.reason = function() { + var target = this._target(); + target._unsetRejectionIsUnhandled(); + return reason.call(target); + }; + + Promise.prototype._value = function() { + return this._settledValue(); + }; + + Promise.prototype._reason = function() { + this._unsetRejectionIsUnhandled(); + return this._settledValue(); + }; + + Promise.PromiseInspection = PromiseInspection; + }; + + },{}],33:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, INTERNAL) { + var util = _dereq_("./util"); + var errorObj = util.errorObj; + var isObject = util.isObject; + + function tryConvertToPromise(obj, context) { + if (isObject(obj)) { + if (obj instanceof Promise) return obj; + var then = getThen(obj); + if (then === errorObj) { + if (context) context._pushContext(); + var ret = Promise.reject(then.e); + if (context) context._popContext(); + return ret; + } else if (typeof then === "function") { + if (isAnyBluebirdPromise(obj)) { + var ret = new Promise(INTERNAL); + obj._then( + ret._fulfill, + ret._reject, + undefined, + ret, + null + ); + return ret; + } + return doThenable(obj, then, context); + } + } + return obj; + } + + function doGetThen(obj) { + return obj.then; + } + + function getThen(obj) { + try { + return doGetThen(obj); + } catch (e) { + errorObj.e = e; + return errorObj; + } + } + + var hasProp = {}.hasOwnProperty; + function isAnyBluebirdPromise(obj) { + try { + return hasProp.call(obj, "_promise0"); + } catch (e) { + return false; + } + } + + function doThenable(x, then, context) { + var promise = new Promise(INTERNAL); + var ret = promise; + if (context) context._pushContext(); + promise._captureStackTrace(); + if (context) context._popContext(); + var synchronous = true; + var result = util.tryCatch(then).call(x, resolve, reject); + synchronous = false; + + if (promise && result === errorObj) { + promise._rejectCallback(result.e, true, true); + promise = null; + } + + function resolve(value) { + if (!promise) return; + promise._resolveCallback(value); + promise = null; + } + + function reject(reason) { + if (!promise) return; + promise._rejectCallback(reason, synchronous, true); + promise = null; + } + return ret; + } + + return tryConvertToPromise; + }; + + },{"./util":36}],34:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function(Promise, INTERNAL, debug) { + var util = _dereq_("./util"); + var TimeoutError = Promise.TimeoutError; + + function HandleWrapper(handle) { + this.handle = handle; + } + + HandleWrapper.prototype._resultCancelled = function() { + clearTimeout(this.handle); + }; + + var afterValue = function(value) { return delay(+this).thenReturn(value); }; + var delay = Promise.delay = function (ms, value) { + var ret; + var handle; + if (value !== undefined) { + ret = Promise.resolve(value) + ._then(afterValue, null, null, ms, undefined); + if (debug.cancellation() && value instanceof Promise) { + ret._setOnCancel(value); + } + } else { + ret = new Promise(INTERNAL); + handle = setTimeout(function() { ret._fulfill(); }, +ms); + if (debug.cancellation()) { + ret._setOnCancel(new HandleWrapper(handle)); + } + ret._captureStackTrace(); + } + ret._setAsyncGuaranteed(); + return ret; + }; + + Promise.prototype.delay = function (ms) { + return delay(ms, this); + }; + + var afterTimeout = function (promise, message, parent) { + var err; + if (typeof message !== "string") { + if (message instanceof Error) { + err = message; + } else { + err = new TimeoutError("operation timed out"); + } + } else { + err = new TimeoutError(message); + } + util.markAsOriginatingFromRejection(err); + promise._attachExtraTrace(err); + promise._reject(err); + + if (parent != null) { + parent.cancel(); + } + }; + + function successClear(value) { + clearTimeout(this.handle); + return value; + } + + function failureClear(reason) { + clearTimeout(this.handle); + throw reason; + } + + Promise.prototype.timeout = function (ms, message) { + ms = +ms; + var ret, parent; + + var handleWrapper = new HandleWrapper(setTimeout(function timeoutTimeout() { + if (ret.isPending()) { + afterTimeout(ret, message, parent); + } + }, ms)); + + if (debug.cancellation()) { + parent = this.then(); + ret = parent._then(successClear, failureClear, + undefined, handleWrapper, undefined); + ret._setOnCancel(handleWrapper); + } else { + ret = this._then(successClear, failureClear, + undefined, handleWrapper, undefined); + } + + return ret; + }; + + }; + + },{"./util":36}],35:[function(_dereq_,module,exports){ + "use strict"; + module.exports = function (Promise, apiRejection, tryConvertToPromise, + createContext, INTERNAL, debug) { + var util = _dereq_("./util"); + var TypeError = _dereq_("./errors").TypeError; + var inherits = _dereq_("./util").inherits; + var errorObj = util.errorObj; + var tryCatch = util.tryCatch; + var NULL = {}; + + function thrower(e) { + setTimeout(function(){throw e;}, 0); + } + + function castPreservingDisposable(thenable) { + var maybePromise = tryConvertToPromise(thenable); + if (maybePromise !== thenable && + typeof thenable._isDisposable === "function" && + typeof thenable._getDisposer === "function" && + thenable._isDisposable()) { + maybePromise._setDisposable(thenable._getDisposer()); + } + return maybePromise; + } + function dispose(resources, inspection) { + var i = 0; + var len = resources.length; + var ret = new Promise(INTERNAL); + function iterator() { + if (i >= len) return ret._fulfill(); + var maybePromise = castPreservingDisposable(resources[i++]); + if (maybePromise instanceof Promise && + maybePromise._isDisposable()) { + try { + maybePromise = tryConvertToPromise( + maybePromise._getDisposer().tryDispose(inspection), + resources.promise); + } catch (e) { + return thrower(e); + } + if (maybePromise instanceof Promise) { + return maybePromise._then(iterator, thrower, + null, null, null); + } + } + iterator(); + } + iterator(); + return ret; + } + + function Disposer(data, promise, context) { + this._data = data; + this._promise = promise; + this._context = context; + } + + Disposer.prototype.data = function () { + return this._data; + }; + + Disposer.prototype.promise = function () { + return this._promise; + }; + + Disposer.prototype.resource = function () { + if (this.promise().isFulfilled()) { + return this.promise().value(); + } + return NULL; + }; + + Disposer.prototype.tryDispose = function(inspection) { + var resource = this.resource(); + var context = this._context; + if (context !== undefined) context._pushContext(); + var ret = resource !== NULL + ? this.doDispose(resource, inspection) : null; + if (context !== undefined) context._popContext(); + this._promise._unsetDisposable(); + this._data = null; + return ret; + }; + + Disposer.isDisposer = function (d) { + return (d != null && + typeof d.resource === "function" && + typeof d.tryDispose === "function"); + }; + + function FunctionDisposer(fn, promise, context) { + this.constructor$(fn, promise, context); + } + inherits(FunctionDisposer, Disposer); + + FunctionDisposer.prototype.doDispose = function (resource, inspection) { + var fn = this.data(); + return fn.call(resource, resource, inspection); + }; + + function maybeUnwrapDisposer(value) { + if (Disposer.isDisposer(value)) { + this.resources[this.index]._setDisposable(value); + return value.promise(); + } + return value; + } + + function ResourceList(length) { + this.length = length; + this.promise = null; + this[length-1] = null; + } + + ResourceList.prototype._resultCancelled = function() { + var len = this.length; + for (var i = 0; i < len; ++i) { + var item = this[i]; + if (item instanceof Promise) { + item.cancel(); + } + } + }; + + Promise.using = function () { + var len = arguments.length; + if (len < 2) return apiRejection( + "you must pass at least 2 arguments to Promise.using"); + var fn = arguments[len - 1]; + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var input; + var spreadArgs = true; + if (len === 2 && Array.isArray(arguments[0])) { + input = arguments[0]; + len = input.length; + spreadArgs = false; + } else { + input = arguments; + len--; + } + var resources = new ResourceList(len); + for (var i = 0; i < len; ++i) { + var resource = input[i]; + if (Disposer.isDisposer(resource)) { + var disposer = resource; + resource = resource.promise(); + resource._setDisposable(disposer); + } else { + var maybePromise = tryConvertToPromise(resource); + if (maybePromise instanceof Promise) { + resource = + maybePromise._then(maybeUnwrapDisposer, null, null, { + resources: resources, + index: i + }, undefined); + } + } + resources[i] = resource; + } + + var reflectedResources = new Array(resources.length); + for (var i = 0; i < reflectedResources.length; ++i) { + reflectedResources[i] = Promise.resolve(resources[i]).reflect(); + } + + var resultPromise = Promise.all(reflectedResources) + .then(function(inspections) { + for (var i = 0; i < inspections.length; ++i) { + var inspection = inspections[i]; + if (inspection.isRejected()) { + errorObj.e = inspection.error(); + return errorObj; + } else if (!inspection.isFulfilled()) { + resultPromise.cancel(); + return; + } + inspections[i] = inspection.value(); + } + promise._pushContext(); + + fn = tryCatch(fn); + var ret = spreadArgs + ? fn.apply(undefined, inspections) : fn(inspections); + var promiseCreated = promise._popContext(); + debug.checkForgottenReturns( + ret, promiseCreated, "Promise.using", promise); + return ret; + }); + + var promise = resultPromise.lastly(function() { + var inspection = new Promise.PromiseInspection(resultPromise); + return dispose(resources, inspection); + }); + resources.promise = promise; + promise._setOnCancel(resources); + return promise; + }; + + Promise.prototype._setDisposable = function (disposer) { + this._bitField = this._bitField | 131072; + this._disposer = disposer; + }; + + Promise.prototype._isDisposable = function () { + return (this._bitField & 131072) > 0; + }; + + Promise.prototype._getDisposer = function () { + return this._disposer; + }; + + Promise.prototype._unsetDisposable = function () { + this._bitField = this._bitField & (~131072); + this._disposer = undefined; + }; + + Promise.prototype.disposer = function (fn) { + if (typeof fn === "function") { + return new FunctionDisposer(fn, this, createContext()); + } + throw new TypeError(); + }; + + }; + + },{"./errors":12,"./util":36}],36:[function(_dereq_,module,exports){ + "use strict"; + var es5 = _dereq_("./es5"); + var canEvaluate = typeof navigator == "undefined"; + + var errorObj = {e: {}}; + var tryCatchTarget; + var globalObject = typeof self !== "undefined" ? self : + typeof window !== "undefined" ? window : + typeof global !== "undefined" ? global : + this !== undefined ? this : null; + + function tryCatcher() { + try { + var target = tryCatchTarget; + tryCatchTarget = null; + return target.apply(this, arguments); + } catch (e) { + errorObj.e = e; + return errorObj; + } + } + function tryCatch(fn) { + tryCatchTarget = fn; + return tryCatcher; + } + + var inherits = function(Child, Parent) { + var hasProp = {}.hasOwnProperty; + + function T() { + this.constructor = Child; + this.constructor$ = Parent; + for (var propertyName in Parent.prototype) { + if (hasProp.call(Parent.prototype, propertyName) && + propertyName.charAt(propertyName.length-1) !== "$" + ) { + this[propertyName + "$"] = Parent.prototype[propertyName]; + } + } + } + T.prototype = Parent.prototype; + Child.prototype = new T(); + return Child.prototype; + }; + + + function isPrimitive(val) { + return val == null || val === true || val === false || + typeof val === "string" || typeof val === "number"; + + } + + function isObject(value) { + return typeof value === "function" || + typeof value === "object" && value !== null; + } + + function maybeWrapAsError(maybeError) { + if (!isPrimitive(maybeError)) return maybeError; + + return new Error(safeToString(maybeError)); + } + + function withAppended(target, appendee) { + var len = target.length; + var ret = new Array(len + 1); + var i; + for (i = 0; i < len; ++i) { + ret[i] = target[i]; + } + ret[i] = appendee; + return ret; + } + + function getDataPropertyOrDefault(obj, key, defaultValue) { + if (es5.isES5) { + var desc = Object.getOwnPropertyDescriptor(obj, key); + + if (desc != null) { + return desc.get == null && desc.set == null + ? desc.value + : defaultValue; + } + } else { + return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined; + } + } + + function notEnumerableProp(obj, name, value) { + if (isPrimitive(obj)) return obj; + var descriptor = { + value: value, + configurable: true, + enumerable: false, + writable: true + }; + es5.defineProperty(obj, name, descriptor); + return obj; + } + + function thrower(r) { + throw r; + } + + var inheritedDataKeys = (function() { + var excludedPrototypes = [ + Array.prototype, + Object.prototype, + Function.prototype + ]; + + var isExcludedProto = function(val) { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (excludedPrototypes[i] === val) { + return true; + } + } + return false; + }; + + if (es5.isES5) { + var getKeys = Object.getOwnPropertyNames; + return function(obj) { + var ret = []; + var visitedKeys = Object.create(null); + while (obj != null && !isExcludedProto(obj)) { + var keys; + try { + keys = getKeys(obj); + } catch (e) { + return ret; + } + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (visitedKeys[key]) continue; + visitedKeys[key] = true; + var desc = Object.getOwnPropertyDescriptor(obj, key); + if (desc != null && desc.get == null && desc.set == null) { + ret.push(key); + } + } + obj = es5.getPrototypeOf(obj); + } + return ret; + }; + } else { + var hasProp = {}.hasOwnProperty; + return function(obj) { + if (isExcludedProto(obj)) return []; + var ret = []; + + /*jshint forin:false */ + enumeration: for (var key in obj) { + if (hasProp.call(obj, key)) { + ret.push(key); + } else { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (hasProp.call(excludedPrototypes[i], key)) { + continue enumeration; + } + } + ret.push(key); + } + } + return ret; + }; + } + + })(); + + var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/; + function isClass(fn) { + try { + if (typeof fn === "function") { + var keys = es5.names(fn.prototype); + + var hasMethods = es5.isES5 && keys.length > 1; + var hasMethodsOtherThanConstructor = keys.length > 0 && + !(keys.length === 1 && keys[0] === "constructor"); + var hasThisAssignmentAndStaticMethods = + thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0; + + if (hasMethods || hasMethodsOtherThanConstructor || + hasThisAssignmentAndStaticMethods) { + return true; + } + } + return false; + } catch (e) { + return false; + } + } + + function toFastProperties(obj) { + /*jshint -W027,-W055,-W031*/ + function FakeConstructor() {} + FakeConstructor.prototype = obj; + var l = 8; + while (l--) new FakeConstructor(); + return obj; + eval(obj); + } + + var rident = /^[a-z$_][a-z$_0-9]*$/i; + function isIdentifier(str) { + return rident.test(str); + } + + function filledRange(count, prefix, suffix) { + var ret = new Array(count); + for(var i = 0; i < count; ++i) { + ret[i] = prefix + i + suffix; + } + return ret; + } + + function safeToString(obj) { + try { + return obj + ""; + } catch (e) { + return "[no string representation]"; + } + } + + function isError(obj) { + return obj !== null && + typeof obj === "object" && + typeof obj.message === "string" && + typeof obj.name === "string"; + } + + function markAsOriginatingFromRejection(e) { + try { + notEnumerableProp(e, "isOperational", true); + } + catch(ignore) {} + } + + function originatesFromRejection(e) { + if (e == null) return false; + return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) || + e["isOperational"] === true); + } + + function canAttachTrace(obj) { + return isError(obj) && es5.propertyIsWritable(obj, "stack"); + } + + var ensureErrorObject = (function() { + if (!("stack" in new Error())) { + return function(value) { + if (canAttachTrace(value)) return value; + try {throw new Error(safeToString(value));} + catch(err) {return err;} + }; + } else { + return function(value) { + if (canAttachTrace(value)) return value; + return new Error(safeToString(value)); + }; + } + })(); + + function classString(obj) { + return {}.toString.call(obj); + } + + function copyDescriptors(from, to, filter) { + var keys = es5.names(from); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (filter(key)) { + try { + es5.defineProperty(to, key, es5.getDescriptor(from, key)); + } catch (ignore) {} + } + } + } + + var asArray = function(v) { + if (es5.isArray(v)) { + return v; + } + return null; + }; + + if (typeof Symbol !== "undefined" && Symbol.iterator) { + var ArrayFrom = typeof Array.from === "function" ? function(v) { + return Array.from(v); + } : function(v) { + var ret = []; + var it = v[Symbol.iterator](); + var itResult; + while (!((itResult = it.next()).done)) { + ret.push(itResult.value); + } + return ret; + }; + + asArray = function(v) { + if (es5.isArray(v)) { + return v; + } else if (v != null && typeof v[Symbol.iterator] === "function") { + return ArrayFrom(v); + } + return null; + }; + } + + var isNode = typeof process !== "undefined" && + classString(process).toLowerCase() === "[object process]"; + + var hasEnvVariables = typeof process !== "undefined" && + typeof process.env !== "undefined"; + + function env(key) { + return hasEnvVariables ? process.env[key] : undefined; + } + + function getNativePromise() { + if (typeof Promise === "function") { + try { + var promise = new Promise(function(){}); + if ({}.toString.call(promise) === "[object Promise]") { + return Promise; + } + } catch (e) {} + } + } + + function domainBind(self, cb) { + return self.bind(cb); + } + + var ret = { + isClass: isClass, + isIdentifier: isIdentifier, + inheritedDataKeys: inheritedDataKeys, + getDataPropertyOrDefault: getDataPropertyOrDefault, + thrower: thrower, + isArray: es5.isArray, + asArray: asArray, + notEnumerableProp: notEnumerableProp, + isPrimitive: isPrimitive, + isObject: isObject, + isError: isError, + canEvaluate: canEvaluate, + errorObj: errorObj, + tryCatch: tryCatch, + inherits: inherits, + withAppended: withAppended, + maybeWrapAsError: maybeWrapAsError, + toFastProperties: toFastProperties, + filledRange: filledRange, + toString: safeToString, + canAttachTrace: canAttachTrace, + ensureErrorObject: ensureErrorObject, + originatesFromRejection: originatesFromRejection, + markAsOriginatingFromRejection: markAsOriginatingFromRejection, + classString: classString, + copyDescriptors: copyDescriptors, + hasDevTools: typeof chrome !== "undefined" && chrome && + typeof chrome.loadTimes === "function", + isNode: isNode, + hasEnvVariables: hasEnvVariables, + env: env, + global: globalObject, + getNativePromise: getNativePromise, + domainBind: domainBind + }; + ret.isRecentNode = ret.isNode && (function() { + var version = process.versions.node.split(".").map(Number); + return (version[0] === 0 && version[1] > 10) || (version[0] > 0); + })(); + + if (ret.isNode) ret.toFastProperties(process); + + try {throw new Error(); } catch (e) {ret.lastLineError = e;} + module.exports = ret; + + },{"./es5":13}]},{},[4])(4) + }); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; } + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(45), __webpack_require__(11), __webpack_require__(137).setImmediate)) + + /***/ }), + /* 14 */ + /***/ (function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(1), + root = __webpack_require__(0); + + /* Built-in method references that are verified to be native. */ + var Map = getNative(root, 'Map'); + + module.exports = Map; + + + /***/ }), + /* 15 */ + /***/ (function(module, exports, __webpack_require__) { + + var root = __webpack_require__(0); + + /** Built-in value references. */ + var Symbol = root.Symbol; + + module.exports = Symbol; + + + /***/ }), + /* 16 */ + /***/ (function(module, exports, __webpack_require__) { + + var Uint8Array = __webpack_require__(55); + + /** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; + } + + module.exports = cloneArrayBuffer; + + + /***/ }), + /* 17 */ + /***/ (function(module, exports, __webpack_require__) { + + var arrayFilter = __webpack_require__(60), + stubArray = __webpack_require__(44); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Built-in value references. */ + var propertyIsEnumerable = objectProto.propertyIsEnumerable; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeGetSymbols = Object.getOwnPropertySymbols; + + /** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); + }; + + module.exports = getSymbols; + + + /***/ }), + /* 18 */ + /***/ (function(module, exports) { + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ + function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; + } + + module.exports = isPrototype; + + + /***/ }), + /* 19 */ + /***/ (function(module, exports) { + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + module.exports = isArray; + + + /***/ }), + /* 20 */ + /***/ (function(module, exports, __webpack_require__) { + + var isFunction = __webpack_require__(42), + isLength = __webpack_require__(43); + + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + + module.exports = isArrayLike; + + + /***/ }), + /* 21 */ + /***/ (function(module, exports) { + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } + + module.exports = isObjectLike; + + + /***/ }), + /* 22 */ + /***/ (function(module, exports, __webpack_require__) { + + var arrayLikeKeys = __webpack_require__(25), + baseKeys = __webpack_require__(68), + isArrayLike = __webpack_require__(20); + + /** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ + function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); + } + + module.exports = keys; + + + /***/ }), + /* 23 */ + /***/ (function(module, exports, __webpack_require__) { + + var arrayLikeKeys = __webpack_require__(25), + baseKeysIn = __webpack_require__(69), + isArrayLike = __webpack_require__(20); + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); + } + + module.exports = keysIn; + + + /***/ }), + /* 24 */ + /***/ (function(module, exports) { + + /** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ + function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); + } + + module.exports = apply; + + + /***/ }), + /* 25 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseTimes = __webpack_require__(71), + isArguments = __webpack_require__(129), + isArray = __webpack_require__(19), + isBuffer = __webpack_require__(41), + isIndex = __webpack_require__(36), + isTypedArray = __webpack_require__(130); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ + function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; + } + + module.exports = arrayLikeKeys; + + + /***/ }), + /* 26 */ + /***/ (function(module, exports) { + + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + + module.exports = arrayPush; + + + /***/ }), + /* 27 */ + /***/ (function(module, exports) { + + /** + * A specialized version of `_.reduce` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the first element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduce(array, iteratee, accumulator, initAccum) { + var index = -1, + length = array == null ? 0 : array.length; + + if (initAccum && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + + module.exports = arrayReduce; + + + /***/ }), + /* 28 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseAssignValue = __webpack_require__(29), + eq = __webpack_require__(9); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + module.exports = assignValue; + + + /***/ }), + /* 29 */ + /***/ (function(module, exports, __webpack_require__) { + + var defineProperty = __webpack_require__(32); + + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } + } + + module.exports = baseAssignValue; + + + /***/ }), + /* 30 */ + /***/ (function(module, exports, __webpack_require__) { + + var arrayPush = __webpack_require__(26), + isArray = __webpack_require__(19); + + /** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ + function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); + } + + module.exports = baseGetAllKeys; + + + /***/ }), + /* 31 */ + /***/ (function(module, exports, __webpack_require__) { + + var identity = __webpack_require__(40), + overRest = __webpack_require__(117), + setToString = __webpack_require__(119); + + /** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); + } + + module.exports = baseRest; + + + /***/ }), + /* 32 */ + /***/ (function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(1); + + var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} + }()); + + module.exports = defineProperty; + + + /***/ }), + /* 33 */ + /***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + module.exports = freeGlobal; + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(11))) + + /***/ }), + /* 34 */ + /***/ (function(module, exports, __webpack_require__) { + + var overArg = __webpack_require__(37); + + /** Built-in value references. */ + var getPrototype = overArg(Object.getPrototypeOf, Object); + + module.exports = getPrototype; + + + /***/ }), + /* 35 */ + /***/ (function(module, exports, __webpack_require__) { + + var arrayPush = __webpack_require__(26), + getPrototype = __webpack_require__(34), + getSymbols = __webpack_require__(17), + stubArray = __webpack_require__(44); + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeGetSymbols = Object.getOwnPropertySymbols; + + /** + * Creates an array of the own and inherited enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; + }; + + module.exports = getSymbolsIn; + + + /***/ }), + /* 36 */ + /***/ (function(module, exports) { + + /** Used as references for various `Number` constants. */ + var MAX_SAFE_INTEGER = 9007199254740991; + + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && + (typeof value == 'number' || reIsUint.test(value)) && + (value > -1 && value % 1 == 0 && value < length); + } + + module.exports = isIndex; + + + /***/ }), + /* 37 */ + /***/ (function(module, exports) { + + /** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + + module.exports = overArg; + + + /***/ }), + /* 38 */ + /***/ (function(module, exports) { + + /** Used for built-in method references. */ + var funcProto = Function.prototype; + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } + + module.exports = toSource; + + + /***/ }), + /* 39 */ + /***/ (function(module, exports, __webpack_require__) { + + var apply = __webpack_require__(24), + assignInWith = __webpack_require__(126), + baseRest = __webpack_require__(31), + customDefaultsAssignIn = __webpack_require__(85); + + /** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var defaults = baseRest(function(args) { + args.push(undefined, customDefaultsAssignIn); + return apply(assignInWith, undefined, args); + }); + + module.exports = defaults; + + + /***/ }), + /* 40 */ + /***/ (function(module, exports) { + + /** + * This method returns the first argument it receives. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {*} value Any value. + * @returns {*} Returns `value`. + * @example + * + * var object = { 'a': 1 }; + * + * console.log(_.identity(object) === object); + * // => true + */ + function identity(value) { + return value; + } + + module.exports = identity; + + + /***/ }), + /* 41 */ + /***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(0), + stubFalse = __webpack_require__(131); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Built-in value references. */ + var Buffer = moduleExports ? root.Buffer : undefined; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined; + + /** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ + var isBuffer = nativeIsBuffer || stubFalse; + + module.exports = isBuffer; + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12)(module))) + + /***/ }), + /* 42 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseGetTag = __webpack_require__(6), + isObject = __webpack_require__(2); + + /** `Object#toString` result references. */ + var asyncTag = '[object AsyncFunction]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + proxyTag = '[object Proxy]'; + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; + } + + module.exports = isFunction; + + + /***/ }), + /* 43 */ + /***/ (function(module, exports) { + + /** Used as references for various `Number` constants. */ + var MAX_SAFE_INTEGER = 9007199254740991; + + /** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ + function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + + module.exports = isLength; + + + /***/ }), + /* 44 */ + /***/ (function(module, exports) { + + /** + * This method returns a new empty array. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {Array} Returns the new empty array. + * @example + * + * var arrays = _.times(2, _.stubArray); + * + * console.log(arrays); + * // => [[], []] + * + * console.log(arrays[0] === arrays[1]); + * // => false + */ + function stubArray() { + return []; + } + + module.exports = stubArray; + + + /***/ }), + /* 45 */ + /***/ (function(module, exports) { + +// shim for using process in browser + var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + + var cachedSetTimeout; + var cachedClearTimeout; + + function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); + } + function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); + } + (function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } + } ()) + function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + + } + function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + + } + var queue = []; + var draining = false; + var currentQueue; + var queueIndex = -1; + + function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } + } + + function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); + } + + process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } + }; + +// v8 likes predictible objects + function Item(fun, array) { + this.fun = fun; + this.array = array; + } + Item.prototype.run = function () { + this.fun.apply(null, this.array); + }; + process.title = 'browser'; + process.browser = true; + process.env = {}; + process.argv = []; + process.version = ''; // empty string to avoid regexp issues + process.versions = {}; + + function noop() {} + + process.on = noop; + process.addListener = noop; + process.once = noop; + process.off = noop; + process.removeListener = noop; + process.removeAllListeners = noop; + process.emit = noop; + + process.binding = function (name) { + throw new Error('process.binding is not supported'); + }; + + process.cwd = function () { return '/' }; + process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); + }; + process.umask = function() { return 0; }; + + + /***/ }), + /* 46 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + Object.defineProperty(exports, "__esModule", { value: true }); + var util_1 = __webpack_require__(10); + var Swatch = (function () { + function Swatch(rgb, population) { + this._rgb = rgb; + this._population = population; + } + Swatch.prototype.getRgb = function () { return this._rgb; }; + Swatch.prototype.getHsl = function () { + if (!this._hsl) { + var _a = this._rgb, r = _a[0], g = _a[1], b = _a[2]; + this._hsl = util_1.rgbToHsl(r, g, b); + } + return this._hsl; + }; + Swatch.prototype.getPopulation = function () { return this._population; }; + Swatch.prototype.getHex = function () { + if (!this._hex) { + var _a = this._rgb, r = _a[0], g = _a[1], b = _a[2]; + this._hex = util_1.rgbToHex(r, g, b); + } + return this._hex; + }; + Swatch.prototype.getYiq = function () { + if (!this._yiq) { + var rgb = this._rgb; + this._yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; + } + return this._yiq; + }; + Swatch.prototype.getTitleTextColor = function () { + return this.getYiq() < 200 ? '#fff' : '#000'; + }; + Swatch.prototype.getBodyTextColor = function () { + return this.getYiq() < 150 ? '#fff' : '#000'; + }; + return Swatch; + }()); + exports.Swatch = Swatch; + + + /***/ }), + /* 47 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + Object.defineProperty(exports, "__esModule", { value: true }); + var Bluebird = __webpack_require__(13); + var defaults = __webpack_require__(39); + var builder_1 = __webpack_require__(138); + var Util = __webpack_require__(10); + var Quantizer = __webpack_require__(145); + var Generator = __webpack_require__(142); + var Filter = __webpack_require__(140); + var Vibrant = (function () { + function Vibrant(_src, opts) { + this._src = _src; + this.opts = defaults({}, opts, Vibrant.DefaultOpts); + } + Vibrant.from = function (src) { + return new builder_1.default(src); + }; + Vibrant.prototype._process = function (image) { + var _this = this; + var opts = this.opts; + var quantizer = opts.quantizer, generator = opts.generator; + image.scaleDown(opts); + var imageData = image.getImageData(); + return Bluebird.resolve(quantizer(imageData.data, opts)) + .then(function (colors) { return Bluebird.resolve(generator(colors)); }) + .tap(function (palette) { return _this._palette = palette; }) + .finally(function () { return image.remove(); }); + }; + Vibrant.prototype.palette = function () { + return this.swatches(); + }; + Vibrant.prototype.swatches = function () { + return this._palette; + }; + Vibrant.prototype.getPalette = function (cb) { + var _this = this; + var image = new this.opts.ImageClass(); + return image.load(this._src) + .then(function (image) { return _this._process(image); }) + .asCallback(cb); + }; + return Vibrant; + }()); + Vibrant.Builder = builder_1.default; + Vibrant.Quantizer = Quantizer; + Vibrant.Generator = Generator; + Vibrant.Filter = Filter; + Vibrant.Util = Util; + Vibrant.DefaultOpts = { + colorCount: 64, + quality: 5, + generator: Generator.Default, + ImageClass: null, + quantizer: Quantizer.MMCQ, + filters: [Filter.Default] + }; + exports.default = Vibrant; + + + /***/ }), + /* 48 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var vibrant_1 = __webpack_require__(47); + var browser_1 = __webpack_require__(144); + vibrant_1.default.DefaultOpts.ImageClass = browser_1.default; + module.exports = vibrant_1.default; + + + /***/ }), + /* 49 */ + /***/ (function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(1), + root = __webpack_require__(0); + + /* Built-in method references that are verified to be native. */ + var DataView = getNative(root, 'DataView'); + + module.exports = DataView; + + + /***/ }), + /* 50 */ + /***/ (function(module, exports, __webpack_require__) { + + var hashClear = __webpack_require__(91), + hashDelete = __webpack_require__(92), + hashGet = __webpack_require__(93), + hashHas = __webpack_require__(94), + hashSet = __webpack_require__(95); + + /** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + +// Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + + module.exports = Hash; + + + /***/ }), + /* 51 */ + /***/ (function(module, exports, __webpack_require__) { + + var mapCacheClear = __webpack_require__(107), + mapCacheDelete = __webpack_require__(108), + mapCacheGet = __webpack_require__(109), + mapCacheHas = __webpack_require__(110), + mapCacheSet = __webpack_require__(111); + + /** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + +// Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + + module.exports = MapCache; + + + /***/ }), + /* 52 */ + /***/ (function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(1), + root = __webpack_require__(0); + + /* Built-in method references that are verified to be native. */ + var Promise = getNative(root, 'Promise'); + + module.exports = Promise; + + + /***/ }), + /* 53 */ + /***/ (function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(1), + root = __webpack_require__(0); + + /* Built-in method references that are verified to be native. */ + var Set = getNative(root, 'Set'); + + module.exports = Set; + + + /***/ }), + /* 54 */ + /***/ (function(module, exports, __webpack_require__) { + + var ListCache = __webpack_require__(4), + stackClear = __webpack_require__(121), + stackDelete = __webpack_require__(122), + stackGet = __webpack_require__(123), + stackHas = __webpack_require__(124), + stackSet = __webpack_require__(125); + + /** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; + } + +// Add methods to `Stack`. + Stack.prototype.clear = stackClear; + Stack.prototype['delete'] = stackDelete; + Stack.prototype.get = stackGet; + Stack.prototype.has = stackHas; + Stack.prototype.set = stackSet; + + module.exports = Stack; + + + /***/ }), + /* 55 */ + /***/ (function(module, exports, __webpack_require__) { + + var root = __webpack_require__(0); + + /** Built-in value references. */ + var Uint8Array = root.Uint8Array; + + module.exports = Uint8Array; + + + /***/ }), + /* 56 */ + /***/ (function(module, exports, __webpack_require__) { + + var getNative = __webpack_require__(1), + root = __webpack_require__(0); + + /* Built-in method references that are verified to be native. */ + var WeakMap = getNative(root, 'WeakMap'); + + module.exports = WeakMap; + + + /***/ }), + /* 57 */ + /***/ (function(module, exports) { + + /** + * Adds the key-value `pair` to `map`. + * + * @private + * @param {Object} map The map to modify. + * @param {Array} pair The key-value pair to add. + * @returns {Object} Returns `map`. + */ + function addMapEntry(map, pair) { + // Don't return `map.set` because it's not chainable in IE 11. + map.set(pair[0], pair[1]); + return map; + } + + module.exports = addMapEntry; + + + /***/ }), + /* 58 */ + /***/ (function(module, exports) { + + /** + * Adds `value` to `set`. + * + * @private + * @param {Object} set The set to modify. + * @param {*} value The value to add. + * @returns {Object} Returns `set`. + */ + function addSetEntry(set, value) { + // Don't return `set.add` because it's not chainable in IE 11. + set.add(value); + return set; + } + + module.exports = addSetEntry; + + + /***/ }), + /* 59 */ + /***/ (function(module, exports) { + + /** + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEach(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + + module.exports = arrayEach; + + + /***/ }), + /* 60 */ + /***/ (function(module, exports) { + + /** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; + } + + module.exports = arrayFilter; + + + /***/ }), + /* 61 */ + /***/ (function(module, exports, __webpack_require__) { + + var copyObject = __webpack_require__(3), + keys = __webpack_require__(22); + + /** + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssign(object, source) { + return object && copyObject(source, keys(source), object); + } + + module.exports = baseAssign; + + + /***/ }), + /* 62 */ + /***/ (function(module, exports, __webpack_require__) { + + var copyObject = __webpack_require__(3), + keysIn = __webpack_require__(23); + + /** + * The base implementation of `_.assignIn` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssignIn(object, source) { + return object && copyObject(source, keysIn(source), object); + } + + module.exports = baseAssignIn; + + + /***/ }), + /* 63 */ + /***/ (function(module, exports, __webpack_require__) { + + var Stack = __webpack_require__(54), + arrayEach = __webpack_require__(59), + assignValue = __webpack_require__(28), + baseAssign = __webpack_require__(61), + baseAssignIn = __webpack_require__(62), + cloneBuffer = __webpack_require__(73), + copyArray = __webpack_require__(80), + copySymbols = __webpack_require__(81), + copySymbolsIn = __webpack_require__(82), + getAllKeys = __webpack_require__(86), + getAllKeysIn = __webpack_require__(87), + getTag = __webpack_require__(89), + initCloneArray = __webpack_require__(96), + initCloneByTag = __webpack_require__(97), + initCloneObject = __webpack_require__(98), + isArray = __webpack_require__(19), + isBuffer = __webpack_require__(41), + isObject = __webpack_require__(2), + keys = __webpack_require__(22); + + /** Used to compose bitmasks for cloning. */ + var CLONE_DEEP_FLAG = 1, + CLONE_FLAT_FLAG = 2, + CLONE_SYMBOLS_FLAG = 4; + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]', + weakMapTag = '[object WeakMap]'; + + var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + + /** Used to identify `toStringTag` values supported by `_.clone`. */ + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = + cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = + cloneableTags[boolTag] = cloneableTags[dateTag] = + cloneableTags[float32Tag] = cloneableTags[float64Tag] = + cloneableTags[int8Tag] = cloneableTags[int16Tag] = + cloneableTags[int32Tag] = cloneableTags[mapTag] = + cloneableTags[numberTag] = cloneableTags[objectTag] = + cloneableTags[regexpTag] = cloneableTags[setTag] = + cloneableTags[stringTag] = cloneableTags[symbolTag] = + cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = + cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = + cloneableTags[weakMapTag] = false; + + /** + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} bitmask The bitmask flags. + * 1 - Deep clone + * 2 - Flatten inherited properties + * 4 - Clone symbols + * @param {Function} [customizer] The function to customize cloning. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. + * @returns {*} Returns the cloned value. + */ + function baseClone(value, bitmask, customizer, key, object, stack) { + var result, + isDeep = bitmask & CLONE_DEEP_FLAG, + isFlat = bitmask & CLONE_FLAT_FLAG, + isFull = bitmask & CLONE_SYMBOLS_FLAG; + + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return copyArray(value, result); + } + } else { + var tag = getTag(value), + isFunc = tag == funcTag || tag == genTag; + + if (isBuffer(value)) { + return cloneBuffer(value, isDeep); + } + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + result = (isFlat || isFunc) ? {} : initCloneObject(value); + if (!isDeep) { + return isFlat + ? copySymbolsIn(value, baseAssignIn(result, value)) + : copySymbols(value, baseAssign(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag(value, tag, baseClone, isDeep); + } + } + // Check for circular references and return its corresponding clone. + stack || (stack = new Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + + var keysFunc = isFull + ? (isFlat ? getAllKeysIn : getAllKeys) + : (isFlat ? keysIn : keys); + + var props = isArr ? undefined : keysFunc(value); + arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + return result; + } + + module.exports = baseClone; + + + /***/ }), + /* 64 */ + /***/ (function(module, exports, __webpack_require__) { + + var isObject = __webpack_require__(2); + + /** Built-in value references. */ + var objectCreate = Object.create; + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; + }()); + + module.exports = baseCreate; + + + /***/ }), + /* 65 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseGetTag = __webpack_require__(6), + isObjectLike = __webpack_require__(21); + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]'; + + /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; + } + + module.exports = baseIsArguments; + + + /***/ }), + /* 66 */ + /***/ (function(module, exports, __webpack_require__) { + + var isFunction = __webpack_require__(42), + isMasked = __webpack_require__(101), + isObject = __webpack_require__(2), + toSource = __webpack_require__(38); + + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + + /** Used to detect host constructors (Safari). */ + var reIsHostCtor = /^\[object .+?Constructor\]$/; + + /** Used for built-in method references. */ + var funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to detect if a method is native. */ + var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); + + /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + + module.exports = baseIsNative; + + + /***/ }), + /* 67 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseGetTag = __webpack_require__(6), + isLength = __webpack_require__(43), + isObjectLike = __webpack_require__(21); + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + weakMapTag = '[object WeakMap]'; + + var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + + /** Used to identify `toStringTag` values of typed arrays. */ + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = + typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = + typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = + typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = + typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = + typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = + typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = + typedArrayTags[errorTag] = typedArrayTags[funcTag] = + typedArrayTags[mapTag] = typedArrayTags[numberTag] = + typedArrayTags[objectTag] = typedArrayTags[regexpTag] = + typedArrayTags[setTag] = typedArrayTags[stringTag] = + typedArrayTags[weakMapTag] = false; + + /** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ + function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; + } + + module.exports = baseIsTypedArray; + + + /***/ }), + /* 68 */ + /***/ (function(module, exports, __webpack_require__) { + + var isPrototype = __webpack_require__(18), + nativeKeys = __webpack_require__(113); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; + } + + module.exports = baseKeys; + + + /***/ }), + /* 69 */ + /***/ (function(module, exports, __webpack_require__) { + + var isObject = __webpack_require__(2), + isPrototype = __webpack_require__(18), + nativeKeysIn = __webpack_require__(114); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + + module.exports = baseKeysIn; + + + /***/ }), + /* 70 */ + /***/ (function(module, exports, __webpack_require__) { + + var constant = __webpack_require__(128), + defineProperty = __webpack_require__(32), + identity = __webpack_require__(40); + + /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + + module.exports = baseSetToString; + + + /***/ }), + /* 71 */ + /***/ (function(module, exports) { + + /** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ + function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; + } + + module.exports = baseTimes; + + + /***/ }), + /* 72 */ + /***/ (function(module, exports) { + + /** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ + function baseUnary(func) { + return function(value) { + return func(value); + }; + } + + module.exports = baseUnary; + + + /***/ }), + /* 73 */ + /***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(0); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Built-in value references. */ + var Buffer = moduleExports ? root.Buffer : undefined, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined; + + /** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ + function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; + } + + module.exports = cloneBuffer; + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12)(module))) + + /***/ }), + /* 74 */ + /***/ (function(module, exports, __webpack_require__) { + + var cloneArrayBuffer = __webpack_require__(16); + + /** + * Creates a clone of `dataView`. + * + * @private + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. + */ + function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); + } + + module.exports = cloneDataView; + + + /***/ }), + /* 75 */ + /***/ (function(module, exports, __webpack_require__) { + + var addMapEntry = __webpack_require__(57), + arrayReduce = __webpack_require__(27), + mapToArray = __webpack_require__(112); + + /** Used to compose bitmasks for cloning. */ + var CLONE_DEEP_FLAG = 1; + + /** + * Creates a clone of `map`. + * + * @private + * @param {Object} map The map to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned map. + */ + function cloneMap(map, isDeep, cloneFunc) { + var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map); + return arrayReduce(array, addMapEntry, new map.constructor); + } + + module.exports = cloneMap; + + + /***/ }), + /* 76 */ + /***/ (function(module, exports) { + + /** Used to match `RegExp` flags from their coerced string values. */ + var reFlags = /\w*$/; + + /** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ + function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; + } + + module.exports = cloneRegExp; + + + /***/ }), + /* 77 */ + /***/ (function(module, exports, __webpack_require__) { + + var addSetEntry = __webpack_require__(58), + arrayReduce = __webpack_require__(27), + setToArray = __webpack_require__(118); + + /** Used to compose bitmasks for cloning. */ + var CLONE_DEEP_FLAG = 1; + + /** + * Creates a clone of `set`. + * + * @private + * @param {Object} set The set to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned set. + */ + function cloneSet(set, isDeep, cloneFunc) { + var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set); + return arrayReduce(array, addSetEntry, new set.constructor); + } + + module.exports = cloneSet; + + + /***/ }), + /* 78 */ + /***/ (function(module, exports, __webpack_require__) { + + var Symbol = __webpack_require__(15); + + /** Used to convert symbols to primitives and strings. */ + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined; + + /** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ + function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; + } + + module.exports = cloneSymbol; + + + /***/ }), + /* 79 */ + /***/ (function(module, exports, __webpack_require__) { + + var cloneArrayBuffer = __webpack_require__(16); + + /** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ + function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); + } + + module.exports = cloneTypedArray; + + + /***/ }), + /* 80 */ + /***/ (function(module, exports) { + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + + module.exports = copyArray; + + + /***/ }), + /* 81 */ + /***/ (function(module, exports, __webpack_require__) { + + var copyObject = __webpack_require__(3), + getSymbols = __webpack_require__(17); + + /** + * Copies own symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); + } + + module.exports = copySymbols; + + + /***/ }), + /* 82 */ + /***/ (function(module, exports, __webpack_require__) { + + var copyObject = __webpack_require__(3), + getSymbolsIn = __webpack_require__(35); + + /** + * Copies own and inherited symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbolsIn(source, object) { + return copyObject(source, getSymbolsIn(source), object); + } + + module.exports = copySymbolsIn; + + + /***/ }), + /* 83 */ + /***/ (function(module, exports, __webpack_require__) { + + var root = __webpack_require__(0); + + /** Used to detect overreaching core-js shims. */ + var coreJsData = root['__core-js_shared__']; + + module.exports = coreJsData; + + + /***/ }), + /* 84 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseRest = __webpack_require__(31), + isIterateeCall = __webpack_require__(99); + + /** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + + module.exports = createAssigner; + + + /***/ }), + /* 85 */ + /***/ (function(module, exports, __webpack_require__) { + + var eq = __webpack_require__(9); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Used by `_.defaults` to customize its `_.assignIn` use to assign properties + * of source objects to the destination object for all destination properties + * that resolve to `undefined`. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to assign. + * @param {Object} object The parent object of `objValue`. + * @returns {*} Returns the value to assign. + */ + function customDefaultsAssignIn(objValue, srcValue, key, object) { + if (objValue === undefined || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { + return srcValue; + } + return objValue; + } + + module.exports = customDefaultsAssignIn; + + + /***/ }), + /* 86 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseGetAllKeys = __webpack_require__(30), + getSymbols = __webpack_require__(17), + keys = __webpack_require__(22); + + /** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); + } + + module.exports = getAllKeys; + + + /***/ }), + /* 87 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseGetAllKeys = __webpack_require__(30), + getSymbolsIn = __webpack_require__(35), + keysIn = __webpack_require__(23); + + /** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); + } + + module.exports = getAllKeysIn; + + + /***/ }), + /* 88 */ + /***/ (function(module, exports, __webpack_require__) { + + var Symbol = __webpack_require__(15); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var nativeObjectToString = objectProto.toString; + + /** Built-in value references. */ + var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + + /** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ + function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; + } + + module.exports = getRawTag; + + + /***/ }), + /* 89 */ + /***/ (function(module, exports, __webpack_require__) { + + var DataView = __webpack_require__(49), + Map = __webpack_require__(14), + Promise = __webpack_require__(52), + Set = __webpack_require__(53), + WeakMap = __webpack_require__(56), + baseGetTag = __webpack_require__(6), + toSource = __webpack_require__(38); + + /** `Object#toString` result references. */ + var mapTag = '[object Map]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + setTag = '[object Set]', + weakMapTag = '[object WeakMap]'; + + var dataViewTag = '[object DataView]'; + + /** Used to detect maps, sets, and weakmaps. */ + var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + + /** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + var getTag = baseGetTag; + +// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. + if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; + } + + module.exports = getTag; + + + /***/ }), + /* 90 */ + /***/ (function(module, exports) { + + /** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function getValue(object, key) { + return object == null ? undefined : object[key]; + } + + module.exports = getValue; + + + /***/ }), + /* 91 */ + /***/ (function(module, exports, __webpack_require__) { + + var nativeCreate = __webpack_require__(8); + + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; + } + + module.exports = hashClear; + + + /***/ }), + /* 92 */ + /***/ (function(module, exports) { + + /** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; + } + + module.exports = hashDelete; + + + /***/ }), + /* 93 */ + /***/ (function(module, exports, __webpack_require__) { + + var nativeCreate = __webpack_require__(8); + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; + } + + module.exports = hashGet; + + + /***/ }), + /* 94 */ + /***/ (function(module, exports, __webpack_require__) { + + var nativeCreate = __webpack_require__(8); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); + } + + module.exports = hashHas; + + + /***/ }), + /* 95 */ + /***/ (function(module, exports, __webpack_require__) { + + var nativeCreate = __webpack_require__(8); + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; + } + + module.exports = hashSet; + + + /***/ }), + /* 96 */ + /***/ (function(module, exports) { + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ + function initCloneArray(array) { + var length = array.length, + result = array.constructor(length); + + // Add properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; + } + + module.exports = initCloneArray; + + + /***/ }), + /* 97 */ + /***/ (function(module, exports, __webpack_require__) { + + var cloneArrayBuffer = __webpack_require__(16), + cloneDataView = __webpack_require__(74), + cloneMap = __webpack_require__(75), + cloneRegExp = __webpack_require__(76), + cloneSet = __webpack_require__(77), + cloneSymbol = __webpack_require__(78), + cloneTypedArray = __webpack_require__(79); + + /** `Object#toString` result references. */ + var boolTag = '[object Boolean]', + dateTag = '[object Date]', + mapTag = '[object Map]', + numberTag = '[object Number]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]'; + + var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + + /** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneByTag(object, tag, cloneFunc, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return cloneArrayBuffer(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case dataViewTag: + return cloneDataView(object, isDeep); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + return cloneTypedArray(object, isDeep); + + case mapTag: + return cloneMap(object, isDeep, cloneFunc); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + return cloneRegExp(object); + + case setTag: + return cloneSet(object, isDeep, cloneFunc); + + case symbolTag: + return cloneSymbol(object); + } + } + + module.exports = initCloneByTag; + + + /***/ }), + /* 98 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseCreate = __webpack_require__(64), + getPrototype = __webpack_require__(34), + isPrototype = __webpack_require__(18); + + /** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; + } + + module.exports = initCloneObject; + + + /***/ }), + /* 99 */ + /***/ (function(module, exports, __webpack_require__) { + + var eq = __webpack_require__(9), + isArrayLike = __webpack_require__(20), + isIndex = __webpack_require__(36), + isObject = __webpack_require__(2); + + /** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; + } + + module.exports = isIterateeCall; + + + /***/ }), + /* 100 */ + /***/ (function(module, exports) { + + /** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ + function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); + } + + module.exports = isKeyable; + + + /***/ }), + /* 101 */ + /***/ (function(module, exports, __webpack_require__) { + + var coreJsData = __webpack_require__(83); + + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); + + /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } + + module.exports = isMasked; + + + /***/ }), + /* 102 */ + /***/ (function(module, exports) { + + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + this.size = 0; + } + + module.exports = listCacheClear; + + + /***/ }), + /* 103 */ + /***/ (function(module, exports, __webpack_require__) { + + var assocIndexOf = __webpack_require__(5); + + /** Used for built-in method references. */ + var arrayProto = Array.prototype; + + /** Built-in value references. */ + var splice = arrayProto.splice; + + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; + } + + module.exports = listCacheDelete; + + + /***/ }), + /* 104 */ + /***/ (function(module, exports, __webpack_require__) { + + var assocIndexOf = __webpack_require__(5); + + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; + } + + module.exports = listCacheGet; + + + /***/ }), + /* 105 */ + /***/ (function(module, exports, __webpack_require__) { + + var assocIndexOf = __webpack_require__(5); + + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + + module.exports = listCacheHas; + + + /***/ }), + /* 106 */ + /***/ (function(module, exports, __webpack_require__) { + + var assocIndexOf = __webpack_require__(5); + + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } + + module.exports = listCacheSet; + + + /***/ }), + /* 107 */ + /***/ (function(module, exports, __webpack_require__) { + + var Hash = __webpack_require__(50), + ListCache = __webpack_require__(4), + Map = __webpack_require__(14); + + /** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ + function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; + } + + module.exports = mapCacheClear; + + + /***/ }), + /* 108 */ + /***/ (function(module, exports, __webpack_require__) { + + var getMapData = __webpack_require__(7); + + /** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; + } + + module.exports = mapCacheDelete; + + + /***/ }), + /* 109 */ + /***/ (function(module, exports, __webpack_require__) { + + var getMapData = __webpack_require__(7); + + /** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } + + module.exports = mapCacheGet; + + + /***/ }), + /* 110 */ + /***/ (function(module, exports, __webpack_require__) { + + var getMapData = __webpack_require__(7); + + /** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } + + module.exports = mapCacheHas; + + + /***/ }), + /* 111 */ + /***/ (function(module, exports, __webpack_require__) { + + var getMapData = __webpack_require__(7); + + /** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ + function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; + } + + module.exports = mapCacheSet; + + + /***/ }), + /* 112 */ + /***/ (function(module, exports) { + + /** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ + function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; + } + + module.exports = mapToArray; + + + /***/ }), + /* 113 */ + /***/ (function(module, exports, __webpack_require__) { + + var overArg = __webpack_require__(37); + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeKeys = overArg(Object.keys, Object); + + module.exports = nativeKeys; + + + /***/ }), + /* 114 */ + /***/ (function(module, exports) { + + /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + module.exports = nativeKeysIn; + + + /***/ }), + /* 115 */ + /***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(module) {var freeGlobal = __webpack_require__(33); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Detect free variable `process` from Node.js. */ + var freeProcess = moduleExports && freeGlobal.process; + + /** Used to access faster Node.js helpers. */ + var nodeUtil = (function() { + try { + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} + }()); + + module.exports = nodeUtil; + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12)(module))) + + /***/ }), + /* 116 */ + /***/ (function(module, exports) { + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var nativeObjectToString = objectProto.toString; + + /** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ + function objectToString(value) { + return nativeObjectToString.call(value); + } + + module.exports = objectToString; + + + /***/ }), + /* 117 */ + /***/ (function(module, exports, __webpack_require__) { + + var apply = __webpack_require__(24); + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeMax = Math.max; + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; + } + + module.exports = overRest; + + + /***/ }), + /* 118 */ + /***/ (function(module, exports) { + + /** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ + function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; + } + + module.exports = setToArray; + + + /***/ }), + /* 119 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseSetToString = __webpack_require__(70), + shortOut = __webpack_require__(120); + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = shortOut(baseSetToString); + + module.exports = setToString; + + + /***/ }), + /* 120 */ + /***/ (function(module, exports) { + + /** Used to detect hot functions by number of calls within a span of milliseconds. */ + var HOT_COUNT = 800, + HOT_SPAN = 16; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeNow = Date.now; + + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; + } + + module.exports = shortOut; + + + /***/ }), + /* 121 */ + /***/ (function(module, exports, __webpack_require__) { + + var ListCache = __webpack_require__(4); + + /** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ + function stackClear() { + this.__data__ = new ListCache; + this.size = 0; + } + + module.exports = stackClear; + + + /***/ }), + /* 122 */ + /***/ (function(module, exports) { + + /** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; + } + + module.exports = stackDelete; + + + /***/ }), + /* 123 */ + /***/ (function(module, exports) { + + /** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function stackGet(key) { + return this.__data__.get(key); + } + + module.exports = stackGet; + + + /***/ }), + /* 124 */ + /***/ (function(module, exports) { + + /** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function stackHas(key) { + return this.__data__.has(key); + } + + module.exports = stackHas; + + + /***/ }), + /* 125 */ + /***/ (function(module, exports, __webpack_require__) { + + var ListCache = __webpack_require__(4), + Map = __webpack_require__(14), + MapCache = __webpack_require__(51); + + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + + /** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ + function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; + } + + module.exports = stackSet; + + + /***/ }), + /* 126 */ + /***/ (function(module, exports, __webpack_require__) { + + var copyObject = __webpack_require__(3), + createAssigner = __webpack_require__(84), + keysIn = __webpack_require__(23); + + /** + * This method is like `_.assignIn` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extendWith + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignInWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keysIn(source), object, customizer); + }); + + module.exports = assignInWith; + + + /***/ }), + /* 127 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseClone = __webpack_require__(63); + + /** Used to compose bitmasks for cloning. */ + var CLONE_SYMBOLS_FLAG = 4; + + /** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @see _.cloneDeep + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ + function clone(value) { + return baseClone(value, CLONE_SYMBOLS_FLAG); + } + + module.exports = clone; + + + /***/ }), + /* 128 */ + /***/ (function(module, exports) { + + /** + * Creates a function that returns `value`. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Util + * @param {*} value The value to return from the new function. + * @returns {Function} Returns the new constant function. + * @example + * + * var objects = _.times(2, _.constant({ 'a': 1 })); + * + * console.log(objects); + * // => [{ 'a': 1 }, { 'a': 1 }] + * + * console.log(objects[0] === objects[1]); + * // => true + */ + function constant(value) { + return function() { + return value; + }; + } + + module.exports = constant; + + + /***/ }), + /* 129 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseIsArguments = __webpack_require__(65), + isObjectLike = __webpack_require__(21); + + /** Used for built-in method references. */ + var objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Built-in value references. */ + var propertyIsEnumerable = objectProto.propertyIsEnumerable; + + /** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; + + module.exports = isArguments; + + + /***/ }), + /* 130 */ + /***/ (function(module, exports, __webpack_require__) { + + var baseIsTypedArray = __webpack_require__(67), + baseUnary = __webpack_require__(72), + nodeUtil = __webpack_require__(115); + + /* Node.js helper references. */ + var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + + /** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ + var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + + module.exports = isTypedArray; + + + /***/ }), + /* 131 */ + /***/ (function(module, exports) { + + /** + * This method returns `false`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `false`. + * @example + * + * _.times(2, _.stubFalse); + * // => [false, false] + */ + function stubFalse() { + return false; + } + + module.exports = stubFalse; + + + /***/ }), + /* 132 */ + /***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/punycode v1.4.1 by @mathias */ + ;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw new RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * https://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.4.1', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + true + ) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { + return punycode; + }.call(exports, __webpack_require__, exports, module), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { + // in Node.js, io.js, or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { + // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { + // in Rhino or a web browser + root.punycode = punycode; + } + + }(this)); + + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12)(module), __webpack_require__(11))) + + /***/ }), + /* 133 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +// If obj.hasOwnProperty has been overridden, then calling +// obj.hasOwnProperty(prop) will break. +// See: https://github.com/joyent/node/issues/1707 + function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); + } + + module.exports = function(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + var obj = {}; + + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } + + var regexp = /\+/g; + qs = qs.split(sep); + + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } + + var len = qs.length; + // maxKeys <= 0 means that we should not limit keys count + if (maxKeys > 0 && len > maxKeys) { + len = maxKeys; + } + + for (var i = 0; i < len; ++i) { + var x = qs[i].replace(regexp, '%20'), + idx = x.indexOf(eq), + kstr, vstr, k, v; + + if (idx >= 0) { + kstr = x.substr(0, idx); + vstr = x.substr(idx + 1); + } else { + kstr = x; + vstr = ''; + } + + k = decodeURIComponent(kstr); + v = decodeURIComponent(vstr); + + if (!hasOwnProperty(obj, k)) { + obj[k] = v; + } else if (isArray(obj[k])) { + obj[k].push(v); + } else { + obj[k] = [obj[k], v]; + } + } + + return obj; + }; + + var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; + }; + + + /***/ }), + /* 134 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + + var stringifyPrimitive = function(v) { + switch (typeof v) { + case 'string': + return v; + + case 'boolean': + return v ? 'true' : 'false'; + + case 'number': + return isFinite(v) ? v : ''; + + default: + return ''; + } + }; + + module.exports = function(obj, sep, eq, name) { + sep = sep || '&'; + eq = eq || '='; + if (obj === null) { + obj = undefined; + } + + if (typeof obj === 'object') { + return map(objectKeys(obj), function(k) { + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; + if (isArray(obj[k])) { + return map(obj[k], function(v) { + return ks + encodeURIComponent(stringifyPrimitive(v)); + }).join(sep); + } else { + return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + } + }).join(sep); + + } + + if (!name) return ''; + return encodeURIComponent(stringifyPrimitive(name)) + eq + + encodeURIComponent(stringifyPrimitive(obj)); + }; + + var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; + }; + + function map (xs, f) { + if (xs.map) return xs.map(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + res.push(f(xs[i], i)); + } + return res; + } + + var objectKeys = Object.keys || function (obj) { + var res = []; + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); + } + return res; + }; + + + /***/ }), + /* 135 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + + exports.decode = exports.parse = __webpack_require__(133); + exports.encode = exports.stringify = __webpack_require__(134); + + + /***/ }), + /* 136 */ + /***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(global, process) {(function (global, undefined) { + "use strict"; + + if (global.setImmediate) { + return; + } + + var nextHandle = 1; // Spec says greater than zero + var tasksByHandle = {}; + var currentlyRunningATask = false; + var doc = global.document; + var registerImmediate; + + function setImmediate(callback) { + // Callback can either be a function or a string + if (typeof callback !== "function") { + callback = new Function("" + callback); + } + // Copy function arguments + var args = new Array(arguments.length - 1); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i + 1]; + } + // Store and register the task + var task = { callback: callback, args: args }; + tasksByHandle[nextHandle] = task; + registerImmediate(nextHandle); + return nextHandle++; + } + + function clearImmediate(handle) { + delete tasksByHandle[handle]; + } + + function run(task) { + var callback = task.callback; + var args = task.args; + switch (args.length) { + case 0: + callback(); + break; + case 1: + callback(args[0]); + break; + case 2: + callback(args[0], args[1]); + break; + case 3: + callback(args[0], args[1], args[2]); + break; + default: + callback.apply(undefined, args); + break; + } + } + + function runIfPresent(handle) { + // From the spec: "Wait until any invocations of this algorithm started before this one have completed." + // So if we're currently running a task, we'll need to delay this invocation. + if (currentlyRunningATask) { + // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a + // "too much recursion" error. + setTimeout(runIfPresent, 0, handle); + } else { + var task = tasksByHandle[handle]; + if (task) { + currentlyRunningATask = true; + try { + run(task); + } finally { + clearImmediate(handle); + currentlyRunningATask = false; + } + } + } + } + + function installNextTickImplementation() { + registerImmediate = function(handle) { + process.nextTick(function () { runIfPresent(handle); }); + }; + } + + function canUsePostMessage() { + // The test against `importScripts` prevents this implementation from being installed inside a web worker, + // where `global.postMessage` means something completely different and can't be used for this purpose. + if (global.postMessage && !global.importScripts) { + var postMessageIsAsynchronous = true; + var oldOnMessage = global.onmessage; + global.onmessage = function() { + postMessageIsAsynchronous = false; + }; + global.postMessage("", "*"); + global.onmessage = oldOnMessage; + return postMessageIsAsynchronous; + } + } + + function installPostMessageImplementation() { + // Installs an event handler on `global` for the `message` event: see + // * https://developer.mozilla.org/en/DOM/window.postMessage + // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages + + var messagePrefix = "setImmediate$" + Math.random() + "$"; + var onGlobalMessage = function(event) { + if (event.source === global && + typeof event.data === "string" && + event.data.indexOf(messagePrefix) === 0) { + runIfPresent(+event.data.slice(messagePrefix.length)); + } + }; + + if (global.addEventListener) { + global.addEventListener("message", onGlobalMessage, false); + } else { + global.attachEvent("onmessage", onGlobalMessage); + } + + registerImmediate = function(handle) { + global.postMessage(messagePrefix + handle, "*"); + }; + } + + function installMessageChannelImplementation() { + var channel = new MessageChannel(); + channel.port1.onmessage = function(event) { + var handle = event.data; + runIfPresent(handle); + }; + + registerImmediate = function(handle) { + channel.port2.postMessage(handle); + }; + } + + function installReadyStateChangeImplementation() { + var html = doc.documentElement; + registerImmediate = function(handle) { + // Create a \ No newline at end of file diff --git a/src/renderer/views/components/mediaitem-artwork.ejs b/src/renderer/views/components/mediaitem-artwork.ejs index 7c96e926..7e169943 100644 --- a/src/renderer/views/components/mediaitem-artwork.ejs +++ b/src/renderer/views/components/mediaitem-artwork.ejs @@ -1,5 +1,5 @@ \ No newline at end of file + diff --git a/src/renderer/views/components/mediaitem-square-large.ejs b/src/renderer/views/components/mediaitem-square-large.ejs index 04b713b1..4bb1098f 100644 --- a/src/renderer/views/components/mediaitem-square-large.ejs +++ b/src/renderer/views/components/mediaitem-square-large.ejs @@ -1,5 +1,4 @@ @@ -43,8 +55,9 @@ }, size: { type: String, - default: '300' - } + default: '190' + }, + 'contextExt': {type: Object, required: false}, }, data: function () { return { @@ -53,16 +66,105 @@ guid: this.uuidv4(), noplay: ["apple-curators"], nomenu: ["artists", "stations", "apple-curators"], - app: this.$root + app: this.$root, + badges: this.$root.socialBadges.badgeMap, + itemBadges: [] } }, + async mounted() { + await this.getBadges() + }, methods: { + getBgColor() { + let color = `#${(this.item.attributes.artwork.bgColor != null) ? (this.item.attributes.artwork.bgColor) : `333333`}` + let c = color.substring(1); // strip # + var rgb = parseInt(c, 16); // convert rrggbb to decimal + var r = (rgb >> 16) & 0xff; // extract red + var g = (rgb >> 8) & 0xff; // extract green + var b = (rgb >> 0) & 0xff; // extract blue + + var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709 + + console.log(color) + console.log(luma) + if (luma > 140) { + return "#aaaaaa" + }else{ + return color + } + + + }, + getSubtitle() { + if(this.kind == 'card') { + try { + if (typeof this.item.attributes.artistNames != "undefined") { + return this.item.attributes.artistNames + } else if (typeof this.item.attributes.editorialNotes != "undefined") { + return this.item.attributes.editorialNotes.short + } else if (typeof this.item.attributes.artistName != "undefined") { + return this.item.attributes.artistName + } else { + return '' + } + }catch(e) { + return '' + } + }else { + if (typeof this.item.attributes.artistName != "undefined") { + return this.item.attributes.artistName + } else { + return '' + } + } + }, + getSubtitleNavigation() { + if(this.kind == 'card') { + try { + if (typeof this.item.attributes.artistNames != "undefined") { + return app.routeView(this.item) + } else if (typeof this.item.attributes.editorialNotes != "undefined") { + return app.routeView(this.item) + } else if (typeof this.item.attributes.artistName != "undefined") { + return app.searchAndNavigate(this.item,'artist') + } else { + return app.routeView(this.item) + } + }catch(e) { + return app.routeView(this.item) + } + }else { + if (typeof this.item.attributes.artistName != "undefined") { + return app.searchAndNavigate(this.item,'artist') + } else { + return app.routeView(this.item) + } + } + }, + async getBadges() { + let self = this + if (this.badges[this.item.attributes.playParams.id ?? this.item.id]) { + let friends = this.badges[this.item.attributes.playParams.id ?? this.item.id] + if (friends) { + friends.forEach(function (friend) { + self.app.mk.api.socialProfile(friend).then(data => { + self.itemBadges.push(data) + }) + }) + } + } + }, revisedRandId() { return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10); }, async isInLibrary() { if (this.item.type && !this.item.type.includes("library")) { - var params = {"fields[playlists]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library", "extend": this.revisedRandId()} + var params = { + "fields[playlists]": "inLibrary", + "fields[albums]": "inLibrary", + "relate": "library", + "extend": this.revisedRandId() + } var res = await app.mkapi(this.item.attributes.playParams.kind ?? this.item.type, this.item.attributes.playParams.isLibrary ?? false, this.item.attributes.playParams.id ?? this.item.id, params); this.addedToLibrary = (res && res.attributes && res.attributes.inLibrary) ? res.attributes.inLibrary : false } else { @@ -70,7 +172,13 @@ } }, async removeFromLibrary(id) { - var params = {"fields[playlists]": "inLibrary","fields[songs]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library", "extend": this.revisedRandId()} + var params = { + "fields[playlists]": "inLibrary", + "fields[songs]": "inLibrary", + "fields[albums]": "inLibrary", + "relate": "library", + "extend": this.revisedRandId() + } var id = this.item.id ?? this.item.attributes.playParams.id var res = await app.mkapi(this.item.attributes.playParams.kind ?? this.item.type, this.item.attributes.playParams.isLibrary ?? false, this.item.attributes.playParams.id ?? this.item.id, params); if (res && res.relationships && res.relationships.library && res.relationships.library.data && res.relationships.library.data.length > 0) { @@ -86,14 +194,21 @@ (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) ); }, - getArtworkUrl() { + getArtworkUrl(size = -1, includeUrl = false) { let artwork = this.item.attributes.artwork ? this.item.attributes.artwork.url : '' + if(size != -1) { + artwork = artwork.replace('{w}', size).replace('{h}', size).replace('{f}', "webp").replace('{c}', ((size === 900) ? "sr" : "cc")) + } switch (this.kind) { case "385": artwork = this.item.attributes.editorialArtwork.subscriptionHero.url break; } - return artwork + if(!includeUrl) { + return artwork + }else{ + return `url("${artwork}")` + } }, getClasses() { let type = this.item.type @@ -104,12 +219,15 @@ default: return [] break; + case "card": + return ["mediaitem-card"] + break; case "385": // editorial return ["mediaitem-brick"] break; case "small": return ["mediaitem-small"] - break; + break; case "music-videos": case "uploadedVideo": case "uploaded-videos": @@ -120,7 +238,7 @@ visibilityChanged: function (isVisible, entry) { this.isVisible = isVisible }, - async contextMenu(event) { + async contextMenu(event) { if (this.nomenu.includes(this.item.type)) { return } @@ -134,7 +252,7 @@ let useMenu = "normal" if (app.selectedMediaItems.length <= 1) { app.selectedMediaItems = [] - app.select_selectMediaItem(this.item.attributes.playParams.id ?? this.item.id, this.item.attributes.playParams.kind ?? this.item.type, this.index, this.guid) + app.select_selectMediaItem(this.item.attributes.playParams.id ?? this.item.id, this.item.attributes.playParams.kind ?? this.item.type, this.index, this.guid, this.item.attributes.playParams.isLibrary ?? false) } else { useMenu = "multiple" } @@ -186,6 +304,14 @@ }, normal: { items: [ + { + "icon": "./assets/feather/list.svg", + "id": "addToPlaylist", + "name": "Add to Playlist...", + "action": function () { + app.promptAddToPlaylist() + } + }, { "name": "Play Next", "action": function () { @@ -203,31 +329,100 @@ } }, { - "name": "Add to Playlist...", - "action": function () { - app.promptAddToPlaylist() - } - }, - { - "name": (this.addedToLibrary) ? "Remove from Library..." : "Add to Library...", + "icon": "./assets/feather/plus.svg", + "name": (this.addedToLibrary) ? "Remove from Library..." : "Add to Library...", "action": async function () { let item_id = self.item.attributes.playParams.id ?? self.item.id; let data_type = self.item.attributes.playParams.kind ?? self.item.type; - if (self.addedToLibrary != true) { console.log("add"); app.addToLibrary(item_id); self.addedToLibrary = true} - else { console.log("remove"); await self.removeFromLibrary(item_id); self.addedToLibrary = false}; + if (self.addedToLibrary != true) { + console.log("add"); + app.addToLibrary(item_id); + self.addedToLibrary = true + } else { + console.log("remove"); + await self.removeFromLibrary(item_id); + self.addedToLibrary = false + } + ; } }, + { + "icon": "./assets/feather/heart.svg", + "id": "love", + "name": "Love", + "disabled": true, + "action": function () { + app.love(self.item) + } + }, + { + "icon": "./assets/feather/x-circle.svg", + "id": "unlove", + "name": "Unlove", + "disabled": true, + "action": function () { + app.unlove(self.item) + } + }, + { + "icon": "./assets/feather/thumbs-down.svg", + "id": "dislike", + "name": "Dislike", + "disabled": true, + "action": function () { + app.dislike(self.item) + } + }, + { + "icon": "./assets/feather/x-circle.svg", + "id": "undo_dislike", + "name": "Undo dislike", + "disabled": true, + "action": function () { + app.unlove(self.item) + } + }, + { + "icon": "./assets/feather/share.svg", + "name": "Share", + "action": function () { + self.app.copyToClipboard(self.item.attributes.url) + } + } ] } } - if ((self.item.attributes.playParams.kind ?? self.item.type).includes("playlist")) { menus.normal.items.splice(2, 1);} + if ((self.item.attributes.playParams.kind ?? self.item.type).includes("playlist")) { + // remove the add to playlist option by id "addToPlaylist" using the .filter() method + menus.normal.items = menus.normal.items.filter(function (item) { + return item.id != "addToPlaylist" + }) + } + let rating = await app.getRating(self.item) + if (rating == 0) { + menus.normal.items.find(x => x.id == 'love').disabled = false + menus.normal.items.find(x => x.id == 'dislike').disabled = false + } else if (rating == 1) { + menus.normal.items.find(x => x.id == 'unlove').disabled = false + } else if (rating == -1) { + menus.normal.items.find(x => x.id == 'undo_dislike').disabled = false + } + + if (this.contextExt) { + if (this.contextExt.normal) { + menus.normal.items = menus.normal.items.concat(this.contextExt.normal) + } + if (this.contextExt.multiple) { + menus.multiple.items = menus.multiple.items.concat(this.contextExt.multiple) + } + } CiderContextMenu.Create(event, menus[useMenu]) }, }, beforeDestroy: function () { - this.item = null; - this.kind = null; - this.size = null; + // this.item = null; + // this.kind = null; + // this.size = null; } }); \ No newline at end of file diff --git a/src/renderer/views/components/sidebar-playlist.ejs b/src/renderer/views/components/sidebar-playlist.ejs new file mode 100644 index 00000000..b5ba0271 --- /dev/null +++ b/src/renderer/views/components/sidebar-playlist.ejs @@ -0,0 +1,221 @@ + + + \ No newline at end of file diff --git a/src/renderer/views/components/spatial-properties.ejs b/src/renderer/views/components/spatial-properties.ejs new file mode 100644 index 00000000..4627f8f6 --- /dev/null +++ b/src/renderer/views/components/spatial-properties.ejs @@ -0,0 +1,355 @@ + + + \ No newline at end of file diff --git a/src/renderer/views/main.ejs b/src/renderer/views/main.ejs index f914890d..e0d409a3 100644 --- a/src/renderer/views/main.ejs +++ b/src/renderer/views/main.ejs @@ -18,9 +18,11 @@ + + @@ -67,7 +69,9 @@ + + + + diff --git a/src/renderer/views/svg/explicit.svg b/src/renderer/views/svg/explicit.svg new file mode 100644 index 00000000..b9f347b4 --- /dev/null +++ b/src/renderer/views/svg/explicit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/views/svg/list.svg b/src/renderer/views/svg/list.svg new file mode 100644 index 00000000..5a8ca2c3 --- /dev/null +++ b/src/renderer/views/svg/list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/views/svg/quote-right.svg b/src/renderer/views/svg/quote-right.svg new file mode 100644 index 00000000..629ab4ee --- /dev/null +++ b/src/renderer/views/svg/quote-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/vuex.min.js b/src/renderer/vuex.min.js new file mode 100644 index 00000000..0ffa5978 --- /dev/null +++ b/src/renderer/vuex.min.js @@ -0,0 +1,6 @@ +/** + * vuex v2.0.0 + * (c) 2016 Evan You + * @license MIT + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.Vuex=e()}(this,function(){"use strict";function t(t){b&&(t._devtoolHook=b,b.emit("vuex:init",t),b.on("vuex:travel-to-state",function(e){t.replaceState(e)}),t.subscribe(function(t,e){b.emit("vuex:mutation",t,e)}))}function e(t){function e(){var t=this.$options;t.store?this.$store=t.store:t.parent&&t.parent.$store&&(this.$store=t.parent.$store)}var n=Number(t.version.split(".")[0]);if(n>=2){var o=t.config._lifecycleHooks.indexOf("init")>-1;t.mixin(o?{init:e}:{beforeCreate:e})}else{var i=t.prototype._init;t.prototype._init=function(t){void 0===t&&(t={}),t.init=t.init?[e].concat(t.init):e,i.call(this,t)}}}function n(t){var e={};return s(t).forEach(function(t){var n=t.key,o=t.val;e[n]=function(){return"function"==typeof o?o.call(this,this.$store.state,this.$store.getters):this.$store.state[o]}}),e}function o(t){var e={};return s(t).forEach(function(t){var n=t.key,o=t.val;e[n]=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return this.$store.commit.apply(this.$store,[o].concat(t))}}),e}function i(t){var e={};return s(t).forEach(function(t){var n=t.key,o=t.val;e[n]=function(){return o in this.$store.getters||console.error("[vuex] unknown getter: "+o),this.$store.getters[o]}}),e}function r(t){var e={};return s(t).forEach(function(t){var n=t.key,o=t.val;e[n]=function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return this.$store.dispatch.apply(this.$store,[o].concat(t))}}),e}function s(t){return Array.isArray(t)?t.map(function(t){return{key:t,val:t}}):Object.keys(t).map(function(e){return{key:e,val:t[e]}})}function u(t){return null!==t&&"object"==typeof t}function a(t){return t&&"function"==typeof t.then}function c(t,e){if(!t)throw new Error("[vuex] "+e)}function f(t,e){if(e.actions&&(t.actions=e.actions),e.mutations&&(t.mutations=e.mutations),e.getters&&(t.getters=e.getters),e.modules)for(var n in e.modules){if(!t.modules||!t.modules[n])return void console.warn("[vuex] trying to add a new module '"+n+"' on hot reloading, manual reload is needed");f(t.modules[n],e.modules[n])}}function l(t){t._actions=Object.create(null),t._mutations=Object.create(null),t._wrappedGetters=Object.create(null);var e=t.state;p(t,e,[],t._options,!0),Object.keys(t._runtimeModules).forEach(function(n){p(t,e,n.split("."),t._runtimeModules[n],!0)}),h(t,e)}function h(t,e){var n=t._vm;t.getters={};var o=t._wrappedGetters,i={};Object.keys(o).forEach(function(e){var n=o[e];i[e]=function(){return n(t)},Object.defineProperty(t.getters,e,{get:function(){return t._vm[e]}})});var r=w.config.silent;w.config.silent=!0,t._vm=new w({data:{state:e},computed:i}),w.config.silent=r,t.strict&&y(t),n&&(t._withCommit(function(){n.state=null}),w.nextTick(function(){return n.$destroy()}))}function p(t,e,n,o,i){var r=!n.length,s=o.state,u=o.actions,a=o.mutations,c=o.getters,f=o.modules;if(!r&&!i){var l=_(e,n.slice(0,-1)),h=n[n.length-1];t._withCommit(function(){w.set(l,h,s||{})})}a&&Object.keys(a).forEach(function(e){d(t,e,a[e],n)}),u&&Object.keys(u).forEach(function(e){m(t,e,u[e],n)}),c&&v(t,c,n),f&&Object.keys(f).forEach(function(o){p(t,e,n.concat(o),f[o],i)})}function d(t,e,n,o){void 0===o&&(o=[]);var i=t._mutations[e]||(t._mutations[e]=[]);i.push(function(e){n(_(t.state,o),e)})}function m(t,e,n,o){void 0===o&&(o=[]);var i=t._actions[e]||(t._actions[e]=[]),r=t.dispatch,s=t.commit;i.push(function(e,i){var u=n({dispatch:r,commit:s,getters:t.getters,state:_(t.state,o),rootState:t.state},e,i);return a(u)||(u=Promise.resolve(u)),t._devtoolHook?u.catch(function(e){throw t._devtoolHook.emit("vuex:error",e),e}):u})}function v(t,e,n){Object.keys(e).forEach(function(o){var i=e[o];return t._wrappedGetters[o]?void console.error("[vuex] duplicate getter key: "+o):void(t._wrappedGetters[o]=function(t){return i(_(t.state,n),t.getters,t.state)})})}function y(t){t._vm.$watch("state",function(){c(t._committing,"Do not mutate vuex store state outside mutation handlers.")},{deep:!0,sync:!0})}function _(t,e){return e.length?e.reduce(function(t,e){return t[e]},t):t}function g(t){return w?void console.error("[vuex] already installed. Vue.use(Vuex) should be called only once."):(w=t,void e(w))}var w,b="undefined"!=typeof window&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,x=function(e){var n=this;void 0===e&&(e={}),c(w,"must call Vue.use(Vuex) before creating a store instance."),c("undefined"!=typeof Promise,"vuex requires a Promise polyfill in this browser.");var o=e.state;void 0===o&&(o={});var i=e.plugins;void 0===i&&(i=[]);var r=e.strict;void 0===r&&(r=!1),this._options=e,this._committing=!1,this._actions=Object.create(null),this._mutations=Object.create(null),this._wrappedGetters=Object.create(null),this._runtimeModules=Object.create(null),this._subscribers=[],this._watcherVM=new w;var s=this,u=this,a=u.dispatch,f=u.commit;this.dispatch=function(t,e){return a.call(s,t,e)},this.commit=function(t,e,n){return f.call(s,t,e,n)},this.strict=r,p(this,o,[],e),h(this,o),i.concat(t).forEach(function(t){return t(n)})},O={state:{}};O.state.get=function(){return this._vm.state},O.state.set=function(t){c(!1,"Use store.replaceState() to explicit replace store state.")},x.prototype.commit=function(t,e,n){var o=this;u(t)&&t.type&&(n=e,e=t,t=t.type);var i={type:t,payload:e},r=this._mutations[t];return r?(this._withCommit(function(){r.forEach(function(t){t(e)})}),void(n&&n.silent||this._subscribers.forEach(function(t){return t(i,o.state)}))):void console.error("[vuex] unknown mutation type: "+t)},x.prototype.dispatch=function(t,e){u(t)&&t.type&&(e=t,t=t.type);var n=this._actions[t];return n?n.length>1?Promise.all(n.map(function(t){return t(e)})):n[0](e):void console.error("[vuex] unknown action type: "+t)},x.prototype.subscribe=function(t){var e=this._subscribers;return e.indexOf(t)<0&&e.push(t),function(){var n=e.indexOf(t);n>-1&&e.splice(n,1)}},x.prototype.watch=function(t,e,n){var o=this;return c("function"==typeof t,"store.watch only accepts a function."),this._watcherVM.$watch(function(){return t(o.state)},e,n)},x.prototype.replaceState=function(t){var e=this;this._withCommit(function(){e._vm.state=t})},x.prototype.registerModule=function(t,e){"string"==typeof t&&(t=[t]),c(Array.isArray(t),"module path must be a string or an Array."),this._runtimeModules[t.join(".")]=e,p(this,this.state,t,e),h(this,this.state)},x.prototype.unregisterModule=function(t){var e=this;"string"==typeof t&&(t=[t]),c(Array.isArray(t),"module path must be a string or an Array."),delete this._runtimeModules[t.join(".")],this._withCommit(function(){var n=_(e.state,t.slice(0,-1));w.delete(n,t[t.length-1])}),l(this)},x.prototype.hotUpdate=function(t){f(this._options,t),l(this)},x.prototype._withCommit=function(t){var e=this._committing;this._committing=!0,t(),this._committing=e},Object.defineProperties(x.prototype,O),"undefined"!=typeof window&&window.Vue&&g(window.Vue);var k={Store:x,install:g,mapState:n,mapMutations:o,mapGetters:i,mapActions:r};return k}); \ No newline at end of file