Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/TriliumNext/Notes into d…
Browse files Browse the repository at this point in the history
…evelop
  • Loading branch information
adoriandoran committed Dec 6, 2024
2 parents 501cac3 + 774c267 commit bb07b04
Show file tree
Hide file tree
Showing 13 changed files with 175 additions and 59 deletions.
41 changes: 39 additions & 2 deletions src/public/app/desktop.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import macInit from './services/mac_init.js';
import electronContextMenu from "./menus/electron_context_menu.js";
import glob from "./services/glob.js";
import { t } from "./services/i18n.js";
import options from "./services/options.js";

await appContext.earlyInit();

Expand All @@ -30,8 +31,7 @@ bundleService.getWidgetBundlesByParent().then(async widgetBundles => {
glob.setupGlobs();

if (utils.isElectron()) {
utils.dynamicRequire('electron').ipcRenderer.on('globalShortcut',
async (event, actionName) => appContext.triggerCommand(actionName));
initOnElectron();
}

macInit.init();
Expand All @@ -43,3 +43,40 @@ noteAutocompleteService.init();
if (utils.isElectron()) {
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 });
}
}
25 changes: 19 additions & 6 deletions src/public/app/layouts/desktop_layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import CopyImageReferenceButton from "../widgets/floating_buttons/copy_image_ref
import ScrollPaddingWidget from "../widgets/scroll_padding.js";
import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js";
import options from "../services/options.js";
import utils from "../services/utils.js";

