Created
July 30, 2021 13:58
-
-
Save eertmanhidde/9668848a2c5b6596f8aec9aabc95e481 to your computer and use it in GitHub Desktop.
Phoenix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Preferences | |
Phoenix.set({ | |
daemon: false, | |
openAtLogin: true, | |
}); | |
Event.on('willTerminate', () => { | |
Storage.remove('lastPositions'); | |
Storage.remove('maxHeight'); | |
}) | |
function frameRatio(a, b){ | |
const widthRatio = b.width / a.width; | |
const heightRatio = b.height / a.height; | |
return ({width, height, x, y}) => { | |
width = Math.round(width * widthRatio); | |
height = Math.round(height * heightRatio); | |
x = Math.round(b.x + (x - a.x) * widthRatio); | |
y = Math.round(b.y + (y - a.y) * heightRatio); | |
return {width, height, x, y}; | |
}; | |
} | |
// Globals | |
const HIDDEN_DOCK_MARGIN = 3; | |
const INCREMENT = 0.05; | |
const SHIFT_OPTION = ['shift', 'alt']; | |
const CONTROL_ALT_SHIFT = ['ctrl', 'alt', 'shift']; | |
// Relative Directions | |
const LEFT = 'left'; | |
const RIGHT = 'right'; | |
const CENTRE = 'centre'; | |
// Cardinal Directions | |
const NW = 'nw'; | |
const NE = 'ne'; | |
const SE = 'se'; | |
const SW = 'sw'; | |
const EAST = 'east'; | |
const WEST = 'west'; | |
const NORTH = 'north'; | |
const SOUTH = 'south'; | |
class ChainWindow { | |
constructor(window, margin = 10) { | |
this.window = window; | |
this.margin = margin; | |
this.frame = window.frame(); | |
this.parent = window.screen().flippedVisibleFrame(); | |
} | |
// Difference frame | |
difference() { | |
const { parent, frame } = this; | |
return { | |
x: parent.x - frame.x, | |
y: parent.y - frame.y, | |
width: parent.width - frame.width, | |
height: parent.height - frame.height, | |
}; | |
} | |
// Set frame | |
set() { | |
const { window, frame } = this; | |
window.setFrame(frame); | |
this.frame = window.frame(); | |
return this; | |
} | |
// Move to screen | |
screen(screen) { | |
this.parent = screen.flippedVisibleFrame(); | |
return this; | |
} | |
// Move to cardinal directions NW, NE, SE, SW or relative direction CENTRE | |
to(direction) { | |
const { parent, margin } = this; | |
const difference = this.difference(); | |
// X-coordinate | |
switch (direction) { | |
case NW: | |
case SW: | |
this.frame.x = parent.x + margin; | |
break; | |
case NE: | |
case SE: | |
this.frame.x = parent.x + difference.width - margin ; | |
break; | |
case CENTRE: | |
this.frame.x = parent.x + (difference.width / 2); | |
break; | |
default: | |
} | |
// Y-coordinate | |
switch (direction) { | |
case NW: | |
case NE: | |
this.frame.y = parent.y + margin; | |
break; | |
case SE: | |
case SW: | |
this.frame.y = parent.y + difference.height - margin; | |
break; | |
case CENTRE: | |
this.frame.y = parent.y + (difference.height / 2); | |
break; | |
default: | |
} | |
return this; | |
} | |
// Resize SE-corner by factor | |
resize(factor) { | |
const { parent, margin, frame } = this; | |
const difference = this.difference(); | |
let delta; | |
if (factor.width) { | |
delta = Math.min(parent.width * factor.width, difference.x + difference.width - margin); | |
this.frame.width += delta; | |
} else if (factor.height) { | |
delta = Math.min( | |
parent.height * factor.height, | |
difference.height - frame.y + margin + HIDDEN_DOCK_MARGIN, | |
); | |
this.frame.height += delta; | |
} | |
return this; | |
} | |
// Maximise to fill whole screen | |
maximise() { | |
const { parent, margin } = this; | |
this.frame.width = parent.width - (2 * margin); | |
this.frame.height = parent.height - (2 * margin); | |
return this; | |
} | |
// Halve width | |
halve() { | |
this.frame.width /= 2; | |
return this; | |
} | |
// Fit to screen | |
fit() { | |
const difference = this.difference(); | |
if (difference.width < 0 || difference.height < 0) { | |
this.maximise(); | |
} | |
return this; | |
} | |
// Fill relatively to LEFT or RIGHT-side of screen, or fill whole screen | |
fill(direction) { | |
this.maximise(); | |
if (direction === LEFT || direction === RIGHT) { | |
this.halve(); | |
} | |
switch (direction) { | |
case LEFT: | |
this.to(NW); | |
break; | |
case RIGHT: | |
this.to(NE); | |
break; | |
default: | |
this.to(NW); | |
} | |
return this; | |
} | |
} | |
// Chain a Window-object | |
Window.prototype.chain = function () { | |
return new ChainWindow(this); | |
}; | |
// To direction in screen | |
Window.prototype.to = function (direction, screen) { | |
const window = this.chain(); | |
if (screen) { | |
window.screen(screen).fit(); | |
} | |
window.to(direction).set(); | |
}; | |
// Fill in screen | |
Window.prototype.fill = function (direction, screen) { | |
const window = this.chain(); | |
if (screen) { | |
window.screen(screen); | |
} | |
window.fill(direction).set(); | |
// Ensure position for windows larger than expected | |
if (direction === RIGHT) { | |
window.to(NE).set(); | |
} | |
}; | |
// Resize by factor | |
Window.prototype.resize = function (factor) { | |
this.chain().resize(factor).set(); | |
}; | |
/* Position Bindings */ | |
Key.on('q', SHIFT_OPTION, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.to(NW, window.screen().next()); | |
} | |
}); | |
Key.on('w', SHIFT_OPTION, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.to(NE); | |
} | |
}); | |
Key.on('s', SHIFT_OPTION, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.to(SE); | |
} | |
}); | |
Key.on('a', SHIFT_OPTION, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.to(SW); | |
} | |
}); | |
Key.on('z', SHIFT_OPTION, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.to(CENTRE); | |
} | |
}); | |
Key.on('q', CONTROL_ALT_SHIFT, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.to(NW, window.screen().next()); | |
} | |
}); | |
Key.on('w', CONTROL_ALT_SHIFT, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.to(NE, window.screen().next()); | |
} | |
}); | |
Key.on('s', CONTROL_ALT_SHIFT, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.to(SE, window.screen().next()); | |
} | |
}); | |
Key.on('a', CONTROL_ALT_SHIFT, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.to(SW, window.screen().next()); | |
} | |
}); | |
Key.on('z', CONTROL_ALT_SHIFT, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.to(CENTRE, window.screen().next()); | |
} | |
}); | |
/* Fill Bindings */ | |
Key.on('o', SHIFT_OPTION, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.fill(LEFT); | |
} | |
}); | |
Key.on('p', SHIFT_OPTION, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.fill(RIGHT); | |
} | |
}); | |
/* Size Bindings */ | |
Key.on("'", SHIFT_OPTION, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.resize({ height: INCREMENT }); | |
} | |
}); | |
Key.on(';', SHIFT_OPTION, () => { | |
const window = Window.focused(); | |
if (window) { | |
window.resize({ height: -INCREMENT }); | |
} | |
}); | |
/* Focus Bindings */ | |
Key.on('<', SHIFT_OPTION, () => { | |
const last = _.last(Window.recent()); | |
if (last) { | |
last.focus(); | |
} | |
}); | |
Key.on('.', SHIFT_OPTION, () => { | |
const window = Window.focused(); | |
if(!window){ | |
return | |
} | |
const oldScreen = window.screen(); | |
const newScreen = oldScreen.next(); | |
if(oldScreen.isEqual(newScreen)){ | |
return; | |
} | |
const ratio = frameRatio( | |
oldScreen.flippedVisibleFrame(), | |
newScreen.flippedVisibleFrame(), | |
) | |
window.setFrame(ratio(window.frame())); | |
}) | |
/** toggle max screen **/ | |
Key.on('f', SHIFT_OPTION, () => { | |
const window = | |
Window.focused(); | |
if(!window) return; | |
const margin = | |
window.chain().margin; | |
const windowId = | |
window.hash(); | |
const screen = | |
window.screen().flippedVisibleFrame() | |
let lastPositions = | |
Storage.get('lastPositions') || {}; | |
if(!lastPositions[windowId]){ | |
lastPositions[windowId] = | |
{x: window.topLeft().x, y: window.topLeft().y, width: window.size().width, height: window.size().height} | |
} | |
const maxHeight = | |
Storage.get('maxHeight') || screen.height; | |
const maxWidth = | |
Storage.get('maxWidth') || screen.width; | |
if(window.size().width !== maxWidth || window.size().height !== maxHeight){ | |
lastPositions[windowId] = | |
{x: window.topLeft().x, y: window.topLeft().y, width: window.size().width, height: window.size().height} | |
Storage.set('lastPositions', lastPositions) | |
window.setTopLeft({ | |
x: screen.x, | |
y: screen.y, | |
}) | |
window.setSize({ | |
height: screen.height, | |
width: screen.width | |
}); | |
Storage.set('maxHeight', window.size().height); | |
Storage.set('maxWidth', window.size().width); | |
return; | |
} | |
if(window){ | |
window.setSize({ | |
width: lastPositions[windowId].width, | |
height: lastPositions[windowId].height, | |
}); | |
window.setTopLeft({ | |
x: lastPositions[windowId].x, | |
y: lastPositions[windowId].y | |
}); | |
} | |
}) | |
Key.on('7', SHIFT_OPTION, function(){ | |
App.launch('Iterm').focus(); | |
}) | |
Key.on('8', SHIFT_OPTION, function(){ | |
App.launch('Firefox').focus(); | |
}) | |
Key.on('9', SHIFT_OPTION, function(){ | |
App.launch('Slack').focus(); | |
}) | |
Key.on('0', SHIFT_OPTION, function(){ | |
App.launch('Spotify').focus(); | |
}) | |
Key.on('-', SHIFT_OPTION, function(){ | |
App.launch('Discord').focus(); | |
}) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment