Skip to content

Commit 2cf988f

Browse files
committed
Setting of blur
1 parent eeb8869 commit 2cf988f

10 files changed

Lines changed: 102 additions & 44 deletions

File tree

src-main/index.js

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
const {app, nativeTheme} = require('electron');
2-
3-
// Force dark theme on Windows for acrylic effect (doesn't follow system)
4-
if (process.platform === 'win32') {
5-
nativeTheme.themeSource = 'dark';
6-
}
1+
const { app } = require('electron');
72

83
// requestSingleInstanceLock() crashes the app in signed MAS builds
94
// https://github.com/electron/electron/issues/15958
@@ -14,8 +9,8 @@ if (!process.mas && !app.requestSingleInstanceLock()) {
149
const path = require('path');
1510
const AbstractWindow = require('./windows/abstract');
1611
const EditorWindow = require('./windows/editor');
17-
const {checkForUpdates} = require('./update-checker');
18-
const {tranlateOrNull} = require('./l10n');
12+
const { checkForUpdates } = require('./update-checker');
13+
const { tranlateOrNull } = require('./l10n');
1914
const migrate = require('./migrate');
2015
const settings = require('./settings');
2116
require('./protocols');

src-main/l10n/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,10 @@
263263
"string": "Exit F11 fullscreen mode (not the fullscreen button in the editor) when pressing escape",
264264
"developer_comment": "Refering to when an entire window is in fullscreen by pressing F11 or the maximize button on macOS, not the fullscreen mode you get by pressing the fullscreen button in the editor."
265265
},
266+
"desktop-settings.useBlurBackground": {
267+
"string": "Enable window background blur (Windows only)",
268+
"developer_comment": "Show beautiful effect on the Window background."
269+
},
266270
"desktop-settings.rich-presence": {
267271
"string": "Enable Rich Presence",
268272
"developer_comment": "Option to enable Discord Rich Presence support, which shows the name of the project someone is editing on their Discord profile. For compliance with Scratch policies don't use the word \"Discord\" in the translation."

src-main/l10n/generated-translations.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1781,6 +1781,7 @@
17811781
"desktop-settings.editor-must-be-open": "错误:请打开编辑器配置媒体设备",
17821782
"desktop-settings.error": "错误:{error}",
17831783
"desktop-settings.exit-fullscreen-on-escape": "当按下 Esc 键时,退出 F11 全屏模式(不是编辑器全屏)",
1784+
"desktop-settings.useBlurBackground": "启用窗口背景模糊(只支持Windows)",
17841785
"desktop-settings.hardware-acceleration": "启用图形加速(重启后生效)",
17851786
"desktop-settings.hardware-acceleration-disabled": "禁用图形加速会显著降低性能。某些项目的运行速度可能下降100倍以上,因为所有渲染工作都将转由CPU承担。只有当图形加速导致程序崩溃时,才应将此作为最后的手段。",
17861787
"desktop-settings.hardware-acceleration-when-available": "在可用时启用图形加速(重启后生效)",

src-main/settings.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,13 @@ class Settings {
177177
set richPresence (richPresence) {
178178
this.data.richPresence = richPresence;
179179
}
180+
181+
get useBlurBackground() {
182+
return this.data.useBlurBackground !== false;
183+
}
184+
set useBlurBackground(useBlurBackground) {
185+
this.data.useBlurBackground = useBlurBackground;
186+
}
180187
}
181188

182189
module.exports = new Settings();

src-main/update-checker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const currentVersion = packageJSON.version;
88
const getRepositoryInfo = () => {
99
const fallback = {
1010
owner: 'AstraEditor',
11-
repo: 'desktop'
11+
repo: 'Desktop'
1212
};
1313

1414
const repositoryURL = packageJSON?.repository?.url;

src-main/windows/desktop-settings.js

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
const {app, shell} = require('electron');
1+
const { app, shell, nativeTheme } = require('electron');
22
const AbstractWindow = require('./abstract');
3-
const {translate, getStrings, getLocale} = require('../l10n');
4-
const {APP_NAME} = require('../brand');
3+
const { translate, getStrings, getLocale } = require('../l10n');
4+
const { APP_NAME } = require('../brand');
55
const settings = require('../settings');
6-
const {isUpdateCheckerAllowed} = require('../update-checker');
6+
const { isUpdateCheckerAllowed } = require('../update-checker');
77
const RichPresence = require('../rich-presence');
88

99
class DesktopSettingsWindow extends AbstractWindow {
10-
constructor () {
10+
constructor() {
1111
super();
1212

1313
this.window.setTitle(`${translate('desktop-settings.title')} - ${APP_NAME}`);
@@ -28,6 +28,7 @@ class DesktopSettingsWindow extends AbstractWindow {
2828
bypassCORS: settings.bypassCORS,
2929
spellchecker: settings.spellchecker,
3030
exitFullscreenOnEscape: settings.exitFullscreenOnEscape,
31+
useBlurBackground: settings.useBlurBackground,
3132
richPresenceAvailable: RichPresence.isAvailable(),
3233
richPresence: settings.richPresence
3334
}
@@ -89,8 +90,8 @@ class DesktopSettingsWindow extends AbstractWindow {
8990

9091
this.ipc.handle('set-rich-presence', async (event, richPresence) => {
9192
settings.richPresence = richPresence;
92-
if (richPresence) {
93-
RichPresence.enable();
93+
if (richPrece) {
94+
RichPresencesen.enable();
9495
} else {
9596
RichPresence.disable();
9697
}
@@ -101,25 +102,36 @@ class DesktopSettingsWindow extends AbstractWindow {
101102
shell.showItemInFolder(app.getPath('userData'));
102103
});
103104

105+
this.ipc.handle('use-blur-background', async (event, useBlurBackground) => {
106+
settings.useBlurBackground = useBlurBackground;
107+
await settings.save();
108+
109+
const EditorWindow = require('./editor');
110+
const editorWindows = AbstractWindow.getWindowsByClass(EditorWindow);
111+
for (const win of editorWindows) {
112+
win.updateBlurBackground(useBlurBackground);
113+
}
114+
})
115+
104116
this.loadURL('tw-desktop-settings://./desktop-settings.html');
105117
}
106118

107-
getDimensions () {
119+
getDimensions() {
108120
return {
109121
width: 550,
110122
height: 500
111123
};
112124
}
113125

114-
getPreload () {
126+
getPreload() {
115127
return 'desktop-settings';
116128
}
117129

118-
isPopup () {
130+
isPopup() {
119131
return true;
120132
}
121133

122-
static show () {
134+
static show() {
123135
const window = AbstractWindow.singleton(DesktopSettingsWindow);
124136
window.show();
125137
}

src-main/windows/editor.js

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ const path = require('path');
33
const nodeURL = require('url');
44
const zlib = require('zlib');
55
const nodeCrypto = require('crypto');
6-
const {app, dialog} = require('electron');
6+
const { app, dialog, nativeTheme } = require('electron');
77
const ProjectRunningWindow = require('./project-running-window');
88
const AddonsWindow = require('./addons');
99
const DesktopSettingsWindow = require('./desktop-settings');
1010
const PrivacyWindow = require('./privacy');
1111
const AboutWindow = require('./about');
1212
const PackagerWindow = require('./packager');
13-
const {createAtomicWriteStream} = require('../atomic-write-stream');
14-
const {translate, updateLocale, getStrings} = require('../l10n');
15-
const {APP_NAME} = require('../brand');
13+
const { createAtomicWriteStream } = require('../atomic-write-stream');
14+
const { translate, updateLocale, getStrings } = require('../l10n');
15+
const { APP_NAME } = require('../brand');
1616
const prompts = require('../prompts');
1717
const settings = require('../settings');
1818
const privilegedFetch = require('../fetch');
@@ -68,7 +68,7 @@ const getCachedExtensionsRedirect = (input) => {
6868
};
6969

7070
class OpenedFile {
71-
constructor (type, path) {
71+
constructor(type, path) {
7272
/** @type {TYPE_FILE|TYPE_URL|TYPE_SCRATCH|TYPE_SAMPLE|TYPE_SAMPLE_ASTRA} */
7373
this.type = type;
7474

@@ -79,7 +79,7 @@ class OpenedFile {
7979
this.path = path;
8080
}
8181

82-
async read () {
82+
async read() {
8383
if (this.type === TYPE_FILE) {
8484
return {
8585
name: path.basename(this.path),
@@ -273,7 +273,7 @@ class EditorWindow extends ProjectRunningWindow {
273273
* @param {OpenedFile|null} initialFile
274274
* @param {boolean} isInitiallyFullscreen
275275
*/
276-
constructor (initialFile, isInitiallyFullscreen) {
276+
constructor(initialFile, isInitiallyFullscreen) {
277277
super();
278278

279279
/**
@@ -369,7 +369,7 @@ class EditorWindow extends ProjectRunningWindow {
369369

370370
this.ipc.handle('get-file', async (event, id) => {
371371
const file = getFileById(id);
372-
const {name, data} = await file.read();
372+
const { name, data } = await file.read();
373373
return {
374374
name,
375375
type: file.type,
@@ -468,7 +468,7 @@ class EditorWindow extends ProjectRunningWindow {
468468
.replace('{APP_NAME}', unsafePath.app)
469469
.replace('{file}', filePath),
470470
noLink: true
471-
});
471+
});
472472
return null;
473473
}
474474

@@ -668,35 +668,44 @@ class EditorWindow extends ProjectRunningWindow {
668668
this.isInEditorFullScreen = !!isFullScreen;
669669
});
670670

671+
this.ipc.handle('set-window-theme', (event, theme) => {
672+
if (process.platform === 'win32') {
673+
if (theme === 'light' || theme === 'dark') {
674+
nativeTheme.themeSource = theme;
675+
} else {
676+
nativeTheme.themeSource = 'dark'; // default
677+
}
678+
}
679+
});
680+
671681
this.loadURL('tw-editor://./gui/gui.html');
672682
this.show();
673683

674684
// Windows acrylic blur effect (theme controlled by nativeTheme.themeSource in index.js)
675-
if (process.platform === 'win32') {
685+
if (process.platform === 'win32' && settings.useBlurBackground) {
676686
this.window.setBackgroundMaterial('acrylic');
677687
}
678688
}
679689

680-
getPreload () {
690+
getPreload() {
681691
return 'editor';
682692
}
683693

684-
getDimensions () {
694+
getDimensions() {
685695
return {
686696
width: 1280,
687697
height: 800
688698
};
689699
}
690700

691-
getBackgroundColor () {
692-
// Windows acrylic handles background, return solid color for animations
701+
getBackgroundColor() {
693702
if (process.platform === 'win32') {
694703
return '#333333';
695704
}
696705
return '#33333300';
697706
}
698707

699-
getWindowOptions () {
708+
getWindowOptions() {
700709
const options = super.getWindowOptions();
701710
options.frame = false;
702711
options.minWidth = 1024;
@@ -712,19 +721,28 @@ class EditorWindow extends ProjectRunningWindow {
712721
// Windows uses setBackgroundMaterial instead of transparent
713722
if (process.platform === 'win32') {
714723
options.transparent = false;
715-
options.backgroundColor = '#333333';
716724
} else {
717725
options.transparent = true;
718726
}
719727

720728
return options;
721729
}
722730

723-
applySettings () {
731+
applySettings() {
724732
this.window.webContents.setBackgroundThrottling(settings.backgroundThrottling);
725733
}
726734

727-
enumerateMediaDevices () {
735+
updateBlurBackground(useBlurBackground) {
736+
if (process.platform !== 'win32') return;
737+
738+
if (useBlurBackground) {
739+
this.window.setBackgroundMaterial('acrylic');
740+
} else {
741+
this.window.setBackgroundMaterial('none');
742+
}
743+
}
744+
745+
enumerateMediaDevices() {
728746
// Used by desktop settings
729747
return new Promise((resolve, reject) => {
730748
this.ipc.once('enumerated-media-devices', (event, result) => {
@@ -738,7 +756,7 @@ class EditorWindow extends ProjectRunningWindow {
738756
});
739757
}
740758

741-
handleWindowOpen (details) {
759+
handleWindowOpen(details) {
742760
const url = new URL(details.url);
743761
const params = new URLSearchParams(url.search);
744762

@@ -786,11 +804,11 @@ class EditorWindow extends ProjectRunningWindow {
786804
return super.handleWindowOpen(details);
787805
}
788806

789-
canExitFullscreenByPressingEscape () {
807+
canExitFullscreenByPressingEscape() {
790808
return !this.isInEditorFullScreen;
791809
}
792810

793-
updateRichPresence () {
811+
updateRichPresence() {
794812
RichPresence.setActivity(this.projectTitle, this.openedProjectAt);
795813
}
796814

@@ -799,7 +817,7 @@ class EditorWindow extends ProjectRunningWindow {
799817
* @param {boolean} fullscreen
800818
* @param {string|null} workingDirectory
801819
*/
802-
static openFiles (files, fullscreen, workingDirectory) {
820+
static openFiles(files, fullscreen, workingDirectory) {
803821
if (files.length === 0) {
804822
EditorWindow.newWindow(fullscreen);
805823
} else {
@@ -813,7 +831,7 @@ class EditorWindow extends ProjectRunningWindow {
813831
* Open a new window with the default project.
814832
* @param {boolean} fullscreen
815833
*/
816-
static newWindow (fullscreen) {
834+
static newWindow(fullscreen) {
817835
new EditorWindow(null, fullscreen);
818836
}
819837
}

src-preload/desktop-settings.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ contextBridge.exposeInMainWorld('DesktopSettingsPreload', {
1212
setSpellchecker: (spellchecker) => ipcRenderer.invoke('set-spellchecker', spellchecker),
1313
setExitFullscreenOnEscape: (exitFullscreenOnEscape) => ipcRenderer.invoke('set-exit-fullscreen-on-escape', exitFullscreenOnEscape),
1414
setRichPresence: (richPresence) => ipcRenderer.invoke('set-rich-presence', richPresence),
15+
setBlurBackground: (useBlurBackground) => ipcRenderer.invoke('use-blur-background', useBlurBackground),
1516
openUserData: () => ipcRenderer.invoke('open-user-data')
1617
});

src-preload/editor.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ contextBridge.exposeInMainWorld('EditorPreload', {
2626
exportForPackager = callback;
2727
},
2828
setIsFullScreen: (isFullScreen) => ipcRenderer.invoke('set-is-full-screen', isFullScreen),
29-
getLocalStorage: (key) => localStorage.getItem(key)
29+
getLocalStorage: (key) => localStorage.getItem(key),
3030
});
3131

3232
let exportForPackager = () => Promise.reject(new Error('exportForPackager missing'));
@@ -52,6 +52,13 @@ window.addEventListener('message', (e) => {
5252
}
5353
});
5454

55+
window.addEventListener('storage', () => {
56+
const theme = localStorage.getItem('tw:theme');
57+
if (process.platform === 'win32') {
58+
ipcRenderer.invoke('set-window-theme', theme);
59+
}
60+
})
61+
5562
ipcRenderer.on('enumerate-media-devices', (e) => {
5663
navigator.mediaDevices.enumerateDevices()
5764
.then((devices) => {

src-renderer/desktop-settings/desktop-settings.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,19 @@ <h1 class="title"></h1>
301301
document.querySelector('.exit-fullscreen-on-escape-label').textContent = strings['desktop-settings.exit-fullscreen-on-escape'];
302302
</script>
303303

304+
<label>
305+
<input type="checkbox" class="useBlurBackground-checkbox" autocomplete="off">
306+
<span class="useBlurBackground-label"></span>
307+
</label>
308+
<script>
309+
const useBlurBackground = document.querySelector('.useBlurBackground-checkbox');
310+
useBlurBackground.onchange = () => {
311+
DesktopSettingsPreload.setBlurBackground(useBlurBackground.checked);
312+
};
313+
useBlurBackground.checked = settings.useBlurBackground;
314+
document.querySelector('.useBlurBackground-label').textContent = strings['desktop-settings.useBlurBackground'];
315+
</script>
316+
304317
<label>
305318
<input type="checkbox" class="rich-presence-checkbox" autocomplete="off">
306319
<span class="rich-presence-label"></span>

0 commit comments

Comments
 (0)