Contributing - lekakid/ArcaRefresher GitHub Wiki
개발 환경을 준수바랍니다.
프로젝트 폴더 구조
- component: 여러곳에서 공통으로 사용되는 컴포넌트 모음
- core: 리프레셔 구현에 필요한 스트링, Redux Store 등 모음
- feature: 각종 기능 컴포넌트 모음
- func: 함수 모음
- menu: 공통된 인터페이스를 제공하기 위한 컴포넌트 모음
- hooks: 리액트 커스텀 훅 모음
기능 폴더의 구조
{GroupName}
|-- {FeatureName}
| |-- ArticleMenu.jsx
| |-- ConfigMenu
| | |-- View.jsx
| | `-- index.jsx
| |-- ContextMenu
| | |-- View.jsx
| | `-- index.jsx
| |-- Feature.jsx
| |-- FeatureInfo.jsx
| `-- slice.jsx
|-- {FeatureName}
| |-- ...
각 기능 컴포넌트와 메뉴 구현 컴포넌트는 feature/index.jsx
와 menu/index.jsx
에서 Webpack context 기능을 통해 자동으로 포함됩니다.
주의사항
/ArticleMenu
,/ConfigMenu
,/ContextMenu
,/Feature
,/slice.jsx
의 이름을 바꿔선 안됩니다.- Group이 서로 다른 기능이더라도 이름이 같아선 안됩니다.
설정 데이터의 관리
💡 redux slice의 기본적인 작성법은 Redux Toolkit 문서를 참고바랍니다.
각 기능들의 설정 데이터는 slice.jsx
의 리듀서 정의를 통해 관리됩니다.
defaultStorage
오브젝트를 통해 유저스크립트 확장 프로그램이 관리할 데이터를 정할 수 있습니다.
const defaultStorage = {
myNewConfig: 'hello!',
};
defaultStorage
는 이후 initialState.storage
에 할당합니다.
🚫 할당하는 이름(storage)을 바꾸면 안됩니다.
const initialState = {
storage: getValue(Info.ID, defaultStorage),
// 이 아래에 인터페이스 제어용 state 추가
show: true,
};
storage
를 제어하는 리듀서는 이름이 $
로 시작해야합니다. $
로 시작하는 리듀서를 호출할 때 마다 저장할 데이터에 변화가 있다고 판단합니다. 자세한 구조는 core/storage.jsx
의 createMonkeySyncMiddleware
를 참고바랍니다.
export const slice = createSlice({
name: Info.ID,
initialState,
reducers: {
// 아래와 같이 추가합니다.
toggleShow(state) {
state.show = !state.show;
},
// storage를 제어하는 리듀서는 탭간 동기화 구분을 위해 이름을 $로 시작해야합니다!!
$setMyNewConfig(state, action) {
state.storage.myNewConfig = action.payload;
},
},
});
설정 데이터의 업데이트
const defaultStorage = {
version: 1,
contextRange: 'articleItem',
variant: 'badge',
memo: {},
};
function formatUpdater(storage, defaultValue) {
// version 0 => 1
const version = storage?.version || 0;
switch (version) {
case 0: {
const memo = Object.fromEntries(
Object.entries(storage.memo).map(([key, msg]) => [key, { msg }]),
);
const data = getValue('UserColor');
if (data) {
Object.entries(data.color).forEach(([key, color]) => {
(memo[key] ??= {}).color = color;
});
deleteValue('UserColor');
}
const updateStorage = { ...storage };
updateStorage.memo = memo;
updateStorage.version = 1;
return updateStorage;
}
default:
console.warn('지원하지 않는 버전 데이터입니다.', storage);
return defaultValue;
}
}
const initialState = {
storage: getValue(Info.ID, defaultStorage, formatUpdater),
};
getValue
의 3번째 인자로 formatUpdater
함수를 받을 수 있습니다. 저장 데이터 내에 version
값을 지정하고 이 값에 따라 데이터를 필요에 따라 변환할 수 있습니다. 변환 전 데이터는 내부 저장소에 {FeatureName}_v{version}
백업데이터로 남습니다.