Skip to content
This repository has been archived by the owner on Jun 4, 2023. It is now read-only.

Commit

Permalink
feat: add support for theme-color, fixes #122
Browse files Browse the repository at this point in the history
  • Loading branch information
sentialx committed Feb 2, 2019
1 parent c9a73ac commit 4ccfa32
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 34 deletions.
7 changes: 7 additions & 0 deletions src/main/browser-view-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ export default class BrowserViewWrapper extends BrowserView {
);
});

this.webContents.addListener('did-change-theme-color', (e, color) => {
appWindow.window.webContents.send(
`browserview-theme-color-updated-${this.tabId}`,
color,
);
});

(this.webContents as any).addListener(
'certificate-error',
(
Expand Down
88 changes: 63 additions & 25 deletions src/renderer/app/models/tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ipcRenderer } from 'electron';
import { TABS_PADDING, TAB_ANIMATION_DURATION } from '../constants';
import { closeWindow } from '../utils';
import { createElement } from 'ui';
import { shadeBlendConvert, getColorBrightness } from '../utils/colors';

let id = 0;

Expand All @@ -24,6 +25,7 @@ export class Tab {

private _favicon: string = '';
private _title: string;
private _background: string | null = null;

constructor() {
this.root = (
Expand All @@ -44,6 +46,8 @@ export class Tab {
</div>
) as any;

this.background = null;

app.tabs.container.appendChild(this.root);

ipcRenderer.send('browserview-create', this.id);
Expand All @@ -62,6 +66,14 @@ export class Tab {
},
);

ipcRenderer.on(
`browserview-theme-color-updated-${this.id}`,
(e: any, themeColor: string) => {
console.log(themeColor);
this.background = themeColor;
},
);

requestAnimationFrame(this.tick);
}

Expand Down Expand Up @@ -95,6 +107,10 @@ export class Tab {
return app.tabs.list[app.tabs.list.indexOf(this) - 1];
}

public get nextTab() {
return app.tabs.list[app.tabs.list.indexOf(this) + 1];
}

public get favicon() {
return this._favicon;
}
Expand All @@ -120,22 +136,56 @@ export class Tab {
this.rightBorder.style.display = value ? 'block' : 'none';
}

public onMouseEnter = () => {
this.root.classList.add('hover');
public get background() {
return this._background;
}

public set background(value: string | null) {
if (value && getColorBrightness(value) > 170) {
return;
}

this._background = value || '#2196F3';
this.update();
}

public update = () => {
const canHideSeparator = this.isHovered || this.selected;

const previousTab = this.previousTab;
if (previousTab) {
previousTab.rightBorderVisible = false;
previousTab.rightBorderVisible = !canHideSeparator;
}
};
this.rightBorderVisible = !canHideSeparator;

public onMouseLeave = () => {
this.root.classList.remove('hover');
if (this.selected) {
this.root.classList.add('selected');

const previousTab = this.previousTab;
if (previousTab && !this.selected) {
previousTab.rightBorderVisible = true;
const background = shadeBlendConvert(0.85, this.background);

this.root.style.backgroundColor = background;
this.titleElement.style.color = this.background;
} else {
this.root.classList.remove('selected');

this.titleElement.style.color = 'rgba(0, 0, 0, 0.87)';
this.root.style.backgroundColor = 'transparent';
}

if (this.isHovered) {
this.root.classList.add('hover');
} else {
this.root.classList.remove('hover');
}
};

public onMouseEnter = () => {
this.update();
};

public onMouseLeave = () => {
this.update();
if (this.nextTab) this.nextTab.update();
};

public onMouseDown = (e: any) => {
Expand Down Expand Up @@ -212,26 +262,14 @@ export class Tab {
public select() {
const { selectedTab } = app.tabs;

if (selectedTab) {
selectedTab.rightBorderVisible = true;
selectedTab.root.classList.remove('selected');

const previousTab = selectedTab.previousTab;
if (previousTab) {
previousTab.rightBorderVisible = true;
}
}

this.root.classList.add('selected');
this.rightBorderVisible = false;

app.tabs.selectedTabId = this.id;

const previousTab = this.previousTab;
if (previousTab) {
previousTab.rightBorderVisible = false;
if (selectedTab) {
selectedTab.update();
}

this.update();

ipcRenderer.send('browserview-select', this.id);
}

Expand Down
4 changes: 1 addition & 3 deletions src/renderer/app/models/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,8 @@ export class Tabs {
this.list = tabsCopy;

for (const tab of this.list) {
tab.rightBorderVisible = true;
tab.update();
}

firstTab.select();
}

public getTabsToReplace(callingTab: Tab, direction: string) {
Expand Down
9 changes: 3 additions & 6 deletions src/renderer/app/scss/tabs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,6 @@

&.selected {
z-index: 2;
background-color: #e3f2fd;

& .tab-title {
color: #2196f3;
}

&:after {
background-color: rgba(33, 150, 243, 0.08);
Expand Down Expand Up @@ -117,8 +112,10 @@

.tab-icon {
min-width: 16px;
height: 16px;
height: 100%;
background-size: 16px;
background-repeat: no-repeat;
background-position: center;
margin-right: 8px;
opacity: 0;
transition: 0.2s opacity;
Expand Down
124 changes: 124 additions & 0 deletions src/renderer/app/utils/colors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// https://stackoverflow.com/a/13542669
export const shadeBlendConvert = function (
this: any,
p: any,
from: any,
to: any = null,
) {
if (
typeof p !== 'number' ||
p < -1 ||
p > 1 ||
typeof from !== 'string' ||
(from[0] !== 'r' && from[0] !== '#') ||
(to && typeof to !== 'string')
) {
return null;
} // ErrorCheck
if (!(this as any).sbcRip) {
this.sbcRip = (d: any) => {
const l = d.length;
const RGB: any = {};

if (l > 9) {
d = d.split(',');
if (d.length < 3 || d.length > 4) return null; // ErrorCheck
(RGB[0] = i(d[0].split('(')[1])),
(RGB[1] = i(d[1])),
(RGB[2] = i(d[2])),
(RGB[3] = d[3] ? parseFloat(d[3]) : -1);
} else {
if (l === 8 || l === 6 || l < 4) return null; // ErrorCheck
if (l < 6) {
d = `#${d[1]}${d[1]}${d[2]}${d[2]}${d[3]}${d[3]}${
l > 4 ? `${d[4]}${d[4]}` : ''
}`;
} // 3 or 4 digit
(d = i(d.slice(1), 16)),
(RGB[0] = (d >> 16) & 255),
(RGB[1] = (d >> 8) & 255),
(RGB[2] = d & 255),
(RGB[3] = -1);
if (l === 9 || l === 5) {
(RGB[3] = r((RGB[2] / 255) * 10000) / 10000),
(RGB[2] = RGB[1]),
(RGB[1] = RGB[0]),
(RGB[0] = (d >> 24) & 255);
}
}
return RGB;
};
}
const i = parseInt;
const r = Math.round;
let h = from.length > 9;
h =
typeof to === 'string'
? to.length > 9
? true
: to === 'c'
? !h
: false
: h;
const b = p < 0;
p = b ? p * -1 : p;
to = to && to !== 'c' ? to : b ? '#000000' : '#FFFFFF';
const f = this.sbcRip(from);
const t = this.sbcRip(to);
if (!f || !t) return null; // ErrorCheck
if (h) {
return `rgb${f[3] > -1 || t[3] > -1 ? 'a(' : '('}${r(
(t[0] - f[0]) * p + f[0],
)},${r((t[1] - f[1]) * p + f[1])},${r((t[2] - f[2]) * p + f[2])}${
f[3] < 0 && t[3] < 0
? ')'
: `,${
f[3] > -1 && t[3] > -1
? r(((t[3] - f[3]) * p + f[3]) * 10000) / 10000
: t[3] < 0
? f[3]
: t[3]
})`
}`;
}

return `#${(
0x100000000 +
r((t[0] - f[0]) * p + f[0]) * 0x1000000 +
r((t[1] - f[1]) * p + f[1]) * 0x10000 +
r((t[2] - f[2]) * p + f[2]) * 0x100 +
(f[3] > -1 && t[3] > -1
? r(((t[3] - f[3]) * p + f[3]) * 255)
: t[3] > -1
? r(t[3] * 255)
: f[3] > -1
? r(f[3] * 255)
: 255)
)
.toString(16)
.slice(1, f[3] > -1 || t[3] > -1 ? undefined : -2)}`;
};

export const getColorBrightness = (color: any) => {
let r;
let g;
let b;

if (color.match(/^rgb/)) {
color = color.match(
/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/,
);

r = color[1];
g = color[2];
b = color[3];
} else {
color = +`0x${color.slice(1).replace(color.length < 5 && /./g, '$&$&')}`;

r = color >> 16;
g = (color >> 8) & 255;
b = color & 255;
}

return Math.sqrt(0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b));
};

0 comments on commit 4ccfa32

Please sign in to comment.