新增HTTP开放API服务
This commit is contained in:
@@ -87,6 +87,7 @@ export const init = () => {
|
||||
onPlay(line, text) {
|
||||
setText(text, Math.max(line, 0))
|
||||
setStatusText(text)
|
||||
window.app_event.lyricLinePlay(text)
|
||||
// console.log(line, text)
|
||||
},
|
||||
onSetLyric(lines, offset) { // listening lyrics seting event
|
||||
@@ -185,6 +186,10 @@ export const setLyric = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export const setAutoPause = (autoPause: boolean) => {
|
||||
lrc.setAutoPause(autoPause)
|
||||
}
|
||||
|
||||
|
||||
export const play = () => {
|
||||
// if (!musicInfo.lrc) return
|
||||
|
||||
@@ -4,6 +4,7 @@ import { proxy, isFullscreen, themeId } from '@renderer/store'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
|
||||
import useSync from './useSync'
|
||||
import useOpenAPI from './useOpenAPI'
|
||||
import useUpdate from './useUpdate'
|
||||
import useDataInit from './useDataInit'
|
||||
import useHandleEnvParams from './useHandleEnvParams'
|
||||
@@ -25,6 +26,7 @@ export default () => {
|
||||
|
||||
const router = useRouter()
|
||||
const initSyncService = useSync()
|
||||
const initOpenAPI = useOpenAPI()
|
||||
useEventListener()
|
||||
const initPlayer = usePlayer()
|
||||
const handleEnvParams = useHandleEnvParams()
|
||||
@@ -62,6 +64,7 @@ export default () => {
|
||||
handleEnvParams(envParams) // 处理传入的启动参数
|
||||
void initDeeplink(envParams)
|
||||
void initSyncService()
|
||||
void initOpenAPI()
|
||||
sendInited()
|
||||
|
||||
handleListAutoUpdate()
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { watch } from '@common/utils/vueTools'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import { sendOpenAPIAction } from '@renderer/utils/ipc'
|
||||
import { openAPI } from '@renderer/store'
|
||||
import { setAutoPause } from '@renderer/core/lyric'
|
||||
|
||||
export default () => {
|
||||
const handleEnable = async(enable: boolean, port: string) => {
|
||||
await sendOpenAPIAction({
|
||||
action: 'enable',
|
||||
data: {
|
||||
enable,
|
||||
port,
|
||||
},
|
||||
}).then((status) => {
|
||||
openAPI.address = status.address
|
||||
openAPI.message = status.message
|
||||
}).catch((error) => {
|
||||
openAPI.address = ''
|
||||
openAPI.message = error.message
|
||||
}).finally(() => {
|
||||
if (openAPI.address) {
|
||||
setAutoPause(false)
|
||||
} else {
|
||||
setAutoPause(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
watch(() => appSetting['openAPI.enable'], enable => {
|
||||
void handleEnable(enable, appSetting['openAPI.port'])
|
||||
})
|
||||
|
||||
watch(() => appSetting['openAPI.port'], port => {
|
||||
void handleEnable(appSetting['openAPI.enable'], port)
|
||||
})
|
||||
|
||||
return async() => {
|
||||
if (appSetting['openAPI.enable']) {
|
||||
void handleEnable(true, appSetting['openAPI.port'])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { onBeforeUnmount, watch } from '@common/utils/vueTools'
|
||||
import { formatPlayTime2, getRandom } from '@common/utils/common'
|
||||
import { throttle } from '@common/utils'
|
||||
import { setTaskBarProgress, savePlayInfo } from '@renderer/utils/ipc'
|
||||
import { savePlayInfo } from '@renderer/utils/ipc'
|
||||
import { onTimeupdate, getCurrentTime, getDuration, setCurrentTime, onVisibilityChange } from '@renderer/plugins/player'
|
||||
import { playProgress, setNowPlayTime, setMaxplayTime } from '@renderer/store/player/playProgress'
|
||||
import { musicInfo, playMusicInfo, playInfo } from '@renderer/store/player/state'
|
||||
@@ -14,7 +14,6 @@ const delaySavePlayInfo = throttle(savePlayInfo, 2000)
|
||||
|
||||
export default () => {
|
||||
let restorePlayTime = 0
|
||||
let prevProgressStatus: Electron.ProgressBarOptions['mode'] = 'none'
|
||||
const mediaBuffer: {
|
||||
timeout: NodeJS.Timeout | null
|
||||
playTime: number
|
||||
@@ -75,32 +74,18 @@ export default () => {
|
||||
// if (!isPlay) audio.play()
|
||||
}
|
||||
|
||||
const handleSetTaskBarState = (progress: number, status?: Electron.ProgressBarOptions['mode']) => {
|
||||
if (appSetting['player.isShowTaskProgess']) setTaskBarProgress(progress, status)
|
||||
}
|
||||
|
||||
const handlePlay = () => {
|
||||
prevProgressStatus = 'normal'
|
||||
handleSetTaskBarState(playProgress.progress, prevProgressStatus)
|
||||
}
|
||||
const handlePause = () => {
|
||||
prevProgressStatus = 'paused'
|
||||
handleSetTaskBarState(playProgress.progress, prevProgressStatus)
|
||||
clearBufferTimeout()
|
||||
}
|
||||
|
||||
const handleStop = () => {
|
||||
setNowPlayTime(0)
|
||||
setMaxplayTime(0)
|
||||
prevProgressStatus = 'none'
|
||||
handleSetTaskBarState(playProgress.progress, prevProgressStatus)
|
||||
}
|
||||
|
||||
const handleError = () => {
|
||||
restorePlayTime ||= getCurrentTime() // 记录出错的播放时间
|
||||
console.log('handleError')
|
||||
prevProgressStatus = 'error'
|
||||
handleSetTaskBarState(playProgress.progress, prevProgressStatus)
|
||||
}
|
||||
|
||||
const handleLoadeddata = () => {
|
||||
@@ -157,10 +142,6 @@ export default () => {
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => playProgress.progress, (newValue, oldValue) => {
|
||||
if (newValue.toFixed(2) === oldValue.toFixed(2)) return
|
||||
handleSetTaskBarState(newValue, prevProgressStatus)
|
||||
})
|
||||
watch(() => playProgress.nowPlayTime, (newValue, oldValue) => {
|
||||
if (Math.abs(newValue - oldValue) > 2) window.app_event.activePlayProgressTransition()
|
||||
if (appSetting['player.isSavePlayTime'] && !playMusicInfo.isTempPlay) {
|
||||
@@ -183,7 +164,7 @@ export default () => {
|
||||
}
|
||||
})
|
||||
|
||||
window.app_event.on('play', handlePlay)
|
||||
// window.app_event.on('play', handlePlay)
|
||||
window.app_event.on('pause', handlePause)
|
||||
window.app_event.on('stop', handleStop)
|
||||
window.app_event.on('error', handleError)
|
||||
@@ -213,7 +194,7 @@ export default () => {
|
||||
onBeforeUnmount(() => {
|
||||
rOnTimeupdate()
|
||||
rVisibilityChange()
|
||||
window.app_event.off('play', handlePlay)
|
||||
// window.app_event.off('play', handlePlay)
|
||||
window.app_event.off('pause', handlePause)
|
||||
window.app_event.off('stop', handleStop)
|
||||
window.app_event.off('error', handleError)
|
||||
|
||||
@@ -1,55 +1,65 @@
|
||||
import { onBeforeUnmount } from '@common/utils/vueTools'
|
||||
import { setPlayerAction, onPlayerAction } from '@renderer/utils/ipc'
|
||||
import { onBeforeUnmount, watch } from '@common/utils/vueTools'
|
||||
import { sendPlayerStatus, onPlayerAction } from '@renderer/utils/ipc'
|
||||
// import store from '@renderer/store'
|
||||
|
||||
import { loveList } from '@renderer/store/list/state'
|
||||
import { addListMusics, removeListMusics, checkListExistMusic } from '@renderer/store/list/action'
|
||||
import { playMusicInfo } from '@renderer/store/player/state'
|
||||
import { playMusicInfo, musicInfo } from '@renderer/store/player/state'
|
||||
import { throttle } from '@common/utils'
|
||||
import { pause, play, playNext, playPrev } from '@renderer/core/player'
|
||||
import { playProgress } from '@renderer/store/player/playProgress'
|
||||
|
||||
export default () => {
|
||||
// const setVisibleDesktopLyric = useCommit('setVisibleDesktopLyric')
|
||||
// const setLockDesktopLyric = useCommit('setLockDesktopLyric')
|
||||
let collect = false
|
||||
|
||||
const buttons = {
|
||||
empty: true,
|
||||
collect: false,
|
||||
play: false,
|
||||
prev: true,
|
||||
next: true,
|
||||
lrc: false,
|
||||
lockLrc: false,
|
||||
}
|
||||
const setButtons = () => {
|
||||
setPlayerAction(buttons)
|
||||
}
|
||||
const updateCollectStatus = async() => {
|
||||
let status = !!playMusicInfo.musicInfo && await checkListExistMusic(loveList.id, playMusicInfo.musicInfo.id)
|
||||
if (buttons.collect == status) return false
|
||||
buttons.collect = status
|
||||
if (collect == status) return false
|
||||
collect = status
|
||||
return true
|
||||
}
|
||||
|
||||
const handlePlay = () => {
|
||||
buttons.empty &&= false
|
||||
buttons.play = true
|
||||
setButtons()
|
||||
sendPlayerStatus({ status: 'playing' })
|
||||
}
|
||||
const handlePause = () => {
|
||||
buttons.empty &&= false
|
||||
buttons.play = false
|
||||
setButtons()
|
||||
sendPlayerStatus({ status: 'paused' })
|
||||
}
|
||||
const handleStop = () => {
|
||||
if (playMusicInfo.musicInfo != null) return
|
||||
buttons.collect &&= false
|
||||
buttons.empty = true
|
||||
setButtons()
|
||||
sendPlayerStatus({ status: 'stoped' })
|
||||
}
|
||||
const handleSetPlayInfo = () => {
|
||||
void updateCollectStatus().then(isExist => {
|
||||
if (isExist) setButtons()
|
||||
const handleError = () => {
|
||||
sendPlayerStatus({ status: 'error' })
|
||||
}
|
||||
const handleSetPlayInfo = async() => {
|
||||
await updateCollectStatus()
|
||||
sendPlayerStatus({
|
||||
collect,
|
||||
name: musicInfo.name,
|
||||
singer: musicInfo.singer,
|
||||
albumName: musicInfo.album,
|
||||
picUrl: musicInfo.pic ?? '',
|
||||
lyric: musicInfo.lrc ?? '',
|
||||
lyricLineText: '',
|
||||
})
|
||||
}
|
||||
const handleSetLyric = () => {
|
||||
sendPlayerStatus({
|
||||
lyric: musicInfo.lrc ?? '',
|
||||
lyricLineText: '',
|
||||
})
|
||||
}
|
||||
const handleSetPic = () => {
|
||||
sendPlayerStatus({
|
||||
picUrl: musicInfo.pic ?? '',
|
||||
})
|
||||
}
|
||||
const handleSetLyricLine = (text: string) => {
|
||||
sendPlayerStatus({
|
||||
lyricLineText: text,
|
||||
})
|
||||
}
|
||||
// const handleSetTaskbarThumbnailClip = (clip) => {
|
||||
@@ -57,7 +67,7 @@ export default () => {
|
||||
// }
|
||||
const throttleListChange = throttle(async listIds => {
|
||||
if (!listIds.includes(loveList.id)) return
|
||||
if (await updateCollectStatus()) setButtons()
|
||||
if (await updateCollectStatus()) sendPlayerStatus({ collect })
|
||||
})
|
||||
// const updateSetting = () => {
|
||||
// const setting = store.getters.setting
|
||||
@@ -82,12 +92,12 @@ export default () => {
|
||||
case 'collect':
|
||||
if (!playMusicInfo.musicInfo) return
|
||||
void addListMusics(loveList.id, ['progress' in playMusicInfo.musicInfo ? playMusicInfo.musicInfo.metadata.musicInfo : playMusicInfo.musicInfo])
|
||||
if (await updateCollectStatus()) setButtons()
|
||||
if (await updateCollectStatus()) sendPlayerStatus({ collect })
|
||||
break
|
||||
case 'unCollect':
|
||||
if (!playMusicInfo.musicInfo) return
|
||||
void removeListMusics({ listId: loveList.id, ids: ['progress' in playMusicInfo.musicInfo ? playMusicInfo.musicInfo.metadata.musicInfo.id : playMusicInfo.musicInfo.id] })
|
||||
if (await updateCollectStatus()) setButtons()
|
||||
if (await updateCollectStatus()) sendPlayerStatus({ collect })
|
||||
break
|
||||
// case 'lrc':
|
||||
// setVisibleDesktopLyric(true)
|
||||
@@ -107,10 +117,24 @@ export default () => {
|
||||
// break
|
||||
}
|
||||
})
|
||||
watch(() => playProgress.nowPlayTime, (newValue, oldValue) => {
|
||||
// console.log(playProgress.nowPlayTime, newValue, oldValue)
|
||||
// if (newValue.toFixed(2) === oldValue.toFixed(2)) return
|
||||
// console.log(playProgress.nowPlayTime)
|
||||
sendPlayerStatus({ progress: newValue })
|
||||
})
|
||||
watch(() => playProgress.maxPlayTime, (newValue) => {
|
||||
sendPlayerStatus({ duration: newValue })
|
||||
})
|
||||
|
||||
window.app_event.on('play', handlePlay)
|
||||
window.app_event.on('pause', handlePause)
|
||||
window.app_event.on('stop', handleStop)
|
||||
window.app_event.on('error', handleError)
|
||||
window.app_event.on('musicToggled', handleSetPlayInfo)
|
||||
window.app_event.on('lyricUpdated', handleSetLyric)
|
||||
window.app_event.on('picUpdated', handleSetPic)
|
||||
window.app_event.on('lyricLinePlay', handleSetLyricLine)
|
||||
// window.app_event.on(eventTaskbarNames.setTaskbarThumbnailClip, handleSetTaskbarThumbnailClip)
|
||||
window.app_event.on('myListUpdate', throttleListChange)
|
||||
|
||||
@@ -119,7 +143,11 @@ export default () => {
|
||||
window.app_event.off('play', handlePlay)
|
||||
window.app_event.off('pause', handlePause)
|
||||
window.app_event.off('stop', handleStop)
|
||||
window.app_event.off('error', handleError)
|
||||
window.app_event.off('musicToggled', handleSetPlayInfo)
|
||||
window.app_event.off('lyricUpdated', handleSetLyric)
|
||||
window.app_event.off('picUpdated', handleSetPic)
|
||||
window.app_event.off('lyricLinePlay', handleSetLyricLine)
|
||||
// window.app_event.off(eventTaskbarNames.setTaskbarThumbnailClip, handleSetTaskbarThumbnailClip)
|
||||
window.app_event.off('myListUpdate', throttleListChange)
|
||||
})
|
||||
@@ -129,7 +157,14 @@ export default () => {
|
||||
// buttons.lrc = setting.desktopLyric.enable
|
||||
// buttons.lockLrc = setting.desktopLyric.isLock
|
||||
await updateCollectStatus()
|
||||
if (playMusicInfo.musicInfo != null) buttons.empty = false
|
||||
setButtons()
|
||||
if (playMusicInfo.musicInfo == null) return
|
||||
sendPlayerStatus({
|
||||
collect,
|
||||
name: musicInfo.name,
|
||||
singer: musicInfo.singer,
|
||||
albumName: musicInfo.album,
|
||||
picUrl: musicInfo.pic ?? '',
|
||||
lyric: musicInfo.lrc ?? '',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { watch } from '@common/utils/vueTools'
|
||||
import { isFullscreen, proxy, sync, windowSizeList } from '@renderer/store'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import { sendSyncAction, setTaskBarProgress, setWindowSize } from '@renderer/utils/ipc'
|
||||
import { sendSyncAction, setWindowSize } from '@renderer/utils/ipc'
|
||||
import { setLanguage } from '@root/lang'
|
||||
import { setUserApi } from '../apiSource'
|
||||
// import { applyTheme, getThemes } from '@renderer/store/utils'
|
||||
@@ -106,11 +106,4 @@ export default () => {
|
||||
watch(() => appSetting['network.proxy.port'], port => {
|
||||
proxy.port = port
|
||||
})
|
||||
|
||||
watch(() => appSetting['player.isShowTaskProgess'], val => {
|
||||
if (val) return
|
||||
setTimeout(() => {
|
||||
setTaskBarProgress(-1, 'normal')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -144,6 +144,11 @@ export class AppEvent extends Event {
|
||||
this.emit('lyricOffsetUpdate')
|
||||
}
|
||||
|
||||
// 歌词行播放
|
||||
lyricLinePlay(text: string) {
|
||||
this.emit('lyricLinePlay', text)
|
||||
}
|
||||
|
||||
// 我的列表改变事件
|
||||
myListUpdate(ids: string[]) {
|
||||
this.emit('myListUpdate', ids)
|
||||
|
||||
@@ -73,6 +73,11 @@ export const sync: {
|
||||
},
|
||||
})
|
||||
|
||||
export const openAPI = reactive({
|
||||
address: '',
|
||||
message: '',
|
||||
})
|
||||
|
||||
|
||||
export const windowSizeActive = computed(() => {
|
||||
return windowSizeList.find(i => i.id === appSetting['common.windowSizeId']) ?? windowSizeList[0]
|
||||
|
||||
Vendored
+1
@@ -16,3 +16,4 @@ import '@common/types/config_files'
|
||||
import '@common/types/music_metadata'
|
||||
import '@common/types/sound_effect'
|
||||
import '@common/types/dislike_list'
|
||||
import '@common/types/open_api'
|
||||
|
||||
@@ -172,11 +172,13 @@ export const userApiRequestCancel = (requestKey: LX.UserApi.UserApiRequestCancel
|
||||
// }
|
||||
// }
|
||||
|
||||
export const setTaskBarProgress = (progress: number, mode?: Electron.ProgressBarOptions['mode']) => {
|
||||
rendererSend<LX.Player.ProgressBarOptions>(WIN_MAIN_RENDERER_EVENT_NAME.progress, {
|
||||
progress: progress < 0 ? progress : Math.max(0.01, progress),
|
||||
mode: mode ?? 'normal',
|
||||
})
|
||||
export const sendPlayerStatus = (status: Partial<LX.Player.Status>) => {
|
||||
rendererSend<Partial<LX.Player.Status>>(WIN_MAIN_RENDERER_EVENT_NAME.player_status, status)
|
||||
}
|
||||
|
||||
|
||||
export const sendOpenAPIAction = async(action: LX.OpenAPI.Actions) => {
|
||||
return rendererInvoke<LX.OpenAPI.Actions, LX.OpenAPI.Status>(WIN_MAIN_RENDERER_EVENT_NAME.open_api_action, action)
|
||||
}
|
||||
|
||||
export const saveLastStartInfo = (version: string) => {
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<template lang="pug">
|
||||
dt#sync {{ $t('setting__open_api') }}
|
||||
dd.gap-top
|
||||
div
|
||||
base-checkbox.gap-top(id="setting_open_api_enable" :model-value="appSetting['openAPI.enable']" :label="$t('setting__open_api_enable')" @update:model-value="updateSetting({ 'openAPI.enable': $event })")
|
||||
.p.gap-top.small {{ $t('setting__open_api_address', { address: openAPI.address || '' }) }}
|
||||
.p.small(v-if="openAPI.message") {{ openAPI.message }}
|
||||
.p
|
||||
.p.small {{ $t('setting__open_api_port') }}
|
||||
div
|
||||
base-input.gap-left(:class="$style.portInput" :model-value="appSetting['openAPI.port']" type="number" :placeholder="$t('setting__open_api_port_tip')" @update:model-value="setPort")
|
||||
|
||||
dd.gap-top
|
||||
div
|
||||
.p
|
||||
| {{ $t('setting__open_api_tip') }}
|
||||
strong.hover.underline(aria-label="https://lyswhut.github.io/lx-music-doc/desktop/faq/open-api" @click="openUrl('https://lyswhut.github.io/lx-music-doc/desktop/open-api')") {{ $t('setting__open_api_tip_link') }}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import { computed } from '@common/utils/vueTools'
|
||||
import { openAPI } from '@renderer/store'
|
||||
import { openUrl } from '@common/utils/electron'
|
||||
import { appSetting, updateSetting } from '@renderer/store/setting'
|
||||
import { debounce } from '@common/utils'
|
||||
|
||||
export default {
|
||||
name: 'SettingOpenAPI',
|
||||
setup() {
|
||||
const setPort = debounce(port => {
|
||||
updateSetting({ 'openAPI.port': port.trim() })
|
||||
}, 500)
|
||||
|
||||
return {
|
||||
appSetting,
|
||||
updateSetting,
|
||||
openAPI,
|
||||
openUrl,
|
||||
setPort,
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" module>
|
||||
@import '@renderer/assets/styles/layout.less';
|
||||
.portInput[disabled], .hostInput[disabled] {
|
||||
opacity: .8 !important;
|
||||
}
|
||||
</style>
|
||||
@@ -60,6 +60,7 @@ import SettingSearch from './components/SettingSearch.vue'
|
||||
import SettingList from './components/SettingList.vue'
|
||||
import SettingDownload from './components/SettingDownload.vue'
|
||||
import SettingSync from './components/SettingSync/index.vue'
|
||||
import SettingOpenAPI from './components/SettingOpenAPI.vue'
|
||||
import SettingHotKey from './components/SettingHotKey.vue'
|
||||
import SettingNetwork from './components/SettingNetwork.vue'
|
||||
import SettingOdc from './components/SettingOdc.vue'
|
||||
@@ -79,6 +80,7 @@ export default {
|
||||
SettingList,
|
||||
SettingDownload,
|
||||
SettingSync,
|
||||
SettingOpenAPI,
|
||||
SettingHotKey,
|
||||
SettingNetwork,
|
||||
SettingOdc,
|
||||
@@ -102,8 +104,9 @@ export default {
|
||||
{ id: 'SettingSearch', title: t('setting__search') },
|
||||
{ id: 'SettingList', title: t('setting__list') },
|
||||
{ id: 'SettingDownload', title: t('setting__download') },
|
||||
{ id: 'SettingSync', title: t('setting__sync') },
|
||||
{ id: 'SettingHotKey', title: t('setting__hot_key') },
|
||||
{ id: 'SettingSync', title: t('setting__sync') },
|
||||
{ id: 'SettingOpenAPI', title: t('setting__open_api') },
|
||||
{ id: 'SettingNetwork', title: t('setting__network') },
|
||||
{ id: 'SettingOdc', title: t('setting__odc') },
|
||||
{ id: 'SettingBackup', title: t('setting__backup') },
|
||||
|
||||
Reference in New Issue
Block a user