播放详情页新增桌面歌词显示/隐藏切换按钮

This commit is contained in:
lyswhut 2023-12-31 11:43:22 +08:00
parent 4cddb9c947
commit 81c8d98508
15 changed files with 195 additions and 57 deletions

View File

@ -10,6 +10,7 @@
- 新增APP全局字体阴影默认关闭可到设置-主题设置启用 - 新增APP全局字体阴影默认关闭可到设置-主题设置启用
- 新增启用竖屏首页横向滚动设置,默认开启(原来的行为),如果你不想要竖屏的首页左右滑动则可以关闭此设置(#397 - 新增启用竖屏首页横向滚动设置,默认开启(原来的行为),如果你不想要竖屏的首页左右滑动则可以关闭此设置(#397
- 新增“使用系统文件选择器”设置,默认启用,启用该选项后,导入备份文件、自定义源等操作将不需要申请存储权限,但可能在某些系统上不可用 - 新增“使用系统文件选择器”设置,默认启用,启用该选项后,导入备份文件、自定义源等操作将不需要申请存储权限,但可能在某些系统上不可用
- 播放详情页新增桌面歌词显示/隐藏切换按钮,长按可切换歌词锁定状态
- 添加 Android 5 特别版(版本号包含`android_5`)与墨·状态栏特别版(版本号包含`sl`)的 release 构建 - 添加 Android 5 特别版(版本号包含`android_5`)与墨·状态栏特别版(版本号包含`sl`)的 release 构建
### 优化 ### 优化

View File

@ -0,0 +1,61 @@
import { forwardRef, useImperativeHandle, useRef } from 'react'
import ConfirmAlert, { type ConfirmAlertType } from '@/components/common/ConfirmAlert'
import { toast } from '@/utils/tools'
import { useI18n } from '@/lang'
import { checkDesktopLyricOverlayPermission, hideDesktopLyric, openDesktopLyricOverlayPermissionActivity, showDesktopLyric } from '@/core/desktopLyric'
import { updateSetting } from '@/core/common'
export interface DesktopLyricEnableType {
setEnabled: (enabled: boolean) => void
}
export default forwardRef<DesktopLyricEnableType, {}>((props, ref) => {
const t = useI18n()
// const setIsShowDesktopLyric = useDispatch('common', 'setIsShowDesktopLyric')
const confirmAlertRef = useRef<ConfirmAlertType>(null)
useImperativeHandle(ref, () => ({
setEnabled(enabled) {
void handleChangeEnableDesktopLyric(enabled)
},
}))
const handleChangeEnableDesktopLyric = async(isEnable: boolean) => {
if (isEnable) {
try {
await checkDesktopLyricOverlayPermission()
await showDesktopLyric()
} catch (err) {
console.log(err)
confirmAlertRef.current?.setVisible(true)
// return false
}
} else await hideDesktopLyric()
// return true
updateSetting({ 'desktopLyric.enable': isEnable })
}
const handleTipsCancel = () => {
updateSetting({ 'desktopLyric.enable': false })
toast(t('disagree_tip'), 'long')
}
const handleTipsConfirm = () => {
confirmAlertRef.current?.setVisible(false)
void openDesktopLyricOverlayPermissionActivity()
}
return (
<ConfirmAlert
ref={confirmAlertRef}
onCancel={handleTipsCancel}
onConfirm={handleTipsConfirm}
bgHide={false}
closeBtn={false}
cancelText={t('disagree')}
confirmText={t('agree_go')}
text={t('setting_lyric_dektop_permission_tip')} />
)
})

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1,58 +1,28 @@
import { memo, useRef } from 'react' import { memo, useRef } from 'react'
import { View } from 'react-native' import { View } from 'react-native'
import ConfirmAlert, { type ConfirmAlertType } from '@/components/common/ConfirmAlert'
import CheckBoxItem from '../../components/CheckBoxItem' import CheckBoxItem from '../../components/CheckBoxItem'
import { createStyle, toast } from '@/utils/tools' import { createStyle } from '@/utils/tools'
import { useI18n } from '@/lang' import { useI18n } from '@/lang'
import { useSettingValue } from '@/store/setting/hook' import { useSettingValue } from '@/store/setting/hook'
import { checkDesktopLyricOverlayPermission, hideDesktopLyric, openDesktopLyricOverlayPermissionActivity, showDesktopLyric } from '@/core/desktopLyric' import DesktopLyricEnable, { type DesktopLyricEnableType } from '@/components/DesktopLyricEnable'
import { updateSetting } from '@/core/common'
export default memo(() => { export default memo(() => {
const t = useI18n() const t = useI18n()
const isEnable = useSettingValue('desktopLyric.enable') const isEnable = useSettingValue('desktopLyric.enable')
// const setIsShowDesktopLyric = useDispatch('common', 'setIsShowDesktopLyric') // const setIsShowDesktopLyric = useDispatch('common', 'setIsShowDesktopLyric')
const confirmAlertRef = useRef<ConfirmAlertType>(null) const desktopLyricEnableRef = useRef<DesktopLyricEnableType>(null)
const handleChangeEnableDesktopLyric = async(isEnable: boolean) => { const handleChangeEnableDesktopLyric = async(isEnable: boolean) => {
if (isEnable) { desktopLyricEnableRef.current?.setEnabled(isEnable)
try {
await checkDesktopLyricOverlayPermission()
await showDesktopLyric()
} catch (err) {
console.log(err)
confirmAlertRef.current?.setVisible(true)
// return false
}
} else await hideDesktopLyric()
// return true
updateSetting({ 'desktopLyric.enable': isEnable })
}
const handleTipsCancel = () => {
updateSetting({ 'desktopLyric.enable': false })
toast(t('disagree_tip'), 'long')
}
const handleTipsConfirm = () => {
confirmAlertRef.current?.setVisible(false)
void openDesktopLyricOverlayPermissionActivity()
} }
return ( return (
<View style={styles.content}> <View style={styles.content}>
<CheckBoxItem check={isEnable} onChange={(enable) => { void handleChangeEnableDesktopLyric(enable) }} label={t('setting_lyric_desktop_enable')} /> <CheckBoxItem check={isEnable} onChange={(enable) => { void handleChangeEnableDesktopLyric(enable) }} label={t('setting_lyric_desktop_enable')} />
<ConfirmAlert <DesktopLyricEnable ref={desktopLyricEnableRef} />
ref={confirmAlertRef}
onCancel={handleTipsCancel}
onConfirm={handleTipsConfirm}
bgHide={false}
closeBtn={false}
cancelText={t('disagree')}
confirmText={t('agree_go')}
text={t('setting_lyric_dektop_permission_tip')} />
</View> </View>
) )
}) })

View File

@ -8,15 +8,16 @@ import { HEADER_HEIGHT } from '@/config/constant'
export const BTN_WIDTH = scaleSizeW(HEADER_HEIGHT) export const BTN_WIDTH = scaleSizeW(HEADER_HEIGHT)
export const BTN_ICON_SIZE = 20 export const BTN_ICON_SIZE = 20
export default ({ icon, size, color, onPress }: { export default ({ icon, size, color, onPress, onLongPress }: {
icon: string icon: string
size?: number size?: number
color?: string color?: string
onPress: () => void onPress: () => void
onLongPress?: () => void
}) => { }) => {
const theme = useTheme() const theme = useTheme()
return ( return (
<TouchableOpacity style={{ ...styles.cotrolBtn, width: BTN_WIDTH, height: BTN_WIDTH }} activeOpacity={0.5} onPress={onPress}> <TouchableOpacity style={{ ...styles.cotrolBtn, width: BTN_WIDTH, height: BTN_WIDTH }} activeOpacity={0.5} onPress={onPress} onLongPress={onLongPress}>
<Icon name={icon} color={color ?? theme['c-550']} size={size ?? BTN_ICON_SIZE} /> <Icon name={icon} color={color ?? theme['c-550']} size={size ?? BTN_ICON_SIZE} />
</TouchableOpacity> </TouchableOpacity>
) )

View File

@ -0,0 +1,29 @@
import Btn from './Btn'
import { useSettingValue } from '@/store/setting/hook'
import DesktopLyricEnable, { type DesktopLyricEnableType } from '@/components/DesktopLyricEnable'
import { memo, useRef } from 'react'
import { toggleDesktopLyricLock } from '@/core/desktopLyric'
import { updateSetting } from '@/core/common'
import settingState from '@/store/setting/state'
export default memo(() => {
const enabledLyric = useSettingValue('desktopLyric.enable')
const desktopLyricEnableRef = useRef<DesktopLyricEnableType>(null)
const update = () => {
desktopLyricEnableRef.current?.setEnabled(!enabledLyric)
}
const updateLock = () => {
const isLock = !settingState.setting['desktopLyric.isLock']
void toggleDesktopLyricLock(isLock).then(() => {
updateSetting({ 'desktopLyric.isLock': isLock })
})
}
return (
<>
<Btn icon={enabledLyric ? 'lyric-on' : 'lyric-off'} onPress={update} onLongPress={updateLock} />
<DesktopLyricEnable ref={desktopLyricEnableRef} />
</>
)
})

View File

@ -13,6 +13,7 @@ import commonState from '@/store/common/state'
import CommentBtn from './CommentBtn' import CommentBtn from './CommentBtn'
import Btn from './Btn' import Btn from './Btn'
import SettingPopup, { type SettingPopupType } from '../../components/SettingPopup' import SettingPopup, { type SettingPopupType } from '../../components/SettingPopup'
import DesktopLyricBtn from './DesktopLyricBtn'
export const HEADER_HEIGHT = scaleSizeH(_HEADER_HEIGHT) export const HEADER_HEIGHT = scaleSizeH(_HEADER_HEIGHT)
@ -46,6 +47,7 @@ export default memo(() => {
<Icon name="chevron-left" size={18} /> <Icon name="chevron-left" size={18} />
</TouchableOpacity> </TouchableOpacity>
<Title /> <Title />
<DesktopLyricBtn />
<CommentBtn /> <CommentBtn />
<Btn icon="slider" onPress={showSetting} /> <Btn icon="slider" onPress={showSetting} />
</View> </View>

View File

@ -7,14 +7,15 @@ import { scaleSizeW } from '@/utils/pixelRatio'
export const BTN_WIDTH = scaleSizeW(36) export const BTN_WIDTH = scaleSizeW(36)
export const BTN_ICON_SIZE = 24 export const BTN_ICON_SIZE = 24
export default ({ icon, color, onPress }: { export default ({ icon, color, onPress, onLongPress }: {
icon: string icon: string
color?: string color?: string
onPress: () => void onPress: () => void
onLongPress?: () => void
}) => { }) => {
const theme = useTheme() const theme = useTheme()
return ( return (
<TouchableOpacity style={{ ...styles.cotrolBtn, width: BTN_WIDTH, height: BTN_WIDTH }} activeOpacity={0.5} onPress={onPress}> <TouchableOpacity style={{ ...styles.cotrolBtn, width: BTN_WIDTH, height: BTN_WIDTH }} activeOpacity={0.5} onPress={onPress} onLongPress={onLongPress}>
<Icon name={icon} color={color ?? theme['c-font-label']} size={BTN_ICON_SIZE} /> <Icon name={icon} color={color ?? theme['c-font-label']} size={BTN_ICON_SIZE} />
</TouchableOpacity> </TouchableOpacity>
) )

View File

@ -0,0 +1,29 @@
import Btn from './Btn'
import { useSettingValue } from '@/store/setting/hook'
import DesktopLyricEnable, { type DesktopLyricEnableType } from '@/components/DesktopLyricEnable'
import { memo, useRef } from 'react'
import { toggleDesktopLyricLock } from '@/core/desktopLyric'
import { updateSetting } from '@/core/common'
import settingState from '@/store/setting/state'
export default memo(() => {
const enabledLyric = useSettingValue('desktopLyric.enable')
const desktopLyricEnableRef = useRef<DesktopLyricEnableType>(null)
const update = () => {
desktopLyricEnableRef.current?.setEnabled(!enabledLyric)
}
const updateLock = () => {
const isLock = !settingState.setting['desktopLyric.isLock']
void toggleDesktopLyricLock(isLock).then(() => {
updateSetting({ 'desktopLyric.isLock': isLock })
})
}
return (
<>
<Btn icon={enabledLyric ? 'lyric-on' : 'lyric-off'} onPress={update} onLongPress={updateLock} />
<DesktopLyricEnable ref={desktopLyricEnableRef} />
</>
)
})

View File

@ -2,13 +2,13 @@ import { createStyle } from '@/utils/tools'
import { View } from 'react-native' import { View } from 'react-native'
import PlayModeBtn from './PlayModeBtn' import PlayModeBtn from './PlayModeBtn'
import MusicAddBtn from './MusicAddBtn' import MusicAddBtn from './MusicAddBtn'
import TimeoutExitBtn from './TimeoutExitBtn' import DesktopLyricBtn from './DesktopLyricBtn'
import CommentBtn from './CommentBtn' import CommentBtn from './CommentBtn'
export default () => { export default () => {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<TimeoutExitBtn /> <DesktopLyricBtn />
<MusicAddBtn /> <MusicAddBtn />
<PlayModeBtn /> <PlayModeBtn />
<CommentBtn /> <CommentBtn />

View File

@ -0,0 +1,28 @@
import { TouchableOpacity } from 'react-native'
import { Icon } from '@/components/common/Icon'
import { createStyle } from '@/utils/tools'
import { scaleSizeH } from '@/utils/pixelRatio'
import { HEADER_HEIGHT as _HEADER_HEIGHT } from '@/config/constant'
export const HEADER_HEIGHT = scaleSizeH(_HEADER_HEIGHT)
export default ({ icon, color, onPress }: {
icon: string
color?: string
onPress: () => void
}) => {
return (
<TouchableOpacity onPress={onPress} style={{ ...styles.button, width: HEADER_HEIGHT }}>
<Icon name={icon} color={color} size={18} />
</TouchableOpacity>
)
}
const styles = createStyle({
button: {
justifyContent: 'center',
alignItems: 'center',
height: '100%',
flex: 0,
},
})

View File

@ -1,8 +1,7 @@
import { memo, useRef } from 'react' import { memo, useRef } from 'react'
import { View, StyleSheet, TouchableOpacity } from 'react-native' import { View, StyleSheet } from 'react-native'
import { Icon } from '@/components/common/Icon'
import { pop } from '@/navigation' import { pop } from '@/navigation'
import StatusBar from '@/components/common/StatusBar' import StatusBar from '@/components/common/StatusBar'
import { useTheme } from '@/store/theme/hook' import { useTheme } from '@/store/theme/hook'
@ -13,6 +12,8 @@ import { HEADER_HEIGHT as _HEADER_HEIGHT, NAV_SHEAR_NATIVE_IDS } from '@/config/
import commonState from '@/store/common/state' import commonState from '@/store/common/state'
import SettingPopup, { type SettingPopupType } from '../../components/SettingPopup' import SettingPopup, { type SettingPopupType } from '../../components/SettingPopup'
import { useStatusbarHeight } from '@/store/common/hook' import { useStatusbarHeight } from '@/store/common/hook'
import Btn from './Btn'
import TimeoutExitBtn from './TimeoutExitBtn'
export const HEADER_HEIGHT = scaleSizeH(_HEADER_HEIGHT) export const HEADER_HEIGHT = scaleSizeH(_HEADER_HEIGHT)
@ -45,13 +46,10 @@ export default memo(() => {
<View style={{ height: HEADER_HEIGHT + statusBarHeight, paddingTop: statusBarHeight }} nativeID={NAV_SHEAR_NATIVE_IDS.playDetail_header}> <View style={{ height: HEADER_HEIGHT + statusBarHeight, paddingTop: statusBarHeight }} nativeID={NAV_SHEAR_NATIVE_IDS.playDetail_header}>
<StatusBar /> <StatusBar />
<View style={styles.container}> <View style={styles.container}>
<TouchableOpacity onPress={back} style={{ ...styles.button, width: HEADER_HEIGHT }}> <Btn icon="chevron-left" onPress={back} />
<Icon name="chevron-left" size={18} />
</TouchableOpacity>
<Title /> <Title />
<TouchableOpacity onPress={showSetting} style={{ ...styles.button, width: HEADER_HEIGHT }}> <TimeoutExitBtn />
<Icon name="slider" size={19} /> <Btn icon="slider" onPress={showSetting} />
</TouchableOpacity>
</View> </View>
<SettingPopup ref={popupRef} direction="vertical" /> <SettingPopup ref={popupRef} direction="vertical" />
</View> </View>
@ -65,15 +63,10 @@ const styles = StyleSheet.create({
// justifyContent: 'center', // justifyContent: 'center',
height: '100%', height: '100%',
}, },
button: {
justifyContent: 'center',
alignItems: 'center',
height: '100%',
flex: 0,
},
titleContent: { titleContent: {
flex: 1, flex: 1,
alignItems: 'center', paddingHorizontal: 5,
// alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
}, },
title: { title: {

View File

@ -0,0 +1,23 @@
import { memo, useRef } from 'react'
import TimeoutExitEditModal, { type TimeoutExitEditModalType, useTimeInfo } from '@/components/TimeoutExitEditModal'
import { useTheme } from '@/store/theme/hook'
import Btn from './Btn'
export default memo(() => {
const theme = useTheme()
const modalRef = useRef<TimeoutExitEditModalType>(null)
const timeInfo = useTimeInfo()
const handleShow = () => {
modalRef.current?.show()
}
return (
<>
<Btn icon="music_time" color={timeInfo.active ? theme['c-primary-font-active'] : theme['c-font']} onPress={handleShow} />
<TimeoutExitEditModal ref={modalRef} timeInfo={timeInfo} />
</>
)
})