Skip to content

Commit

Permalink
Merge pull request #18 from Barba828/feat/auto-b
Browse files Browse the repository at this point in the history
Feat/auto b
  • Loading branch information
Barba828 authored Feb 21, 2024
2 parents 03d2530 + 231f719 commit 13aef53
Show file tree
Hide file tree
Showing 50 changed files with 1,527 additions and 1,002 deletions.
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
"singleQuote": true,
"semi": false,
"trailingComma": "es5",
"printWidth": 100
"printWidth": 120
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FC, useState, memo } from 'react'
import { ModeType, ToneSchema, transFifthsCircle } from '@buitar/to-guitar'
import { ModeType, ToneSchema, generateFifthCircle } from '@buitar/to-guitar'
import classnames from 'classnames'

import styles from './fifths-circle.module.scss'
Expand All @@ -21,8 +21,8 @@ const angle = [
(-Math.PI * 2) / 3,
]

const OUTER_TONES = transFifthsCircle('C')
const INNER_TONES = transFifthsCircle('A')
const OUTER_TONES = generateFifthCircle('C')
const INNER_TONES = generateFifthCircle('A')

export type FifthCircleProps = {
/**
Expand Down Expand Up @@ -116,13 +116,12 @@ export const FifthsCircle: FC<FifthCircleProps> = memo(({
className={styles.arc}
checked={checked - 12}
onClick={(index: number) => {
index += 12
if(index === checked) {
if(index + 12 === checked) {
setChecked(-1)
onClick?.({ mode: 'minor'})
return
}
setChecked(index)
setChecked(index + 12)
onClick?.({ tone: INNER_TONES[index], mode: 'minor' })
}}
></Arc>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React, { FC, useMemo, useState, memo, useCallback } from 'react'
import { useBoardContext } from '../../board-provider'
import { SvgChord, transToSvgPoints } from '@/components/svg-chord'
import { Icon } from '@/components/icon'
import { Portal, getBoardOptionsNote } from '@/components'
import { BoardChord, NOTE_LIST, Point, getDegreeTag, transInterval } from '@buitar/to-guitar'
import { Portal } from '@/components'
import { BoardChord, NOTE_LIST, Point, toDegreeTag, intervalToSemitones } from '@buitar/to-guitar'
import { CardCollector } from './card-collector.component'
import { CardDownloader } from './card-downloader.component'
import { getBoardChordName } from './utils'
Expand All @@ -28,20 +28,14 @@ export const ChordCard: FC<{
size?: number
extra?: JSX.Element | JSX.Element[]
}> = memo(({ taps, title, className, size = 160, extra, disableCollect, onRemoveCollection }) => {

const {
player,
guitarBoardOption: { keyboard },
} = useBoardContext()
const [collectionVisible, setCollectionVisible] = useState(false)
const [downloadVisible, setDownloadVisible] = useState(false)

const cls = cx(
'primary-button',
styles['chord-card'],
className,
taps.length === 0 && styles['chord-card-hidden']
)
const cls = cx('primary-button', styles['chord-card'], className, taps.length === 0 && styles['chord-card-hidden'])

const svgPoints = useMemo(() => transToSvgPoints(taps, keyboard?.length), [taps])

Expand Down Expand Up @@ -108,11 +102,7 @@ export const ChordCard: FC<{
</div>
</div>

<CardCollector
visible={collectionVisible}
data={collectionData}
onCancel={toggleCollectionVisible}
/>
<CardCollector visible={collectionVisible} data={collectionData} onCancel={toggleCollectionVisible} />
<CardDownloader visible={downloadVisible} onCancel={toggleDownloadVisible} {...svgData} />
</div>
)
Expand All @@ -125,21 +115,21 @@ export const ChordCard: FC<{
)
})

export const DetailCard: FC<{ chordType?: BoardChord['chordType'] }> = ({ chordType }) => {
const { boardSettings } = useBoardContext()
const chordName = getBoardChordName(chordType, boardSettings)
export const DetailCard: FC<{ chordType?: BoardChord['chordType'] }> = memo(({ chordType }) => {
const { guitarBoardOption } = useBoardContext()
const chordName = getBoardChordName(chordType, guitarBoardOption)

if (!chordType || !chordType.tone) {
if (!chordType) {
return null
}

const offset = NOTE_LIST.indexOf(chordType?.over?.note || chordType.tone.note)
const offset = chordType.tone || 0
const constitute = chordType.constitute
const constituteTag = constitute?.map((item) => getDegreeTag(item))
const constituteTag = constitute?.map((item) => toDegreeTag(item))
const chordList = constitute?.map((pitch, index) => {
const noteIndex = (offset + transInterval(pitch)) % NOTE_LIST.length
const noteIndex = (offset + intervalToSemitones(pitch)) % NOTE_LIST.length
return {
note: getBoardOptionsNote(noteIndex, boardSettings),
note: guitarBoardOption.notesOnC?.[noteIndex],
degreeTag: constituteTag?.[index],
degree: constitute?.[index],
}
Expand All @@ -159,18 +149,13 @@ export const DetailCard: FC<{ chordType?: BoardChord['chordType'] }> = ({ chordT
<div className={styles['detail-chord']}>
{chordList?.length &&
chordList.map(({ note, degree, degreeTag }, index) => (
<div
key={index}
className={cx('primary-button', styles['detail-chord-note'], 'flex-center')}
>
<div key={index} className={cx('primary-button', styles['detail-chord-note'], 'flex-center')}>
<div className={styles['detail-chord-tag']}>{degreeTag}</div>
<div className={styles['detail-chord-title']}>{note}</div>
<div className={cx(styles['detail-chord-tag'], styles['detail-chord-tag__end'])}>
{degree}
</div>
<div className={cx(styles['detail-chord-tag'], styles['detail-chord-tag__end'])}>{degree}</div>
</div>
))}
</div>
</div>
)
}
})
Original file line number Diff line number Diff line change
@@ -1,40 +1,30 @@
import { BoardChord } from "@buitar/to-guitar"
import { GuitarBoardSetting } from '@/pages/settings/config/controller.type'
import { getBoardOptionsNote } from '@/components/guitar-board/utils'

import { BoardChord } from '@buitar/to-guitar'
import { BoardOption } from '@buitar/to-guitar'

/**
* 根据 chordType 获取和弦名称
* @param chordType
* @param boardSettings
* @returns
*/
export const getBoardChordName = (
chordType?: BoardChord['chordType'],
boardSettings?: Pick<GuitarBoardSetting, 'isSharpSemitone'>
) => {
export const getBoardChordName = (chordType?: BoardChord['chordType'], guitarBoardOption?: Partial<BoardOption>) => {
if (!chordType) {
return ''
return ' '
}
// 自定义名称直接返回
if (chordType.tag === '*') {
return chordType.name
}

// 根据 tone 获取和弦名称
if (!chordType.tone) return ' '
const tone = boardSettings
? getBoardOptionsNote(chordType.tone, boardSettings)
: chordType.tone.note
const over = chordType.over
? boardSettings
? getBoardOptionsNote(chordType.over, boardSettings)
: chordType.over.note
: ''
if (chordType?.tone === undefined || !guitarBoardOption?.notesOnC) {
return ' '
}
const note = guitarBoardOption?.notesOnC[chordType.tone % 12]
const over = chordType.over ? guitarBoardOption?.notesOnC[chordType.over % 12] : ''
const tag = chordType.tag
if (over === tone) {
return `${tone}${tag}`
if (!over || over === note) {
return `${note}${tag}`
} else {
return `${over}${tag}/${tone}`
return `${over}${tag}/${note}`
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FC, useCallback, useEffect, useState } from 'react'
import { Chord, chordDegreeMap, ChordDegreeNum, transChord, getDegreeTag } from '@buitar/to-guitar'
import { DegreeChord, chordDegreeMap, ChordDegreeNum, rootToChord, toDegreeTag } from '@buitar/to-guitar'
import { useBoardContext, ChordTapsController } from '@/components/guitar-board'
import { FifthCircleController } from '../fifth-circle-controller'
import { tagList, tagTypedList } from '@/pages/chord-progressions/progressions.config'
Expand All @@ -24,7 +24,7 @@ export const ChordController: FC = (props) => {
className={cx(styles['chord-tab'])}
values={chordControllConfig}
defaultValue={chordControllConfig[tabIndex]}
onChange={(value, index) => {
onChange={(_value, index) => {
setTabIndex(index)
}}
renderItem={(item) => item.name_zh}
Expand Down Expand Up @@ -59,11 +59,7 @@ export const ChordController: FC = (props) => {
* 左侧五度圈的选择器
* @returns
*/
export const ChordControllerInner: FC<{ left?: JSX.Element; minor?: boolean }> = ({
left,
minor,
children,
}) => {
export const ChordControllerInner: FC<{ left?: JSX.Element; minor?: boolean }> = ({ left, minor, children }) => {
return (
<>
<div className={styles['container']}>
Expand All @@ -74,15 +70,19 @@ export const ChordControllerInner: FC<{ left?: JSX.Element; minor?: boolean }> =
)
}

/**
* 和弦类型选择器
*/
const ChordTypePicker = () => {
const { guitarBoardOption, setChord } = useBoardContext()
const [type, setType] = useState('')

useEffect(() => {
if (!guitarBoardOption.scale) {
return
}
const _chord = transChord(guitarBoardOption.scale, type)
/**
* 五度圈选择器中已经设置了scale调式,和弦的显示通过scale调式决定
* 这里和弦音Note和Scale调式是一个,根据类型来选择永远都是一级和弦,所以这里获取和弦半音程直接 on C 获取
*/
const _chord = rootToChord('C', type)
if (!_chord) {
return
}
Expand All @@ -92,10 +92,11 @@ const ChordTypePicker = () => {
return <ChordTagPicker onChange={setType} tag={type} />
}

export const ChordTagPicker: FC<{ onChange(tag: string): void; tag?: string }> = ({
onChange,
tag,
}) => {
/**
* 和弦Tag类型选择器
* @todo 类型tab不合理
*/
export const ChordTagPicker: FC<{ onChange(tag: string): void; tag?: string }> = ({ onChange, tag }) => {
const [list, setList] = useState(tagList)
const tabQuery = ['all', '3', '7', '9', 'm', 'maj', 'sus', 'aug']
const defaultQuery = '3'
Expand Down Expand Up @@ -179,9 +180,7 @@ const ChordNumPickerController: FC<ControllerListProps<ChordDegreeNum>> = (props
return (
<div className={styles['scale-item']}>
{item}
<span className={styles['scale-item-mode']}>
{chordDegreeMap.get(item)?.name.split(' ')[0]}
</span>
<span className={styles['scale-item-mode']}>{chordDegreeMap.get(item)?.name.split(' ')[0]}</span>
</div>
)
}}
Expand All @@ -195,42 +194,31 @@ const ChordNumPickerController: FC<ControllerListProps<ChordDegreeNum>> = (props
* @param props
* @returns
*/
const ChordPickerController: FC<ControllerListProps<Chord>> = ({ ...props }) => {
const {
chord,
setChord,
guitarBoardOption,
boardSettings: { isSharpSemitone },
} = useBoardContext()

const handleClick = useCallback((item: Chord) => {
setChord(item.chord)
const ChordPickerController: FC<ControllerListProps<DegreeChord>> = ({ ...props }) => {
const { chord, setChord, guitarBoardOption } = useBoardContext()

const handleClick = useCallback((item: DegreeChord) => {
setChord(item.chord.map((degree) => degree.interval))
}, [])

return (
<ControllerList
{...props}
list={guitarBoardOption.chords || []}
onClickItem={handleClick}
renderListItem={(item) => <DegreeChordItem item={item} isSharpSemitone={isSharpSemitone} />}
checkedItem={(item) => item.chord === chord}
renderListItem={(item) => <DegreeChordItem item={item} />}
checkedItem={(item) => item.chord[0].interval === chord[0]}
/>
)
}

export const DegreeChordItem: FC<{ item: Chord; isSharpSemitone?: boolean; withtag?: boolean }> = ({
item,
isSharpSemitone = true,
withtag = true,
}) => {
export const DegreeChordItem: FC<{ item: DegreeChord; withtag?: boolean }> = ({ item, withtag = true }) => {
return (
<div className={styles['chord-item']}>
<div className={styles['chord-item-grade']}>{getDegreeTag(item.degree.degreeNum)}</div>
<span className={styles['chord-item-note']}>
{isSharpSemitone ? item.tone.note : item.tone.noteFalling}
</span>
<div className={styles['chord-item-grade']}>{toDegreeTag(item.degreeNum)}</div>
<span className={styles['chord-item-note']}>{item.note}</span>
{withtag && <span className={styles['chord-item-tag']}>{item.chordType?.[0]?.tag}</span>}
<div className={styles['chord-item-scale']}>{item.degree.scale}</div>
<div className={styles['chord-item-scale']}>{item.scale}</div>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
useConfigContext,
usePlayerContext,
} from '@/components'
import { transChord, transChordTaps, DEGREE_TAG_LIST } from '@buitar/to-guitar'
import { rootToChord, transChordTaps, DEGREE_TAG_LIST } from '@buitar/to-guitar'
import { ControllerList, ControllerListProps } from '@/components/controller'
import cx from 'classnames'

Expand Down Expand Up @@ -252,30 +252,29 @@ export const DegreeChordController: FC<ControllerListProps<any>> = () => {
guitarBoardOption,
setChord,
setChordTaps,
boardSettings: { isSharpSemitone },
} = useBoardContext()
const { progressions, progressionIndex, soundListIndex, setSoundList, setSoundListIndex } =
usePlayerContext()

const chords = useMemo(() => {
if (!progressions[progressionIndex]) {
if (!progressions[progressionIndex] || !guitarBoardOption.chords) {
return []
}
const tones = guitarBoardOption.chords?.map((chord) => chord.tone)
return progressions[progressionIndex].procession.map((degree) => {
const tone = tones![degree.name - 1]
const chord = transChord(tone.note, degree.tag)!
return progressions[progressionIndex].procession.map((item) => {
const degree = guitarBoardOption.chords![item.name - 1]
const chord = rootToChord(degree.note!, item.tag)!
return {
...chord,
tone,
degree: DEGREE_TAG_LIST[degree.name - 1],
tag: item.tag,
degree,
degreeText: DEGREE_TAG_LIST[item.name - 1],
}
})
}, [guitarBoardOption.chords])

useEffect(() => {
const soundList = chords.map((item) => {
return transChordTaps(item.chord, guitarBoardOption)[0].chordTaps
return transChordTaps(item.chord.map((pitch) => guitarBoardOption.notes![pitch % 12]), guitarBoardOption)[0].chordTaps
})
setSoundList(soundList)
}, [guitarBoardOption.chords])
Expand Down Expand Up @@ -306,12 +305,12 @@ export const DegreeChordController: FC<ControllerListProps<any>> = () => {
renderListItem={(item) => {
return (
<div className={styles['chord-item']}>
<div className={styles['chord-item-grade']}>{item.degree}</div>
<div className={styles['chord-item-grade']}>{item.degreeText}</div>
<div>
<span className={styles['chord-item-note']}>
{isSharpSemitone ? item.tone.note : item.tone.noteFalling}
{item.degree.note}
</span>
<span className={styles['chord-item-tag']}>{item.chordType.tag}</span>
<span className={styles['chord-item-tag']}>{item.tag}</span>
</div>
<div className={styles['chord-item-name']}>{item.chordType.name_zh}</div>
</div>
Expand Down
Loading

0 comments on commit 13aef53

Please sign in to comment.