mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00:00
feat(electron): add global context menu (#13218)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added automatic synchronization of language settings between the desktop app and the system environment. * Context menu actions (Cut, Copy, Paste) in the desktop app are now localized according to the selected language. * **Improvements** * Context menu is always available with standard editing actions, regardless of spell check settings. * **Localization** * Added translations for "Cut", "Copy", and "Paste" in the context menu. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { I18n } from '@affine/i18n';
|
||||
import { ipcMain } from 'electron';
|
||||
|
||||
import { AFFINE_API_CHANNEL_NAME } from '../shared/type';
|
||||
@@ -21,6 +22,12 @@ export const debugHandlers = {
|
||||
},
|
||||
};
|
||||
|
||||
export const i18nHandlers = {
|
||||
changeLanguage: async (_: Electron.IpcMainInvokeEvent, language: string) => {
|
||||
return I18n.changeLanguage(language);
|
||||
},
|
||||
};
|
||||
|
||||
// Note: all of these handlers will be the single-source-of-truth for the apis exposed to the renderer process
|
||||
export const allHandlers = {
|
||||
debug: debugHandlers,
|
||||
@@ -33,6 +40,7 @@ export const allHandlers = {
|
||||
worker: workerHandlers,
|
||||
recording: recordingHandlers,
|
||||
popup: popupHandlers,
|
||||
i18n: i18nHandlers,
|
||||
};
|
||||
|
||||
export const registerHandlers = () => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { join } from 'node:path';
|
||||
|
||||
import { I18n } from '@affine/i18n';
|
||||
import {
|
||||
app,
|
||||
BrowserWindow,
|
||||
@@ -822,42 +823,53 @@ export class WebContentViewsManager {
|
||||
},
|
||||
});
|
||||
|
||||
if (spellCheckSettings.enabled) {
|
||||
view.webContents.on('context-menu', (_event, params) => {
|
||||
const shouldShow =
|
||||
params.misspelledWord && params.dictionarySuggestions.length > 0;
|
||||
view.webContents.on('context-menu', (_event, params) => {
|
||||
const menu = Menu.buildFromTemplate([
|
||||
{
|
||||
id: 'cut',
|
||||
label: I18n['com.affine.context-menu.cut'](),
|
||||
role: 'cut',
|
||||
enabled: params.editFlags.canCut,
|
||||
},
|
||||
{
|
||||
id: 'copy',
|
||||
label: I18n['com.affine.context-menu.copy'](),
|
||||
role: 'copy',
|
||||
enabled: params.editFlags.canCopy,
|
||||
},
|
||||
{
|
||||
id: 'paste',
|
||||
label: I18n['com.affine.context-menu.paste'](),
|
||||
role: 'paste',
|
||||
enabled: params.editFlags.canPaste,
|
||||
},
|
||||
]);
|
||||
|
||||
if (!shouldShow) {
|
||||
return;
|
||||
}
|
||||
const menu = new Menu();
|
||||
// Add each spelling suggestion
|
||||
for (const suggestion of params.dictionarySuggestions) {
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: suggestion,
|
||||
click: () => view.webContents.replaceMisspelling(suggestion),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Add each spelling suggestion
|
||||
for (const suggestion of params.dictionarySuggestions) {
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: suggestion,
|
||||
click: () => view.webContents.replaceMisspelling(suggestion),
|
||||
})
|
||||
);
|
||||
}
|
||||
// Allow users to add the misspelled word to the dictionary
|
||||
if (params.misspelledWord) {
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: 'Add to dictionary', // TODO: i18n
|
||||
click: () =>
|
||||
view.webContents.session.addWordToSpellCheckerDictionary(
|
||||
params.misspelledWord
|
||||
),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Allow users to add the misspelled word to the dictionary
|
||||
if (params.misspelledWord) {
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: 'Add to dictionary', // TODO: i18n
|
||||
click: () =>
|
||||
view.webContents.session.addWordToSpellCheckerDictionary(
|
||||
params.misspelledWord
|
||||
),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
menu.popup();
|
||||
});
|
||||
}
|
||||
menu.popup();
|
||||
});
|
||||
|
||||
this.webViewsMap$.next(this.tabViewsMap.set(viewId, view));
|
||||
let unsub = () => {};
|
||||
|
||||
Reference in New Issue
Block a user