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

Commit

Permalink
feat: add "media playing" indicator (#440)
Browse files Browse the repository at this point in the history
* Avoid unnecessary "subscription" for zoom updates

* Add playing/mute indicator

* Fixed removal of did-navigate event
  • Loading branch information
BlobCodes authored Apr 25, 2020
1 parent df86f2d commit 3c11b11
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 40 deletions.
4 changes: 3 additions & 1 deletion src/interfaces/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ export type TabEvent =
| 'pinned'
| 'credentials'
| 'blocked-ad'
| 'zoom-updated';
| 'zoom-updated'
| 'media-playing'
| 'media-paused';
12 changes: 3 additions & 9 deletions src/main/view-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ export class ViewManager {

private window: AppWindow;

private zoomUpdateSubscribers: Electron.WebContents[] = [];

public get fullscreen() {
return this._fullscreen;
}
Expand Down Expand Up @@ -76,11 +74,6 @@ export class ViewManager {
this.clear();
});

ipcMain.on('subscribe-zoom-factor-updates', (e) => {
e.reply('send-zoom-factor', this.selected.webContents.zoomFactor);
this.zoomUpdateSubscribers.push(e.sender);
});

ipcMain.on('change-zoom', (e, zoomDirection) => {
const newZoomFactor =
this.selected.webContents.zoomFactor +
Expand Down Expand Up @@ -233,8 +226,9 @@ export class ViewManager {
}

public emitZoomUpdate(showDialog: boolean = true) {
this.zoomUpdateSubscribers.forEach((e) =>
e.send('zoom-factor-updated', this.selected.webContents.zoomFactor),
this.window.dialogs.zoomDialog.send(
'zoom-factor-updated',
this.selected.webContents.zoomFactor
);
this.window.webContents.send(
'zoom-factor-updated',
Expand Down
8 changes: 8 additions & 0 deletions src/main/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,14 @@ export class View {
},
);

this.webContents.addListener('media-started-playing', () => {
this.emitEvent('media-playing', true);
});

this.webContents.addListener('media-paused', () => {
this.emitEvent('media-paused', true);
});

if (url.startsWith(NEWTAB_URL)) this.isNewTab = true;

this.webContents.loadURL(url);
Expand Down
3 changes: 2 additions & 1 deletion src/renderer/constants/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ export const ICON_INCOGNITO = require('~/renderer/resources/icons/incognito.svg'
export const ICON_LOCATION = require('~/renderer/resources/icons/location.svg');
export const ICON_AUTOFILL = require('~/renderer/resources/icons/autofill.svg');
export const ICON_PALETTE = require('~/renderer/resources/icons/palette.svg');
export const ICON_MUTE = require('~/renderer/resources/icons/mute.svg');
export const ICON_POWER = require('~/renderer/resources/icons/power.svg');
export const ICON_ARROW_RIGHT = require('~/renderer/resources/icons/arrow-right.svg');
export const ICON_PRINT = require('~/renderer/resources/icons/print.svg');
Expand All @@ -51,6 +50,8 @@ export const ICON_TOPMOST = require('~/renderer/resources/icons/top-most.svg');
export const ICON_TUNE = require('~/renderer/resources/icons/tune.svg');
export const ICON_MAGNIFY_PLUS = require('~/renderer/resources/icons/magnify-plus.svg');
export const ICON_MAGNIFY_MINUS = require('~/renderer/resources/icons/magnify-minus.svg');
export const ICON_VOLUME_HIGH = require('~/renderer/resources/icons/volume-high.svg');
export const ICON_VOLUME_OFF = require('~/renderer/resources/icons/volume-off.svg');

export const ICON_WEATHER_DAY_CLEAR = require('~/renderer/resources/icons/weather/day/clear.png');
export const ICON_WEATHER_DAY_FEW_CLOUDS = require('~/renderer/resources/icons/weather/day/few-clouds.png');
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/renderer/resources/icons/volume-off.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 43 additions & 19 deletions src/renderer/views/app/components/Tab/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,36 @@ import {
StyledIcon,
StyledTitle,
StyledClose,
StyledAction,
StyledPinAction,
TabContainer,
} from './style';
import {
ICON_VOLUME_HIGH,
ICON_VOLUME_OFF,
} from '~/renderer/constants';
import { ITab } from '../../models';
import store from '../../store';
import { remote, ipcRenderer } from 'electron';
import { ICON_MUTE } from '~/renderer/constants/icons';

const removeTab = (tab: ITab) => (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
tab.close();
};

const toggleMuteTab = (tab: ITab) => (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
tab.isMuted ? store.tabs.unmuteTab(tab) : store.tabs.muteTab(tab)
};

const onCloseMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
};

const onVolumeMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
};

const onMouseDown = (tab: ITab) => (e: React.MouseEvent<HTMLDivElement>) => {
const { pageX, button } = e;

Expand Down Expand Up @@ -196,7 +210,9 @@ const Content = observer(({ tab }: { tab: ITab }) => {
<StyledIcon
isIconSet={tab.favicon !== ''}
style={{ backgroundImage: `url(${tab.favicon})` }}
></StyledIcon>
>
<PinnedVolume tab={tab} />
</StyledIcon>
)}

{tab.loading && (
Expand All @@ -213,11 +229,34 @@ const Content = observer(({ tab }: { tab: ITab }) => {
{tab.title}
</StyledTitle>
)}
<ExpandedVolume tab={tab} />
<Close tab={tab} />
</StyledContent>
);
});

const ExpandedVolume = observer(({ tab }: { tab: ITab }) => {
return (
<StyledAction
onMouseDown={onVolumeMouseDown}
onClick={toggleMuteTab(tab)}
visible={tab.isExpanded && !tab.isPinned && tab.isPlaying}
icon={tab.isMuted ? ICON_VOLUME_OFF : ICON_VOLUME_HIGH}
/>
);
});

const PinnedVolume = observer(({ tab }: { tab: ITab }) => {
return (
<StyledPinAction
onMouseDown={onVolumeMouseDown}
onClick={toggleMuteTab(tab)}
visible={tab.isPinned && tab.isPlaying}
icon={tab.isMuted ? ICON_VOLUME_OFF : ICON_VOLUME_HIGH}
/>
);
});

const Close = observer(({ tab }: { tab: ITab }) => {
return (
<StyledClose
Expand Down Expand Up @@ -254,26 +293,11 @@ export default observer(({ tab }: { tab: ITab }) => {
backgroundColor: tab.isSelected
? store.theme['toolbar.backgroundColor']
: tab.isHovered
? defaultHoverColor
: defaultColor,
? defaultHoverColor
: defaultColor,
}}
>
<Content tab={tab} />
{tab.isMuted && !tab.loading && !tab.isPinned && (
<StyledIcon
isIconSet={tab.isMuted}
style={{
backgroundImage: `url(${ICON_MUTE})`,
position: 'absolute',
right: 32,
zIndex: 9999,
filter: store.theme['toolbar.lightForeground']
? 'invert(100%)'
: 'none',
opacity: 0.54,
}}
/>
)}
</TabContainer>
</StyledTab>
);
Expand Down
55 changes: 55 additions & 0 deletions src/renderer/views/app/components/Tab/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,61 @@ export const StyledClose = styled.div`
}
`;

interface ActionProps {
visible: boolean;
icon: string;
theme?: ITheme;
}

export const StyledAction = styled.div`
height: 20px;
width: 20px;
margin-left: 2px;
border-radius: 2px;
transition: 0.1s background-color;
z-index: 10;
${centerIcon(16)};
${({ visible, theme, icon }: ActionProps) => css`
opacity: ${visible ? transparency.icons.inactive : 0};
display: ${visible ? 'block' : 'none'};
filter: ${theme['toolbar.lightForeground'] ? 'invert(100%)' : 'none'};
background-image: url('${icon}');
`}
&:hover {
background-color: rgba(0, 0, 0, 0.1);
}
`;

interface PinActionProps {
visible: boolean;
icon: string;
theme?: ITheme;
}

export const StyledPinAction = styled.div`
height: 12px;
width: 12px;
border-radius: 100%;
transition: 0.1s background-color;
z-index: 10;
position: fixed;
right: 8px;
top: 8px;
${centerIcon(10)};
${({ visible, theme, icon }: PinActionProps) => css`
display: ${visible ? 'block' : 'none'};
background-color: ${theme['toolbar.lightForeground'] ? 'rgb(255, 255, 255)' : 'rgb(0, 0, 0)'};
background-image: url('${icon}');
`}
&:hover {
filter: invert(100%);
}
`;

interface TabProps {
selected: boolean;
}
Expand Down
5 changes: 4 additions & 1 deletion src/renderer/views/app/models/tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export class ITab {
@observable
public isMuted = false;

@observable
public isPlaying = false;

@observable
public title = 'New tab';

Expand Down Expand Up @@ -173,7 +176,7 @@ export class ITab {

const width =
(containerWidth - pinnedTabs * (TAB_PINNED_WIDTH + TABS_PADDING)) /
realTabsLength -
realTabsLength -
TABS_PADDING -
store.tabs.leftMargins / realTabsLength;

Expand Down
12 changes: 8 additions & 4 deletions src/renderer/views/app/store/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ export class TabsStore {
}
} else if (event === 'did-navigate') {
tab.favicon = '';
} else if (event === 'media-playing') {
tab.isPlaying = true;
} else if (event === 'media-paused') {
tab.isPlaying = false;
} else if (
event === 'loading' ||
event === 'pinned' ||
Expand Down Expand Up @@ -491,7 +495,7 @@ export class TabsStore {
if (
callingTab.left < tabGroup.left ||
callingTab.left + callingTab.width >=
tabGroup.left + tabGroup.width + 20
tabGroup.left + tabGroup.width + 20
) {
callingTab.removeFromGroup();
return;
Expand Down Expand Up @@ -595,9 +599,9 @@ export class TabsStore {
if (
newLeft + selectedTab.width >
container.current.scrollLeft +
container.current.offsetWidth -
TABS_PADDING +
20
container.current.offsetWidth -
TABS_PADDING +
20
) {
left =
container.current.scrollLeft +
Expand Down
6 changes: 2 additions & 4 deletions src/renderer/views/zoom/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ export class Store extends DialogStore {
this.zoomFactor = zoomFactor;
});

ipcRenderer.send('subscribe-zoom-factor-updates');

const zoomFactorChange = reaction(
() => this.zoomFactor,
() => this.resetHideTimer()
Expand All @@ -25,7 +23,7 @@ export class Store extends DialogStore {

public async onVisibilityChange(visible: boolean) {
this.visible = visible;
if(visible) {
if (visible) {
this.resetHideTimer();
}
}
Expand All @@ -37,7 +35,7 @@ export class Store extends DialogStore {
context.hide();
}, 1500);
}

public stopHideTimer() {
clearTimeout(this.timer);
}
Expand Down

0 comments on commit 3c11b11

Please sign in to comment.