Merge branch 'develop' into update-owo
This commit is contained in:
commit
62b8666f81
18 changed files with 1413 additions and 999 deletions
|
@ -14,13 +14,13 @@ jobs:
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
name: Restore Yarn Package Cache
|
name: Restore Yarn Package Cache
|
||||||
keys:
|
keys:
|
||||||
- yarn-packages-{{ checksum "yarn.lock" }}
|
- yarn-packages-{{ checksum "cider-yarn.lock" }}
|
||||||
- run:
|
- run:
|
||||||
name: Install Dependencies
|
name: Install Dependencies
|
||||||
command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
|
command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
|
||||||
- save_cache:
|
- save_cache:
|
||||||
name: Save Yarn Package Cache
|
name: Save Yarn Package Cache
|
||||||
key: yarn-packages-{{ checksum "yarn.lock" }}
|
key: yarn-packages-{{ checksum "cider-yarn.lock" }}
|
||||||
paths:
|
paths:
|
||||||
- ~/.cache/yarn
|
- ~/.cache/yarn
|
||||||
- run:
|
- run:
|
||||||
|
@ -34,15 +34,6 @@ jobs:
|
||||||
sudo dpkg --add-architecture i386
|
sudo dpkg --add-architecture i386
|
||||||
sudo apt-get update -y
|
sudo apt-get update -y
|
||||||
sudo apt-get install -y wine32
|
sudo apt-get install -y wine32
|
||||||
- run:
|
|
||||||
name: Start X VNC Server
|
|
||||||
command: x11vnc -forever -nopw -create
|
|
||||||
background: true
|
|
||||||
#- run:
|
|
||||||
#name: Base Functionality Testing
|
|
||||||
#command: yarn test
|
|
||||||
- store_test_results:
|
|
||||||
path: test-results
|
|
||||||
- run:
|
- run:
|
||||||
name: Append Commit BuildID to Version
|
name: Append Commit BuildID to Version
|
||||||
command: yarn circle:append-bid
|
command: yarn circle:append-bid
|
||||||
|
|
1736
cider-yarn.lock
1736
cider-yarn.lock
File diff suppressed because it is too large
Load diff
|
@ -352,6 +352,8 @@
|
||||||
"settings.option.experimental.compactUI": "Compact UI",
|
"settings.option.experimental.compactUI": "Compact UI",
|
||||||
"settings.option.experimental.close_button_hide": "Close Button Should Hide the Application",
|
"settings.option.experimental.close_button_hide": "Close Button Should Hide the Application",
|
||||||
"settings.option.experimental.inline_playlists": "Inline Playlists and Albums",
|
"settings.option.experimental.inline_playlists": "Inline Playlists and Albums",
|
||||||
|
"settings.option.advanced.playlistTrackMapping": "Playlist Track Mapping",
|
||||||
|
"settings.option.advanced.playlistTrackMapping.description": "Enables deep scanning of playlists to determine which tracks are in which playlists.",
|
||||||
"spatial.notTurnedOn": "Audio Spatialization is disabled. To use, please enable it first.",
|
"spatial.notTurnedOn": "Audio Spatialization is disabled. To use, please enable it first.",
|
||||||
"spatial.spatialProperties": "Spatial Properties",
|
"spatial.spatialProperties": "Spatial Properties",
|
||||||
"spatial.width": "Width",
|
"spatial.width": "Width",
|
||||||
|
|
|
@ -352,6 +352,8 @@
|
||||||
"settings.option.experimental.compactUI": "Compact UI",
|
"settings.option.experimental.compactUI": "Compact UI",
|
||||||
"settings.option.experimental.close_button_hide": "Close Button Should Hide the Application",
|
"settings.option.experimental.close_button_hide": "Close Button Should Hide the Application",
|
||||||
"settings.option.experimental.inline_playlists": "Inline Playlists and Albums",
|
"settings.option.experimental.inline_playlists": "Inline Playlists and Albums",
|
||||||
|
"settings.option.advanced.playlistTrackMapping": "Playlist Track Mapping",
|
||||||
|
"settings.option.advanced.playlistTrackMapping.description": "Enables deep scanning of playlists to determine which tracks are in which playlists.",
|
||||||
"spatial.notTurnedOn": "Audio Spatialization is disabled. To use, please enable it first.",
|
"spatial.notTurnedOn": "Audio Spatialization is disabled. To use, please enable it first.",
|
||||||
"spatial.spatialProperties": "Spatial Properties",
|
"spatial.spatialProperties": "Spatial Properties",
|
||||||
"spatial.width": "Width",
|
"spatial.width": "Width",
|
||||||
|
|
|
@ -184,10 +184,6 @@ export class BrowserWindow {
|
||||||
page: "plugins-github",
|
page: "plugins-github",
|
||||||
component: `<plugins-github></plugins-github>`,
|
component: `<plugins-github></plugins-github>`,
|
||||||
condition: `page == 'plugins-github'`
|
condition: `page == 'plugins-github'`
|
||||||
}, {
|
|
||||||
page: "podcasts",
|
|
||||||
component: `<apple-podcasts></apple-podcasts>`,
|
|
||||||
condition: `page == 'podcasts'`
|
|
||||||
}, {
|
}, {
|
||||||
page: "remote-pair",
|
page: "remote-pair",
|
||||||
component: `<remote-pair></remote-pair>`,
|
component: `<remote-pair></remote-pair>`,
|
||||||
|
@ -726,79 +722,22 @@ export class BrowserWindow {
|
||||||
event.returnValue = this.devMode;
|
event.returnValue = this.devMode;
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on("put-library-songs", (_event, arg) => {
|
ipcMain.handle("put-cache", (_event, arg) => {
|
||||||
writeFileSync(
|
writeFileSync(
|
||||||
join(utils.getPath('ciderCache'), "library-songs.json"),
|
join(utils.getPath('ciderCache'), `${arg.file}.json`),
|
||||||
JSON.stringify(arg)
|
arg.data
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on("put-library-artists", (_event, arg) => {
|
ipcMain.on("get-cache", (event, arg) => {
|
||||||
writeFileSync(
|
let read = ""
|
||||||
join(utils.getPath('ciderCache'), "library-artists.json"),
|
if (existsSync(join(utils.getPath('ciderCache'), `${arg}.json`))) {
|
||||||
JSON.stringify(arg)
|
read = readFileSync(
|
||||||
);
|
join(utils.getPath('ciderCache'), `${arg}.json`),
|
||||||
});
|
"utf8"
|
||||||
|
);
|
||||||
ipcMain.on("put-library-albums", (_event, arg) => {
|
}
|
||||||
writeFileSync(
|
event.returnValue = read;
|
||||||
join(utils.getPath('ciderCache'), "library-albums.json"),
|
|
||||||
JSON.stringify(arg)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on("put-library-playlists", (_event, arg) => {
|
|
||||||
writeFileSync(
|
|
||||||
join(utils.getPath('ciderCache'), "library-playlists.json"),
|
|
||||||
JSON.stringify(arg)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on("put-library-recentlyAdded", (_event, arg) => {
|
|
||||||
writeFileSync(
|
|
||||||
join(utils.getPath('ciderCache'), "library-recentlyAdded.json"),
|
|
||||||
JSON.stringify(arg)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on("get-library-songs", (event) => {
|
|
||||||
let librarySongs = readFileSync(
|
|
||||||
join(utils.getPath('ciderCache'), "library-songs.json"),
|
|
||||||
"utf8"
|
|
||||||
);
|
|
||||||
event.returnValue = JSON.parse(librarySongs);
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on("get-library-artists", (event) => {
|
|
||||||
let libraryArtists = readFileSync(
|
|
||||||
join(utils.getPath('ciderCache'), "library-artists.json"),
|
|
||||||
"utf8"
|
|
||||||
);
|
|
||||||
event.returnValue = JSON.parse(libraryArtists);
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on("get-library-albums", (event) => {
|
|
||||||
let libraryAlbums = readFileSync(
|
|
||||||
join(utils.getPath('ciderCache'), "library-albums.json"),
|
|
||||||
"utf8"
|
|
||||||
);
|
|
||||||
event.returnValue = JSON.parse(libraryAlbums);
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on("get-library-playlists", (event) => {
|
|
||||||
let libraryPlaylists = readFileSync(
|
|
||||||
join(utils.getPath('ciderCache'), "library-playlists.json"),
|
|
||||||
"utf8"
|
|
||||||
);
|
|
||||||
event.returnValue = JSON.parse(libraryPlaylists);
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on("get-library-recentlyAdded", (event) => {
|
|
||||||
let libraryRecentlyAdded = readFileSync(
|
|
||||||
join(utils.getPath('ciderCache'), "library-recentlyAdded.json"),
|
|
||||||
"utf8"
|
|
||||||
);
|
|
||||||
event.returnValue = JSON.parse(libraryRecentlyAdded);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle("getYTLyrics", async (_event, track, artist) => {
|
ipcMain.handle("getYTLyrics", async (_event, track, artist) => {
|
||||||
|
|
|
@ -118,7 +118,8 @@ export class Store {
|
||||||
},
|
},
|
||||||
"advanced": {
|
"advanced": {
|
||||||
"AudioContext": false,
|
"AudioContext": false,
|
||||||
"experiments": []
|
"experiments": [],
|
||||||
|
"playlistTrackMapping": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private migrations: any = {}
|
private migrations: any = {}
|
||||||
|
|
|
@ -1,5 +1,29 @@
|
||||||
Vue.use(VueHorizontal);
|
Vue.use(VueHorizontal);
|
||||||
Vue.use(VueObserveVisibility);
|
Vue.use(VueObserveVisibility);
|
||||||
|
|
||||||
|
const CiderCache = {
|
||||||
|
async getCache(file) {
|
||||||
|
let cache = await ipcRenderer.sendSync("get-cache", file)
|
||||||
|
if (isJson(cache)) {
|
||||||
|
cache = JSON.parse(cache)
|
||||||
|
if (Object.keys(cache).length === 0) {
|
||||||
|
cache = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cache = false
|
||||||
|
}
|
||||||
|
return cache
|
||||||
|
},
|
||||||
|
async putCache(file, data) {
|
||||||
|
console.log(`Caching ${file}`)
|
||||||
|
ipcRenderer.invoke("put-cache", {
|
||||||
|
file: file,
|
||||||
|
data: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var notyf = new Notyf();
|
var notyf = new Notyf();
|
||||||
|
|
||||||
const MusicKitObjects = {
|
const MusicKitObjects = {
|
||||||
|
@ -49,10 +73,10 @@ Array.prototype.limit = function (n) {
|
||||||
const store = new Vuex.Store({
|
const store = new Vuex.Store({
|
||||||
state: {
|
state: {
|
||||||
library: {
|
library: {
|
||||||
songs: ipcRenderer.sendSync("get-library-songs"),
|
// songs: ipcRenderer.sendSync("get-library-songs"),
|
||||||
albums: ipcRenderer.sendSync("get-library-albums"),
|
// albums: ipcRenderer.sendSync("get-library-albums"),
|
||||||
recentlyAdded: ipcRenderer.sendSync("get-library-recentlyAdded"),
|
// recentlyAdded: ipcRenderer.sendSync("get-library-recentlyAdded"),
|
||||||
playlists: ipcRenderer.sendSync("get-library-playlists")
|
// playlists: ipcRenderer.sendSync("get-library-playlists")
|
||||||
},
|
},
|
||||||
artwork: {
|
artwork: {
|
||||||
playerLCD: ""
|
playerLCD: ""
|
||||||
|
@ -178,7 +202,8 @@ const app = new Vue({
|
||||||
listing: [],
|
listing: [],
|
||||||
details: {},
|
details: {},
|
||||||
loadingState: 0, // 0 loading, 1 loaded, 2 error
|
loadingState: 0, // 0 loading, 1 loaded, 2 error
|
||||||
id: ""
|
id: "",
|
||||||
|
trackMapping: {}
|
||||||
},
|
},
|
||||||
webremoteurl: "",
|
webremoteurl: "",
|
||||||
webremoteqr: "",
|
webremoteqr: "",
|
||||||
|
@ -233,7 +258,8 @@ const app = new Vue({
|
||||||
topChromeVisible: true,
|
topChromeVisible: true,
|
||||||
progresshover: false,
|
progresshover: false,
|
||||||
windowControlPosition: "right",
|
windowControlPosition: "right",
|
||||||
contentAreaScrolling: true
|
contentAreaScrolling: true,
|
||||||
|
showCursor: false
|
||||||
},
|
},
|
||||||
collectionList: {
|
collectionList: {
|
||||||
response: {},
|
response: {},
|
||||||
|
@ -302,6 +328,330 @@ const app = new Vue({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
simulateController() {
|
||||||
|
this.chrome.showCursor = true
|
||||||
|
let cursorPos = [0, 0];
|
||||||
|
let intTabIndex = 0
|
||||||
|
let self = this
|
||||||
|
const cursorSpeedPvt = 8
|
||||||
|
const cursorSize = 16
|
||||||
|
let scrollSpeed = 8
|
||||||
|
let buttonPressDelay = 500
|
||||||
|
let stickDeadZone = 0.2
|
||||||
|
let scrollGroup = null
|
||||||
|
let scrollGroupY = null
|
||||||
|
let elementFocusEnabled = true
|
||||||
|
|
||||||
|
let cursorSpeed = cursorSpeedPvt
|
||||||
|
|
||||||
|
let lastButtonPress = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var sounds = {
|
||||||
|
Confirm: new Audio("./sounds/confirm.ogg"),
|
||||||
|
Menu: new Audio("./sounds/btn1.ogg"),
|
||||||
|
Hover: new Audio("./sounds/hover.ogg")
|
||||||
|
}
|
||||||
|
|
||||||
|
let element = document.elementFromPoint(0, 0)
|
||||||
|
let elementType = 0
|
||||||
|
|
||||||
|
function appLoop() {
|
||||||
|
var gamepads = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : []);
|
||||||
|
if (!gamepads) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var gp = gamepads[0];
|
||||||
|
|
||||||
|
// LEFT STICK
|
||||||
|
if (gp.axes[0] > stickDeadZone) {
|
||||||
|
cursorPos[0] += (gp.axes[0] * cursorSpeed)
|
||||||
|
} else if (gp.axes[0] < -stickDeadZone) {
|
||||||
|
cursorPos[0] += (gp.axes[0] * cursorSpeed)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gp.axes[1] > stickDeadZone) {
|
||||||
|
cursorPos[1] += (gp.axes[1] * cursorSpeed)
|
||||||
|
} else if (gp.axes[1] < -stickDeadZone) {
|
||||||
|
cursorPos[1] += (gp.axes[1] * cursorSpeed)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursorPos[0] < cursorSize) {
|
||||||
|
cursorPos[0] = cursorSize
|
||||||
|
}
|
||||||
|
if (cursorPos[1] < cursorSize) {
|
||||||
|
cursorPos[1] = cursorSize
|
||||||
|
}
|
||||||
|
if (cursorPos[0] > window.innerWidth - cursorSize) {
|
||||||
|
cursorPos[0] = window.innerWidth - cursorSize
|
||||||
|
}
|
||||||
|
if (cursorPos[1] > window.innerHeight - cursorSize) {
|
||||||
|
cursorPos[1] = window.innerHeight - cursorSize
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// RIGHT STICK.
|
||||||
|
if (scrollGroupY) {
|
||||||
|
if (gp.axes[3] > stickDeadZone) {
|
||||||
|
$(scrollGroupY).scrollTop($(scrollGroupY).scrollTop() + (gp.axes[3] * scrollSpeed))
|
||||||
|
elementFocusEnabled = false
|
||||||
|
} else if (gp.axes[3] < -stickDeadZone) {
|
||||||
|
$(scrollGroupY).scrollTop($(scrollGroupY).scrollTop() + (gp.axes[3] * scrollSpeed))
|
||||||
|
elementFocusEnabled = false
|
||||||
|
} else {
|
||||||
|
elementFocusEnabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (scrollGroup) {
|
||||||
|
if (gp.axes[2] > stickDeadZone) {
|
||||||
|
$(scrollGroup).scrollLeft($(scrollGroup).scrollLeft() + (gp.axes[2] * scrollSpeed))
|
||||||
|
elementFocusEnabled = false
|
||||||
|
} else if (gp.axes[2] < -stickDeadZone) {
|
||||||
|
$(scrollGroup).scrollLeft($(scrollGroup).scrollLeft() + (gp.axes[2] * scrollSpeed))
|
||||||
|
elementFocusEnabled = false
|
||||||
|
} else {
|
||||||
|
elementFocusEnabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$(".cursor").css({
|
||||||
|
top: cursorPos[1] + "px",
|
||||||
|
left: cursorPos[0] + "px",
|
||||||
|
display: "block"
|
||||||
|
})
|
||||||
|
|
||||||
|
// A BUTTON
|
||||||
|
if (gp.buttons[0].pressed) {
|
||||||
|
if (!lastButtonPress["A"]) {
|
||||||
|
lastButtonPress["A"] = 0
|
||||||
|
}
|
||||||
|
if (Date.now() - lastButtonPress["A"] > buttonPressDelay) {
|
||||||
|
lastButtonPress["A"] = Date.now()
|
||||||
|
sounds.Confirm.play()
|
||||||
|
if (elementType == 0) {
|
||||||
|
document.activeElement.dispatchEvent(new Event("click"))
|
||||||
|
document.activeElement.dispatchEvent(new Event("controller-click"))
|
||||||
|
} else {
|
||||||
|
element.dispatchEvent(new Event("click"))
|
||||||
|
element.dispatchEvent(new Event("controller-click"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// B BUTTON
|
||||||
|
if (gp.buttons[1].pressed) {
|
||||||
|
|
||||||
|
if (!lastButtonPress["B"]) {
|
||||||
|
lastButtonPress["B"] = 0
|
||||||
|
}
|
||||||
|
if (Date.now() - lastButtonPress["B"] > buttonPressDelay) {
|
||||||
|
lastButtonPress["B"] = Date.now()
|
||||||
|
if (elementType == 0) {
|
||||||
|
document.activeElement.dispatchEvent(new Event("contextmenu"))
|
||||||
|
setTimeout(() => {
|
||||||
|
if ($(".menu-option").length > 0) {
|
||||||
|
let bounds = $(".menu-option")[0].getBoundingClientRect()
|
||||||
|
cursorPos[0] = bounds.left + (bounds.width / 2)
|
||||||
|
cursorPos[1] = bounds.top + (bounds.height / 2)
|
||||||
|
}
|
||||||
|
}, 100)
|
||||||
|
} else {
|
||||||
|
element.dispatchEvent(new Event("contextmenu"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// right bumper
|
||||||
|
if (gp.buttons[5].pressed) {
|
||||||
|
if (!lastButtonPress["RB"]) {
|
||||||
|
lastButtonPress["RB"] = 0
|
||||||
|
}
|
||||||
|
if (Date.now() - lastButtonPress["RB"] > buttonPressDelay) {
|
||||||
|
lastButtonPress["RB"] = Date.now()
|
||||||
|
app.navigateForward()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// left bumper
|
||||||
|
if (gp.buttons[4].pressed) {
|
||||||
|
if (!lastButtonPress["LB"]) {
|
||||||
|
lastButtonPress["LB"] = 0
|
||||||
|
}
|
||||||
|
if (Date.now() - lastButtonPress["LB"] > buttonPressDelay) {
|
||||||
|
lastButtonPress["LB"] = Date.now()
|
||||||
|
app.navigateBack()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// cursor hover
|
||||||
|
if (elementFocusEnabled) {
|
||||||
|
element = document.elementFromPoint(cursorPos[0], cursorPos[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
|
||||||
|
let closest = element.closest("[tabindex], input, button, a")
|
||||||
|
|
||||||
|
// VERT SCROLL
|
||||||
|
let scrollGroupCloY = element.closest(`[scrollaxis="y"]`)
|
||||||
|
if (scrollGroupCloY) {
|
||||||
|
scrollGroupY = scrollGroupCloY
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// HOZ SCROLL
|
||||||
|
let scrollGroupClo = element.closest(".v-hl-container")
|
||||||
|
|
||||||
|
if (scrollGroupClo) {
|
||||||
|
if (scrollGroupClo.classList.contains("v-hl-container")) {
|
||||||
|
scrollGroup = scrollGroupClo
|
||||||
|
scrollGroup.style["scroll-snap-type"] = "unset"
|
||||||
|
} else {
|
||||||
|
scrollGroup.style["scroll-snap-type"] = ""
|
||||||
|
scrollGroup = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closest) {
|
||||||
|
elementType = 0
|
||||||
|
closest.focus()
|
||||||
|
} else {
|
||||||
|
if (closest) {
|
||||||
|
closest.blur()
|
||||||
|
}
|
||||||
|
elementType = 1
|
||||||
|
element.focus()
|
||||||
|
}
|
||||||
|
cursorSpeed = cursorSpeedPvt
|
||||||
|
if (!element.classList.contains("app-chrome")
|
||||||
|
&& !element.classList.contains("app-content")) {
|
||||||
|
cursorSpeed = cursorSpeedPvt
|
||||||
|
}
|
||||||
|
// console.log($._data($(element), "events"))
|
||||||
|
} else {
|
||||||
|
cursorSpeed = 12
|
||||||
|
}
|
||||||
|
// console.log(gp.axes[0], gp.axes[1])
|
||||||
|
start = requestAnimationFrame(appLoop);
|
||||||
|
}
|
||||||
|
|
||||||
|
// controller pairing
|
||||||
|
notyf.error("Press the button on your controller to pair it to Cider.")
|
||||||
|
window.addEventListener("gamepadconnected", function (e) {
|
||||||
|
console.log("Gamepad connected at index %d: %s. %d buttons, %d axes.",
|
||||||
|
e.gamepad.index, e.gamepad.id,
|
||||||
|
e.gamepad.buttons.length, e.gamepad.axes.length);
|
||||||
|
notyf.success("Pairing successful!")
|
||||||
|
appLoop()
|
||||||
|
}, { once: true });
|
||||||
|
|
||||||
|
document.addEventListener("keydown", (e) => {
|
||||||
|
sounds.Confirm.currentTime = 0
|
||||||
|
sounds.Menu.currentTime = 0
|
||||||
|
sounds.Hover.currentTime = 0
|
||||||
|
let tabbable = $("[tabindex]")
|
||||||
|
console.log(e.key)
|
||||||
|
switch (e.key) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case "ArrowLeft":
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
cursorPos[0] -= cursorSpeed
|
||||||
|
break;
|
||||||
|
case "ArrowRight":
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
cursorPos[0] += cursorSpeed
|
||||||
|
break;
|
||||||
|
case "ArrowUp":
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
cursorPos[1] -= cursorSpeed
|
||||||
|
// sounds.Hover.play()
|
||||||
|
// if(intTabIndex <= 0) {
|
||||||
|
// intTabIndex = 0
|
||||||
|
// }else{
|
||||||
|
// intTabIndex--
|
||||||
|
// }
|
||||||
|
// $(tabbable[intTabIndex]).focus()
|
||||||
|
// $("#app-content").scrollTop($(document.activeElement).offset().top)
|
||||||
|
break;
|
||||||
|
case "ArrowDown":
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
cursorPos[1] += cursorSpeed
|
||||||
|
// if(intTabIndex < tabbable.length) {
|
||||||
|
// intTabIndex++
|
||||||
|
// }else{
|
||||||
|
// intTabIndex = tabbable.length
|
||||||
|
// }
|
||||||
|
// $(tabbable[intTabIndex]).focus()
|
||||||
|
// $("#app-content").scrollTop($(document.activeElement).offset().top)
|
||||||
|
break;
|
||||||
|
case "c":
|
||||||
|
app.resetState()
|
||||||
|
break;
|
||||||
|
case "x":
|
||||||
|
// set cursorPos to the top right of the screen
|
||||||
|
// sounds.Menu.play()
|
||||||
|
if (elementType == 0) {
|
||||||
|
document.activeElement.dispatchEvent(new Event("contextmenu"))
|
||||||
|
} else {
|
||||||
|
element.dispatchEvent(new Event("contextmenu"))
|
||||||
|
}
|
||||||
|
|
||||||
|
e.preventDefault()
|
||||||
|
break;
|
||||||
|
case "z":
|
||||||
|
sounds.Confirm.play()
|
||||||
|
if (elementType == 0) {
|
||||||
|
document.activeElement.dispatchEvent(new Event("click"))
|
||||||
|
document.activeElement.dispatchEvent(new Event("controller-click"))
|
||||||
|
} else {
|
||||||
|
element.dispatchEvent(new Event("click"))
|
||||||
|
element.dispatchEvent(new Event("controller-click"))
|
||||||
|
}
|
||||||
|
|
||||||
|
e.preventDefault()
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(".cursor").css({
|
||||||
|
top: cursorPos[1] + "px",
|
||||||
|
left: cursorPos[0] + "px"
|
||||||
|
})
|
||||||
|
function lerp(a, b, n) {
|
||||||
|
return (1 - n) * a + n * b
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
element = document.elementFromPoint(cursorPos[0], cursorPos[1])
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
let closest = element.closest("[tabindex], input, button, a")
|
||||||
|
if (closest) {
|
||||||
|
elementType = 0
|
||||||
|
closest.focus()
|
||||||
|
} else {
|
||||||
|
elementType = 1
|
||||||
|
element.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(element)
|
||||||
|
});
|
||||||
|
},
|
||||||
songLinkShare(amUrl) {
|
songLinkShare(amUrl) {
|
||||||
notyf.open({ type: "info", className: "notyf-info", message: app.getLz('term.song.link.generate') })
|
notyf.open({ type: "info", className: "notyf-info", message: app.getLz('term.song.link.generate') })
|
||||||
let self = this
|
let self = this
|
||||||
|
@ -675,12 +1025,14 @@ const app = new Vue({
|
||||||
// })
|
// })
|
||||||
|
|
||||||
// load cached library
|
// load cached library
|
||||||
if (localStorage.getItem("librarySongs") != null) {
|
let librarySongs = await CiderCache.getCache("library-songs")
|
||||||
this.library.songs.listing = JSON.parse(localStorage.getItem("librarySongs"))
|
let libraryAlbums = await CiderCache.getCache("library-albums")
|
||||||
|
if (librarySongs) {
|
||||||
|
this.library.songs.listing = librarySongs
|
||||||
this.library.songs.displayListing = this.library.songs.listing
|
this.library.songs.displayListing = this.library.songs.listing
|
||||||
}
|
}
|
||||||
if (localStorage.getItem("libraryAlbums") != null) {
|
if (libraryAlbums) {
|
||||||
this.library.albums.listing = JSON.parse(localStorage.getItem("libraryAlbums"))
|
this.library.albums.listing = libraryAlbums
|
||||||
this.library.albums.displayListing = this.library.albums.listing
|
this.library.albums.displayListing = this.library.albums.listing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,11 +1137,20 @@ const app = new Vue({
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcRenderer.on('SoundCheckTag', (event, tag) => {
|
ipcRenderer.on('SoundCheckTag', (event, tag) => {
|
||||||
let replaygain = self.parseSCTagToRG(tag)
|
// let replaygain = self.parseSCTagToRG(tag)
|
||||||
console.debug(`[Cider][MaikiwiSoundCheck] Replay Gain: ${JSON.stringify(replaygain)} | Attenuating '${Math.log10(replaygain.gain) * 20}' dB`)
|
let soundcheck = tag.split(" ")
|
||||||
|
let numbers = []
|
||||||
|
for (item of soundcheck) {
|
||||||
|
numbers.push(parseInt(item, 16))
|
||||||
|
|
||||||
|
}
|
||||||
|
numbers.shift()
|
||||||
|
let peak = Math.max(numbers[6], numbers[7]) / 32768.0
|
||||||
|
let gain = Math.pow(10, ((-7.63 - (Math.log10(peak) * 20)) / 20))// EBU R 128 Compliant
|
||||||
|
console.debug(`[Cider][MaikiwiSoundCheck] Peak Gain: ${Math.log10(peak) * 20} | Adjusting '${Math.log10(gain) * 20}' dB`)
|
||||||
try {
|
try {
|
||||||
//CiderAudio.audioNodes.gainNode.gain.value = (Math.min(Math.pow(10, (replaygain.gain / 20)), (1 / replaygain.peak)))
|
//CiderAudio.audioNodes.gainNode.gain.value = (Math.min(Math.pow(10, (replaygain.gain / 20)), (1 / replaygain.peak)))
|
||||||
CiderAudio.audioNodes.gainNode.gain.value = replaygain.gain
|
CiderAudio.audioNodes.gainNode.gain.value = gain
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -888,7 +1249,7 @@ const app = new Vue({
|
||||||
this.cfg.audio.volume = this.mk.volume
|
this.cfg.audio.volume = this.mk.volume
|
||||||
})
|
})
|
||||||
|
|
||||||
this.refreshPlaylists()
|
this.refreshPlaylists(this.isDev)
|
||||||
document.body.removeAttribute("loading")
|
document.body.removeAttribute("loading")
|
||||||
if (window.location.hash != "") {
|
if (window.location.hash != "") {
|
||||||
this.appRoute(window.location.hash)
|
this.appRoute(window.location.hash)
|
||||||
|
@ -905,7 +1266,7 @@ const app = new Vue({
|
||||||
}, 500)
|
}, 500)
|
||||||
ipcRenderer.invoke("renderer-ready", true)
|
ipcRenderer.invoke("renderer-ready", true)
|
||||||
document.querySelector("#LOADER").remove()
|
document.querySelector("#LOADER").remove()
|
||||||
if(this.cfg.general.themeUpdateNotification) {
|
if (this.cfg.general.themeUpdateNotification) {
|
||||||
this.checkForThemeUpdates()
|
this.checkForThemeUpdates()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -919,7 +1280,7 @@ const app = new Vue({
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res[0].sha != theme.commit) {
|
if (res[0].sha != theme.commit) {
|
||||||
const notify = notyf.open({ className: "notyf-info", type: "info", message: `[Themes] ${theme.name} has an update available.` })
|
const notify = notyf.open({ className: "notyf-info", type: "info", message: `[Themes] ${theme.name} has an update available.` })
|
||||||
notify.on("click", ()=>{
|
notify.on("click", () => {
|
||||||
app.appRoute("themes-github")
|
app.appRoute("themes-github")
|
||||||
notyf.dismiss(notify)
|
notyf.dismiss(notify)
|
||||||
})
|
})
|
||||||
|
@ -965,9 +1326,9 @@ const app = new Vue({
|
||||||
}
|
}
|
||||||
if (directives[directive]) {
|
if (directives[directive]) {
|
||||||
return this.chrome.appliedTheme.info.directives[directive].value
|
return this.chrome.appliedTheme.info.directives[directive].value
|
||||||
} else if(this.cfg.visual.directives[directive]) {
|
} else if (this.cfg.visual.directives[directive]) {
|
||||||
return this.cfg.visual.directives.windowLayout
|
return this.cfg.visual.directives.windowLayout
|
||||||
}else{
|
} else {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1041,15 +1402,81 @@ const app = new Vue({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async refreshPlaylists() {
|
async refreshPlaylists(localOnly = false, trackMap = true) {
|
||||||
let self = this
|
let self = this
|
||||||
this.apiCall('https://api.music.apple.com/v1/me/library/playlist-folders/p.playlistsroot/children/', res => {
|
let newListing = []
|
||||||
self.playlists.listing = res.data
|
let trackMapping = {}
|
||||||
self.playlists.listing.forEach(playlist => {
|
const cachedPlaylist = await CiderCache.getCache("library-playlists")
|
||||||
playlist.parent = "p.playlistsroot"
|
const cachedTrackMapping = await CiderCache.getCache("library-playlists-tracks")
|
||||||
})
|
|
||||||
|
if (cachedPlaylist) {
|
||||||
|
console.log("using cached playlists")
|
||||||
|
this.playlists.listing = cachedPlaylist
|
||||||
self.sortPlaylists()
|
self.sortPlaylists()
|
||||||
})
|
} else {
|
||||||
|
console.log("playlist has no cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cachedTrackMapping) {
|
||||||
|
console.log("using cached track mapping")
|
||||||
|
this.playlists.trackMapping = cachedTrackMapping
|
||||||
|
}
|
||||||
|
if (localOnly) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.library.backgroundNotification.message = "Building playlist cache..."
|
||||||
|
this.library.backgroundNotification.show = true
|
||||||
|
|
||||||
|
async function deepScan(parent = "p.playlistsroot") {
|
||||||
|
console.log(`scanning ${parent}`)
|
||||||
|
const playlistData = await app.mk.api.v3.music(`/v1/me/library/playlist-folders/${parent}/children/`)
|
||||||
|
await asyncForEach(playlistData.data.data, async (playlist) => {
|
||||||
|
playlist.parent = parent
|
||||||
|
playlist.children = []
|
||||||
|
playlist.tracks = []
|
||||||
|
try {
|
||||||
|
if (trackMap) {
|
||||||
|
let tracks = await app.mk.api.v3.music(playlist.href + "/tracks").catch(e => {
|
||||||
|
// no tracks
|
||||||
|
e = null
|
||||||
|
})
|
||||||
|
tracks.data.data.forEach(track => {
|
||||||
|
if (!trackMapping[track.id]) {
|
||||||
|
trackMapping[track.id] = []
|
||||||
|
}
|
||||||
|
trackMapping[track.id].push(playlist.id)
|
||||||
|
|
||||||
|
if (typeof track.attributes.playParams.catalogId == "string") {
|
||||||
|
if (!trackMapping[track.attributes.playParams.catalogId]) {
|
||||||
|
trackMapping[track.attributes.playParams.catalogId] = []
|
||||||
|
}
|
||||||
|
trackMapping[track.attributes.playParams.catalogId].push(playlist.id)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (e) { }
|
||||||
|
if (playlist.type == "library-playlist-folders") {
|
||||||
|
try {
|
||||||
|
await deepScan(playlist.id).catch(e => { })
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newListing.push(playlist)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
await deepScan()
|
||||||
|
|
||||||
|
this.library.backgroundNotification.show = false
|
||||||
|
this.playlists.listing = newListing
|
||||||
|
self.sortPlaylists()
|
||||||
|
if (trackMap) {
|
||||||
|
CiderCache.putCache("library-playlists-tracks", trackMapping)
|
||||||
|
this.playlists.trackMapping = trackMapping
|
||||||
|
}
|
||||||
|
CiderCache.putCache("library-playlists", newListing)
|
||||||
},
|
},
|
||||||
sortPlaylists() {
|
sortPlaylists() {
|
||||||
this.playlists.listing.sort((a, b) => {
|
this.playlists.listing.sort((a, b) => {
|
||||||
|
@ -2063,6 +2490,7 @@ const app = new Vue({
|
||||||
async getLibrarySongsFull(force = false) {
|
async getLibrarySongsFull(force = false) {
|
||||||
let self = this
|
let self = this
|
||||||
let library = []
|
let library = []
|
||||||
|
let cacheId = "library-songs"
|
||||||
let downloaded = null;
|
let downloaded = null;
|
||||||
if ((this.library.songs.downloadState == 2) && !force) {
|
if ((this.library.songs.downloadState == 2) && !force) {
|
||||||
return
|
return
|
||||||
|
@ -2070,8 +2498,9 @@ const app = new Vue({
|
||||||
if (this.library.songs.downloadState == 1) {
|
if (this.library.songs.downloadState == 1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (localStorage.getItem("librarySongs") != null) {
|
let librarySongs = await CiderCache.getCache(cacheId)
|
||||||
this.library.songs.listing = JSON.parse(localStorage.getItem("librarySongs"))
|
if (librarySongs) {
|
||||||
|
this.library.songs.listing = librarySongs
|
||||||
this.searchLibrarySongs()
|
this.searchLibrarySongs()
|
||||||
}
|
}
|
||||||
if (this.songstest) {
|
if (this.songstest) {
|
||||||
|
@ -2148,7 +2577,7 @@ const app = new Vue({
|
||||||
self.library.songs.downloadState = 2
|
self.library.songs.downloadState = 2
|
||||||
self.library.backgroundNotification.show = false
|
self.library.backgroundNotification.show = false
|
||||||
self.searchLibrarySongs()
|
self.searchLibrarySongs()
|
||||||
localStorage.setItem("librarySongs", JSON.stringify(library))
|
CiderCache.putCache(cacheId, library)
|
||||||
}
|
}
|
||||||
if (downloaded.meta.total > library.length || typeof downloaded.meta.next != "undefined") {
|
if (downloaded.meta.total > library.length || typeof downloaded.meta.next != "undefined") {
|
||||||
console.log(`downloading next chunk - ${library.length} songs so far`)
|
console.log(`downloading next chunk - ${library.length} songs so far`)
|
||||||
|
@ -2158,7 +2587,7 @@ const app = new Vue({
|
||||||
self.library.songs.downloadState = 2
|
self.library.songs.downloadState = 2
|
||||||
self.library.backgroundNotification.show = false
|
self.library.backgroundNotification.show = false
|
||||||
self.searchLibrarySongs()
|
self.searchLibrarySongs()
|
||||||
localStorage.setItem("librarySongs", JSON.stringify(library))
|
CiderCache.putCache(cacheId, library)
|
||||||
// console.log(library)
|
// console.log(library)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2169,12 +2598,14 @@ const app = new Vue({
|
||||||
async getLibraryAlbumsFull(force = false, index) {
|
async getLibraryAlbumsFull(force = false, index) {
|
||||||
let self = this
|
let self = this
|
||||||
let library = []
|
let library = []
|
||||||
|
let cacheId = "library-albums"
|
||||||
let downloaded = null;
|
let downloaded = null;
|
||||||
if ((this.library.albums.downloadState == 2 || this.library.albums.downloadState == 1) && !force) {
|
if ((this.library.albums.downloadState == 2 || this.library.albums.downloadState == 1) && !force) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (localStorage.getItem("libraryAlbums") != null) {
|
let libraryAlbums = await CiderCache.getCache(cacheId)
|
||||||
this.library.albums.listing = JSON.parse(localStorage.getItem("libraryAlbums"))
|
if (libraryAlbums) {
|
||||||
|
this.library.albums.listing = libraryAlbums
|
||||||
this.searchLibraryAlbums(index)
|
this.searchLibraryAlbums(index)
|
||||||
}
|
}
|
||||||
if (this.songstest) {
|
if (this.songstest) {
|
||||||
|
@ -2255,7 +2686,7 @@ const app = new Vue({
|
||||||
self.library.albums.listing = library
|
self.library.albums.listing = library
|
||||||
self.library.albums.downloadState = 2
|
self.library.albums.downloadState = 2
|
||||||
self.library.backgroundNotification.show = false
|
self.library.backgroundNotification.show = false
|
||||||
localStorage.setItem("libraryAlbums", JSON.stringify(library))
|
CiderCache.putCache(cacheId, library)
|
||||||
self.searchLibraryAlbums(index)
|
self.searchLibraryAlbums(index)
|
||||||
}
|
}
|
||||||
if (downloaded.meta.total > library.length || typeof downloaded.meta.next != "undefined") {
|
if (downloaded.meta.total > library.length || typeof downloaded.meta.next != "undefined") {
|
||||||
|
@ -2266,7 +2697,7 @@ const app = new Vue({
|
||||||
self.library.albums.listing = library
|
self.library.albums.listing = library
|
||||||
self.library.albums.downloadState = 2
|
self.library.albums.downloadState = 2
|
||||||
self.library.backgroundNotification.show = false
|
self.library.backgroundNotification.show = false
|
||||||
localStorage.setItem("libraryAlbums", JSON.stringify(library))
|
CiderCache.putCache(cacheId, library)
|
||||||
self.searchLibraryAlbums(index)
|
self.searchLibraryAlbums(index)
|
||||||
// console.log(library)
|
// console.log(library)
|
||||||
}
|
}
|
||||||
|
@ -2278,12 +2709,14 @@ const app = new Vue({
|
||||||
async getLibraryArtistsFull(force = false, index) {
|
async getLibraryArtistsFull(force = false, index) {
|
||||||
let self = this
|
let self = this
|
||||||
let library = []
|
let library = []
|
||||||
|
let cacheId = "library-artists"
|
||||||
let downloaded = null;
|
let downloaded = null;
|
||||||
if ((this.library.artists.downloadState == 2 || this.library.artists.downloadState == 1) && !force) {
|
if ((this.library.artists.downloadState == 2 || this.library.artists.downloadState == 1) && !force) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (localStorage.getItem("libraryArtists") != null) {
|
let libraryArtists = await CiderCache.getCache(cacheId)
|
||||||
this.library.artists.listing = JSON.parse(localStorage.getItem("libraryArtists"))
|
if (libraryArtists) {
|
||||||
|
this.library.artists.listing = libraryArtists
|
||||||
this.searchLibraryArtists(index)
|
this.searchLibraryArtists(index)
|
||||||
}
|
}
|
||||||
if (this.songstest) {
|
if (this.songstest) {
|
||||||
|
@ -2362,7 +2795,7 @@ const app = new Vue({
|
||||||
self.library.artists.listing = library
|
self.library.artists.listing = library
|
||||||
self.library.artists.downloadState = 2
|
self.library.artists.downloadState = 2
|
||||||
self.library.artists.show = false
|
self.library.artists.show = false
|
||||||
localStorage.setItem("libraryArtists", JSON.stringify(library))
|
CiderCache.putCache(cacheId, library)
|
||||||
self.searchLibraryArtists(index)
|
self.searchLibraryArtists(index)
|
||||||
}
|
}
|
||||||
if (downloaded.meta.total > library.length || typeof downloaded.meta.next != "undefined") {
|
if (downloaded.meta.total > library.length || typeof downloaded.meta.next != "undefined") {
|
||||||
|
@ -2373,7 +2806,7 @@ const app = new Vue({
|
||||||
self.library.artists.listing = library
|
self.library.artists.listing = library
|
||||||
self.library.artists.downloadState = 2
|
self.library.artists.downloadState = 2
|
||||||
self.library.backgroundNotification.show = false
|
self.library.backgroundNotification.show = false
|
||||||
localStorage.setItem("libraryArtists", JSON.stringify(library))
|
CiderCache.putCache(cacheId, library)
|
||||||
self.searchLibraryArtists(index)
|
self.searchLibraryArtists(index)
|
||||||
// console.log(library)
|
// console.log(library)
|
||||||
}
|
}
|
||||||
|
@ -3397,7 +3830,7 @@ const app = new Vue({
|
||||||
let artworkSize = 50
|
let artworkSize = 50
|
||||||
if (app.getThemeDirective("lcdArtworkSize") != "") {
|
if (app.getThemeDirective("lcdArtworkSize") != "") {
|
||||||
artworkSize = app.getThemeDirective("lcdArtworkSize")
|
artworkSize = app.getThemeDirective("lcdArtworkSize")
|
||||||
}else if(this.cfg.visual.directives.windowLayout == "twopanel") {
|
} else if (this.cfg.visual.directives.windowLayout == "twopanel") {
|
||||||
artworkSize = 70
|
artworkSize = 70
|
||||||
}
|
}
|
||||||
this.currentArtUrl = '';
|
this.currentArtUrl = '';
|
||||||
|
@ -3835,6 +4268,7 @@ const app = new Vue({
|
||||||
element.onclick = app.LastFMDeauthorize;
|
element.onclick = app.LastFMDeauthorize;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
parseSCTagToRG: function (tag) {
|
parseSCTagToRG: function (tag) {
|
||||||
let soundcheck = tag.split(" ")
|
let soundcheck = tag.split(" ")
|
||||||
let numbers = []
|
let numbers = []
|
||||||
|
@ -3850,7 +4284,7 @@ const app = new Vue({
|
||||||
gain: gain,
|
gain: gain,
|
||||||
peak: peak
|
peak: peak
|
||||||
}
|
}
|
||||||
},
|
},*/
|
||||||
fullscreen(flag) {
|
fullscreen(flag) {
|
||||||
if (flag) {
|
if (flag) {
|
||||||
ipcRenderer.send('setFullScreen', true);
|
ipcRenderer.send('setFullScreen', true);
|
||||||
|
@ -4306,6 +4740,24 @@ async function webGPU() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isJson(item) {
|
||||||
|
item = typeof item !== "string"
|
||||||
|
? JSON.stringify(item)
|
||||||
|
: item;
|
||||||
|
|
||||||
|
try {
|
||||||
|
item = JSON.parse(item);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof item === "object" && item !== null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
webGPU().then()
|
webGPU().then()
|
||||||
|
|
||||||
let screenWidth = screen.width;
|
let screenWidth = screen.width;
|
||||||
|
|
BIN
src/renderer/sounds/btn1.ogg
Normal file
BIN
src/renderer/sounds/btn1.ogg
Normal file
Binary file not shown.
BIN
src/renderer/sounds/confirm.ogg
Normal file
BIN
src/renderer/sounds/confirm.ogg
Normal file
Binary file not shown.
BIN
src/renderer/sounds/hover.ogg
Normal file
BIN
src/renderer/sounds/hover.ogg
Normal file
Binary file not shown.
|
@ -3152,6 +3152,20 @@ body[platform='darwin'] {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cursor {
|
||||||
|
background: rgb(255 255 255 / 50%);
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 9999999999;
|
||||||
|
pointer-events: none;
|
||||||
|
border-radius: 100%;
|
||||||
|
box-shadow: 0px 0px 0px 2px rgb(200 200 200 / 100%);
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
@import url("less/macos.less");
|
@import url("less/macos.less");
|
||||||
@import url("less/linux.less");
|
@import url("less/linux.less");
|
||||||
@import url("less/compact.less");
|
@import url("less/compact.less");
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div id="app-content" :style="{'overflow': (chrome.contentAreaScrolling ? '' : 'hidden')}">
|
<div id="app-content" scrollaxis="y" :style="{'overflow': (chrome.contentAreaScrolling ? '' : 'hidden')}">
|
||||||
<div id="navigation-bar">
|
<div id="navigation-bar">
|
||||||
<button class="nav-item" @click="navigateBack()">
|
<button class="nav-item" @click="navigateBack()">
|
||||||
<%- include('../svg/chevron-left.svg') %>
|
<%- include('../svg/chevron-left.svg') %>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-sidebar-content">
|
<div class="app-sidebar-content" scrollaxis="y">
|
||||||
<div class="app-sidebar-header-text">
|
<div class="app-sidebar-header-text">
|
||||||
{{$root.getLz('app.name')}}
|
{{$root.getLz('app.name')}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script type="text/x-template" id="artist-chip">
|
<script type="text/x-template" id="artist-chip">
|
||||||
<div class="artist-chip" @click.self="route">
|
<div class="artist-chip" @click.self="route" tabindex="0">
|
||||||
<div class="artist-chip__image">
|
<div class="artist-chip__image">
|
||||||
<mediaitem-artwork v-if="artist.id != null" :url="artist.attributes.artwork.url" :size="32"></mediaitem-artwork>
|
<mediaitem-artwork v-if="artist.id != null" :url="artist.attributes.artwork.url" :size="32"></mediaitem-artwork>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
@mouseenter="checkLibrary"
|
@mouseenter="checkLibrary"
|
||||||
@mouseover="showInLibrary = true"
|
@mouseover="showInLibrary = true"
|
||||||
@mouseleave="showInLibrary = false"
|
@mouseleave="showInLibrary = false"
|
||||||
|
@dblclick="route()"
|
||||||
|
@controller-click="route()"
|
||||||
|
tabindex="0"
|
||||||
:class="[{'mediaitem-selected': app.select_hasMediaItem(guid)}, addClasses]">
|
:class="[{'mediaitem-selected': app.select_hasMediaItem(guid)}, addClasses]">
|
||||||
<template v-if="isVisible">
|
<template v-if="isVisible">
|
||||||
<div class="isLibrary" v-if="showLibraryStatus == true">
|
<div class="isLibrary" v-if="showLibraryStatus == true">
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<script type="text/x-template" id="mediaitem-square">
|
<script type="text/x-template" id="mediaitem-square">
|
||||||
<div tabindex="0"
|
<div
|
||||||
|
tabindex="0"
|
||||||
|
@click.self="app.routeView(item)"
|
||||||
|
@controller-click="app.routeView(item)"
|
||||||
|
@contextmenu.self="contextMenu"
|
||||||
class="cd-mediaitem-square" :class="getClasses()" @contextmenu="contextMenu"
|
class="cd-mediaitem-square" :class="getClasses()" @contextmenu="contextMenu"
|
||||||
v-observe-visibility="{callback: visibilityChanged}"
|
v-observe-visibility="{callback: visibilityChanged}"
|
||||||
:style="{'--spcolor': getBgColor()}">
|
:style="{'--spcolor': getBgColor()}">
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
<%- include('app/panels'); %>
|
<%- include('app/panels'); %>
|
||||||
|
<div class="cursor" v-if="chrome.showCursor"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<% for(var i=0; i < Object.keys(env.components).length ; i++) {%>
|
<% for(var i=0; i < Object.keys(env.components).length ; i++) {%>
|
||||||
|
|
|
@ -673,6 +673,17 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="md-option-line">
|
||||||
|
<div class="md-option-segment">
|
||||||
|
{{$root.getLz('settings.option.advanced.playlistTrackMapping')}}
|
||||||
|
<br>
|
||||||
|
<small>{{$root.getLz('settings.option.advanced.playlistTrackMapping.description')}}</small>
|
||||||
|
</div>
|
||||||
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
|
<input type="checkbox" v-model="app.cfg.advanced.playlistTrackMapping" switch/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="md-option-line">
|
<div class="md-option-line">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue