Skip to content

Commit

Permalink
hide share btn & fix next & prev btns in menu
Browse files Browse the repository at this point in the history
  • Loading branch information
miaowing committed Jul 3, 2019
1 parent 108ef46 commit cefcdc1
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 73 deletions.
31 changes: 29 additions & 2 deletions src/actions/UserAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ export class UserAction {
}

public static comment(userId: string, content: string, replyUserId?: string, commentId?: string) {
return async dispatch => {
return async (dispatch, state: () => IState) => {
const url = 'http://mobileapi.5sing.kugou.com/comments/create';
const form = { rootId: userId, content, owner: userId, rootKind: 'guestBook', replyUserId, commentId };
const response: AxiosResponse<I5singResponse<any>> = await instance.post(
Expand All @@ -225,7 +225,34 @@ export class UserAction {
return message.error(response.data.message);
}

dispatch(UserAction.getMusicianComments(userId, commentId));
if (replyUserId) {
const exists = state().comment.guestBook || [];
const target = exists.filter(exist => exist.id === commentId)[0];
if (target) {
target.replies.unshift({
id: '',
content,
createTime: new Date().toString(),
repliesCount: 0,
like: 0,
isLike: false,
replyUser: {
id: Number(replyUserId),
nickname: replyUserId,
image: '',
},
user: {
id: 0,
nickname: '',
image: ''
},
});
dispatch({ type: COMMENT, action: SET, data: { guestBook: exists } });
}
} else {
dispatch(UserAction.getMusicianComments(userId, commentId));
}

}
}
}
50 changes: 25 additions & 25 deletions src/components/Play.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,47 +33,47 @@ export class Play extends React.Component<IPlayProps, IPlayState> {
const spread = this.state.spread;
return [
<p>
<span>歌曲数:{ songCount }</span>
<span>最近更新:{ updatedAt }</span>
<span>歌曲数:{songCount}</span>
<span>最近更新:{updatedAt}</span>
</p>,
<p className={ !spread ? 'balabala' : '' } style={ { paddingRight: 14 } }>
<i style={ { visibility: 'hidden' } }></i>述:{ description }
<Icon className={ styles.spread_btn }
type={ spread ? 'caret-up' : 'caret-down' }
onClick={ () => this.setState({ spread: !this.state.spread }) }/>
<p className={!spread ? 'balabala' : ''} style={{ paddingRight: 14 }}>
<i style={{ visibility: 'hidden' }}></i>述:{description}
<Icon className={styles.spread_btn}
type={spread ? 'caret-up' : 'caret-down'}
onClick={() => this.setState({ spread: !this.state.spread })}/>
</p>
]
}

renderTools() {
const { collects, shares, isLike, onLike, onPlayAll } = this.props;
return <div className={ styles.tools }>
<Button type="primary" onClick={ onPlayAll }><Icon type="play-circle"/>播放全部</Button>
<Button onClick={ this.props.onDownloadAll }><Icon type="download"/>下载全部</Button>
{ !isUndefined(collects) && <Button onClick={ onLike }>
<Icon type="select"/>{ isLike ? '已' : '' }收藏({ collects })
</Button> }
{ !isUndefined(shares) && <Button onClick={ this.props.onDownloadAll }>
<Icon type="share-alt"/>分享({ shares })
</Button> }
const { collects, isLike, onLike, onPlayAll } = this.props;
return <div className={styles.tools}>
<Button type="primary" onClick={onPlayAll}><Icon type="play-circle"/>播放全部</Button>
<Button onClick={this.props.onDownloadAll}><Icon type="download"/>下载全部</Button>
{!isUndefined(collects) && <Button onClick={onLike}>
<Icon type="select"/>{isLike ? '已' : ''}收藏({collects})
</Button>}
{/*{ !isUndefined(shares) && <Button onClick={ this.props.onDownloadAll }>*/}
{/* <Icon type="share-alt"/>分享({ shares })*/}
{/*</Button> }*/}
</div>
}

render() {
const { image, title, type = 'play' } = this.props;
return <div className={ styles.play }>
<div className={ styles.play_top }>
<img src={ image } alt={ title }/>
<div className={ styles.play_info }>
<h1><span>歌单</span>{ title }</h1>
{ type === 'play' ?
return <div className={styles.play}>
<div className={styles.play_top}>
<img src={image} alt={title}/>
<div className={styles.play_info}>
<h1><span>歌单</span>{title}</h1>
{type === 'play' ?
[this.renderTools(), this.renderInfo()] :
[this.renderInfo(), this.renderTools()]
}
</div>
</div>
<div className={ styles.play_content }>
{ this.props.children }
<div className={styles.play_content}>
{this.props.children}
</div>
</div>
}
Expand Down
2 changes: 2 additions & 0 deletions src/constants/Events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ export const LOGOUT_EVENT = 'LOGOUT_EVENT';
export const LOGIN_SUCCESS_EVENT = 'LOGIN_SUCCESS_EVENT';
export const SYNC_CACHE_EVENT = 'SYNC_CACHE_EVENT';
export const SYNC_LRC_EVENT = 'SYNC_LRC_EVENT';
export const SONG_CHANGE_EVENT = 'SONG_CHANGE_EVENT';
export const SEARCH_EVENT = 'SEARCH_EVENT';
13 changes: 7 additions & 6 deletions src/main/menu.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { shell, BrowserWindow, app, MenuItemConstructorOptions, Menu } from 'electron';
import { checkVersion } from "./upgrade";
import { SONG_CHANGE_EVENT } from "../constants/Events";

export const initAppMenu = (window: BrowserWindow) => {
if (process.platform === 'darwin') {
Expand All @@ -13,21 +14,21 @@ export const initWindowsMenu = (window: BrowserWindow): MenuItemConstructorOptio
label: '播放/暂停',
accelerator: 'MediaPlayPause',
click: () => {
window.webContents.send('change-song', 'pre');
window.webContents.send(SONG_CHANGE_EVENT, 'play_pause');
}
},
{
label: '上一曲',
accelerator: 'MediaPreviousTrack',
click: () => {
window.webContents.send('change-song', 'pre');
window.webContents.send(SONG_CHANGE_EVENT, 'pre');
}
},
{
label: '下一曲',
accelerator: 'MediaNextTrack',
click: function () {
window.webContents.send('change-song', 'next');
window.webContents.send(SONG_CHANGE_EVENT, 'next');
}
},
{
Expand Down Expand Up @@ -164,21 +165,21 @@ export const initMacMenu = (window: BrowserWindow): MenuItemConstructorOptions[]
label: '播放/暂停',
accelerator: 'MediaPlayPause',
click: () => {
window.webContents.send('change-song', 'play');
window.webContents.send(SONG_CHANGE_EVENT, 'play_pause');
}
},
{
label: '上一曲',
accelerator: 'MediaPreviousTrack',
click: () => {
window.webContents.send('change-song', 'pre');
window.webContents.send(SONG_CHANGE_EVENT, 'pre');
}
},
{
label: '下一曲',
accelerator: 'MediaNextTrack',
click: function () {
window.webContents.send('change-song', 'next');
window.webContents.send(SONG_CHANGE_EVENT, 'next');
}
}
]
Expand Down
3 changes: 2 additions & 1 deletion src/main/touch-bar.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { TouchBar, nativeImage, BrowserWindow } from 'electron';
import { resolve } from "path";
import { SEARCH_EVENT } from "../constants/Events";

export const initTouchBar = (window: BrowserWindow): TouchBar => {
const favoriteIcon = nativeImage.createFromPath(resolve(__dirname, '../../src/assets/touch-bar/TouchBarFavorite.png'));
const searchIcon = nativeImage.createFromPath(resolve(__dirname, '../../src/assets/touch-bar/TouchBarSearch.png'));
const touchBar = new TouchBar({
items: [
new TouchBar.TouchBarButton({ icon: favoriteIcon }),
new TouchBar.TouchBarButton({ icon: searchIcon }),
new TouchBar.TouchBarButton({ icon: searchIcon, click: () => window.webContents.send(SEARCH_EVENT) }),
new TouchBar.TouchBarSpacer({ size: 'large' }),
]
});
Expand Down
4 changes: 2 additions & 2 deletions src/modules/core/Event.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ export class Event extends React.Component<any> {
this.props.dispatch({
type: DOWNLOAD,
action: UPDATE_PROPERTY,
path: `${ item.songKind }-${ item.songId }`,
path: `${item.songKind}-${item.songId}`,
data: item
});
this.props.dispatch({ type: DOWNLOAD, action: SET, data: this.props.downloads });
});
ipcRenderer.on(LOGIN_SUCCESS_EVENT, (evt, system) => {
console.log(system);
this.props.dispatch({ type: SYSTEM, action: SET, data: system });
})
});
}

render() {
Expand Down
31 changes: 22 additions & 9 deletions src/modules/core/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { bindActionCreators, Dispatch } from "redux";
import { actions } from "../../utils/ActionUtil";
import { SystemAction } from "../../actions/SystemAction";
import { HistoryAction } from "../../actions/HistoryAction";
import { ipcRenderer } from "electron";
import { SEARCH_EVENT } from "../../constants/Events";

export interface IHeaderProps {
system?: ISystem;
Expand All @@ -30,6 +32,16 @@ export interface IHeaderProps {
})
)
export class Header extends React.Component<IHeaderProps> {
private el = null;

componentDidMount(): void {
ipcRenderer.on(SEARCH_EVENT, evt => {
if (this.el) {
this.el.input.focus();
}
});
}

go() {
this.props.actions.history.go();
this.props.actions.system.refreshSystem();
Expand All @@ -50,18 +62,19 @@ export class Header extends React.Component<IHeaderProps> {
}
return <div className="header">
<div className="histories-btn-group">
<Icon className={ `histories-btn ${ canGoBack ? '' : 'disabled' }` }
<Icon className={`histories-btn ${canGoBack ? '' : 'disabled'}`}
type="left"
onClick={ () => this.back() }/>
<Icon className={ `histories-btn ${ canGoForward ? '' : 'disabled' }` }
onClick={() => this.back()}/>
<Icon className={`histories-btn ${canGoForward ? '' : 'disabled'}`}
type="right"
onClick={ () => this.go() }/>
onClick={() => this.go()}/>
</div>
<Input.Search
ref={el => this.el = el}
className="search-input"
size="small"
defaultValue={ decodeURIComponent(searchValue) }
onSearch={ value => {
defaultValue={decodeURIComponent(searchValue)}
onSearch={value => {
const current = location.hash;
if (current.includes('#/search')) {
const chunks = current.split('/');
Expand All @@ -74,11 +87,11 @@ export class Header extends React.Component<IHeaderProps> {
}
location.hash = hash + '/' + encodeURIComponent(value);
} else {
location.hash = `search/song/${ encodeURIComponent(value) }`;
location.hash = `search/song/${encodeURIComponent(value)}`;
}
} }
}}
/>
<a onClick={ () => location.hash = '#/settings' } className="settings-btn">
<a onClick={() => location.hash = '#/settings'} className="settings-btn">
<Icon type="bars" className="settings-btn-icon"/>
</a>
</div>
Expand Down
75 changes: 47 additions & 28 deletions src/modules/core/Player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { ISong } from "../../interfaces/ISong";
import { Link } from "react-router-dom";
import { toMap } from "../../utils/DataUtil";
import { PlaySongs } from "./PlaySongs";
import { SYNC_LRC_EVENT } from "../../constants/Events";
import { SONG_CHANGE_EVENT, SYNC_LRC_EVENT } from "../../constants/Events";

export interface IPlayerProps {
current?: number;
Expand Down Expand Up @@ -65,7 +65,26 @@ class Player extends React.Component<IPlayerProps, IPlayerState> {
} else {
ipcRenderer.send(SYNC_LRC_EVENT, { text: this.props.currentTime < 3 ? '暂无歌词' : '' });
}
})
});
ipcRenderer.on(SONG_CHANGE_EVENT, (evt, type) => {
switch (type) {
case 'pre':
this.previous();
break;
case 'next':
this.next();
break;
default:
if (this.props.soundCloudAudio.playing) {
this.previous()
} else {
const song = this.props.songList[this.props.current];
if (song) {
this.play(song);
}
}
}
});
}

next(index?: number) {
Expand Down Expand Up @@ -103,7 +122,7 @@ class Player extends React.Component<IPlayerProps, IPlayerState> {
const currentTime = this.props.currentTime;
const url = song.local || song.hqurl || song.squrl || song.lqurl;
this.props.soundCloudAudio.play({
streamUrl: song.local ? url : `http://127.0.0.1:56562/play-music?url=${ encodeURIComponent(url) }`
streamUrl: song.local ? url : `http://127.0.0.1:56562/play-music?url=${encodeURIComponent(url)}`
});

this.props.soundCloudAudio.setTime(currentTime);
Expand Down Expand Up @@ -162,41 +181,41 @@ class Player extends React.Component<IPlayerProps, IPlayerState> {
render() {
const { current, soundCloudAudio, songList, loveSongs, seq } = this.props;
const song: ISong = songList[current] || { songName: '', name: '' };
const loves = toMap<ISong>(loveSongs, i => `${ i.kind }-${ i.id }`);
const loves = toMap<ISong>(loveSongs, i => `${i.kind}-${i.id}`);
const user = get(song, 'user', { image: defaultUserImage, nickname: '', id: '' });
const key = `${ song.kind }-${ song.id }`;
const key = `${song.kind}-${song.id}`;
const hasLoved = !!loves[key];
return <div className={ styles.player }>
<img className={ styles.user_image } src={ user.image || defaultUserImage } alt={ user.nickname }/>
<div className={ styles.info }>
<h3 className="balabala">{ song.name }</h3>
return <div className={styles.player}>
<img className={styles.user_image} src={user.image || defaultUserImage} alt={user.nickname}/>
<div className={styles.info}>
<h3 className="balabala">{song.name}</h3>
<h3 className="balabala">
<Link to={ user.id === -1 ? `/clouds` : `/musicians/${ user.id }` }>{ user.nickname }</Link>
<Link to={user.id === -1 ? `/clouds` : `/musicians/${user.id}`}>{user.nickname}</Link>
</h3>
</div>
<div className={ styles.play_btn_group }>
<div className={styles.play_btn_group}>
<Icon type="heart" theme="filled"
onClick={ () => this.love(hasLoved, song) }
className={ `${ styles.like_btn } ${ hasLoved ? styles.highlight : '' }` }/>
<Timer className={ styles.time } { ...this.props } />
<Icon className={ styles.prev_btn } type="vertical-right" onClick={ () => this.previous() }/>
{ !soundCloudAudio.playing ?
<Icon className={ styles.play_btn } type="play-circle" onClick={ () => this.play(song) }/> :
<Icon className={ styles.pause_btn } type="pause-circle" onClick={ () => this.pause() }/>
onClick={() => this.love(hasLoved, song)}
className={`${styles.like_btn} ${hasLoved ? styles.highlight : ''}`}/>
<Timer className={styles.time} {...this.props} />
<Icon className={styles.prev_btn} type="vertical-right" onClick={() => this.previous()}/>
{!soundCloudAudio.playing ?
<Icon className={styles.play_btn} type="play-circle" onClick={() => this.play(song)}/> :
<Icon className={styles.pause_btn} type="pause-circle" onClick={() => this.pause()}/>
}
<Icon className={ styles.next_btn } type="vertical-left" onClick={ () => this.next() }/>
<span className={ styles.sequence } onClick={ () => this.nextSeq() }>
<Tag>{ this.prettySeq(seq) }</Tag>
<Icon className={styles.next_btn} type="vertical-left" onClick={() => this.next()}/>
<span className={styles.sequence} onClick={() => this.nextSeq()}>
<Tag>{this.prettySeq(seq)}</Tag>
</span>
<Icon className={ styles.share_btn } type="export"/>
{/*<Icon className={ styles.share_btn } type="export"/>*/}
</div>

<Icon className={ styles.list_btn } type="menu-unfold" onClick={ () => this.togglePlayList() }/>
<Slider className={ styles.voice_slider } defaultValue={ 100 } max={ 100 } min={ 0 }
onChange={ (value: number) => soundCloudAudio.setVolume(value / 100) }/>
<Icon className={ styles.voice_btn } type="sound"/>
<Progress className={ styles.progress } { ...this.props }/>
{ this.state.visible ? <PlaySongs/> : null }
<Icon className={styles.list_btn} type="menu-unfold" onClick={() => this.togglePlayList()}/>
<Slider className={styles.voice_slider} defaultValue={100} max={100} min={0}
onChange={(value: number) => soundCloudAudio.setVolume(value / 100)}/>
<Icon className={styles.voice_btn} type="sound"/>
<Progress className={styles.progress} {...this.props}/>
{this.state.visible ? <PlaySongs/> : null}
</div>
}
}
Expand Down

0 comments on commit cefcdc1

Please sign in to comment.