mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-08-10 18:39:22 +08:00
Merge pull request #702 from TriliumNext/feature/native_window_buttons
Native title bar buttons
This commit is contained in:
commit
e22e974786
@ -8,6 +8,7 @@ import macInit from './services/mac_init.js';
|
|||||||
import electronContextMenu from "./menus/electron_context_menu.js";
|
import electronContextMenu from "./menus/electron_context_menu.js";
|
||||||
import glob from "./services/glob.js";
|
import glob from "./services/glob.js";
|
||||||
import { t } from "./services/i18n.js";
|
import { t } from "./services/i18n.js";
|
||||||
|
import options from "./services/options.js";
|
||||||
|
|
||||||
await appContext.earlyInit();
|
await appContext.earlyInit();
|
||||||
|
|
||||||
@ -30,8 +31,7 @@ bundleService.getWidgetBundlesByParent().then(async widgetBundles => {
|
|||||||
glob.setupGlobs();
|
glob.setupGlobs();
|
||||||
|
|
||||||
if (utils.isElectron()) {
|
if (utils.isElectron()) {
|
||||||
utils.dynamicRequire('electron').ipcRenderer.on('globalShortcut',
|
initOnElectron();
|
||||||
async (event, actionName) => appContext.triggerCommand(actionName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macInit.init();
|
macInit.init();
|
||||||
@ -43,3 +43,40 @@ noteAutocompleteService.init();
|
|||||||
if (utils.isElectron()) {
|
if (utils.isElectron()) {
|
||||||
electronContextMenu.setupContextMenu();
|
electronContextMenu.setupContextMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initOnElectron() {
|
||||||
|
const electron = utils.dynamicRequire('electron');
|
||||||
|
electron.ipcRenderer.on('globalShortcut', async (event, actionName) => appContext.triggerCommand(actionName));
|
||||||
|
|
||||||
|
if (options.get("nativeTitleBarVisible") !== "true") {
|
||||||
|
initTitleBarButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initTitleBarButtons() {
|
||||||
|
const electronRemote = utils.dynamicRequire("@electron/remote");
|
||||||
|
const currentWindow = electronRemote.getCurrentWindow();
|
||||||
|
const style = window.getComputedStyle(document.body);
|
||||||
|
|
||||||
|
if (window.glob.platform === "win32") {
|
||||||
|
const applyWindowsOverlay = () => {
|
||||||
|
const color = style.getPropertyValue("--native-titlebar-background");
|
||||||
|
const symbolColor = style.getPropertyValue("--native-titlebar-foreground");
|
||||||
|
if (color && symbolColor) {
|
||||||
|
currentWindow.setTitleBarOverlay({ color, symbolColor });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
applyWindowsOverlay();
|
||||||
|
|
||||||
|
// Register for changes to the native title bar colors.
|
||||||
|
window.matchMedia("(prefers-color-scheme: dark)")
|
||||||
|
.addEventListener("change", applyWindowsOverlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.glob.platform === "darwin") {
|
||||||
|
const xOffset = parseInt(style.getPropertyValue("--native-titlebar-darwin-x-offset"), 10);
|
||||||
|
const yOffset = parseInt(style.getPropertyValue("--native-titlebar-darwin-y-offset"), 10);
|
||||||
|
currentWindow.setWindowButtonPosition({ x: xOffset, y: yOffset });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -84,6 +84,7 @@ import CopyImageReferenceButton from "../widgets/floating_buttons/copy_image_ref
|
|||||||
import ScrollPaddingWidget from "../widgets/scroll_padding.js";
|
import ScrollPaddingWidget from "../widgets/scroll_padding.js";
|
||||||
import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js";
|
import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js";
|
||||||
import options from "../services/options.js";
|
import options from "../services/options.js";
|
||||||
|
import utils from "../services/utils.js";
|
||||||
|
|
||||||
export default class DesktopLayout {
|
export default class DesktopLayout {
|
||||||
constructor(customWidgets) {
|
constructor(customWidgets) {
|
||||||
@ -95,15 +96,27 @@ export default class DesktopLayout {
|
|||||||
|
|
||||||
const launcherPaneIsHorizontal = (options.get("layoutOrientation") === "horizontal");
|
const launcherPaneIsHorizontal = (options.get("layoutOrientation") === "horizontal");
|
||||||
const launcherPane = this.#buildLauncherPane(launcherPaneIsHorizontal);
|
const launcherPane = this.#buildLauncherPane(launcherPaneIsHorizontal);
|
||||||
|
const isElectron = (utils.isElectron());
|
||||||
|
const isMac = (window.glob.platform === "darwin");
|
||||||
|
const isWindows = (window.glob.platform === "win32");
|
||||||
|
const hasNativeTitleBar = (window.glob.hasNativeTitleBar);
|
||||||
|
|
||||||
return new RootContainer(launcherPaneIsHorizontal)
|
/**
|
||||||
|
* If true, the tab bar is displayed above the launcher pane with full width; if false (default), the tab bar is displayed in the rest pane.
|
||||||
|
* On macOS we need to force the full-width tab bar on Electron in order to allow the semaphore (window controls) enough space.
|
||||||
|
*/
|
||||||
|
const fullWidthTabBar = (launcherPaneIsHorizontal || (isElectron && !hasNativeTitleBar && isMac));
|
||||||
|
const customTitleBarButtons = (hasNativeTitleBar && !isMac && !isWindows);
|
||||||
|
|
||||||
|
return new RootContainer(true)
|
||||||
.setParent(appContext)
|
.setParent(appContext)
|
||||||
.class((launcherPaneIsHorizontal ? "horizontal" : "vertical") + "-layout")
|
.class((launcherPaneIsHorizontal ? "horizontal" : "vertical") + "-layout")
|
||||||
.optChild(launcherPaneIsHorizontal, new FlexContainer('row')
|
.optChild(fullWidthTabBar, new FlexContainer('row')
|
||||||
.class("tab-row-container")
|
.class("tab-row-container")
|
||||||
.child(new LeftPaneToggleWidget(true))
|
.child(new FlexContainer( "row").id("tab-row-left-spacer"))
|
||||||
|
.optChild(launcherPaneIsHorizontal, new LeftPaneToggleWidget(true))
|
||||||
.child(new TabRowWidget().class("full-width"))
|
.child(new TabRowWidget().class("full-width"))
|
||||||
.child(new TitleBarButtonsWidget())
|
.optChild(customTitleBarButtons, new TitleBarButtonsWidget())
|
||||||
.css('height', '40px')
|
.css('height', '40px')
|
||||||
.css('background-color', 'var(--launcher-pane-background-color)')
|
.css('background-color', 'var(--launcher-pane-background-color)')
|
||||||
.setParent(appContext)
|
.setParent(appContext)
|
||||||
@ -120,9 +133,9 @@ export default class DesktopLayout {
|
|||||||
.child(new FlexContainer('column')
|
.child(new FlexContainer('column')
|
||||||
.id('rest-pane')
|
.id('rest-pane')
|
||||||
.css("flex-grow", "1")
|
.css("flex-grow", "1")
|
||||||
.optChild(!launcherPaneIsHorizontal, new FlexContainer('row')
|
.optChild(!fullWidthTabBar, new FlexContainer('row')
|
||||||
.child(new TabRowWidget())
|
.child(new TabRowWidget())
|
||||||
.child(new TitleBarButtonsWidget())
|
.optChild(customTitleBarButtons, new TitleBarButtonsWidget())
|
||||||
.css('height', '40px')
|
.css('height', '40px')
|
||||||
)
|
)
|
||||||
.child(new FlexContainer('row')
|
.child(new FlexContainer('row')
|
||||||
|
@ -143,6 +143,11 @@ const TPL = `
|
|||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<li class="dropdown-item toggle-pin">
|
||||||
|
<span class="bx bx-pin"></span>
|
||||||
|
${t('title_bar_buttons.window-on-top')}
|
||||||
|
</li>
|
||||||
|
|
||||||
<div class="dropdown-divider zoom-container-separator"></div>
|
<div class="dropdown-divider zoom-container-separator"></div>
|
||||||
|
|
||||||
<li class="dropdown-item switch-to-mobile-version-button" data-trigger-command="switchToMobileVersion">
|
<li class="dropdown-item switch-to-mobile-version-button" data-trigger-command="switchToMobileVersion">
|
||||||
@ -294,6 +299,23 @@ export default class GlobalMenuWidget extends BasicWidget {
|
|||||||
|
|
||||||
const isElectron = utils.isElectron();
|
const isElectron = utils.isElectron();
|
||||||
|
|
||||||
|
this.$widget.find(".toggle-pin").toggle(isElectron);
|
||||||
|
if (isElectron) {
|
||||||
|
this.$widget.on("click", ".toggle-pin", (e) => {
|
||||||
|
const $el = $(e.target);
|
||||||
|
const remote = utils.dynamicRequire('@electron/remote');
|
||||||
|
const focusedWindow = remote.BrowserWindow.getFocusedWindow();
|
||||||
|
const isAlwaysOnTop = focusedWindow.isAlwaysOnTop()
|
||||||
|
if (isAlwaysOnTop) {
|
||||||
|
focusedWindow.setAlwaysOnTop(false)
|
||||||
|
$el.removeClass('active');
|
||||||
|
} else {
|
||||||
|
focusedWindow.setAlwaysOnTop(true);
|
||||||
|
$el.addClass('active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.$widget.find(".logout-button").toggle(!isElectron);
|
this.$widget.find(".logout-button").toggle(!isElectron);
|
||||||
this.$widget.find(".logout-button-separator").toggle(!isElectron);
|
this.$widget.find(".logout-button-separator").toggle(!isElectron);
|
||||||
|
|
||||||
|
@ -30,19 +30,14 @@ const TPL = `
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-bar-buttons .top-btn.active{
|
|
||||||
background-color:var(--accented-background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-bar-buttons .btn.focus, .title-bar-buttons .btn:focus {
|
.title-bar-buttons .btn.focus, .title-bar-buttons .btn:focus {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- divs act as a hitbox for the buttons, making them clickable on corners -->
|
<!-- divs act as a hitbox for the buttons, making them clickable on corners -->
|
||||||
<div class="top-btn" title="${t("title_bar_buttons.window-on-top")}"><button class="btn bx bx-pin"></button></div>
|
|
||||||
<div class="minimize-btn"><button class="btn bx bx-minus"></button></div>
|
<div class="minimize-btn"><button class="btn bx bx-minus"></button></div>
|
||||||
<div class="maximize-btn"><button class="btn bx bx-checkbox"></button></div>
|
<div class="maximize-btn"><button class="btn bx bx-checkbox"></button></div>
|
||||||
<div class="close-btn"><button class="btn bx bx-x"></button></div>
|
<div class="close-btn"><button class="btn bx bx-x"></button></div>
|
||||||
@ -56,35 +51,11 @@ export default class TitleBarButtonsWidget extends BasicWidget {
|
|||||||
|
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.contentSized();
|
this.contentSized();
|
||||||
|
|
||||||
const $topBtn = this.$widget.find(".top-btn");
|
|
||||||
const $minimizeBtn = this.$widget.find(".minimize-btn");
|
const $minimizeBtn = this.$widget.find(".minimize-btn");
|
||||||
const $maximizeBtn = this.$widget.find(".maximize-btn");
|
const $maximizeBtn = this.$widget.find(".maximize-btn");
|
||||||
const $closeBtn = this.$widget.find(".close-btn");
|
const $closeBtn = this.$widget.find(".close-btn");
|
||||||
|
|
||||||
// When the window is restarted, the window will not be reset when it is set to the top,
|
|
||||||
// so get the window status and set the icon background
|
|
||||||
setTimeout(() => {
|
|
||||||
const remote = utils.dynamicRequire('@electron/remote');
|
|
||||||
if (remote.BrowserWindow.getFocusedWindow()?.isAlwaysOnTop()) {
|
|
||||||
$topBtn.addClass('active');
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
$topBtn.on('click', () => {
|
|
||||||
$topBtn.trigger('blur');
|
|
||||||
const remote = utils.dynamicRequire('@electron/remote');
|
|
||||||
const focusedWindow = remote.BrowserWindow.getFocusedWindow();
|
|
||||||
const isAlwaysOnTop = focusedWindow.isAlwaysOnTop()
|
|
||||||
if (isAlwaysOnTop) {
|
|
||||||
focusedWindow.setAlwaysOnTop(false)
|
|
||||||
$topBtn.removeClass('active');
|
|
||||||
} else {
|
|
||||||
focusedWindow.setAlwaysOnTop(true);
|
|
||||||
$topBtn.addClass('active');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$minimizeBtn.on('click', () => {
|
$minimizeBtn.on('click', () => {
|
||||||
$minimizeBtn.trigger('blur');
|
$minimizeBtn.trigger('blur');
|
||||||
const remote = utils.dynamicRequire('@electron/remote');
|
const remote = utils.dynamicRequire('@electron/remote');
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--submenu-opening-delay: 300ms;
|
--submenu-opening-delay: 300ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
@ -38,6 +38,15 @@ body {
|
|||||||
color: var(--main-text-color);
|
color: var(--main-text-color);
|
||||||
font-family: var(--main-font-family);
|
font-family: var(--main-font-family);
|
||||||
font-size: var(--main-font-size);
|
font-size: var(--main-font-size);
|
||||||
|
|
||||||
|
--native-titlebar-background: var(--main-background-color);
|
||||||
|
--native-titlebar-foreground: var(--main-text-color);
|
||||||
|
--native-titlebar-darwin-x-offset: 10;
|
||||||
|
--native-titlebar-darwin-y-offset: 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.layout-horizontal {
|
||||||
|
--native-titlebar-background: var(--left-pane-background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.mobile .desktop-only {
|
body.mobile .desktop-only {
|
||||||
@ -1273,6 +1282,19 @@ textarea {
|
|||||||
color: var(--muted-text-color);
|
color: var(--muted-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.electron.platform-darwin:not(.native-titlebar) .tab-row-container {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab-row-left-spacer {
|
||||||
|
width: env(titlebar-area-x);
|
||||||
|
-webkit-app-region: drag;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-row-container {
|
||||||
|
margin-right: calc(100vw - env(titlebar-area-width, 100vw));
|
||||||
|
}
|
||||||
|
|
||||||
.tab-row-container .toggle-button {
|
.tab-row-container .toggle-button {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
:root {
|
:root {
|
||||||
/* --main-font-family: "Noto Sans", sans-serif; */
|
/* --main-font-family: "Noto Sans", sans-serif; */
|
||||||
--main-font-family: "Ubuntu Sans", sans-serif;
|
--main-font-family: "Segoe UI", sans-serif;
|
||||||
/* --main-font-family: "Ubuntu", sans-serif; */
|
/* --main-font-family: "Ubuntu", sans-serif; */
|
||||||
/* --main-font-family: "Nunito", sans-serif; */
|
/* --main-font-family: "Nunito", sans-serif; */
|
||||||
/* --main-font-family: "Inter", sans-serif; */
|
/* --main-font-family: "Inter", sans-serif; */
|
||||||
@ -392,12 +392,24 @@
|
|||||||
background-color: var(--root-background);
|
background-color: var(--root-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
#root-widget.horizontal-layout {
|
body {
|
||||||
|
--native-titlebar-darwin-x-offset: 10;
|
||||||
|
--native-titlebar-darwin-y-offset: 17 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.layout-vertical {
|
||||||
|
--native-titlebar-background: var(--root-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.layout-horizontal {
|
||||||
--launcher-pane-background-color: var(--launcher-pane-horizontal-background-color);
|
--launcher-pane-background-color: var(--launcher-pane-horizontal-background-color);
|
||||||
--launcher-pane-size: var(--launcher-pane-horizontal-size);
|
--launcher-pane-size: var(--launcher-pane-horizontal-size);
|
||||||
--active-tab-background-color: var(--launcher-pane-background-color);
|
--active-tab-background-color: var(--launcher-pane-background-color);
|
||||||
--active-tab-hover-background-color: var(--active-tab-background-color);
|
--active-tab-hover-background-color: var(--active-tab-background-color);
|
||||||
--new-tab-button-background: transparent;
|
--new-tab-button-background: transparent;
|
||||||
|
--tab-bar-height: 44px;
|
||||||
|
--native-titlebar-darwin-x-offset: 12;
|
||||||
|
--native-titlebar-darwin-y-offset: 14 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Matches when the left pane is collapsed */
|
/* Matches when the left pane is collapsed */
|
||||||
@ -426,7 +438,7 @@
|
|||||||
* Launcher pane
|
* Launcher pane
|
||||||
*/
|
*/
|
||||||
#launcher-container,
|
#launcher-container,
|
||||||
#root-widget.horizontal-layout > .horizontal {
|
body.layout-horizontal > .horizontal {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -796,7 +808,7 @@ div.quick-search .search-button.show {
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
#root-widget.horizontal-layout .tab-row-container:after {
|
body.layout-horizontal .tab-row-container:after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@ -806,16 +818,20 @@ div.quick-search .search-button.show {
|
|||||||
border-bottom: 1px solid var(--launcher-pane-horizontal-border-color);
|
border-bottom: 1px solid var(--launcher-pane-horizontal-border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.layout-vertical.electron.platform-darwin .tab-row-container {
|
||||||
|
border-bottom: 1px solid var(--subtle-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
.tab-row-widget-container {
|
.tab-row-widget-container {
|
||||||
margin-top: calc((var(--tab-bar-height) - var(--tab-height)) / 2);
|
margin-top: calc((var(--tab-bar-height) - var(--tab-height)) / 2);
|
||||||
height: var(--tab-height) !important;
|
height: var(--tab-height) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#root-widget.horizontal-layout .tab-row-container {
|
body.layout-horizontal .tab-row-container {
|
||||||
padding-top: calc((var(--tab-bar-height) - var(--tab-height)));
|
padding-top: calc((var(--tab-bar-height) - var(--tab-height)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#root-widget.horizontal-layout .tab-row-widget-container {
|
body.layout-horizontal .tab-row-widget-container {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -842,7 +858,11 @@ div.quick-search .search-button.show {
|
|||||||
transition: none;
|
transition: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#root-widget.horizontal-layout .tab-row-widget .note-tab .note-tab-wrapper {
|
.tab-row-container .title-bar-buttons {
|
||||||
|
margin-top: calc((var(--tab-bar-height) - var(--tab-height)) * -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.layout-horizontal .tab-row-widget .note-tab .note-tab-wrapper {
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
@ -1407,7 +1407,7 @@
|
|||||||
"saved-search-note-refreshed": "Gespeicherte Such-Notiz wurde aktualisiert."
|
"saved-search-note-refreshed": "Gespeicherte Such-Notiz wurde aktualisiert."
|
||||||
},
|
},
|
||||||
"title_bar_buttons": {
|
"title_bar_buttons": {
|
||||||
"window-on-top": "Dieses Fenster immer oben halten."
|
"window-on-top": "Dieses Fenster immer oben halten"
|
||||||
},
|
},
|
||||||
"note_detail": {
|
"note_detail": {
|
||||||
"could_not_find_typewidget": "Konnte typeWidget für Typ ‚{{type}}‘ nicht finden"
|
"could_not_find_typewidget": "Konnte typeWidget für Typ ‚{{type}}‘ nicht finden"
|
||||||
|
@ -1434,7 +1434,7 @@
|
|||||||
"saved-search-note-refreshed": "Saved search note refreshed."
|
"saved-search-note-refreshed": "Saved search note refreshed."
|
||||||
},
|
},
|
||||||
"title_bar_buttons": {
|
"title_bar_buttons": {
|
||||||
"window-on-top": "Keep this window on top."
|
"window-on-top": "Keep Window on Top"
|
||||||
},
|
},
|
||||||
"note_detail": {
|
"note_detail": {
|
||||||
"could_not_find_typewidget": "Could not find typeWidget for type '{{type}}'"
|
"could_not_find_typewidget": "Could not find typeWidget for type '{{type}}'"
|
||||||
|
@ -1432,7 +1432,7 @@
|
|||||||
"saved-search-note-refreshed": "La nota de búsqueda guardada fue recargada."
|
"saved-search-note-refreshed": "La nota de búsqueda guardada fue recargada."
|
||||||
},
|
},
|
||||||
"title_bar_buttons": {
|
"title_bar_buttons": {
|
||||||
"window-on-top": "Mantener esta ventana en la parte superior."
|
"window-on-top": "Mantener esta ventana en la parte superior"
|
||||||
},
|
},
|
||||||
"note_detail": {
|
"note_detail": {
|
||||||
"could_not_find_typewidget": "No se pudo encontrar typeWidget para el tipo '{{type}}'"
|
"could_not_find_typewidget": "No se pudo encontrar typeWidget para el tipo '{{type}}'"
|
||||||
|
@ -1408,7 +1408,7 @@
|
|||||||
"saved-search-note-refreshed": "Note de recherche enregistrée actualisée."
|
"saved-search-note-refreshed": "Note de recherche enregistrée actualisée."
|
||||||
},
|
},
|
||||||
"title_bar_buttons": {
|
"title_bar_buttons": {
|
||||||
"window-on-top": "Épingler cette fenêtre au premier plan."
|
"window-on-top": "Épingler cette fenêtre au premier plan"
|
||||||
},
|
},
|
||||||
"note_detail": {
|
"note_detail": {
|
||||||
"could_not_find_typewidget": "Impossible de trouver typeWidget pour le type '{{type}}'"
|
"could_not_find_typewidget": "Impossible de trouver typeWidget pour le type '{{type}}'"
|
||||||
|
@ -28,10 +28,15 @@ function index(req: Request, res: Response) {
|
|||||||
// The page is restored from cache, but the API call fail.
|
// The page is restored from cache, but the API call fail.
|
||||||
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||||
|
|
||||||
|
const isElectron = utils.isElectron();
|
||||||
res.render(view, {
|
res.render(view, {
|
||||||
csrfToken: csrfToken,
|
csrfToken: csrfToken,
|
||||||
themeCssUrl: getThemeCssUrl(options.theme),
|
themeCssUrl: getThemeCssUrl(options.theme),
|
||||||
headingStyle: options.headingStyle,
|
headingStyle: options.headingStyle,
|
||||||
|
layoutOrientation: options.layoutOrientation,
|
||||||
|
platform: process.platform,
|
||||||
|
isElectron,
|
||||||
|
hasNativeTitleBar: (isElectron && options.nativeTitleBarVisible === "true"),
|
||||||
mainFontSize: parseInt(options.mainFontSize),
|
mainFontSize: parseInt(options.mainFontSize),
|
||||||
treeFontSize: parseInt(options.treeFontSize),
|
treeFontSize: parseInt(options.treeFontSize),
|
||||||
detailFontSize: parseInt(options.detailFontSize),
|
detailFontSize: parseInt(options.detailFontSize),
|
||||||
|
@ -8,7 +8,7 @@ import sqlInit from "./sql_init.js";
|
|||||||
import cls from "./cls.js";
|
import cls from "./cls.js";
|
||||||
import keyboardActionsService from "./keyboard_actions.js";
|
import keyboardActionsService from "./keyboard_actions.js";
|
||||||
import remoteMain from "@electron/remote/main/index.js";
|
import remoteMain from "@electron/remote/main/index.js";
|
||||||
import { App, BrowserWindow, WebContents, ipcMain } from 'electron';
|
import { App, BrowserWindow, BrowserWindowConstructorOptions, WebContents, ipcMain } from 'electron';
|
||||||
|
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
import { dirname } from "path";
|
import { dirname } from "path";
|
||||||
@ -31,7 +31,7 @@ async function createExtraWindow(extraWindowHash: string) {
|
|||||||
contextIsolation: false,
|
contextIsolation: false,
|
||||||
spellcheck: spellcheckEnabled
|
spellcheck: spellcheckEnabled
|
||||||
},
|
},
|
||||||
frame: optionService.getOptionBool('nativeTitleBarVisible'),
|
...getWindowExtraOpts(),
|
||||||
icon: getIcon()
|
icon: getIcon()
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -71,6 +71,8 @@ async function createMainWindow(app: App) {
|
|||||||
|
|
||||||
const { BrowserWindow } = (await import('electron')); // should not be statically imported
|
const { BrowserWindow } = (await import('electron')); // should not be statically imported
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mainWindow = new BrowserWindow({
|
mainWindow = new BrowserWindow({
|
||||||
x: mainWindowState.x,
|
x: mainWindowState.x,
|
||||||
y: mainWindowState.y,
|
y: mainWindowState.y,
|
||||||
@ -82,9 +84,9 @@ async function createMainWindow(app: App) {
|
|||||||
contextIsolation: false,
|
contextIsolation: false,
|
||||||
spellcheck: spellcheckEnabled,
|
spellcheck: spellcheckEnabled,
|
||||||
webviewTag: true
|
webviewTag: true
|
||||||
},
|
},
|
||||||
frame: optionService.getOptionBool('nativeTitleBarVisible'),
|
icon: getIcon(),
|
||||||
icon: getIcon()
|
...getWindowExtraOpts()
|
||||||
});
|
});
|
||||||
|
|
||||||
mainWindowState.manage(mainWindow);
|
mainWindowState.manage(mainWindow);
|
||||||
@ -110,6 +112,28 @@ async function createMainWindow(app: App) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getWindowExtraOpts() {
|
||||||
|
const extraOpts: Partial<BrowserWindowConstructorOptions> = {};
|
||||||
|
|
||||||
|
const isMac = (process.platform === "darwin");
|
||||||
|
const isWindows = (process.platform === "win32");
|
||||||
|
|
||||||
|
if (!optionService.getOptionBool('nativeTitleBarVisible')) {
|
||||||
|
if (isMac) {
|
||||||
|
extraOpts.titleBarStyle = "hiddenInset";
|
||||||
|
extraOpts.titleBarOverlay = true;
|
||||||
|
} else if (isWindows) {
|
||||||
|
extraOpts.titleBarStyle = "hidden";
|
||||||
|
extraOpts.titleBarOverlay = true;
|
||||||
|
} else {
|
||||||
|
// Linux or other platforms.
|
||||||
|
extraOpts.frame = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return extraOpts;
|
||||||
|
}
|
||||||
|
|
||||||
function configureWebContents(webContents: WebContents, spellcheckEnabled: boolean) {
|
function configureWebContents(webContents: WebContents, spellcheckEnabled: boolean) {
|
||||||
remoteMain.enable(webContents);
|
remoteMain.enable(webContents);
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<link rel="manifest" crossorigin="use-credentials" href="manifest.webmanifest">
|
<link rel="manifest" crossorigin="use-credentials" href="manifest.webmanifest">
|
||||||
<title>TriliumNext Notes</title>
|
<title>TriliumNext Notes</title>
|
||||||
</head>
|
</head>
|
||||||
<body class="desktop heading-style-<%= headingStyle %>">
|
<body class="desktop heading-style-<%= headingStyle %> layout-<%= layoutOrientation %> platform-<%= platform %> <%= isElectron ? 'electron' : '' %> <%= hasNativeTitleBar ? 'native-titlebar' : '' %>">
|
||||||
<noscript><%= t("javascript-required") %></noscript>
|
<noscript><%= t("javascript-required") %></noscript>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -36,6 +36,8 @@
|
|||||||
triliumVersion: "<%= triliumVersion %>",
|
triliumVersion: "<%= triliumVersion %>",
|
||||||
assetPath: "<%= assetPath %>",
|
assetPath: "<%= assetPath %>",
|
||||||
appPath: "<%= appPath %>",
|
appPath: "<%= appPath %>",
|
||||||
|
platform: "<%= platform %>",
|
||||||
|
hasNativeTitleBar: <%= hasNativeTitleBar %>,
|
||||||
TRILIUM_SAFE_MODE: <%= !!process.env.TRILIUM_SAFE_MODE %>
|
TRILIUM_SAFE_MODE: <%= !!process.env.TRILIUM_SAFE_MODE %>
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@ -84,5 +86,5 @@
|
|||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="<%= assetPath %>/node_modules/boxicons/css/boxicons.min.css">
|
<link rel="stylesheet" type="text/css" href="<%= assetPath %>/node_modules/boxicons/css/boxicons.min.css">
|
||||||
|
|
||||||
</body>
|
</>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user