refactor context menu as function component

This commit is contained in:
Bruce Liu 2025-03-02 21:41:11 -08:00
parent ba9edbd65b
commit 5ecf189ed6
5 changed files with 576 additions and 694 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,5 @@
import * as React from "react"
import { connect } from "react-redux"
import { ContextMenuContainer } from "../containers/context-menu-container"
import { closeContextMenu } from "../scripts/models/app"
import PageContainer from "../containers/page-container"
import MenuContainer from "../containers/menu-container"
@ -8,6 +7,7 @@ import NavContainer from "../containers/nav-container"
import LogMenuContainer from "../containers/log-menu-container"
import SettingsContainer from "../containers/settings-container"
import { RootState } from "../scripts/reducer"
import { ContextMenu } from "./context-menu"
const Root = ({ locale, dispatch }) =>
locale && (
@ -20,7 +20,7 @@ const Root = ({ locale, dispatch }) =>
<LogMenuContainer />
<MenuContainer />
<SettingsContainer />
<ContextMenuContainer />
<ContextMenu />
</div>
)

View File

@ -1,115 +0,0 @@
import { connect } from "react-redux"
import { createSelector } from "reselect"
import { RootState } from "../scripts/reducer"
import {
ContextMenuType,
closeContextMenu,
toggleSettings,
} from "../scripts/models/app"
import { ContextMenu } from "../components/context-menu"
import {
RSSItem,
markRead,
markUnread,
toggleStarred,
toggleHidden,
markAllRead,
fetchItems,
} from "../scripts/models/item"
import {
showItem,
switchView,
switchFilter,
toggleFilter,
setViewConfigs,
} from "../scripts/models/page"
import { ViewType, ViewConfigs } from "../schema-types"
import { FilterType } from "../scripts/models/feed"
const getContext = (state: RootState) => state.app.contextMenu
const getViewType = (state: RootState) => state.page.viewType
const getFilter = (state: RootState) => state.page.filter
const getViewConfigs = (state: RootState) => state.page.viewConfigs
const mapStateToProps = createSelector(
[getContext, getViewType, getFilter, getViewConfigs],
(context, viewType, filter, viewConfigs) => {
switch (context.type) {
case ContextMenuType.Item:
return {
type: context.type,
event: context.event,
viewConfigs: viewConfigs,
item: context.target[0],
feedId: context.target[1],
}
case ContextMenuType.Text:
return {
type: context.type,
position: context.position,
text: context.target[0],
url: context.target[1],
}
case ContextMenuType.View:
return {
type: context.type,
event: context.event,
viewType: viewType,
filter: filter.type,
}
case ContextMenuType.Group:
return {
type: context.type,
event: context.event,
sids: context.target,
}
case ContextMenuType.Image:
return {
type: context.type,
position: context.position,
}
case ContextMenuType.MarkRead:
return {
type: context.type,
event: context.event,
}
default:
return { type: ContextMenuType.Hidden }
}
}
)
const mapDispatchToProps = dispatch => {
return {
showItem: (feedId: string, item: RSSItem) =>
dispatch(showItem(feedId, item)),
markRead: (item: RSSItem) => dispatch(markRead(item)),
markUnread: (item: RSSItem) => dispatch(markUnread(item)),
toggleStarred: (item: RSSItem) => dispatch(toggleStarred(item)),
toggleHidden: (item: RSSItem) => {
if (!item.hasRead) {
dispatch(markRead(item))
item.hasRead = true // get around chaining error
}
dispatch(toggleHidden(item))
},
switchView: (viewType: ViewType) => {
window.settings.setDefaultView(viewType)
dispatch(switchView(viewType))
},
setViewConfigs: (configs: ViewConfigs) =>
dispatch(setViewConfigs(configs)),
switchFilter: (filter: FilterType) => dispatch(switchFilter(filter)),
toggleFilter: (filter: FilterType) => dispatch(toggleFilter(filter)),
markAllRead: (sids?: number[], date?: Date, before?: boolean) => {
dispatch(markAllRead(sids, date, before))
},
fetchItems: (sids: number[]) => dispatch(fetchItems(false, sids)),
settings: (sids: number[]) => dispatch(toggleSettings(true, sids)),
close: () => dispatch(closeContextMenu()),
}
}
const connector = connect(mapStateToProps, mapDispatchToProps)
export type ContextReduxProps = typeof connector
export const ContextMenuContainer = connector(ContextMenu)

View File

@ -1,29 +1,21 @@
import * as React from "react"
import * as ReactDOM from "react-dom"
import { Provider } from "react-redux"
import { createStore, applyMiddleware } from "redux"
import thunkMiddleware from "redux-thunk"
import { initializeIcons } from "@fluentui/react/lib/Icons"
import { rootReducer, RootState } from "./scripts/reducer"
import Root from "./components/root"
import { AppDispatch } from "./scripts/utils"
import { applyThemeSettings } from "./scripts/settings"
import { initApp, openTextMenu } from "./scripts/models/app"
import { rootStore } from "./scripts/reducer"
window.settings.setProxy()
applyThemeSettings()
initializeIcons("icons/")
const store = createStore(
rootReducer,
applyMiddleware<AppDispatch, RootState>(thunkMiddleware)
)
store.dispatch(initApp())
rootStore.dispatch(initApp())
window.utils.addMainContextListener((pos, text) => {
store.dispatch(openTextMenu(pos, text))
rootStore.dispatch(openTextMenu(pos, text))
})
window.fontList = [""]
@ -32,7 +24,7 @@ window.utils.initFontList().then(fonts => {
})
ReactDOM.render(
<Provider store={store}>
<Provider store={rootStore}>
<Root />
</Provider>,
document.getElementById("app")

View File

@ -1,4 +1,5 @@
import { combineReducers } from "redux"
import { applyMiddleware, combineReducers, createStore } from "redux"
import thunkMiddleware from "redux-thunk"
import { sourceReducer } from "./models/source"
import { itemReducer } from "./models/item"
@ -7,6 +8,13 @@ import { appReducer } from "./models/app"
import { groupReducer } from "./models/group"
import { pageReducer } from "./models/page"
import { serviceReducer } from "./models/service"
import { AppDispatch } from "./utils"
import {
TypedUseSelectorHook,
useDispatch,
useSelector,
useStore,
} from "react-redux"
export const rootReducer = combineReducers({
sources: sourceReducer,
@ -18,4 +26,14 @@ export const rootReducer = combineReducers({
app: appReducer,
})
export const rootStore = createStore(
rootReducer,
applyMiddleware<AppDispatch, RootState>(thunkMiddleware)
)
export type AppStore = typeof rootStore
export type RootState = ReturnType<typeof rootReducer>
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
export const useAppStore: () => AppStore = useStore