import * as Selectors from "../selectors" ; import * as Utils from "../utils" ; import { UPDATE_WINDOW_POSITIONS , TOGGLE_DOUBLESIZE_MODE , WINDOW_SIZE_CHANGED , TOGGLE_WINDOW , CLOSE_WINDOW , TOGGLE_WINDOW_SHADE_MODE , BROWSER_WINDOW_SIZE_CHANGED , RESET_WINDOW_SIZES , TOGGLE_LLAMA_MODE , SET_FOCUSED_WINDOW , } from "../actionTypes" ; import { getPositionDiff , SizeDiff } from "../resizeUtils" ; import { applyDiff } from "../snapUtils" ; import { Action , Thunk , WindowId , WindowPositions , Dispatch } from "../types" ; function withWindowGraphIntegrity ( action ) { return ( dispatch , getState ) => { const state = getState ( ) ; const graph = Selectors . getWindowGraph ( state ) ; const originalSizes = Selectors . getWindowSizes ( state ) ; dispatch ( action ) ; const newSizes = Selectors . getWindowSizes ( getState ( ) ) ; const sizeDiff = { } ; for ( const window of Object . keys ( newSizes ) ) { const original = originalSizes [ window ] ; const current = newSizes [ window ] ; sizeDiff [ window ] = { height : current . height - original . height , width : current . width - original . width , } ; } const positionDiff = getPositionDiff ( graph , sizeDiff ) ; const windowPositions = Selectors . getWindowPositions ( state ) ; const newPositions = Utils . objectMap ( windowPositions , ( position , key ) => applyDiff ( position , positionDiff [ key ] ) ) ; dispatch ( updateWindowPositions ( newPositions ) ) ; } ; } export function toggleDoubleSizeMode ( ) { return withWindowGraphIntegrity ( { type : TOGGLE_DOUBLESIZE_MODE } ) ; } export function toggleLlamaMode ( ) { return { type : TOGGLE_LLAMA_MODE } ; } export function toggleEqualizerShadeMode ( ) { return withWindowGraphIntegrity ( { type : TOGGLE_WINDOW_SHADE_MODE , windowId : "equalizer" , } ) ; } export function toggleMainWindowShadeMode ( ) { return withWindowGraphIntegrity ( { type : TOGGLE_WINDOW_SHADE_MODE , windowId : "main" , } ) ; } export function togglePlaylistShadeMode ( ) { return withWindowGraphIntegrity ( { type : TOGGLE_WINDOW_SHADE_MODE , windowId : "playlist" , } ) ; } export function closeWindow ( windowId ) { return { type : CLOSE_WINDOW , windowId } ; } export function setFocusedWindow ( window ) { return { type : SET_FOCUSED_WINDOW , window } ; } export function setWindowSize ( windowId , size ) { return { type : WINDOW_SIZE_CHANGED , windowId , size } ; } export function toggleWindow ( windowId ) { return { type : TOGGLE_WINDOW , windowId } ; } export function updateWindowPositions ( positions , absolute ? ) { return { type : UPDATE_WINDOW_POSITIONS , positions , absolute } ; } export function centerWindowsInContainer ( container ) { return ( dispatch , getState ) => { if ( ! Selectors . getPositionsAreRelative ( getState ( ) ) ) { return ; } const { left , top } = container . getBoundingClientRect ( ) ; const { scrollWidth : width , scrollHeight : height } = container ; dispatch ( centerWindows ( { left , top , width , height } ) ) ; } ; } export function centerWindowsInView ( ) { return centerWindows ( { left : window . scrollX , top : window . scrollY , width : window . innerWidth , height : window . innerHeight , } ) ; } export function centerWindows ( box ) { return ( dispatch , getState ) => { const state = getState ( ) ; const windowsInfo = Selectors . getWindowsInfo ( state ) ; const getOpen = Selectors . getWindowOpen ( state ) ; const { top , left , width , height } = box ; const offsetLeft = left + window . scrollX ; const offsetTop = top + window . scrollY ; const bounding = Utils . calculateBoundingBox ( windowsInfo . filter ( ( w ) => getOpen ( w . key ) ) ) ; if ( bounding == null ) { return ; } const boxHeight = bounding . bottom - bounding . top ; const boxWidth = bounding . right - bounding . left ; const move = { x : Math . ceil ( offsetLeft - bounding . left + ( width - boxWidth ) / 2 ) , y : Math . ceil ( offsetTop - bounding . top + ( height - boxHeight ) / 2 ) , } ; const newPositions = windowsInfo . reduce ( ( pos , w ) => ( { ... pos , [ w . key ] : { x : move . x + w . x , y : move . y + w . y } , } ) , { } ) ; dispatch ( updateWindowPositions ( newPositions , true ) ) ; } ; } export function browserWindowSizeChanged ( size ) { return ( dispatch ) => { dispatch ( { type : BROWSER_WINDOW_SIZE_CHANGED , ... size } ) ; dispatch ( ensureWindowsAreOnScreen ( ) ) ; } ; } export function resetWindowSizes ( ) { return { type : RESET_WINDOW_SIZES } ; } export function stackWindows ( ) { return ( dispatch , getState ) => { dispatch ( updateWindowPositions ( Selectors . getStackedLayoutPositions ( getState ( ) ) ) ) ; } ; } export function ensureWindowsAreOnScreen ( ) { return ( dispatch , getState ) => { const state = getState ( ) ; const windowsInfo = Selectors . getWindowsInfo ( state ) ; const getOpen = Selectors . getWindowOpen ( state ) ; const { height , width } = Utils . getWindowSize ( ) ; const bounding = Utils . calculateBoundingBox ( windowsInfo . filter ( ( w ) => getOpen ( w . key ) ) ) ; if ( bounding == null ) { return ; } const positions = Selectors . getWindowPositions ( state ) ; if ( bounding . left >= 0 && bounding . top >= 0 && bounding . right <= width && bounding . bottom <= height ) { return ; } const boundingHeight = bounding . bottom - bounding . top ; const boundingWidth = bounding . right - bounding . left ; if ( boundingWidth <= width && boundingHeight <= height ) { let moveY = 0 ; let moveX = 0 ; if ( bounding . top <= 0 ) { moveY = bounding . top ; } else if ( bounding . bottom > height ) { moveY = bounding . bottom - height ; } if ( bounding . left <= 0 ) { moveX = bounding . left ; } else if ( bounding . right > width ) { moveX = bounding . right - width ; } const newPositions = Utils . objectMap ( positions , ( position ) => ( { x : position . x - moveX , y : position . y - moveY , } ) ) ; dispatch ( updateWindowPositions ( newPositions ) ) ; return ; } dispatch ( resetWindowSizes ( ) ) ; dispatch ( stackWindows ( ) ) ; dispatch ( centerWindowsInView ( ) ) ; } ; }