11import React from "react" ;
22import { Modal } from "./flowbite/components/Modal/index" ;
3- import { Spinner , Tabs } from "./flowbite" ;
3+ import { Spinner , Tabs , Tooltip } from "./flowbite" ;
44import { getModsSortedByName , getModsSortedByHumanName , getModsSortedBySize } from "./modSortingHelpers" ;
55import Select , { ActionMeta , SingleValue } from "react-select" ;
66import selectStyle from "./styles/selectStyle" ;
@@ -16,13 +16,29 @@ const ModsMerger = React.memo(() => {
1616 ) ;
1717 const mods = useSelector ( modsNotInDataSelector ) ;
1818
19+ const mergerModsSelector = createSelector (
20+ ( state : { app : AppState } ) => state . app . currentPreset . mods ,
21+ ( mods ) => mods . filter ( ( mod ) => mod . mergedModsData )
22+ ) ;
23+ const mergerMods = useSelector ( mergerModsSelector ) ;
24+
1925 const [ useEnabledModsOnly , setUseEnabledModsOnly ] = React . useState ( true ) ;
26+ const [ isHidingAlreadyMergedMods , setIsHidingAlreadyMergedMods ] = React . useState ( true ) ;
2027 const [ isOpen , setIsOpen ] = React . useState ( false ) ;
2128 const [ modsToMerge , setModsToMerge ] = React . useState < Set < Mod > > ( new Set < Mod > ( ) ) ;
2229 const [ isSpinnerClosed , setIsSpinnerClosed ] = React . useState ( false ) ;
2330 const [ modsMergeSort , setModsMergeSort ] = React . useState ( "Size" as ModsMergeSorts ) ;
2431
2532 let modsToUse = [ ...mods ] ;
33+
34+ if ( isHidingAlreadyMergedMods ) {
35+ modsToUse = modsToUse . filter ( ( mod ) =>
36+ mergerMods . every ( ( mergerMod ) =>
37+ mergerMod . mergedModsData ?. every ( ( mergedModData ) => mergedModData . name != mod . name )
38+ )
39+ ) ;
40+ }
41+
2642 switch ( modsMergeSort ) {
2743 case "Merge" :
2844 modsToUse = modsToUse . sort ( ( firstMod , secondMod ) => {
@@ -72,23 +88,51 @@ const ModsMerger = React.memo(() => {
7288 setModsToMerge ( new Set < Mod > ( modsToMerge ) ) ;
7389 } ;
7490
75- type OptionType = {
91+ type NumModsOptionType = {
7692 value : number ;
7793 label : number ;
7894 } ;
95+ type ExistingMergerOptionType = {
96+ value : string ;
97+ label : string ;
98+ } ;
7999
80- const onReplaceChange = ( newValue : SingleValue < OptionType > , actionMeta : ActionMeta < OptionType > ) => {
100+ const onSelectNumModsChange = (
101+ newValue : SingleValue < NumModsOptionType > ,
102+ actionMeta : ActionMeta < NumModsOptionType >
103+ ) => {
81104 if ( ! newValue ) return ;
82105 console . log ( `label: ${ newValue . label } , value: ${ newValue . value } , action: ${ actionMeta . action } ` ) ;
83106 if ( actionMeta . action === "select-option" ) {
84107 setModsToMerge ( new Set < Mod > ( modsToUse . slice ( 0 , newValue . value ) ) ) ;
85108 }
86109 } ;
110+ const onSelectExistingMergerChange = (
111+ newValue : SingleValue < ExistingMergerOptionType > ,
112+ actionMeta : ActionMeta < ExistingMergerOptionType >
113+ ) => {
114+ if ( ! newValue ) return ;
115+ console . log ( `label: ${ newValue . label } , value: ${ newValue . value } , action: ${ actionMeta . action } ` ) ;
116+ if ( actionMeta . action === "select-option" ) {
117+ const mergerMod = mergerMods . find ( ( mergerMod ) => mergerMod . name == newValue . value ) ;
118+ if ( ! mergerMod || ! mergerMod . mergedModsData ) return ;
119+ const mergedData = mergerMod . mergedModsData ;
120+ setModsToMerge (
121+ new Set < Mod > (
122+ modsToUse . filter ( ( mod ) => mergedData . some ( ( mergedModData ) => mergedModData . name == mod . name ) )
123+ )
124+ ) ;
125+ }
126+ } ;
87127
88- const options : OptionType [ ] = [ 5 , 10 , 15 , 20 , 25 , 30 , 35 , 40 , 50 , 75 , 100 , 0 ] . map ( ( num ) => {
128+ const options : NumModsOptionType [ ] = [ 5 , 10 , 15 , 20 , 25 , 30 , 35 , 40 , 50 , 75 , 100 , 0 ] . map ( ( num ) => {
89129 return { value : num , label : num } ;
90130 } ) ;
91131
132+ const mergerOptions : ExistingMergerOptionType [ ] = mergerMods . map ( ( mod ) => {
133+ return { value : mod . name , label : mod . name } ;
134+ } ) ;
135+
92136 const mergeMods = ( ) => {
93137 if ( modsToMerge . size < 1 ) return ;
94138 window . api ?. mergeMods ( Array . from ( modsToMerge ) ) ;
@@ -112,6 +156,10 @@ const ModsMerger = React.memo(() => {
112156 else setModsMergeSort ( "Pack" ) ;
113157 } ;
114158
159+ const onMergeRightClick = ( ) => {
160+ setModsToMerge ( new Set < Mod > ( ) ) ;
161+ } ;
162+
115163 return (
116164 < div >
117165 < div className = "text-center mt-4" >
@@ -136,31 +184,68 @@ const ModsMerger = React.memo(() => {
136184 ..."scrollbar scrollbar-track-gray-700 scrollbar-thumb-blue-700" . split ( " " ) ,
137185 ] }
138186 >
139- < Modal . Header > Merge Mods</ Modal . Header >
187+ < Modal . Header > Merge Mods{ modsToMerge . size > 0 && ` - ${ modsToMerge . size } selected` } </ Modal . Header >
140188 < Modal . Body >
141189 < Tabs . Group style = "underline" >
142190 < Tabs . Item active = { true } title = "Merge" >
143191 < span className = "absolute top-[6rem] right-0 flex items-center leading-relaxed dark:text-gray-300" >
144- < span className = "mr-10" >
192+ { mergerMods . length > 0 && (
193+ < >
194+ < span className = "make-tooltip-inline" >
195+ < Tooltip style = { "light" } content = { < p > Load mods that are in an existing merged mod.</ p > } >
196+ < span className = "text-center w-full" > Load existing:</ span >
197+ </ Tooltip >
198+ </ span >
199+ < Select
200+ options = { mergerOptions }
201+ styles = { selectStyle }
202+ onChange = { onSelectExistingMergerChange }
203+ value = { null }
204+ className = "mx-2"
205+ > </ Select >
206+ </ >
207+ ) }
208+
209+ < span className = "border-l-2 px-2 border-gray-600" >
210+ < input
211+ type = "checkbox"
212+ id = "merge-hide-already-merged"
213+ checked = { isHidingAlreadyMergedMods }
214+ onChange = { ( ) => {
215+ setIsHidingAlreadyMergedMods ( ! isHidingAlreadyMergedMods ) ;
216+ } }
217+ > </ input >
218+ < label className = "ml-2" htmlFor = "merge-hide-already-merged" >
219+ < span className = "make-tooltip-inline" >
220+ < Tooltip
221+ style = { "light" }
222+ content = { < p > Don't show a mod if it's inside an enabled merged pack.</ p > }
223+ >
224+ < span className = "text-center w-full" > Hide Already Merged</ span >
225+ </ Tooltip >
226+ </ span >
227+ </ label >
228+ </ span >
229+
230+ < span className = "border-x-2 px-2 border-gray-600" >
145231 < input
146232 type = "checkbox"
147- id = "compat -enabled-mod-only"
233+ id = "merge -enabled-mod-only"
148234 checked = { useEnabledModsOnly }
149235 onChange = { ( ) => {
150236 if ( ! useEnabledModsOnly ) setModsToMerge ( new Set < Mod > ( ) ) ;
151237 setUseEnabledModsOnly ( ! useEnabledModsOnly ) ;
152238 } }
153239 > </ input >
154- < label className = "ml-2" htmlFor = "compat -enabled-mod-only" >
240+ < label className = "ml-2" htmlFor = "merge -enabled-mod-only" >
155241 Enabled Mods Only
156242 </ label >
157243 </ span >
158- < span > Select first</ span >
244+ < span className = "ml-2" > Select first</ span >
159245 < Select
160- id = "replacePreset"
161246 options = { options }
162247 styles = { selectStyle }
163- onChange = { onReplaceChange }
248+ onChange = { onSelectNumModsChange }
164249 value = { null }
165250 className = "mx-2"
166251 > </ Select >
@@ -176,6 +261,7 @@ const ModsMerger = React.memo(() => {
176261 < div className = "leading-relaxed dark:text-gray-300 relative gap-2 " >
177262 < div className = "grid grid-cols-9" >
178263 < div
264+ onContextMenu = { ( ) => onMergeRightClick ( ) }
179265 className = {
180266 "col-span-1 justify-center flex " +
181267 ( ( ( modsMergeSort == "Merge" || modsMergeSort == "MergeDesc" ) && "font-bold" ) || "" )
0 commit comments