Skip to content

Commit

Permalink
Sync 0.1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
YanJi314 committed Aug 28, 2024
1 parent c14b0f9 commit da661b3
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 54 deletions.
2 changes: 2 additions & 0 deletions src/frontend/assets/components/PublicConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const defaultConfig = {
loop: 0,
lrcShow: true,
musicFormats: ".mp3 .wav .flac",
showLocator: true,
themeImageType: "cover",
backgroundBlur: true,
audioFade: true,
lyricBlur: true,
Expand Down
35 changes: 18 additions & 17 deletions src/frontend/assets/components/SimAP.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const switchMusic = (playConfig) => {
});
SimAPControls.loadLoop();
document.title = playConfig.title + " - SimMusic";
loadThemeImage();
// 初始化背景
document.getElementById("album").onload = () => {
const themeColors = SimAPTools.getTopColors(document.getElementById("album"));
Expand Down Expand Up @@ -163,6 +164,7 @@ const PlayerBackground = {
},
animate(isInit) {
requestAnimationFrame(() => {PlayerBackground.animate();});
if (!config.getItem("backgroundBlur")) return;
if (!document.body.classList.contains("playing") && !isInit) return;
const ctx = PlayerBackground.ctx;
ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
Expand All @@ -172,24 +174,23 @@ const PlayerBackground = {
blob.y += blob.dy;
if (blob.x - blob.radius < 0 || blob.x + blob.radius > window.innerWidth) blob.dx *= -1;
if (blob.y - blob.radius < 0 || blob.y + blob.radius > window.innerHeight) blob.dy *= -1;
// 绘制
}
PlayerBackground.drawBlobs();
},
update(mainColor, subColors) {
document.getElementById("background").style.background = mainColor;
this.mainColor = mainColor;
this.blobs = [];
for (let i = 0; i < 3; i++) {
this.blobs.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
radius: Math.random() * screen.width / 3 + screen.width / 5,
color: subColors[i],
dx: ((Math.random() < 0.5) ? 1 : -1) * (Math.random() * 0.5 + 0.5),
dy: ((Math.random() < 0.5) ? 1 : -1) * (Math.random() * 0.5 + 0.5),
});
}
for (let i = 0; i < 3; i++) {
this.blobs.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
radius: Math.random() * screen.width / 3 + screen.width / 5,
color: subColors[i],
dx: ((Math.random() < 0.5) ? 1 : -1) * (Math.random() * 0.5 + 0.5),
dy: ((Math.random() < 0.5) ? 1 : -1) * (Math.random() * 0.5 + 0.5),
});
}
PlayerBackground.drawBlobs();
},
drawBlobs() {
Expand Down Expand Up @@ -224,13 +225,13 @@ const SimAPControls = {
const isPlay = audio.paused;
document.body.classList[isPlay ? "add" : "remove"]("playing");
SimAPControls.loadAudioState();
clearInterval(this.audioFadeInterval);
clearInterval(SimAPControls.audioFadeInterval);
// 音频淡入淡出处理
if (config.getItem("audioFade")) {
if (config.getItem("audioFade") && audio.volume) {
const configVolume = config.getItem("volume");
const volumeOffset = configVolume / 10;
if (isPlay) audio.play();
this.audioFadeInterval = setInterval(() => {
SimAPControls.audioFadeInterval = setInterval(() => {
if (isPlay) {
const newVolume = audio.volume + volumeOffset;
if (newVolume > configVolume) {
Expand All @@ -253,10 +254,10 @@ const SimAPControls = {
},
prev() {
const audio = document.getElementById("audio");
if (!config.getItem("fastPlayback") || audio.currentTime / audio.duration < .9) this.switchIndex(-1);
if (!config.getItem("fastPlayback") || audio.currentTime / audio.duration < .9) SimAPControls.switchIndex(-1);
else audio.currentTime = 0;
},
next() {this.switchIndex(1);},
next() {SimAPControls.switchIndex(1);},
switchIndex(offset) {
const list = config.getItem("playList");
const currentPlayingIndex = list.indexOf(config.getItem("currentMusic"));
Expand Down Expand Up @@ -353,7 +354,7 @@ const SimAPUI = {
hide() {
if (this.playingAnimation) return;
if (!document.body.classList.contains("playerShown")) return;
document.exitFullscreen();
document.exitFullscreen().catch(() => {});
document.body.classList.remove("playerShown");
this.playingAnimation = true;
setTimeout(() => {
Expand Down
1 change: 1 addition & 0 deletions src/frontend/assets/components/require.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ const {ipcRenderer, shell} = require("electron");
const fs = require("fs");
const path = require("path");
const musicMetadata = require("music-metadata");
const flacTagger = require("flac-tagger");
const nodeId3 = require("node-id3");
const fflate = require("fflate");
15 changes: 12 additions & 3 deletions src/frontend/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ body:not(.disableHighlight) .right #musicListContainer .tableContainer table td>
.right #musicListContainer .tableContainer table tr:active{background:rgba(0,0,0,.05);}
.right #musicListContainer .tableContainer table tr.active{color:#1E9FFF;}
.right #musicListContainer .tableContainer table tr.selected{background:#DAEFFF!important;}
.right #musicListContainer .musicLocator{position:absolute;right:20px;bottom:100px;height:40px;width:40px;border:1px solid rgba(0,0,0,.1);border-radius:50%;background:rgba(252,252,252,.9);backdrop-filter:blur(20px);font-size:1.2em;display:flex;align-items:center;justify-content:center;transition:all .2s;}
.right #musicListContainer .musicLocator:hover{color:#1E9FFF;}
.right #musicListContainer .musicLocator:active{color:#1E9FFF;transform:scale(.95);filter:brightness(.95);}
.right #musicListContainer .musicLocator.hidden{transform:scale(.2);opacity:0;pointer-events:none;}
.right #musicListContainer .musicListErrorOverlay{position:absolute;inset:180px 0 80px 0;display:flex;align-items:center;justify-content:center;flex-direction:column;}
.right #musicListContainer .musicListErrorOverlay img{width:120px;}
.right #musicListContainer .musicListErrorOverlay div{opacity:.5;margin-top:10px;font-size:1.2em;text-align:center;}
Expand Down Expand Up @@ -203,6 +207,11 @@ body:not(.disableHighlight) .right #musicListContainer .tableContainer table td>
.dragOver #dropTipContainer{opacity:1;}


/* 主窗体 - 主题图片 */
#themeImage{position:fixed;inset:0;width:100%;height:100%;object-fit:cover;opacity:.05;z-index:40;transition:opacity .2s;}
body:not(.themeImage) #themeImage{opacity:0;}
.themeImage #bottom,.themeImage .musicListTitle,.themeImage .right .page .header,.themeImage .musicLocator{background:rgba(255,255,255,.9);}


/* 主窗体 - 底部控件 */
.bottom{position:fixed;bottom:-90px;height:80px;width:100%;background:rgba(252,252,252,.9);backdrop-filter:blur(20px);transition:bottom .2s;}
Expand All @@ -217,7 +226,7 @@ body:not(.disableHighlight) .right #musicListContainer .tableContainer table td>
.bottom .info .img::after{content:"\EA78";font-size:2.5em;background:rgba(0,0,0,.2);position:absolute;inset:0;font-family:"icon";display:flex;align-items:center;justify-content:center;color:white;opacity:0;transition:opacity .2s;}
.bottom .info .img:hover::after,.bottom .info .img:active::after{opacity:1;}
.bottom .info .img>img{width:100%;height:100%;object-fit:cover;}
.bottom .info .musicInfoBottom{max-width:200px;margin-bottom:5px;}
.bottom .info .musicInfoBottom{max-width:200px;}
.bottom .info .musicInfoBottom b{font-size:1.1em;}
.bottom .info .musicInfoBottom>div{position:relative;}
.bottom .info .musicInfoBottom>div div{transition:opacity .2s,transform .2s;}
Expand All @@ -233,7 +242,7 @@ body:not(.miniModeStatus) .bottom .info .musicInfoBottom>div #miniModeStatus{tra


/* 主窗体 - 播放内页 */
#playPage{position:fixed;top:120vh;left:0;width:100%;height:100%;background:white;transition:top .3s;overflow:hidden;user-select:none;}
#playPage{position:fixed;top:120vh;left:0;width:100%;height:100%;background:white;transition:top .3s;overflow:hidden;user-select:none;z-index:50;}
.playerShown #playPage{top:0;}


Expand All @@ -250,7 +259,7 @@ body:not(.miniModeStatus) .bottom .info .musicInfoBottom>div #miniModeStatus{tra
.miniMode .bottom .info{top:0;bottom:0!important;left:0;width:170px;bottom:10px;}
.miniMode .bottom .info .img{width:60px;height:60px;border-radius:0;margin-right:10px;-webkit-app-region:drag;}
.miniMode .bottom .info .img::after{display:none;}
.miniMode .bottom .info .musicInfoBottom{font-size:1.1em;max-width:calc(100px / .75);zoom:.75;}
.miniMode .bottom .info .musicInfoBottom{font-size:1.1em;max-width:calc(100px / .75);zoom:.75;margin-bottom:5px;}
.miniMode .bottom .info .musicInfoBottom>div{margin-top:-1px;}
.miniMode .bottom .center{right:15px;zoom:.7;bottom:7.5px;width:220px;left:unset;}
.miniMode .bottom .center .bottomListBtn{display:none;}
Expand Down
137 changes: 115 additions & 22 deletions src/frontend/assets/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SimMusicVersion = "0.1.2";
SimMusicVersion = "0.1.3";


// 窗口处理
Expand Down Expand Up @@ -49,11 +49,12 @@ document.documentElement.onkeydown = e => {
if (document.activeElement.tagName.toLowerCase() == "input") return;
e.preventDefault();
if (document.activeElement.tagName.toLowerCase() == "input") return;
const moveOffset = e.ctrlKey ? 10 : 1;
switch (e.key.toLowerCase()) {
case "w": config.setItem("desktopLyricsTop", Math.max(config.getItem("desktopLyricsTop") - 2, 0)); break;
case "a": config.setItem("desktopLyricsLeft", Math.max(config.getItem("desktopLyricsLeft") - 2, 0)); break;
case "s": config.setItem("desktopLyricsTop", Math.min(config.getItem("desktopLyricsTop") + 2, screen.height - 100)); break;
case "d": config.setItem("desktopLyricsLeft", Math.min(config.getItem("desktopLyricsLeft") + 2, screen.width)); break;
case "w": config.setItem("desktopLyricsTop", Math.max(config.getItem("desktopLyricsTop") - moveOffset, 0)); break;
case "a": config.setItem("desktopLyricsLeft", Math.max(config.getItem("desktopLyricsLeft") - moveOffset, 0)); break;
case "s": config.setItem("desktopLyricsTop", Math.min(config.getItem("desktopLyricsTop") + moveOffset, screen.height - 100)); break;
case "d": config.setItem("desktopLyricsLeft", Math.min(config.getItem("desktopLyricsLeft") + moveOffset, screen.width)); break;
}
};
document.documentElement.ondragstart = e => {e.preventDefault();};
Expand Down Expand Up @@ -1001,7 +1002,27 @@ const PlayerController = {
const currentMusic = config.getItem("currentMusic");
document.querySelectorAll(".musicListContent>tr").forEach(tr => {
tr.classList[tr.dataset.file == currentMusic ? "add" : "remove"]("active");
})
});
document.querySelectorAll("#musicListContainer>div").forEach(div => {
const activeMusic = div.querySelector("tr.active");
const musicLocator = div.querySelector(".musicLocator");
const tableContainer = div.querySelector(".tableContainer")
if (activeMusic && config.getItem("showLocator")) {
musicLocator.classList.remove("hidden");
musicLocator.onclick = () => {
musicLocator.classList.add("hidden");
activeMusic.scrollIntoView({block: "center", behavior: "smooth"});
setTimeout(() => {activeMusic.classList.add("selected");}, 200);
setTimeout(() => {activeMusic.classList.remove("selected");}, 500);
};
tableContainer.onwheel = () => {
musicLocator.classList.remove("hidden");
};
} else {
musicLocator.classList.add("hidden");
tableContainer.onwheel = null;
}
});
document.querySelectorAll("#playList>div").forEach(div => {
if (div.dataset.file == currentMusic) {
div.classList.add("active");
Expand All @@ -1011,7 +1032,8 @@ const PlayerController = {
setTimeout(() => { PlayerController.listScrollLock = false; }, 500);
}
} else div.classList.remove("active");
})
});
loadThemeImage();
}
}
if (!config.getItem("lrcShow")) document.body.classList.add("hideLyrics");
Expand All @@ -1020,6 +1042,52 @@ config.listenChange("playBtnColor", loadPlayColor); loadPlayColor();
const load3dEffect = () => { document.body.classList[config.getItem("3dEffect") ? "add" : "remove"]("threeEffect"); }
config.listenChange("3dEffect", load3dEffect); load3dEffect();
if (config.getItem("devMode", 1)) document.getElementById("devBtn").hidden = false;
config.listenChange("showLocator", PlayerController.loadMusicListActive);



// 主界面主题图片
function loadThemeImage() {
if (!config.getItem("themeImage")) document.body.classList.remove("themeImage");
else {
const themeImage = document.getElementById("themeImage");
switch (config.getItem("themeImageType")) {
case "cover":
if (config.getItem("currentMusic")) {
document.body.classList.add("themeImage");
themeImage.src = document.getElementById("album").src;
} else {
document.body.classList.remove("themeImage");
}
break;
case "local":
document.body.classList.add("themeImage");
themeImage.src = config.getItem("themeImagePath");
break;
}
themeImage.style.filter = config.getItem("themeImageBlur") ? "blur(20px)" : "none";
}
}
document.getElementById("themeImage").onerror = () => {
document.body.classList.remove("themeImage");
};
config.listenChange("themeImage", loadThemeImage);
config.listenChange("themeImageType", value => {
config.setItem("themeImagePath", "");
if (value == "local") {
const fileInput = document.createElement("input");
fileInput.type = "file";
fileInput.accept = "image/*";
fileInput.multiple = false;
fileInput.click();
fileInput.onchange = e => {
const file = e.target.files[0];
if (file) config.setItem("themeImagePath", file.path);
};
}
});
config.listenChange("themeImagePath", loadThemeImage);
config.listenChange("themeImageBlur", loadThemeImage);



Expand Down Expand Up @@ -1147,21 +1215,41 @@ const DownloadController = {
const coverRes = await fetch(coverData)
coverArrBuffer = await coverRes.arrayBuffer();
}
const metadataResult = nodeId3.write({
title: lastMusicIndex[file].title,
artist: lastMusicIndex[file].artist,
album: lastMusicIndex[file].album,
unsynchronisedLyrics: {
language: "XXX",
text: lastMusicIndex[file].lyrics ? lastMusicIndex[file].lyrics : await ExtensionConfig[fileScheme].player.getLyrics(file)
},
image: {
type: {id: 3, name: "front cover"},
imageBuffer: Buffer.from(coverArrBuffer)
let metadataResult,mediaFormat,fileExtension;
try {
mediaFormat = (await musicMetadata.parseFile(tempPath)).format.container.toLowerCase();
switch (mediaFormat) {
case "flac":
const tagMap = {
title: lastMusicIndex[file].title,
artist: lastMusicIndex[file].artist,
album: lastMusicIndex[file].album,
lyrics: lastMusicIndex[file].lyrics ? lastMusicIndex[file].lyrics : await ExtensionConfig[fileScheme].player.getLyrics(file),
};
await flacTagger.writeFlacTags({ tagMap, picture: { buffer: Buffer.from(coverArrBuffer) } }, tempPath);
metadataResult = true;
fileExtension = "flac";
break;
default:
metadataResult = nodeId3.write({
title: lastMusicIndex[file].title,
artist: lastMusicIndex[file].artist,
album: lastMusicIndex[file].album,
unsynchronisedLyrics: {
language: "XXX",
text: lastMusicIndex[file].lyrics ? lastMusicIndex[file].lyrics : await ExtensionConfig[fileScheme].player.getLyrics(file)
},
image: {
type: {id: 3, name: "front cover"},
imageBuffer: Buffer.from(coverArrBuffer)
}
}, tempPath);
fileExtension = "mp3";
break;
}
}, tempPath);
} catch (err){console.log(err)}
if (metadataResult) {
const renameResult = this.renameDownloadFile(destination, fileName)
const renameResult = this.renameDownloadFile(destination, fileName, fileExtension)
if (renameResult) {
updateDownloadStatus("success", "曲目下载成功", 100);
element.dataset.fileName = renameResult;
Expand All @@ -1180,10 +1268,10 @@ const DownloadController = {
};
xhr.send();
},
renameDownloadFile(dir, filename) {
renameDownloadFile(dir, filename, ext) {
try {
const originalFile = path.join(dir, `${filename}.simtemp`);
const baseTargetFile = path.join(dir, `${filename}.mp3`);
const baseTargetFile = path.join(dir, `${filename}.${ext}`);
let targetFile = baseTargetFile;
let count = 1;
// 序号递增
Expand Down Expand Up @@ -1234,6 +1322,11 @@ const SettingsPage = {
{type: "title", text: "音频扫描"},
{type: "input", text: "音频格式", description: "扫描本地音乐时的音频文件扩展名,以空格分隔。", configItem: "musicFormats"},
{type: "button", text: "清除音频索引", description: "若您更改了音频元数据,可在此删除索引数据以重新从文件读取。", button: "清除", onclick: () => { SimMusicTools.writeMusicIndex({}, () => { alert("索引数据已清除,按「确定」重载此应用生效。", () => { ipcRenderer.invoke("restart"); }); }); }},
{type: "title", text: "歌单界面"},
{type: "boolean", text: "显示「曲目定位」按钮", configItem: "showLocator"},
{type: "boolean", text: "启用主题图片", description: "在 SimMusic 主界面显示主题图片。", configItem: "themeImage"},
{type: "select", text: "选择主题图片", options: [["cover", "曲目封面"], ["local", "本地文件"]], configItem: "themeImageType", attachTo: "themeImage"},
{type: "boolean", text: "图片模糊效果", configItem: "themeImageBlur", attachTo: "themeImage"},
{type: "title", text: "播放界面"},
{type: "boolean", text: "背景动态混色", description: "关闭后可减少播放页对硬件资源的占用。", configItem: "backgroundBlur"},
{type: "boolean", text: "3D 特效", badges: ["experimental"], description: "在播放页的歌曲信息、播放列表与歌词视图使用 3D 视觉效果。", configItem: "3dEffect"},
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/lrc.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
// 移动窗口
function moveWindow(e) {
config.setItem("desktopLyricsTop", e.pageY);
config.setItem("desktopLyricsLeft", Math.max(e.pageX, ));
config.setItem("desktopLyricsLeft", e.pageX);
reloadConfig();
}

Expand Down
6 changes: 6 additions & 0 deletions src/frontend/main.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
<tbody class="musicListContent"></tbody>
</table>
</div>
<i class="musicLocator">&#xF3B5;</i>
<div class="musicListErrorOverlay" hidden><img src="assets/icon-error.svg"><div></div></div>
</div>
<div data-music-list-id="search">
Expand All @@ -97,6 +98,7 @@
</table>
<div id="searchBottomIndicator" style="opacity:0;" onclick="Search.loadMore()"></div>
</div>
<i class="musicLocator">&#xF3B5;</i>
<div class="musicListErrorOverlay" hidden><img src="assets/icon-error.svg"><div></div></div>
</div>
</div>
Expand Down Expand Up @@ -139,6 +141,7 @@
<a>electron/electron</a>
<a>Borewit/music-metadata</a>
<a>Zazama/node-id3</a>
<a>the1812/flac-tagger</a>
<a>zhujin917/3sqrt7-context-menu</a>
<a>101arrowz/fflate</a>
<a>lokesh/color-thief</a>
Expand Down Expand Up @@ -191,6 +194,9 @@
</div>


<img id="themeImage">


<!-- 播放器 -->
<div id="playPage" hidden>
<div class="playerContainer">
Expand Down
Loading

0 comments on commit da661b3

Please sign in to comment.