export default class DesktopLayout {
constructor(customWidgets) {
Expand All @@ -95,15 +96,27 @@ export default class DesktopLayout {

const launcherPaneIsHorizontal = (options.get("layoutOrientation") === "horizontal");
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)
.class((launcherPaneIsHorizontal ? "horizontal" : "vertical") + "-layout")
.optChild(launcherPaneIsHorizontal, new FlexContainer('row')
.optChild(fullWidthTabBar, new FlexContainer('row')
.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 TitleBarButtonsWidget())
.optChild(customTitleBarButtons, new TitleBarButtonsWidget())
.css('height', '40px')
.css('background-color', 'var(--launcher-pane-background-color)')
.setParent(appContext)
Expand All @@ -120,9 +133,9 @@ export default class DesktopLayout {
.child(new FlexContainer('column')
.id('rest-pane')
.css("flex-grow", "1")
.optChild(!launcherPaneIsHorizontal, new FlexContainer('row')
.optChild(!fullWidthTabBar, new FlexContainer('row')
.child(new TabRowWidget())
.child(new TitleBarButtonsWidget())
.optChild(customTitleBarButtons, new TitleBarButtonsWidget())
.css('height', '40px')
)
.child(new FlexContainer('row')
Expand Down
22 changes: 22 additions & 0 deletions src/public/app/widgets/buttons/global_menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ const TPL = `
</div>
</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>
<li class="dropdown-item switch-to-mobile-version-button" data-trigger-command="switchToMobileVersion">
Expand Down Expand Up @@ -294,6 +299,23 @@ export default class GlobalMenuWidget extends BasicWidget {

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-separator").toggle(!isElectron);

Expand Down
35 changes: 3 additions & 32 deletions src/public/app/widgets/title_bar_buttons.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,14 @@ const TPL = `
display: inline-block;
height: 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 {
box-shadow: none;
}
</style>
<!-- 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>
<!-- divs act as a hitbox for the buttons, making them clickable on corners -->
<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="close-btn"><button class="btn bx bx-x"></button></div>
Expand All @@ -56,35 +51,11 @@ export default class TitleBarButtonsWidget extends BasicWidget {

this.$widget = $(TPL);
this.contentSized();

const $topBtn = this.$widget.find(".top-btn");

const $minimizeBtn = this.$widget.find(".minimize-btn");
const $maximizeBtn = this.$widget.find(".maximize-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.trigger('blur');
const remote = utils.dynamicRequire('@electron/remote');
Expand Down
24 changes: 23 additions & 1 deletion src/public/stylesheets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
}

:root {
--submenu-opening-delay: 300ms;
--submenu-opening-delay: 300ms;
}

html {
Expand All @@ -38,6 +38,15 @@ body {
color: var(--main-text-color);
font-family: var(--main-font-family);
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 {
Expand Down Expand Up @@ -1273,6 +1282,19 @@ textarea {
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 {
padding-right: calc(100vw - env(titlebar-area-width, 100vw));
}

.tab-row-container .toggle-button {
background: transparent;
appearance: none;
Expand Down
34 changes: 27 additions & 7 deletions src/public/stylesheets/theme-next.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

:root {
/* --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: "Nunito", sans-serif; */
/* --main-font-family: "Inter", sans-serif; */
Expand Down Expand Up @@ -392,12 +392,24 @@
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-size: var(--launcher-pane-horizontal-size);
--active-tab-background-color: var(--launcher-pane-background-color);
--active-tab-hover-background-color: var(--active-tab-background-color);
--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 */
Expand Down Expand Up @@ -426,7 +438,7 @@
* Launcher pane
*/
#launcher-container,
#root-widget.horizontal-layout > .horizontal {
body.layout-horizontal > .horizontal {
align-items: center;
}

Expand Down Expand Up @@ -837,7 +849,7 @@ div.quick-search .search-button.show {
position: relative;
}

#root-widget.horizontal-layout .tab-row-container:after {
body.layout-horizontal .tab-row-container:after {
content: "";
position: absolute;
bottom: 0;
Expand All @@ -847,16 +859,20 @@ div.quick-search .search-button.show {
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 {
margin-top: calc((var(--tab-bar-height) - var(--tab-height)) / 2);
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)));
}

#root-widget.horizontal-layout .tab-row-widget-container {
body.layout-horizontal .tab-row-widget-container {
margin-top: 0;
position: relative;
overflow: hidden;
Expand All @@ -883,7 +899,11 @@ div.quick-search .search-button.show {
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-right-radius: 0;
}
Expand Down
2 changes: 1 addition & 1 deletion src/public/translations/de/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1407,7 +1407,7 @@
"saved-search-note-refreshed": "Gespeicherte Such-Notiz wurde aktualisiert."
},
"title_bar_buttons": {
"window-on-top": "Dieses Fenster immer oben halten."
"window-on-top": "Dieses Fenster immer oben halten"
},
"note_detail": {
"could_not_find_typewidget": "Konnte typeWidget für Typ ‚{{type}}‘ nicht finden"
Expand Down
2 changes: 1 addition & 1 deletion src/public/translations/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1434,7 +1434,7 @@
"saved-search-note-refreshed": "Saved search note refreshed."
},
"title_bar_buttons": {
"window-on-top": "Keep this window on top."
"window-on-top": "Keep Window on Top"
},
"note_detail": {
"could_not_find_typewidget": "Could not find typeWidget for type '{{type}}'"
Expand Down
2 changes: 1 addition & 1 deletion src/public/translations/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1432,7 +1432,7 @@
"saved-search-note-refreshed": "La nota de búsqueda guardada fue recargada."
},
"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": {
"could_not_find_typewidget": "No se pudo encontrar typeWidget para el tipo '{{type}}'"
Expand Down
2 changes: 1 addition & 1 deletion src/public/translations/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1408,7 +1408,7 @@
"saved-search-note-refreshed": "Note de recherche enregistrée actualisée."
},
"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": {
"could_not_find_typewidget": "Impossible de trouver typeWidget pour le type '{{type}}'"
Expand Down
5 changes: 5 additions & 0 deletions src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,15 @@ function index(req: Request, res: Response) {
// The page is restored from cache, but the API call fail.
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");

const isElectron = utils.isElectron();
res.render(view, {
csrfToken: csrfToken,
themeCssUrl: getThemeCssUrl(options.theme),
headingStyle: options.headingStyle,
layoutOrientation: options.layoutOrientation,
platform: process.platform,
isElectron,
hasNativeTitleBar: (isElectron && options.nativeTitleBarVisible === "true"),
mainFontSize: parseInt(options.mainFontSize),
treeFontSize: parseInt(options.treeFontSize),
detailFontSize: parseInt(options.detailFontSize),
Expand Down
Loading

0 comments on commit bb07b04

Please sign in to comment.