Skip to content

Instantly share code, notes, and snippets.

@eertmanhidde
Created July 30, 2021 13:58
Show Gist options
  • Save eertmanhidde/9668848a2c5b6596f8aec9aabc95e481 to your computer and use it in GitHub Desktop.
Save eertmanhidde/9668848a2c5b6596f8aec9aabc95e481 to your computer and use it in GitHub Desktop.
Phoenix
// 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