diff --git a/src/bridges/utils.ts b/src/bridges/utils.ts index 517d3f3..bf9a71c 100644 --- a/src/bridges/utils.ts +++ b/src/bridges/utils.ts @@ -1,5 +1,6 @@ import { ipcRenderer } from "electron" -import { ImageCallbackTypes } from "../schema-types" +import { ImageCallbackTypes, TouchBarTexts } from "../schema-types" +import { IObjectWithKey } from "@fluentui/react" const utilsBridge = { platform: process.platform, @@ -108,6 +109,19 @@ const utilsBridge = { callback(false) }) }, + + addTouchBarEventsListener: (callback: (IObjectWithKey) => any) => { + ipcRenderer.removeAllListeners("touchbar-event") + ipcRenderer.on("touchbar-event", (_, key: string) => { + callback({ key: key} ) + }) + }, + initTouchBar: (texts: TouchBarTexts) => { + ipcRenderer.invoke("touchbar-init", texts) + }, + destroyTouchBar: () => { + ipcRenderer.invoke("touchbar-destroy") + }, } declare global { diff --git a/src/components/nav.tsx b/src/components/nav.tsx index 0580822..b872e8f 100644 --- a/src/components/nav.tsx +++ b/src/components/nav.tsx @@ -2,7 +2,7 @@ import * as React from "react" import intl from "react-intl-universal" import { Icon } from "@fluentui/react/lib/Icon" import { AppState } from "../scripts/models/app" -import { ProgressIndicator } from "@fluentui/react" +import { ProgressIndicator, IObjectWithKey } from "@fluentui/react" import { getWindowBreakpoint } from "../scripts/utils" type NavProps = { @@ -34,7 +34,7 @@ class Nav extends React.Component { this.setState({ maximized: state }) } - navShortcutsHandler = (e: KeyboardEvent) => { + navShortcutsHandler = (e: KeyboardEvent | IObjectWithKey) => { if (!this.props.state.settings.display) { switch (e.key) { case "F1": @@ -66,6 +66,7 @@ class Nav extends React.Component { componentDidMount() { document.addEventListener("keydown", this.navShortcutsHandler) + if (window.utils.platform === "darwin") window.utils.addTouchBarEventsListener(this.navShortcutsHandler) } componentWillUnmount() { document.removeEventListener("keydown", this.navShortcutsHandler) diff --git a/src/components/settings.tsx b/src/components/settings.tsx index 3034fb4..2ae5f8d 100644 --- a/src/components/settings.tsx +++ b/src/components/settings.tsx @@ -9,6 +9,7 @@ import GroupsTabContainer from "../containers/settings/groups-container" import AppTabContainer from "../containers/settings/app-container" import RulesTabContainer from "../containers/settings/rules-container" import ServiceTabContainer from "../containers/settings/service-container" +import { initTouchBarWithTexts } from "../scripts/utils" type SettingsProps = { display: boolean, @@ -22,6 +23,13 @@ class Settings extends React.Component { super(props) } + componentDidUpdate= (prevProps: SettingsProps) => { + if (this.props.display !== prevProps.display) { + if (this.props.display) window.utils.destroyTouchBar() + else initTouchBarWithTexts() + } + } + render = () => this.props.display && (
diff --git a/src/main/touchbar.ts b/src/main/touchbar.ts new file mode 100644 index 0000000..f833b23 --- /dev/null +++ b/src/main/touchbar.ts @@ -0,0 +1,24 @@ +import { TouchBarTexts } from "../schema-types" +import { BrowserWindow, TouchBar } from "electron" + + +function createTouchBarFunctionButton(window: BrowserWindow, text: string, key: string) { + return new TouchBar.TouchBarButton({ + label: text, + click: () => window.webContents.send("touchbar-event", key) + }) +} + +export function initMainTouchBar(texts: TouchBarTexts, window: BrowserWindow) { + const touchBar = new TouchBar({ + items: [ + createTouchBarFunctionButton(window, texts.menu, "F1"), + createTouchBarFunctionButton(window, texts.search, "F2"), + new TouchBar.TouchBarSpacer({ size: "small" }), + createTouchBarFunctionButton(window, texts.refresh, "F5"), + createTouchBarFunctionButton(window, texts.markAll, "F6"), + createTouchBarFunctionButton(window, texts.notifications, "F7"), + ] + }) + window.setTouchBar(touchBar) +} \ No newline at end of file diff --git a/src/main/utils.ts b/src/main/utils.ts index 53627fa..c6e4361 100644 --- a/src/main/utils.ts +++ b/src/main/utils.ts @@ -1,7 +1,8 @@ -import { ipcMain, shell, dialog, app, session, clipboard } from "electron" +import { ipcMain, shell, dialog, app, session, clipboard, TouchBar } from "electron" import { WindowManager } from "./window" import fs = require("fs") -import { ImageCallbackTypes } from "../schema-types" +import { ImageCallbackTypes, TouchBarTexts } from "../schema-types" +import { initMainTouchBar } from "./touchbar" export function setUtilsListeners(manager: WindowManager) { async function openExternal(url: string, background=false) { @@ -206,4 +207,11 @@ export function setUtilsListeners(manager: WindowManager) { } } }) + + ipcMain.handle("touchbar-init", (_, texts: TouchBarTexts) => { + if (manager.hasWindow()) initMainTouchBar(texts, manager.mainWindow) + }) + ipcMain.handle("touchbar-destroy", () => { + if (manager.hasWindow()) manager.mainWindow.setTouchBar(null) + }) } \ No newline at end of file diff --git a/src/schema-types.ts b/src/schema-types.ts index 4ce99aa..379a12a 100644 --- a/src/schema-types.ts +++ b/src/schema-types.ts @@ -44,6 +44,14 @@ export interface ServiceConfigs { importGroups?: boolean } +export interface TouchBarTexts { + menu: string + search: string + refresh: string + markAll: string + notifications: string +} + export type SchemaTypes = { version: string theme: ThemeSettings diff --git a/src/scripts/models/app.ts b/src/scripts/models/app.ts index 00f138a..36a2185 100644 --- a/src/scripts/models/app.ts +++ b/src/scripts/models/app.ts @@ -1,7 +1,7 @@ import intl from "react-intl-universal" import { INIT_SOURCES, SourceActionTypes, ADD_SOURCE, UPDATE_SOURCE, DELETE_SOURCE, initSources, SourceOpenTarget } from "./source" import { RSSItem, ItemActionTypes, FETCH_ITEMS, fetchItems } from "./item" -import { ActionStatus, AppThunk, getWindowBreakpoint } from "../utils" +import { ActionStatus, AppThunk, getWindowBreakpoint, initTouchBarWithTexts } from "../utils" import { INIT_FEEDS, FeedActionTypes, ALL, initFeeds } from "./feed" import { SourceGroupActionTypes, UPDATE_SOURCE_GROUP, ADD_SOURCE_TO_GROUP, DELETE_SOURCE_GROUP, REMOVE_SOURCE_FROM_GROUP, REORDER_SOURCE_GROUPS } from "./group" import { PageActionTypes, SELECT_PAGE, PageType, selectAllArticles, showItemFromId } from "./page" @@ -276,9 +276,10 @@ export function initIntl(): AppThunk> { export function initApp(): AppThunk { return (dispatch) => { document.body.classList.add(window.utils.platform) - dispatch(initIntl()).then(() => - dispatch(initSources()) - ).then(() => + dispatch(initIntl()).then(async () => { + if (window.utils.platform === "darwin") initTouchBarWithTexts() + await dispatch(initSources()) + }).then(() => dispatch(initFeeds()) ).then(() => { dispatch(selectAllArticles()) diff --git a/src/scripts/utils.ts b/src/scripts/utils.ts index 5a1486a..82a12f5 100644 --- a/src/scripts/utils.ts +++ b/src/scripts/utils.ts @@ -193,3 +193,13 @@ export function validateRegex(regex: string, flags = ""): RegExp { export function platformCtrl(e: React.MouseEvent | React.KeyboardEvent | MouseEvent | KeyboardEvent) { return window.utils.platform === "darwin" ? e.metaKey : e.ctrlKey } + +export function initTouchBarWithTexts() { + window.utils.initTouchBar({ + menu: intl.get("nav.menu"), + search: intl.get("search"), + refresh: intl.get("nav.refresh"), + markAll: intl.get("nav.markAllRead"), + notifications: intl.get("nav.notifications") + }) +}