import produce from 'immer' ; import { config , getDefaultPlatform , OSGiVersionMax } from './config' ; import { Addon , BuildType , Mode , NATIVE_ALL , Preset } from './types' ; import type { RadioOptions } from './ConnectedRadio' ; import type { Binding , BindingDefinition , BindingMapSelection , BuildStore , BuildStoreSnapshot , Version , Language , Native , } from './types' ; export enum Action { BUILD_STATUS = 'BUILD/STATUS' , SELECT_TYPE = 'BUILD/SELECT_TYPE' , SELECT_MODE = 'BUILD/SELECT_MODE' , SELECT_PRESET = 'BUILD/SELECT_PRESET' , SELECT_LANGUAGE = 'BUILD/SELECT_LANGUAGE' , SELECT_VERSION = 'BUILD/SELECT_VERSION' , TOGGLE_DESCRIPTIONS = 'BUILD/TOGGLE_DESCRIPTIONS' , TOGGLE_SOURCE = 'BUILD/TOGGLE_SOURCE' , TOGGLE_JAVADOC = 'BUILD/TOGGLE_JAVADOC' , TOGGLE_INCLUDE_JSON = 'BUILD/TOGGLE_INCLUDE_JSON' , TOGGLE_OSGI = 'BUILD/TOGGLE_OSGI' , TOGGLE_COMPACT = 'BUILD/TOGGLE_COMPACT' , TOGGLE_HARDCODED = 'BUILD/TOGGLE_HARDCODED' , TOGGLE_PLATFORM = 'BUILD/TOGGLE_PLATFORM' , TOGGLE_ARTIFACT = 'BUILD/TOGGLE_ARTIFACT' , TOGGLE_ADDON = 'BUILD/TOGGLE_ADDON' , CONFIG_LOAD = 'BUILD/CONFIG_LOAD' } export type ActionMessage = ActionBuildTypeSelect | ActionConfigLoad | ActionModeSelect | ActionPresetSelect | ActionLanguageSelect | ActionVersionSelect | ActionToggle < Action . TOGGLE_DESCRIPTIONS | Action . TOGGLE_SOURCE | Action . TOGGLE_JAVADOC | Action . TOGGLE_INCLUDE_JSON | Action . TOGGLE_HARDCODED | Action . TOGGLE_OSGI | Action . TOGGLE_COMPACT > | ActionArtifactToggle | ActionPlatformToggle | ActionAddonToggle ; export interface ActionToggle < T > { type : T ; } export interface ActionBuildTypeSelect { type : Action . SELECT_TYPE ; build : BuildType | null ; } export const createActionBuiltTypeSelect = ( build ) : ActionBuildTypeSelect => ( { type : Action . SELECT_TYPE , build , } ) ; export interface ActionConfigLoad { type : Action . CONFIG_LOAD ; payload : BuildStoreSnapshot ; } export const createActionConfigLoad = ( payload ) : ActionConfigLoad => ( { type : Action . CONFIG_LOAD , payload , } ) ; export interface ActionModeSelect { type : Action . SELECT_MODE ; mode : Mode ; } export const createActionModeSelect = ( mode ) : ActionModeSelect => ( { type : Action . SELECT_MODE , mode , } ) ; export interface ActionPresetSelect { type : Action . SELECT_PRESET ; preset : Preset ; } export const createActionPresetSelect = ( preset ) : ActionPresetSelect => ( { type : Action . SELECT_PRESET , preset , } ) ; export interface ActionLanguageSelect { type : Action . SELECT_LANGUAGE ; language : Language ; } export const createActionLanguageSelect = ( language ) : ActionLanguageSelect => ( { type : Action . SELECT_LANGUAGE , language , } ) ; export interface ActionVersionSelect { type : Action . SELECT_VERSION ; version : Version ; } export const createActionVersionSelect = ( version ) : ActionVersionSelect => ( { type : Action . SELECT_VERSION , version , } ) ; export const createActionDescriptionsToggle = ( ) : ActionToggle < Action . TOGGLE_DESCRIPTIONS > => ( { type : Action . TOGGLE_DESCRIPTIONS , } ) ; export const createActionSourceToggle = ( ) : ActionToggle < Action . TOGGLE_SOURCE > => ( { type : Action . TOGGLE_SOURCE , } ) ; export const createActionJavadocToggle = ( ) : ActionToggle < Action . TOGGLE_JAVADOC > => ( { type : Action . TOGGLE_JAVADOC , } ) ; export const createActionIncludeJSONToggle = ( ) : ActionToggle < Action . TOGGLE_INCLUDE_JSON > => ( { type : Action . TOGGLE_INCLUDE_JSON , } ) ; export const createActionOSGiToggle = ( ) : ActionToggle < Action . TOGGLE_OSGI > => ( { type : Action . TOGGLE_OSGI , } ) ; export const createActionCompactToggle = ( ) : ActionToggle < Action . TOGGLE_COMPACT > => ( { type : Action . TOGGLE_COMPACT , } ) ; export const createActionHardcodedToggle = ( ) : ActionToggle < Action . TOGGLE_HARDCODED > => ( { type : Action . TOGGLE_HARDCODED , } ) ; export interface ActionArtifactToggle { type : Action . TOGGLE_ARTIFACT ; artifact : Binding ; } export const createActionArtifactToggle = ( artifact ) : ActionArtifactToggle => ( { type : Action . TOGGLE_ARTIFACT , artifact , } ) ; export interface ActionPlatformToggle { type : Action . TOGGLE_PLATFORM ; platform : Native ; } export const createActionPlatformToggle = ( platform ) : ActionPlatformToggle => ( { type : Action . TOGGLE_PLATFORM , platform , } ) ; export interface ActionAddonToggle { type : Action . TOGGLE_ADDON ; addon : Addon ; } export const createActionAddonToggle = ( addon ) : ActionAddonToggle => ( { type : Action . TOGGLE_ADDON , addon } ) ; export const selectorDescriptions = ( state ) : boolean => state . descriptions ; export const selectorHasLanguageOption = ( state ) : boolean => state . mode === Mode . Gradle ; export const selectorBuild = ( state ) => state . build ; export const selectorBuilds = ( state ) => state . builds ; export const selectorIsBuildSelected = ( state ) : boolean => state . build !== null ; export const selectorIsBuildRelease = ( state ) : boolean => state . build === BuildType . Release ; export const selectorMode = ( state ) => state . mode ; export const selectorModes = ( state ) => state . modes ; const selectorSource = ( state ) => state . source ; const selectorJavaDoc = ( state ) => state . javadoc ; const selectorIncludeJSON = ( state ) => state . includeJSON ; const selectorPreset = ( state ) => state . preset ; const selectorHardcoded = ( state ) => state . hardcoded ; const selectorCompact = ( state ) => state . compact ; const selectorOSGi = ( state ) => state . osgi ; const selectorLanguage = ( state ) => state . language ; const selectorVersion = ( state ) => state . version ; const selectorHasCompactModeOption = ( state ) : boolean => state . mode === Mode . Maven || state . mode === Mode . Ivy ; const selectorIsModeZip = ( state ) : boolean => state . mode === Mode . Zip ; const selectorIsModeNotZip = ( state ) : boolean => state . mode !== Mode . Zip ; const selectorShowOSGi = ( state ) : boolean => state . mode !== Mode . Zip && state . build === BuildType . Release && checkOSGiVersion ( state . version ) ; export const selectorNatives = ( store ) => store . natives ; export const selectorArtifactsVersion = ( store ) => store . artifacts . version ; export const selectorPlatformsSelected = ( store ) => store . platform ; export const selectorAddons = ( store ) => store . addons ; export const selectorAddonsSelected = ( store ) => store . selectedAddons ; export const selectorContents = ( store ) => store . contents ; export const selectorAvailability = ( store ) => store . availability ; export const selectorArtifacts = ( store ) => store . artifacts ; export const fields = { mode : { name : 'mode' , value : selectorMode , action : createActionModeSelect , options : ( { modes : { allIds , byId } , build } ) : RadioOptions => allIds . map ( ( mode ) => ( { value : mode , label : byId [ mode ] . title , } ) ) , } , descriptions : { children : 'Show descriptions' , checked : selectorDescriptions , action : createActionDescriptionsToggle , } , source : { children : 'Include source' , checked : selectorSource , hidden : selectorIsModeNotZip , action : createActionSourceToggle , } , javadoc : { children : 'Include JavaDoc' , checked : selectorJavaDoc , hidden : selectorIsModeNotZip , action : createActionJavadocToggle , } , includeJSON : { children : 'Include build config' , checked : selectorIncludeJSON , hidden : selectorIsModeNotZip , action : createActionIncludeJSONToggle , } , hardcoded : { children : 'Do not use variables' , checked : selectorHardcoded , hidden : selectorIsModeZip , action : createActionHardcodedToggle , } , compact : { children : 'Compact Mode' , checked : selectorCompact , hidden : ( state ) => ! selectorHasCompactModeOption ( state ) , action : createActionCompactToggle , } , osgi : { children : 'OSGi Mode' , checked : selectorOSGi , hidden : ( state ) => ! selectorShowOSGi ( state ) , action : createActionOSGiToggle , } , language : { name : 'language' , value : selectorLanguage , action : createActionLanguageSelect , options : ( { languages : { allIds , byId } } ) : RadioOptions => allIds . map ( ( lang ) => ( { value : lang , label : byId [ lang ] . title , } ) ) , } , preset : { name : 'preset' , value : selectorPreset , action : createActionPresetSelect , options : ( { presets : { allIds , byId } , preset } ) : RadioOptions => allIds . map ( ( presetId ) => ( { value : presetId , label : byId [ presetId ] . title , disabled : preset !== presetId && presetId === 'custom' , } ) ) , } , version : { name : 'version' , value : selectorVersion , action : createActionVersionSelect , options : ( { versions } ) : RadioOptions => versions . map ( ( version ) => ( { value : version , label : version , disabled : version === '3.0.0' , } ) ) , } , } ; export const reducer = ( state = config , action ) => { return produce ( state , ( draft ) => { switch ( action . type ) { case Action . CONFIG_LOAD : loadConfig ( draft , action . payload ) ; break ; case Action . SELECT_TYPE : selectBuild ( draft , action . build !== state . build ? action . build : null ) ; break ; case Action . SELECT_MODE : if ( state . mode !== action . mode ) { selectMode ( draft , action . mode ) ; } break ; case Action . TOGGLE_DESCRIPTIONS : draft . descriptions = ! draft . descriptions ; break ; case Action . TOGGLE_COMPACT : if ( state . mode === Mode . Maven || state . mode === Mode . Ivy ) { draft . compact = ! draft . compact ; } break ; case Action . TOGGLE_HARDCODED : if ( state . mode !== Mode . Zip ) { draft . hardcoded = ! draft . hardcoded ; } break ; case Action . TOGGLE_JAVADOC : if ( state . mode === Mode . Zip ) { draft . javadoc = ! draft . javadoc ; } break ; case Action . TOGGLE_INCLUDE_JSON : if ( state . mode === Mode . Zip ) { draft . includeJSON = ! draft . includeJSON ; } break ; case Action . TOGGLE_SOURCE : if ( state . mode === Mode . Zip ) { draft . source = ! draft . source ; } break ; case Action . TOGGLE_OSGI : if ( state . mode !== Mode . Zip && state . build === BuildType . Release ) { if ( draft . osgi ) { if ( ! checkOSGiVersion ( state . version ) ) { break ; } } draft . osgi = ! draft . osgi ; } break ; case Action . SELECT_PRESET : if ( state . preset !== action . preset ) { selectPreset ( draft , action . preset ) ; } break ; case Action . SELECT_LANGUAGE : if ( state . mode === Mode . Gradle ) { draft . language = action . language ; } break ; case Action . TOGGLE_PLATFORM : const selections = state . natives . allIds . reduce ( ( previousValue , platform ) => previousValue + ( state . platform [ platform ] ? 1 : 0 ) , 0 ) ; if ( selections > 1 || state . platform [ action . platform ] === false ) { draft . platform [ action . platform ] = ! state . platform [ action . platform ] ; computeArtifacts ( draft ) ; } break ; case Action . SELECT_VERSION : if ( state . build === BuildType . Release && state . version !== action . version ) { selectVersion ( draft , action . version ) ; } break ; case Action . TOGGLE_ARTIFACT : if ( action . artifact !== 'lwjgl' ) { doToggleArtifact ( draft , action . artifact ) ; } break ; case Action . TOGGLE_ADDON : doToggleAddon ( draft , action . addon ) ; break ; } } ) ; } ; export function versionNum ( version ) { return parseInt ( version . replace ( /\./g , '' ) , 10 ) ; } export function checkOSGiVersion ( version ) { let vnum = versionNum ( version ) ; return 312 <= vnum && vnum <= versionNum ( OSGiVersionMax ) ; } function selectBuild ( state , build ) { state . build = build ; computeArtifacts ( state ) ; } function selectMode ( state , mode ) { state . mode = mode ; computeArtifacts ( state ) ; } function selectPreset ( state , preset ) { if ( state . presets . byId [ preset ] === undefined ) { return ; } state . preset = preset ; if ( preset === Preset . All ) { state . artifacts . allIds . forEach ( ( artifact ) => { state . contents [ artifact ] = true ; } ) ; } else if ( preset !== Preset . Custom ) { state . artifacts . allIds . forEach ( ( artifact ) => { state . contents [ artifact ] = false ; } ) ; const configPreset = state . presets . byId [ preset ] ; if ( configPreset . artifacts !== undefined ) { configPreset . artifacts . forEach ( ( artifact ) => { state . contents [ artifact ] = true ; } ) ; } } } function computeArtifacts ( state ) { if ( state . build === null ) { return ; } state . artifacts = state . lwjgl [ state . build === BuildType . Release ? state . version : state . build ] ; const vnum = versionNum ( state . artifacts . version ) ; NATIVE_ALL . forEach ( ( p ) => { if ( state . platform [ p ] && vnum < versionNum ( config . natives . byId [ p ] . since ) ) { state . platform [ p ] = false ; } } ) ; if ( ! NATIVE_ALL . some ( ( p ) => state . platform [ p ] ) ) { state . platform [ getDefaultPlatform ( ) ] = true ; } state . availability = { } as BindingMapSelection ; state . presets . allIds . forEach ( ( preset ) => { state . presets . byId [ preset ] . artifacts = [ ] ; } ) ; state . artifacts . allIds . forEach ( ( it ) => { const artifact = state . artifacts . byId [ it ] as BindingDefinition ; state . availability [ it ] = artifact . natives === undefined || artifact . nativesOptional === true || artifact . natives . length === config . natives . allIds . length || artifact . natives . some ( ( platform ) => ! ! state . platform [ platform ] ) ; if ( state . availability [ it ] && artifact . presets !== undefined ) { artifact . presets . forEach ( ( preset ) => { const statePreset = state . presets . byId [ preset ] ; if ( statePreset . artifacts !== undefined ) { statePreset . artifacts . push ( it ) ; } } ) ; } } ) ; if ( state . preset !== Preset . Custom ) { selectPreset ( state , state . preset ) ; } } const selectVersion = ( state , version ) => { state . version = version ; computeArtifacts ( state ) ; if ( state . osgi && ! checkOSGiVersion ( version ) ) { state . osgi = false ; } } ; const doToggleArtifact = ( state , artifact ) => { state . contents [ artifact ] = ! state . contents [ artifact ] ; const selected = state . artifacts . allIds . filter ( ( artifact ) => state . contents [ artifact ] ) ; if ( selected . length === state . artifacts . allIds . length ) { state . preset = Preset . All ; return ; } else if ( selected . length === 1 ) { state . preset = Preset . None ; return ; } const presetFoundMatch = state . presets . allIds . some ( ( presetName ) => { if ( presetName === Preset . Custom || presetName === Preset . All || presetName === Preset . None ) { return false ; } const preset = state . presets . byId [ presetName ] ; if ( preset . artifacts !== undefined ) { const artifacts = preset . artifacts . filter ( ( it ) => ! ! state . artifacts . byId [ it ] ) ; if ( artifacts . length === selected . length && artifacts . every ( ( it , i ) => it === selected [ i ] ) ) { state . preset = presetName ; return true ; } } return false ; } ) ; if ( ! presetFoundMatch ) { state . preset = Preset . Custom ; } } ; const doToggleAddon = ( state , addon ) => { if ( state . selectedAddons . includes ( addon ) ) { state . selectedAddons = state . selectedAddons . filter ( ( it ) => it !== addon ) ; } else { state . selectedAddons . push ( addon ) ; } } ; const loadConfig = ( state , config ) => { if ( config . build === null ) { return ; } state . build = config . build ; state . mode = config . mode ; state . selectedAddons = config . selectedAddons ; state . descriptions = config . descriptions ; state . compact = config . compact ; state . hardcoded = config . hardcoded ; state . javadoc = config . javadoc ; state . includeJSON = config . includeJSON ; state . source = config . source ; state . language = config . language ; state . osgi = ! ! config . osgi ; if ( config . build === BuildType . Release && config . version !== undefined && config . versionLatest !== undefined ) { if ( config . versionLatest === state . versions [ 1 ] ) { state . version = state . versions [ 0 ] ; } else { state . version = config . version ; } } if ( config . mode === Mode . Zip ) { state . natives . allIds . forEach ( ( platform ) => { state . platform [ platform ] = false ; } ) ; config . platform . forEach ( ( platform ) => { state . platform [ platform ] = true ; } ) ; } computeArtifacts ( state ) ; if ( config . preset !== undefined ) { selectPreset ( state , config . preset ) ; } else if ( config . contents !== undefined ) { state . preset = Preset . Custom ; state . contents = { } as BindingMapSelection ; config . contents . forEach ( ( binding ) => { if ( state . artifacts . byId [ binding ] !== undefined ) { state . contents [ binding ] = true ; } } ) ; } else { selectPreset ( state , Preset . GettingStarted ) ; } } ;