poi-plugin-quest-info-2 0.5.0 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,10 +7,12 @@ import {
7
7
  List,
8
8
  ListRowRenderer,
9
9
  } from 'react-virtualized'
10
+ import type { ListRowProps } from 'react-virtualized'
10
11
  import styled from 'styled-components'
11
12
  import { KcanotifyQuestExt, QUEST_STATUS } from '../questHelper'
12
13
  import { useLargeCard } from '../store'
13
14
  import { QuestCard } from './QuestCard'
15
+ import { useIsQuestPluginTab } from '../poi/hooks'
14
16
 
15
17
  const QuestListWrapper = styled.div`
16
18
  flex: 1;
@@ -23,25 +25,9 @@ const cache = new CellMeasurerCache({
23
25
  fixedWidth: true,
24
26
  })
25
27
 
26
- export const QuestList: React.FC<{ quests: KcanotifyQuestExt[] }> = ({
27
- quests,
28
- }) => {
29
- const { largeCard } = useLargeCard()
30
- const listRef = useRef<List>(null)
31
-
32
- useEffect(() => {
33
- const changedIdx = quests.findIndex((i) => i.gameId === largeCard)
34
- cache.clearAll()
35
- listRef.current?.recomputeRowHeights(changedIdx)
36
- }, [quests, largeCard])
37
-
38
- const onResize = useCallback(() => {
39
- cache.clearAll()
40
- listRef.current?.recomputeRowHeights()
41
- }, [])
42
-
43
- const rowRenderer: ListRowRenderer = useCallback(
44
- ({ key, index, style, parent }) => {
28
+ const useQuestsRowRenderer = (quests: KcanotifyQuestExt[]) => {
29
+ const rowRenderer = useCallback(
30
+ ({ key, index, style, parent }: ListRowProps) => {
45
31
  const { gameId, code, name, desc, memo, active } = quests[index]
46
32
  return (
47
33
  <CellMeasurer
@@ -67,6 +53,36 @@ export const QuestList: React.FC<{ quests: KcanotifyQuestExt[] }> = ({
67
53
  },
68
54
  [quests]
69
55
  )
56
+ return rowRenderer
57
+ }
58
+
59
+ export const QuestList: React.FC<{ quests: KcanotifyQuestExt[] }> = ({
60
+ quests,
61
+ }) => {
62
+ const { largeCard } = useLargeCard()
63
+ const activeTab = useIsQuestPluginTab()
64
+ const listRef = useRef<List>(null)
65
+
66
+ useEffect(() => {
67
+ const largeCardIdx = quests.findIndex((i) => i.gameId === largeCard)
68
+ cache.clearAll()
69
+ listRef.current?.recomputeRowHeights(largeCardIdx)
70
+ }, [quests, largeCard])
71
+
72
+ useEffect(() => {
73
+ if (activeTab) {
74
+ cache.clearAll()
75
+ listRef.current?.recomputeRowHeights()
76
+ }
77
+ }, [activeTab])
78
+
79
+ const onResize = useCallback(() => {
80
+ cache.clearAll()
81
+ listRef.current?.recomputeRowHeights()
82
+ }, [])
83
+
84
+ const rowRenderer: ListRowRenderer = useQuestsRowRenderer(quests)
85
+
70
86
  if (!quests.length) {
71
87
  // Prevent Uncaught Error: Requested index 0 is outside of range 0..0
72
88
  // See https://github.com/bvaughn/react-virtualized/issues/1016
package/src/patch.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { name as PACKAGE_NAME } from '../package.json'
2
- import { getPoiStore, importFromPoi } from './poi'
2
+ import { getPoiStore } from './poi/store'
3
+ import { importFromPoi } from './poi/env'
3
4
  import { QuestData } from '../build/kcanotifyGamedata'
4
5
  import { KcwikiQuestData } from '../build/kcQuestsData'
5
6
  import {
@@ -7,6 +8,8 @@ import {
7
8
  getStorage,
8
9
  isSupportedLanguages,
9
10
  } from './store'
11
+ import type { i18n } from 'i18next'
12
+
10
13
  const LEGACY_QUEST_PLUGIN_ID = 'poi-plugin-quest-info'
11
14
  const HACK_KEY = `__patched-from-${PACKAGE_NAME}`
12
15
 
@@ -57,36 +60,37 @@ export const patchLegacyQuestPluginReducer = async () => {
57
60
  return
58
61
  }
59
62
 
60
- const language = (globalThis as any).i18next.language
61
- const initState = {
62
- [HACK_KEY]: true,
63
- quests: getQuestState(language),
64
- questStatus: {},
65
- }
63
+ try {
64
+ const i18next: i18n = await importFromPoi('views/env-parts/i18next')
65
+ const language = i18next.language
66
+ const initState = {
67
+ [HACK_KEY]: true,
68
+ quests: getQuestState(language),
69
+ questStatus: {},
70
+ }
66
71
 
67
- const reducer = (
68
- state = initState,
69
- action: { type: string; [x: string]: any }
70
- ) => {
71
- switch (action.type) {
72
- case '@@Config':
73
- // change language
74
- if (action.path === 'poi.misc.language') {
75
- const newLanguage = action.value
76
- return {
77
- ...state,
78
- quests: getQuestState(newLanguage),
72
+ const reducer = (
73
+ state = initState,
74
+ action: { type: string; [x: string]: any }
75
+ ) => {
76
+ switch (action.type) {
77
+ case '@@Config':
78
+ // change language
79
+ if (action.path === 'poi.misc.language') {
80
+ const newLanguage = action.value
81
+ return {
82
+ ...state,
83
+ quests: getQuestState(newLanguage),
84
+ }
79
85
  }
80
- }
86
+ }
87
+ return state
81
88
  }
82
- return state
83
- }
84
89
 
85
- try {
86
90
  const { extendReducer } = await importFromPoi('views/create-store')
87
91
  extendReducer(LEGACY_QUEST_PLUGIN_ID, reducer)
88
92
  } catch (e) {
89
- console.warn('Hack quest plugin reducer error', e)
93
+ console.error('Hack quest plugin reducer error', e)
90
94
  }
91
95
  }
92
96
 
@@ -105,6 +109,6 @@ export const clearPatchLegacyQuestPluginReducer = async () => {
105
109
  const clearReducer = undefined
106
110
  extendReducer('poi-plugin-quest-info', clearReducer)
107
111
  } catch (e) {
108
- console.warn('Clear hack quest plugin reducer error', e)
112
+ console.error('Clear hack quest plugin reducer error', e)
109
113
  }
110
114
  }
package/src/poi/env.ts ADDED
@@ -0,0 +1,16 @@
1
+ export const IN_POI = 'POI_VERSION' in globalThis
2
+ /**
3
+ * Prevent webpack early error
4
+ * Module not found: Error: Can't resolve 'views/create-store'
5
+ * TODO fix webpack warn
6
+ * Critical dependency: the request of a dependency is an expression
7
+ */
8
+
9
+ export const importFromPoi = <T = any>(path: string): Promise<T> => {
10
+ if (!IN_POI) {
11
+ return new Promise(() => {
12
+ // Never resolve
13
+ })
14
+ }
15
+ return import(path)
16
+ }
@@ -0,0 +1,56 @@
1
+ import { useState, useEffect } from 'react'
2
+ import { useTranslation } from 'react-i18next'
3
+ import { observePluginStore, observePoiStore } from './store'
4
+ import { name as PACKAGE_NAME } from '../../package.json'
5
+ import type { GameQuest, PoiQuestState, PoiState } from './types'
6
+
7
+ export const useActiveQuest = () => {
8
+ const [activeQuests, setActiveQuests] = useState<PoiQuestState>({})
9
+
10
+ useEffect(() => {
11
+ const listener = (activeQuests: PoiQuestState) =>
12
+ setActiveQuests(activeQuests)
13
+
14
+ return observePoiStore(listener, activeQuestsSelector)
15
+ }, [])
16
+
17
+ return activeQuests
18
+ }
19
+
20
+ export const activeQuestsSelector = (state: PoiState): PoiQuestState =>
21
+ state?.info?.quests?.activeQuests ?? {}
22
+
23
+ export const usePluginTranslation = () => {
24
+ return useTranslation(PACKAGE_NAME)
25
+ }
26
+
27
+ export const useGameQuest = () => {
28
+ const [quests, setQuests] = useState<GameQuest[] | null>(null)
29
+ useEffect(() => {
30
+ const listener = (quests: GameQuest[] | null) => setQuests(quests)
31
+ // See reducer.ts
32
+ return observePluginStore(listener, (i) => i?._?.questList)
33
+ }, [])
34
+ return quests
35
+ }
36
+
37
+ const UNKNOWN_TAB = 'unknown'
38
+ const useActiveTab = () => {
39
+ const [activeMainTab, setActiveMainTab] = useState<string>(UNKNOWN_TAB)
40
+
41
+ useEffect(() => {
42
+ const listener = (activeMainTab: string) => setActiveMainTab(activeMainTab)
43
+ // poooi/poi/views/redux/ui.es
44
+ return observePoiStore(
45
+ listener,
46
+ (state) => state?.ui?.activeMainTab ?? UNKNOWN_TAB
47
+ )
48
+ }, [])
49
+
50
+ return activeMainTab
51
+ }
52
+
53
+ export const useIsQuestPluginTab = () => {
54
+ const activeMainTab = useActiveTab()
55
+ return activeMainTab === PACKAGE_NAME
56
+ }
@@ -0,0 +1,80 @@
1
+ import { name as PACKAGE_NAME } from '../../package.json'
2
+ import type { PluginState } from '../reducer'
3
+ import { IN_POI, importFromPoi } from './env'
4
+ import type { PoiState, Store } from './types'
5
+
6
+ const noop = () => {}
7
+ const id = <T>(x: T) => x
8
+
9
+ /**
10
+ * See https://redux.js.org/api/store#subscribelistener
11
+ */
12
+ const observeStore = <State, SelectedState = State>(
13
+ store: Store<State>,
14
+ onChange: (state: SelectedState) => void,
15
+ selector: (s: State) => SelectedState = id as any
16
+ ) => {
17
+ let currentState: SelectedState
18
+
19
+ const handleChange = () => {
20
+ const nextState = selector(store.getState())
21
+ if (nextState !== currentState) {
22
+ currentState = nextState
23
+ onChange(currentState)
24
+ }
25
+ }
26
+
27
+ const unsubscribe = store.subscribe(handleChange)
28
+ handleChange()
29
+ return unsubscribe
30
+ }
31
+
32
+ export const observePoiStore = <SelectedState = PoiState>(
33
+ onChange: (state: SelectedState) => void,
34
+ selector: (state: PoiState) => SelectedState = id as any
35
+ ) => {
36
+ let valid = true
37
+ let unsubscribe = noop
38
+ getPoiStore().then((store) => {
39
+ if (!valid) {
40
+ return
41
+ }
42
+ unsubscribe = observeStore(store, onChange, selector)
43
+ })
44
+
45
+ return () => {
46
+ valid = false
47
+ unsubscribe()
48
+ }
49
+ }
50
+
51
+ export const observePluginStore = <SelectedState = PluginState>(
52
+ onChange: (state: SelectedState) => void,
53
+ selector: (state: PluginState) => SelectedState = id as any
54
+ ) => observePoiStore(onChange, (s) => selector(s?.ext[PACKAGE_NAME]))
55
+
56
+ const fallbackStore: Store<PoiState> = {
57
+ getState: noop as () => PoiState,
58
+ subscribe: () => (() => {}) as () => () => void,
59
+ }
60
+
61
+ let globalStore: Store<PoiState> | null = null
62
+ /**
63
+ * Get poi global Store if in poi env
64
+ */
65
+ export const getPoiStore: () => Promise<Store<PoiState>> = async () => {
66
+ if (globalStore !== null) {
67
+ return globalStore
68
+ }
69
+ if (IN_POI) {
70
+ try {
71
+ const { store } = await importFromPoi('views/create-store')
72
+ globalStore = store
73
+ return store
74
+ } catch (error) {
75
+ console.warn('Load global store error', error)
76
+ }
77
+ }
78
+ globalStore = fallbackStore
79
+ return fallbackStore
80
+ }
@@ -0,0 +1,114 @@
1
+ import type { PluginState } from '../reducer'
2
+
3
+ // See https://github.com/poooi/poi/blob/master/views/redux/info/quests.es
4
+ export type GameQuest = {
5
+ // 1 Default
6
+ // 2 In progress
7
+ // 3 Completed
8
+ api_state: 1 | 2 | 3
9
+ api_no: number
10
+ api_title: string
11
+ api_detail: string
12
+ /**
13
+ * 任务类别
14
+ *
15
+ * 1. Composition
16
+ * 1. Sortie
17
+ * 1. Exercise
18
+ * 1. Expedition
19
+ * 1. Supply/Docking
20
+ * 1. Arsenal
21
+ * 1. Modernization
22
+ *
23
+ * @see https://github.com/poooi/plugin-quest/blob/master/index.es#L49-L57
24
+ */
25
+ api_category: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
26
+ /**
27
+ * 任务类型
28
+ *
29
+ * 1. One-time
30
+ * 1. Daily
31
+ * 1. Weekly
32
+ * 1. -3rd/-7th/-0th
33
+ * 1. -2nd/-8th
34
+ * 1. Monthly
35
+ * 1. Quarterly
36
+ *
37
+ * @see https://github.com/poooi/plugin-quest/blob/master/index.es#L69-L77
38
+ */
39
+ api_type: 1 | 2 | 3 | 4 | 5 | 6 | 7
40
+ // Rewards 油弹钢铝
41
+ api_get_material: [number, number, number, number]
42
+ api_invalid_flag: 0
43
+ api_label_type: 1
44
+ // 0: Empty: [0.0, 0.5)
45
+ // 1: 50%: [0.5, 0.8)
46
+ // 2: 80%: [0.8, 1.0)
47
+ api_progress_flag: 0 | 1 | 2
48
+ api_select_rewards?: [
49
+ {
50
+ api_count: number
51
+ api_kind: number
52
+ api_mst_id: number
53
+ api_no: number
54
+ }[]
55
+ ]
56
+ api_voice_id: 0
57
+ api_bonus_flag: 1
58
+ }
59
+
60
+ type QuestListAction = {
61
+ type: '@@Response/kcsapi/api_get_member/questlist'
62
+ path: '/kcsapi/api_get_member/questlist'
63
+ postBody: {
64
+ api_verno: '1'
65
+ api_tab_id:
66
+ | '0' // All
67
+ | '9' // In progress
68
+ | '1' // Daily
69
+ | '2' // Weekly
70
+ | '3' // Monthly
71
+ | '4' // Once
72
+ | '5' // Others
73
+ }
74
+ body: {
75
+ api_completed_kind: number
76
+ // api_list.length
77
+ api_count: number
78
+ // In progress count
79
+ api_exec_count: number
80
+ api_exec_type: number
81
+ api_list: GameQuest[]
82
+ }
83
+ }
84
+
85
+ type OtherAction = {
86
+ type: 'otherString' // TODO fix me
87
+ path?: string
88
+ postBody?: unknown
89
+ body?: unknown
90
+ }
91
+
92
+ export type PoiAction = QuestListAction | OtherAction
93
+
94
+ export type PoiState = {
95
+ ui: {
96
+ activeMainTab: string
97
+ activeFleetId?: number
98
+ activePluginName?: string
99
+ }
100
+ ext: {
101
+ // TODO fix use constant PACKAGE_NAME
102
+ [packageName: string]: PluginState
103
+ }
104
+ plugins: { id: string; enabled: boolean; [x: string]: unknown }[]
105
+ [x: string]: any
106
+ }
107
+
108
+ export type Store<S> = {
109
+ getState: () => S
110
+ subscribe: (listener: () => void) => () => void
111
+ }
112
+
113
+ // state.info.quests.activeQuests
114
+ export type PoiQuestState = Record<number, { time: number; detail: GameQuest }>
package/src/reducer.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { GameQuest, PoiAction } from './poi'
1
+ import type { GameQuest, PoiAction } from './poi/types'
2
2
 
3
3
  const initState = {
4
4
  questList: null as null | GameQuest[],
@@ -1,14 +1,11 @@
1
- import { useCallback, useEffect, useState } from 'react'
1
+ import { useCallback } from 'react'
2
2
  import { checkIsKcwikiSupportedLanguages } from '.'
3
3
  import { QuestData } from '../../build/kcanotifyGamedata'
4
4
  import {
5
- activeQuestsSelector,
6
- GameQuest,
7
- observePluginStore,
8
- observePoiStore,
9
- PoiQuestState,
5
+ useActiveQuest,
6
+ useGameQuest,
10
7
  usePluginTranslation,
11
- } from '../poi'
8
+ } from '../poi/hooks'
12
9
  import { getCategory, KcanotifyQuestExt } from '../questHelper'
13
10
  import { useKcwikiData } from './kcwiki'
14
11
  import { useStore } from './store'
@@ -35,19 +32,6 @@ export const useLanguage = () => {
35
32
  return lang
36
33
  }
37
34
 
38
- const useActiveQuest = () => {
39
- const [activeQuests, setActiveQuests] = useState<PoiQuestState>({})
40
-
41
- useEffect(() => {
42
- const listener = (activeQuests: PoiQuestState) =>
43
- setActiveQuests(activeQuests)
44
-
45
- return observePoiStore(listener, activeQuestsSelector)
46
- }, [])
47
-
48
- return activeQuests
49
- }
50
-
51
35
  const useQuestMap = () => {
52
36
  const lang = useLanguage()
53
37
  const kcwikiData = useKcwikiData(lang)
@@ -57,16 +41,6 @@ const useQuestMap = () => {
57
41
  return QuestData[lang]
58
42
  }
59
43
 
60
- const useGameQuest = () => {
61
- const [quests, setQuests] = useState<GameQuest[] | null>(null)
62
- useEffect(() => {
63
- const listener = (quests: GameQuest[] | null) => setQuests(quests)
64
- // See reducer.ts
65
- return observePluginStore(listener, (i) => i?._?.questList)
66
- }, [])
67
- return quests
68
- }
69
-
70
44
  export const useQuest = (): KcanotifyQuestExt[] => {
71
45
  const activeQuest = useActiveQuest()
72
46
  const questMap = useQuestMap()
@@ -5,7 +5,6 @@ import React, {
5
5
  useCallback,
6
6
  useContext,
7
7
  } from 'react'
8
- import { IN_POI } from '../poi'
9
8
  import { ALL_TYPE_TAG, ALL_CATEGORY_TAG } from '../tags'
10
9
  import { name as PACKAGE_NAME } from '../../package.json'
11
10
  import { createGlobalState, useMount, useUpdateEffect } from 'react-use'
@@ -19,7 +18,7 @@ export const initialState = {
19
18
  [ALL_CATEGORY_TAG.name]: true,
20
19
  } as Record<string, boolean>,
21
20
  largeCard: null as null | string,
22
- syncWithGame: IN_POI,
21
+ syncWithGame: false,
23
22
  preferKcwikiData: true,
24
23
  }
25
24
 
package/src/tags.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IN_POI } from './poi'
1
+ import { IN_POI } from './poi/env'
2
2
  import {
3
3
  isDailyQuest,
4
4
  isMonthlyQuest,